checkpoint
[slipway.git] / src / edu / berkeley / slipway / FtdiBoardSlave.c
diff --git a/src/edu/berkeley/slipway/FtdiBoardSlave.c b/src/edu/berkeley/slipway/FtdiBoardSlave.c
new file mode 100644 (file)
index 0000000..52f3817
--- /dev/null
@@ -0,0 +1,339 @@
+//\r
+// YOU MUST COMPILE THIS WITH -O3 OR THE AVR WILL NOT BE ABLE TO KEEP UP!!!!\r
+//\r
+\r
+#define F_CPU 12000000\r
+\r
+#if !defined(__AVR_AT94K__)\r
+#error you forgot to put -mmcu=at94k on the command line\r
+#endif\r
+\r
+#include <avr/wdt.h>\r
+#include <util/delay.h>\r
+#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
+\r
+int err = 0;\r
+\r
+void initUART0(unsigned int baudRate, unsigned int doubleRate) {\r
+  UBRRHI  = (((baudRate) >> 8) & 0x000F); \r
+  UBRR0   = ((baudRate) & 0x00FF); \r
+  UCSR0B |= ((1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0)); \r
+\r
+  if (doubleRate)\r
+    UCSR0A |=  (1 << U2X0);\r
+  else\r
+    UCSR0A &= ~(1 << U2X0);\r
+}\r
+\r
+#define BUFSIZE (1024)\r
+\r
+inline void portd(int bit, int on) {\r
+  /*\r
+  if (on) {\r
+    PORTD &= ~(1<<bit);\r
+  } else {\r
+    PORTD |= (1<<bit);\r
+  }\r
+  */\r
+}\r
+\r
+long int numread = 0;\r
+inline void cts(int c) {\r
+  numread++;\r
+  if (c) {\r
+    PORTE &= ~(1 << 7);\r
+    portd(0, 0);\r
+  } else {\r
+    PORTE |= (1 << 7);\r
+    portd(0, 1);\r
+  }\r
+}\r
+\r
+\r
+static volatile int sending = 0;\r
+static volatile int32_t interrupt_count = 0;\r
+\r
+// RECV //////////////////////////////////////////////////////////////////////////////\r
+\r
+char read_buf[BUFSIZE];\r
+volatile int read_buf_head;\r
+volatile int read_buf_tail;\r
+char write_buf[BUFSIZE];\r
+volatile int write_buf_head;\r
+volatile int write_buf_tail;\r
+\r
+inline int inc(int x) { x++; if (x>=BUFSIZE) x=0; return x; }\r
+inline int read_full() { return inc(read_buf_tail)==read_buf_head; }\r
+inline int abs(int x) { return x<0 ? -x : x; }\r
+inline int read_size() { return read_buf_tail<read_buf_head ? (read_buf_head-read_buf_tail) : (read_buf_tail-read_buf_head); }\r
+inline int read_empty() { return read_buf_head==read_buf_tail; }\r
+inline int read_nearlyFull() {\r
+  if (read_buf_tail==read_buf_head) return 0;\r
+  if (read_buf_tail < read_buf_head) return (read_buf_head-read_buf_tail) < (BUFSIZE/2);\r
+  return (read_buf_tail-read_buf_head) > (BUFSIZE/2);\r
+}\r
+\r
+inline int write_full() { return inc(write_buf_tail)==write_buf_head; }\r
+inline int write_empty() { return write_buf_head==write_buf_tail; }\r
+inline int write_nearlyFull() {\r
+  if (write_buf_tail==write_buf_head) return 0;\r
+  if (write_buf_tail < write_buf_head) return (write_buf_head-write_buf_tail) < (BUFSIZE/2);\r
+  return (write_buf_tail-write_buf_head) > (BUFSIZE/2);\r
+}\r
+\r
+inline char recv() {\r
+  int q;\r
+  char ret;\r
+  while(read_empty()) cts(1);\r
+  ret = read_buf[read_buf_head];\r
+  read_buf_head = inc(read_buf_head);\r
+  if (!read_nearlyFull()) cts(1);\r
+  if (PORTE & (1<<3)) PORTE &= ~(1<<3);\r
+  else                PORTE |=  (1<<3);\r
+  return ret;\r
+}\r
+\r
+ISR(SIG_UART0_DATA) {\r
+  if (write_empty()) {\r
+    UCSR0B &= ~(1 << UDRIE0);\r
+    return;\r
+  }\r
+  char ret = write_buf[write_buf_head];\r
+  write_buf_head = inc(write_buf_head);\r
+  UDR0 = (int)ret;\r
+  sei();\r
+}\r
+\r
+void send(char c) {\r
+  while (write_full());\r
+  write_buf[write_buf_tail] = c;\r
+  write_buf_tail = inc(write_buf_tail);\r
+  if (PORTE & (1<<2)) PORTE &= ~(1<<2);\r
+  else                PORTE |=  (1<<2);\r
+  UCSR0B |= (1 << UDRIE0);\r
+}\r
+\r
+\r
+void fpga_interrupts(int on) {\r
+  if (on/* && interrupt_count<301*/) {\r
+    //FISUA = 0x1;\r
+    FISCR = 0x80;\r
+    FISUD = 0x08;\r
+  } else {\r
+    FISUD = 0;\r
+    FISCR = 0;\r
+  }\r
+}\r
+\r
+void init() {\r
+  read_buf_head = 0;\r
+  read_buf_tail = 0;\r
+  write_buf_head = 0;\r
+  write_buf_tail = 0;\r
+  //initUART0(1, 0);  //for slow board\r
+  initUART0(0, 0);  //for slow board\r
+  //initUART0(0, 1);  //for slow board\r
+}\r
+\r
+void conf(int z, int y, int x, int d) {\r
+  FPGAX = x;\r
+  FPGAY = y;\r
+  FPGAZ = z;\r
+  FPGAD = d;\r
+}\r
+\r
+void doreset() {\r
+  int i;\r
+  for(i=0; i<5; i++) {\r
+    PORTD = ~0x01;\r
+    _delay_ms(50);\r
+    PORTD = ~0x02;\r
+    _delay_ms(50);\r
+    PORTD = ~0x04;\r
+    _delay_ms(50);\r
+    PORTD = ~0x08;\r
+    _delay_ms(50);\r
+  }\r
+  PORTD = ~0x00;\r
+  wdt_enable(WDTO_250MS);\r
+  while(1) { }\r
+}\r
+\r
+#define TIMERVAL 100\r
+int portdc = 0;\r
+\r
+ISR(SIG_FPGA_INTERRUPT15) { \r
+  PORTD = portdc++;\r
+  interrupt_count++;\r
+  //PORTD = ~(interrupt_count & 0xff);\r
+  //if (interrupt_count >= 301) fpga_interrupts(0);\r
+  //sei();\r
+  fpga_interrupts(1);\r
+}\r
+/*\r
+ISR(SIG_OVERFLOW0) { \r
+  fpga_interrupts(0);\r
+  PORTD = ~FISUA;\r
+  TCNT0 = TIMERVAL;           // load the nearest-to-one-second value  into the timer0\r
+  TIMSK |= (1<<TOIE0);        // enable the compare match1 interrupt and the timer/counter0 overflow interrupt\r
+  if (sending) UDR1 = FISUA;\r
+  fpga_interrupts(1);\r
+  sei();\r
+} \r
+void init_timer()  { \r
+  TCCR0 |= (1<<CS00);         // set the timer0 prescaler to CK\r
+  TCNT0 = TIMERVAL;           // load the nearest-to-one-second value  into the timer0\r
+  TIMSK |= (1<<TOIE0);        //enable the compare match1 interrupt and the timer/counter0 overflow interrupt\r
+} \r
+*/\r
+ISR(SIG_INTERRUPT0) {   // use interrupt1 since interrupt0 is sent by the watchdog (I think)\r
+  SREG = 0;\r
+  //PORTE |=  (1<<0);\r
+  sei();\r
+}\r
+void die() { cli(); PORTE|=(1<<5); _delay_ms(2000); while(1) { portd(2,0); portd(2,1); } }\r
+\r
+ISR(SIG_UART0_RECV) {\r
+\r
+  if (UCSR0A & (1 << FE0))    err = 201;//{ portd(2,0); portd(3,1); die(); }  // framing error, lock up with LED=01\r
+  if ((UCSR0A & (1 << OR0)))  err = 202;//{ portd(2,1); portd(3,0); die(); }  // overflow; lock up with LED=10\r
+  if (read_full())            err = 203;//{ portd(2,1); portd(3,1); die(); }  // buffer overrun\r
+\r
+  read_buf[read_buf_tail] = UDR0;\r
+  read_buf_tail = inc(read_buf_tail);\r
+  if (read_nearlyFull()) cts(0);\r
+  SREG |= 0x80;\r
+  sei();\r
+}\r
+\r
+inline int hex(char c) {\r
+  if (c >= '0' && c <= '9') return (c - '0');\r
+  if (c >= 'a' && c <= 'f') return ((c - 'a') + 0xa);\r
+  if (c >= 'A' && c <= 'F') return ((c - 'A') + 0xa);\r
+  return -1;\r
+}\r
+\r
+int main() {\r
+  DDRE = (1<<7) | (1<<5) | (1<<3) | (1<<2);\r
+  PORTE = 0;\r
+\r
+  init();\r
+\r
+  EIMF = 0xFF;\r
+  SREG = INT0;\r
+  sei();\r
+\r
+  PORTE &= ~(1<<7);\r
+\r
+  int count = 0;\r
+  long long bad = 0;\r
+  int left = 0;\r
+  char v = 0;\r
+  long int oldi = 0;\r
+  cts(0);\r
+  cts(1);\r
+  /*\r
+  while(1) {\r
+    long int i = recv() & 0xff;\r
+    //if (i < 0) err = 200;\r
+    //if (err < 200) {\r
+      long int newi = oldi+1;\r
+      if (newi >= 256) newi -= 256;\r
+      if (i != newi) err++;\r
+      //}\r
+    oldi = i;\r
+\r
+    send(err >= 10 ? 255 : i);\r
+    //send(err);\r
+  }\r
+  */\r
+\r
+  int x=0, y=0, z=0;\r
+  //while(1) send(/*FISUA*/2);\r
+  for(;;) {\r
+    /*\r
+    if (PORTE & (1<<6)) PORTE &= ~(1<<6);\r
+    else                PORTE |=  (1<<6);\r
+    */\r
+    int i, d=0;\r
+    int r = recv();\r
+    switch(r) {\r
+      case 0:\r
+        send('O');\r
+        send('B');\r
+        send('I');\r
+        send('T');\r
+        send('S');\r
+        PORTE |=  (1<<3);\r
+        break;\r
+      case 1:\r
+        z = recv();\r
+        y = recv();\r
+        x = recv();\r
+        d = recv();\r
+        //portd(1,1);\r
+        conf(z, y, x, d);\r
+        //portd(1,0);\r
+        break;\r
+      case 2:\r
+        //fpga_interrupts(0);\r
+        //portd(1,1);\r
+        send(FISUA);\r
+        //portd(1,0);\r
+        //fpga_interrupts(1);\r
+        break;\r
+        /*\r
+      case 3:\r
+        //init_timer();\r
+        break;\r
+      case 4:\r
+        sending = 1;\r
+        break;\r
+      case 5:\r
+        sending = 0;\r
+        break;\r
+      case 6: {\r
+        int32_t local_interrupt_count = interrupt_count;\r
+        interrupt_count = 0;\r
+        send((local_interrupt_count >> 24) & 0xff);\r
+        send((local_interrupt_count >> 16) & 0xff);\r
+        send((local_interrupt_count >>  8) & 0xff);\r
+        send((local_interrupt_count >>  0) & 0xff);\r
+        fpga_interrupts(1);\r
+        break;\r
+      }\r
+        */\r
+        /*\r
+      default: {\r
+        if ((r & 0x80) == 0x80) {\r
+          switch (r & 0x44) {\r
+            case 0x44: z = recv(); break;\r
+            case 0x40: z++;        break;\r
+            case 0x04: z--;        break;\r
+          }\r
+          switch (r & 0x22) {\r
+            case 0x22: y = recv(); break;\r
+            case 0x20: y++;        break;\r
+            case 0x02: y--;        break;\r
+          }\r
+          switch (r & 0x11) {\r
+            case 0x11: x = recv(); break;\r
+            case 0x10: x++;        break;\r
+            case 0x01: x--;        break;\r
+          }\r
+          d = recv();\r
+          portd(1,1);\r
+          conf(z, y, x, d);\r
+          portd(1,0);\r
+          break;\r
+        }\r
+        die();\r
+      }\r
+        */\r
+    }\r
+  }\r
+  return 0;\r
+\r
+}  \r
+\r