fixed heinous bug in switchbox routing
[slipway.git] / src / edu / berkeley / slipway / FtdiBoardSlave.c
1 //\r
2 // YOU MUST COMPILE THIS WITH -O3 OR THE AVR WILL NOT BE ABLE TO KEEP UP!!!!\r
3 //\r
4 \r
5 #define F_CPU 12000000\r
6 \r
7 #if !defined(__AVR_AT94K__)\r
8 #error you forgot to put -mmcu=at94k on the command line\r
9 #endif\r
10 \r
11 #include <avr/wdt.h>\r
12 #include <util/delay.h>\r
13 #include <avr/io.h>\r
14 #include <avr/interrupt.h>\r
15 \r
16 int err = 0;\r
17 \r
18 void initUART0(unsigned int baudRate, unsigned int doubleRate) {\r
19   UBRRHI  = (((baudRate) >> 8) & 0x000F); \r
20   UBRR0   = ((baudRate) & 0x00FF); \r
21   UCSR0B |= ((1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0)); \r
22 \r
23   if (doubleRate)\r
24     UCSR0A |=  (1 << U2X0);\r
25   else\r
26     UCSR0A &= ~(1 << U2X0);\r
27 }\r
28 \r
29 #define BUFSIZE (1024)\r
30 \r
31 long int numread = 0;\r
32 inline void cts(int c) {\r
33   numread++;\r
34   if (c) {\r
35     PORTE &= ~(1 << 7);\r
36   } else {\r
37     PORTE |= (1 << 7);\r
38   }\r
39 }\r
40 \r
41 \r
42 static volatile int sending = 0;\r
43 static volatile int32_t interrupt_count = 0;\r
44 \r
45 // RECV //////////////////////////////////////////////////////////////////////////////\r
46 \r
47 char read_buf[BUFSIZE];\r
48 volatile int read_buf_head;\r
49 volatile int read_buf_tail;\r
50 char write_buf[BUFSIZE];\r
51 volatile int write_buf_head;\r
52 volatile int write_buf_tail;\r
53 \r
54 inline int inc(int x) { x++; if (x>=BUFSIZE) x=0; return x; }\r
55 inline int read_full() { return inc(read_buf_tail)==read_buf_head; }\r
56 inline int abs(int x) { return x<0 ? -x : x; }\r
57 inline int read_size() { return read_buf_tail<read_buf_head ? (read_buf_head-read_buf_tail) : (read_buf_tail-read_buf_head); }\r
58 inline int read_empty() { return read_buf_head==read_buf_tail; }\r
59 inline int read_nearlyFull() {\r
60   if (read_buf_tail==read_buf_head) return 0;\r
61   if (read_buf_tail < read_buf_head) return (read_buf_head-read_buf_tail) < (BUFSIZE/2);\r
62   return (read_buf_tail-read_buf_head) > (BUFSIZE/2);\r
63 }\r
64 \r
65 inline int write_full() { return inc(write_buf_tail)==write_buf_head; }\r
66 inline int write_empty() { return write_buf_head==write_buf_tail; }\r
67 inline int write_nearlyFull() {\r
68   if (write_buf_tail==write_buf_head) return 0;\r
69   if (write_buf_tail < write_buf_head) return (write_buf_head-write_buf_tail) < (BUFSIZE/2);\r
70   return (write_buf_tail-write_buf_head) > (BUFSIZE/2);\r
71 }\r
72 \r
73 inline char recv() {\r
74   int q;\r
75   char ret;\r
76   while(read_empty()) cts(1);\r
77   ret = read_buf[read_buf_head];\r
78   read_buf_head = inc(read_buf_head);\r
79   if (!read_nearlyFull()) cts(1);\r
80   if (PORTE & (1<<3)) PORTE &= ~(1<<3);\r
81   else                PORTE |=  (1<<3);\r
82   return ret;\r
83 }\r
84 \r
85 // Interrupt Handlers //////////////////////////////////////////////////////////////////////////////\r
86 \r
87 ISR(SIG_UART0_DATA) {\r
88   if (write_empty()) {\r
89     UCSR0B &= ~(1 << UDRIE0);\r
90     return;\r
91   }\r
92   char ret = write_buf[write_buf_head];\r
93   write_buf_head = inc(write_buf_head);\r
94   UDR0 = (int)ret;\r
95   sei();\r
96 }\r
97 \r
98 void send(char c) {\r
99   while (write_full());\r
100   write_buf[write_buf_tail] = c;\r
101   write_buf_tail = inc(write_buf_tail);\r
102   if (PORTE & (1<<2)) PORTE &= ~(1<<2);\r
103   else                PORTE |=  (1<<2);\r
104   UCSR0B |= (1 << UDRIE0);\r
105 }\r
106 \r
107 \r
108 void fpga_interrupts(int on) {\r
109   if (on) {\r
110     //FISUA = 0x1;\r
111     FISCR = 0x80;\r
112     FISUD = 0x08;\r
113   } else {\r
114     FISUD = 0;\r
115     FISCR = 0;\r
116   }\r
117 }\r
118 \r
119 inline void conf(int z, int y, int x, int d) {\r
120   FPGAX = x;\r
121   FPGAY = y;\r
122   FPGAZ = z;\r
123   FPGAD = d;\r
124 }\r
125 \r
126 #define TIMERVAL 100\r
127 \r
128 ISR(SIG_FPGA_INTERRUPT15) { \r
129   interrupt_count++;\r
130   //fpga_interrupts(1);\r
131   sei();\r
132 }\r
133 \r
134 void die() { cli(); PORTE|=(1<<5); _delay_ms(2000); while(1) { } }\r
135 \r
136 ISR(SIG_UART0_RECV) {\r
137   if (UCSR0A & (1 << FE0))    err = 201;//{ portd(2,0); portd(3,1); die(); }  // framing error, lock up with LED=01\r
138   if ((UCSR0A & (1 << OR0)))  err = 202;//{ portd(2,1); portd(3,0); die(); }  // overflow; lock up with LED=10\r
139   if (read_full())            err = 203;//{ portd(2,1); portd(3,1); die(); }  // buffer overrun\r
140 \r
141   read_buf[read_buf_tail] = UDR0;\r
142   read_buf_tail = inc(read_buf_tail);\r
143   if (read_nearlyFull()) cts(0);\r
144   SREG |= 0x80;\r
145   sei();\r
146 }\r
147 \r
148 inline int hex(char c) {\r
149   if (c >= '0' && c <= '9') return (c - '0');\r
150   if (c >= 'a' && c <= 'f') return ((c - 'a') + 0xa);\r
151   if (c >= 'A' && c <= 'F') return ((c - 'A') + 0xa);\r
152   return -1;\r
153 }\r
154 \r
155 int readFPGA() {\r
156   int ret = FISUA;\r
157   //fpga_interrupts(1);\r
158   return ret;\r
159 }\r
160 \r
161 int main() {\r
162   DDRE  = (1<<7) | (1<<5) | (1<<3) | (1<<2);\r
163   PORTE = 0;\r
164 \r
165   read_buf_head = 0;\r
166   read_buf_tail = 0;\r
167   write_buf_head = 0;\r
168   write_buf_tail = 0;\r
169   initUART0(0, 0);  //for slow board\r
170 \r
171   EIMF = 0xFF;\r
172   SREG = INT0;\r
173   sei();\r
174 \r
175   cts(0);\r
176   cts(1);\r
177 \r
178   int x=0, y=0, z=0;\r
179   int flag=0;\r
180   for(;;) {\r
181     int i, d=0;\r
182     int r = recv();\r
183     switch(r) {\r
184       case 0:\r
185         send('O');\r
186         send('B');\r
187         send('I');\r
188         send('T');\r
189         send('S');\r
190         fpga_interrupts(0);\r
191         if (flag) {PORTE |=  (1<<5);}\r
192         break;\r
193 \r
194       case 1:\r
195         z = recv();\r
196         y = recv();\r
197         x = recv();\r
198         d = recv();\r
199         conf(z, y, x, d);\r
200         break;\r
201 \r
202       case 2:\r
203         flag=1;\r
204         send(readFPGA());\r
205         break;\r
206         /*\r
207       case 3: {\r
208         int32_t local_interrupt_count = interrupt_count;\r
209         interrupt_count = 0;\r
210         send((local_interrupt_count >> 24) & 0xff);\r
211         send((local_interrupt_count >> 16) & 0xff);\r
212         send((local_interrupt_count >>  8) & 0xff);\r
213         send((local_interrupt_count >>  0) & 0xff);\r
214         break;\r
215       }\r
216         */\r
217         /*\r
218       case 3:\r
219         //init_timer();\r
220         break;\r
221       case 4:\r
222         sending = 1;\r
223         break;\r
224       case 5:\r
225         sending = 0;\r
226         break;\r
227         */\r
228     }\r
229   }\r
230   return 0;\r
231 \r
232 }  \r
233 \r