]> git.tdb.fi Git - model-railway-devices.git/blobdiff - firmware/s88w-t.c
Add wireless s88 firmware and schematic
[model-railway-devices.git] / firmware / s88w-t.c
diff --git a/firmware/s88w-t.c b/firmware/s88w-t.c
new file mode 100644 (file)
index 0000000..e88a1f5
--- /dev/null
@@ -0,0 +1,111 @@
+/* $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 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
+
+Inputs are pulled high by internal pull-up resistors.  Connect to GND to
+activate.
+*/
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+#define BIT(n) (1<<(n))
+
+void send_state(void);
+void write_serial(uint8_t);
+uint8_t hexdigit(uint8_t);
+
+volatile uint8_t state = 0;
+
+int main()
+{
+       DDRD = 0x02;   // 00000010
+       PORTD = 0xFC;  // 11111100
+       DDRB = 0x20;   // 00100000
+       PORTB = 0x3F;  // 00111111
+
+       // 9600 baud, 8N1
+       UBRR0H = 0;
+       UBRR0L = 103;
+       UCSR0C = BIT(UCSZ00) | BIT(UCSZ01);
+       UCSR0B = BIT(RXEN0) | BIT(TXEN0);
+
+       // 0.5 Hz (CK/1024, TOP=31250)
+       TCCR1A = 0;
+       TCCR1B = BIT(WGM12) | BIT(CS12) | BIT(CS10);
+       OCR1AH = 122;
+       OCR1AL = 18;
+       TIMSK1 = BIT(OCIE1A);
+
+       sei();
+
+       while(1)
+       {
+               uint8_t i;
+               uint8_t input = 0;
+               uint8_t valid = 0xFF;
+
+               for(i=0; i<100; ++i)
+               {
+                       uint8_t pins;
+
+                       pins = ~((PIND>>2) | (PINB<<6));
+                       if(i==0)
+                               input = pins;
+                       valid &= ~(pins^input);
+               }
+
+               input &= valid;
+               input |= state&~valid;
+
+               if(input!=state)
+               {
+                       state = input;
+                       send_state();
+               }
+       }
+
+       return 0;
+}
+
+ISR(TIMER1_COMPA_vect)
+{
+       send_state();
+}
+
+void send_state(void)
+{
+       write_serial(':');
+       write_serial(hexdigit(state>>4));
+       write_serial(hexdigit(state&0xF));
+}
+
+void write_serial(uint8_t c)
+{
+       while(!(UCSR0A&(1<<UDRE0))) ;
+       UDR0 = c;
+}
+
+uint8_t hexdigit(uint8_t n)
+{
+       if(n<10)
+               return '0'+n;
+       else
+               return 'A'+(n-0xA);
+}