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