]> git.tdb.fi Git - model-railway-devices.git/blob - firmware/s88w-r.c
Add some utility functions for interfacing with hardware
[model-railway-devices.git] / firmware / s88w-r.c
1 /* $Id$
2
3 This file is part of the MSP Märklin suite
4 Copyright © 2010  Mikkosoft Productions, Mikko Rasa
5 Distributed under the GPL
6
7 Firmware for wireless S88 receiver module
8
9 S88 pinout:
10 1 - DATA
11 2 - GND
12 3 - CLOCK
13 4 - LOAD
14 5 - RESET
15 6 - POWER
16
17 ATMega pinout:
18 D0 - serial RX
19 D1 - serial TX
20 D2 - S88 DATA
21 D3 - S88 CLOCK
22 D4 - S88 LOAD
23 D5 - S88 RESET
24 */
25
26 #include <avr/io.h>
27 #include <avr/interrupt.h>
28 #include "lcd.h"
29 #include "serial.h"
30
31 #define DATA_OUT PORTD2
32 #define CLOCK    PIND3
33 #define LOAD     PIND4
34 #define RESET    PIND5
35
36 #define BIT(n)   (1<<(n))
37
38 void receive(uint8_t);
39 uint8_t hexdigit(uint8_t);
40 uint8_t decode_hex(uint8_t);
41
42 volatile uint8_t rx_buf[7];
43 volatile uint8_t rx_fill = 0xFF;
44 volatile uint8_t input[128] = { 0 };
45 volatile uint8_t latch[128] = { 0 };
46 uint8_t log_pos = 0;
47
48 int main()
49 {
50         uint8_t clock_high = 0;
51         uint8_t bits = 0;
52         uint8_t n_bits = 8;
53         uint8_t offset = 0;
54
55         DDRD = 0x06;  // 00000110
56         PIND = 0xC0;  // 11000000
57         DDRB = 0x20;  // 00100000
58         PINB = 0x1F;  // 00011111
59
60         serial_init(9600);
61         serial_set_callback(receive);
62         lcd_init();
63         lcd_on();
64         lcd_clear();
65
66         sei();
67
68         while(1)
69         {
70                 uint8_t d_pins;
71
72                 d_pins = PIND;
73
74                 if(d_pins&BIT(CLOCK))
75                 {
76                         if(!clock_high)
77                         {
78                                 if(d_pins&BIT(LOAD))
79                                 {
80                                         offset = 0;
81                                         bits = latch[0];
82                                         n_bits = 8;
83                                 }
84                                 else
85                                 {
86                                         bits >>= 1;
87                                         if(!--n_bits)
88                                         {
89                                                 ++offset;
90                                                 bits = latch[offset];
91                                                 n_bits = 8;
92                                         }
93                                 }
94
95                                 if(bits&1)
96                                         PORTD |= BIT(DATA_OUT);
97                                 else
98                                         PORTD &= ~BIT(DATA_OUT);
99
100                                 clock_high = 1;
101                         }
102                 }
103                 else if(clock_high)
104                         clock_high = 0;
105
106                 if(d_pins&BIT(RESET))
107                 {
108                         uint8_t i;
109                         for(i=0; i<128; ++i)
110                                 latch[i] = input[i];
111                 }
112         }
113 }
114
115 void receive(uint8_t c)
116 {
117         if(rx_fill==0xFF)
118         {
119                 if(c==':')
120                         rx_fill = 0;
121         }
122         else if(c=='.')
123         {
124                 if(rx_fill>=4)
125                 {
126                         uint16_t offset;
127                         uint8_t nibbles;
128                         uint8_t i;
129
130                         offset = (decode_hex(rx_buf[0])<<8) | (decode_hex(rx_buf[1])<<4) | decode_hex(rx_buf[2]);
131                         nibbles = (offset&3);
132                         offset >>= 2;
133                         if(rx_fill>3+nibbles)
134                         {
135                                 for(i=0; i<=nibbles; ++i)
136                                 {
137                                         uint16_t j = offset+nibbles-i;
138                                         uint8_t shift = 4*(j&1);
139                                         uint8_t bits = decode_hex(rx_buf[3+i]);
140                                         input[j/2] = (input[j/2]&~(0xF<<shift)) | (bits<<shift);
141                                         latch[j/2] = input[j/2];
142                                 }
143                         }
144
145                         lcd_gotoxy(0, 0);
146                         for(i=10; i--;)
147                         {
148                                 lcd_write(hexdigit(input[i]>>4));
149                                 lcd_write(hexdigit(input[i]));
150                         }
151                 }
152                 rx_fill = 0xFF;
153         }
154         else
155         {
156                 if(rx_fill<sizeof(rx_buf))
157                         rx_buf[rx_fill++] = c;
158                 else
159                         rx_fill = 0xFF;
160         }
161
162         lcd_gotoxy(log_pos%20, 1+log_pos/20);
163         lcd_write(c);
164         ++log_pos;
165         if(log_pos>=60)
166                 log_pos = 0;
167         lcd_gotoxy(log_pos%20, 1+log_pos/20);
168         lcd_write(255);
169 }
170
171 uint8_t hexdigit(uint8_t n)
172 {
173         n &= 0xF;
174         if(n<10)
175                 return '0'+n;
176         else
177                 return 'A'+(n-0xA);
178 }
179
180 uint8_t decode_hex(uint8_t c)
181 {
182         if(c>='0' && c<='9')
183                 return c-'0';
184         else if(c>='A' && c<='F')
185                 return 0xA+(c-'A');
186         else
187                 return 0;
188 }