X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=s88w%2Fs88w-r.c;fp=s88w%2Fs88w-r.c;h=019897483cc63b2b36dc1f6cc79cf151e4064f72;hb=9c37d18b9c70fdb70dfec453398c4649e9e57586;hp=0000000000000000000000000000000000000000;hpb=49b6b6ad84ec47b4f9eb9ef131975cc5b72372a2;p=model-railway-devices.git diff --git a/s88w/s88w-r.c b/s88w/s88w-r.c new file mode 100644 index 0000000..0198974 --- /dev/null +++ b/s88w/s88w-r.c @@ -0,0 +1,219 @@ +/* +Firmware for wireless S88 receiver module + +S88 pinout: +1 - DATA +2 - GND +3 - CLOCK +4 - LOAD +5 - RESET +6 - POWER + +ATMega pinout: +D0 - serial RX +D1 - serial TX +D2 - S88 DATA +D3 - S88 CLOCK +D4 - S88 LOAD +D5 - S88 RESET +*/ + +#include +#include +#include "lcd.h" +#include "serial.h" +#include "delay.h" + +#define DATA_OUT PORTD2 +#define CLOCK PIND3 +#define LOAD PIND4 +#define RESET PIND5 + +#define LCD_DISABLE PINB4 + +#define BIT(n) (1<<(n)) + +void receive(uint8_t); +uint8_t hexdigit(uint8_t); +uint8_t decode_hex(uint8_t); + +volatile uint8_t rx_buf[7]; +volatile uint8_t rx_fill = 0xFF; +volatile uint8_t input[128] = { 0 }; +volatile uint8_t latch[128] = { 0 }; +volatile uint8_t lcd_enabled = 0; +uint8_t log_row = 0; +uint8_t log_col = 0; + +int main() +{ + uint8_t clock_high = 0; + uint8_t bits = 0; + uint8_t n_bits = 8; + uint8_t offset = 0; + uint8_t i; + + DDRD = 0x06; // 00000110 + PORTD = 0xC0; // 11000000 + DDRB = 0x20; // 00100000 + PORTB = 0x1F; // 00011111 + + serial_init(9600); + lcd_init(); + + sei(); + + while(1) + { + uint8_t b_pins, d_pins; + + b_pins = PINB; + d_pins = PIND; + + if(d_pins&BIT(CLOCK)) + { + if(!clock_high) + { + if(d_pins&BIT(LOAD)) + { + offset = 0; + bits = latch[0]; + n_bits = 8; + } + else + { + bits >>= 1; + if(!--n_bits) + { + ++offset; + bits = latch[offset]; + n_bits = 8; + } + } + + if(bits&1) + PORTD |= BIT(DATA_OUT); + else + PORTD &= ~BIT(DATA_OUT); + + clock_high = 1; + } + } + else if(clock_high) + clock_high = 0; + + if(d_pins&BIT(RESET)) + { + uint8_t i; + for(i=0; i<128; ++i) + latch[i] = input[i]; + } + + if(b_pins&BIT(LCD_DISABLE)) + { + if(lcd_enabled) + { + lcd_enabled = 0; + + lcd_clear(); + } + } + else if(!lcd_enabled) + { + lcd_enabled = 1; + log_row = 0; + log_col = 0; + + lcd_clear(); + for(i=0; i<20; ++i) + lcd_write(hexdigit(input[9-i/2]>>(4-i%2*4))); + lcd_gotoxy(0, 1); + lcd_write(255); + } + } +} + +void receive(uint8_t c) +{ + if(rx_fill==0xFF) + { + if(c==':') + rx_fill = 0; + } + else if(c=='.') + { + if(rx_fill>=4) + { + uint16_t offset; + uint8_t nibbles; + uint8_t i; + + offset = (decode_hex(rx_buf[0])<<8) | (decode_hex(rx_buf[1])<<4) | decode_hex(rx_buf[2]); + nibbles = (offset&3); + offset >>= 2; + if(rx_fill>3+nibbles) + { + for(i=0; i<=nibbles; ++i) + { + uint16_t j = offset+nibbles-i; + uint8_t shift = 4*(j&1); + uint8_t bits = decode_hex(rx_buf[3+i]); + input[j/2] = (input[j/2]&~(0xF<=20) + { + log_col = 0; + ++log_row; + if(log_row>=3) + log_row = 0; + lcd_gotoxy(log_col, 1+log_row); + } + lcd_write(255); + } +} + +SERIAL_SET_CALLBACK(receive) + +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; +}