]> git.tdb.fi Git - model-railway-devices.git/blobdiff - s88w/s88w-r.c
Reorganize the directory structure
[model-railway-devices.git] / s88w / s88w-r.c
diff --git a/s88w/s88w-r.c b/s88w/s88w-r.c
new file mode 100644 (file)
index 0000000..0198974
--- /dev/null
@@ -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 <avr/io.h>
+#include <avr/interrupt.h>
+#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<<shift)) | (bits<<shift);
+                                       latch[j/2] = input[j/2];
+                               }
+
+                               if(lcd_enabled)
+                               {
+                                       lcd_gotoxy(19-offset-nibbles, 0);
+                                       for(i=0; i<=nibbles; ++i)
+                                               lcd_write(rx_buf[3+i]);
+                               }
+                       }
+               }
+               rx_fill = 0xFF;
+       }
+       else
+       {
+               if(rx_fill<sizeof(rx_buf))
+                       rx_buf[rx_fill++] = c;
+               else
+                       rx_fill = 0xFF;
+       }
+
+       if(lcd_enabled)
+       {
+               lcd_gotoxy(log_col, 1+log_row);
+               lcd_write(c);
+               ++log_col;
+               if(log_col>=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;
+}