3 This file is part of the MSP Märklin suite
4 Copyright © 2010 Mikkosoft Productions, Mikko Rasa
5 Distributed under the GPL
7 Firmware for wireless S88 transmitter module
25 Inputs are pulled high by internal pull-up resistors. Connect to GND to
28 The module can be configured by sending a string of form ":Shhh." over the
29 serial port, where hhh is a hex number. Lower two bits indicate the number of
30 inputs (00=4, 01=8, 10=12, 11=16) and upper ten bits indicate offset of lowest
31 input in multiples of 4 bits. At the moment there are no provisions for
32 having 16 physical inputs.
34 Example: ":S016." would configure the module to have 12 inputs at offset 20.
38 #include <avr/interrupt.h>
43 #define BIT(n) (1<<(n))
45 void receive(uint8_t);
46 void send_state(void);
47 uint8_t hexdigit(uint8_t);
48 uint8_t decode_hex(uint8_t);
51 uint8_t rx_fill = 0xFF;
52 volatile uint8_t nibbles = 2;
53 volatile uint8_t offset = 0;
54 volatile uint16_t state = 0;
58 if(eeprom_read(0)==0xA5)
60 offset = eeprom_read(1)<<8;
61 offset |= eeprom_read(2);
62 nibbles = eeprom_read(3);
65 DDRD = 0x02; // 00000010
66 PORTD = 0xFC; // 11111100
67 DDRB = 0x00; // 00000000
68 PORTB = 0x3F; // 00111111
71 timer_start_hz(1, 1, 2);
79 uint16_t valid = 0xFFF;
85 pins = ~((PIND>>2) | ((PINB&0x3F)<<6));
88 valid &= ~(pins^input);
92 input |= state&~valid;
93 input &= (1<<(nibbles*4))-1;
105 void receive(uint8_t c)
114 if(rx_buf[0]=='S' && rx_fill==4)
116 offset = (decode_hex(rx_buf[1])<<8) | (decode_hex(rx_buf[2])<<4) | decode_hex(rx_buf[3]);
117 nibbles = (offset&3)+1;
120 eeprom_write(0, 0xA5);
121 eeprom_write(1, offset>>8);
122 eeprom_write(2, offset);
123 eeprom_write(3, nibbles);
129 if(rx_fill<sizeof(rx_buf))
130 rx_buf[rx_fill++] = c;
136 SERIAL_SET_CALLBACK(receive)
138 void send_state(void)
142 serial_write(hexdigit(offset>>8));
143 serial_write(hexdigit(offset>>4));
144 serial_write(hexdigit(offset|(nibbles-1)));
146 serial_write(hexdigit(state>>(i*4)));
150 TIMER_SET_CALLBACK(1, send_state)
152 uint8_t hexdigit(uint8_t n)
161 uint8_t decode_hex(uint8_t c)
165 else if(c>='A' && c<='F')