+++ /dev/null
-/*
-Firmware for wireless S88 transmitter module
-
-ATMega pinout:
-D0 - serial RX
-D1 - serial TX
-D2 - input 1
-D3 - input 2
-D4 - input 3
-D5 - input 4
-D6 - input 5
-D7 - input 6
-B0 - input 7
-B1 - input 8
-B2 - input 9
-B3 - input 10
-B4 - input 11
-B5 - input 12
-
-Inputs are pulled high by internal pull-up resistors. Connect to GND to
-activate.
-
-The module can be configured by sending a string of form ":Shhh." over the
-serial port, where hhh is a hex number. Lower two bits indicate the number of
-inputs (00=4, 01=8, 10=12, 11=16) and upper ten bits indicate offset of lowest
-input in multiples of 4 bits. At the moment there are no provisions for
-having 16 physical inputs.
-
-Example: ":S016." would configure the module to have 12 inputs at offset 20.
-*/
-
-#include <avr/io.h>
-#include <avr/interrupt.h>
-#include "eeprom.h"
-#include "serial.h"
-#include "timer.h"
-
-#define BIT(n) (1<<(n))
-
-void receive(uint8_t);
-void send_state(void);
-uint8_t hexdigit(uint8_t);
-uint8_t decode_hex(uint8_t);
-
-uint8_t rx_buf[4];
-uint8_t rx_fill = 0xFF;
-volatile uint8_t nibbles = 2;
-volatile uint8_t offset = 0;
-volatile uint16_t state = 0;
-volatile uint8_t time_since_send = 0;
-
-int main()
-{
- if(eeprom_read(0)==0xA5)
- {
- offset = eeprom_read(1)<<8;
- offset |= eeprom_read(2);
- nibbles = eeprom_read(3);
- }
-
- DDRD = 0x02; // 00000010
- PORTD = 0xFC; // 11111100
- DDRB = 0x00; // 00000000
- PORTB = 0x3F; // 00111111
-
- serial_init(9600);
- timer_start_hz(1, 100, 1);
-
- sei();
-
- while(1)
- {
- uint8_t i, j;
- uint16_t input = 0;
- uint16_t valid = 0xFFF;
-
- for(i=0; i<100; ++i)
- {
- uint16_t pins = 0;
- for(j=0; j<100; ++j)
- pins |= ~((PIND>>2) | ((PINB&0x3F)<<6));
-
- if(i==0)
- input = pins;
-
- valid &= ~(pins^input);
- }
-
- input &= valid;
- input |= state&~valid;
- input &= (1<<(nibbles*4))-1;
-
- if(input!=state && time_since_send>5)
- {
- state = input;
- send_state();
- }
- }
-
- return 0;
-}
-
-void receive(uint8_t c)
-{
- if(rx_fill==0xFF)
- {
- if(c==':')
- rx_fill = 0;
- }
- else if(c=='.')
- {
- if(rx_buf[0]=='S' && rx_fill==4)
- {
- offset = (decode_hex(rx_buf[1])<<8) | (decode_hex(rx_buf[2])<<4) | decode_hex(rx_buf[3]);
- nibbles = (offset&3)+1;
- offset &= 0xFFC;
-
- eeprom_write(0, 0xA5);
- eeprom_write(1, offset>>8);
- eeprom_write(2, offset);
- eeprom_write(3, nibbles);
- }
- rx_fill = 0xFF;
- }
- else
- {
- if(rx_fill<sizeof(rx_buf))
- rx_buf[rx_fill++] = c;
- else
- rx_fill = 0xFF;
- }
-}
-
-SERIAL_SET_CALLBACK(receive)
-
-void send_state(void)
-{
- uint8_t i;
-
- serial_write(':');
- serial_write(hexdigit(offset>>8));
- serial_write(hexdigit(offset>>4));
- serial_write(hexdigit(offset|(nibbles-1)));
- for(i=nibbles; i--;)
- serial_write(hexdigit(state>>(i*4)));
- serial_write('.');
-
- time_since_send = 0;
-}
-
-void timer(void)
-{
- ++time_since_send;
- if(time_since_send>200)
- send_state();
-}
-
-TIMER_SET_CALLBACK(1, timer)
-
-uint8_t hexdigit(uint8_t n)
-{
- n &= 0xF;
- if(n<10)
- return '0'+n;
- else
- return 'A'+(n-0xA);
-}
-
-uint8_t decode_hex(uint8_t c)
-{
- if(c>='0' && c<='9')
- return c-'0';
- else if(c>='A' && c<='F')
- return 0xA+(c-'A');
- else
- return 0;
-}