]> git.tdb.fi Git - model-railway-devices.git/blobdiff - firmware/s88w-r.c
Add wireless s88 firmware and schematic
[model-railway-devices.git] / firmware / s88w-r.c
diff --git a/firmware/s88w-r.c b/firmware/s88w-r.c
new file mode 100644 (file)
index 0000000..dac0cfc
--- /dev/null
@@ -0,0 +1,120 @@
+/* $Id$
+
+This file is part of the MSP Märklin suite
+Copyright © 2010  Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+
+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>
+
+#define DATA_OUT PORTD2
+#define CLOCK    PIND3
+#define LOAD     PIND4
+#define RESET    PIND5
+
+#define BIT(n)   (1<<(n))
+
+uint8_t decode_hex(uint8_t);
+
+volatile uint8_t rx_buf[3];
+volatile uint8_t rx_fill = 0;
+volatile uint8_t input = 0;
+volatile uint8_t latch = 0;
+
+int main()
+{
+       uint8_t clock_high = 0;
+       uint8_t bits = 0;
+
+       DDRD = 0x06;  // 00000110
+       PIND = 0xC0;  // 11000000
+       DDRB = 0x20;  // 00100000
+       PINB = 0x1F;  // 00011111
+
+       // 9600 baud, 8N1
+       UBRR0H = 0;
+       UBRR0L = 103;
+       UCSR0C = BIT(UCSZ00) | BIT(UCSZ01);
+       UCSR0B = BIT(RXEN0) | BIT(TXEN0) | BIT(RXCIE0);
+
+       sei();
+
+       while(1)
+       {
+               uint8_t d_pins;
+
+               d_pins = PIND;
+
+               if(d_pins&BIT(CLOCK))
+               {
+                       if(!clock_high)
+                       {
+                               if(d_pins&BIT(LOAD))
+                                       bits = latch;
+                               else
+                                       bits >>= 1;
+
+                               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))
+                       latch = input;
+       }
+}
+
+ISR(USART_RX_vect)
+{
+       uint8_t c = UDR0;
+       if(rx_fill==0)
+       {
+               if(c==':')
+                       rx_buf[rx_fill++] = c;
+       }
+       else
+       {
+               rx_buf[rx_fill++] = c;
+               if(rx_buf[0]==':' && rx_fill==3)
+               {
+                       input = (decode_hex(rx_buf[1])<<4) | decode_hex(rx_buf[2]);
+                       latch |= input;
+                       rx_fill = 0;
+               }
+       }
+}
+
+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;
+}