some bits changed during 24c3 (no comments!) :)
[my-code/fpga.git] / fx2 / fx2.c
index ddea734..0ba6db9 100644 (file)
--- a/fx2/fx2.c
+++ b/fx2/fx2.c
  *
  * author: hackbard@hackdaworld.org
  *
- * number of priorities:
- * - switch on board power
- * - allow high speed usb transfer
+ * feature list:
+ * - switch on board power (done)
+ * - allow high speed bulk usb transfer
  * - do jtag
  * 
  */
 
 /* constant definitions */
-#define TRUE   1
-#define FALSE  0
-#define POWER_ON       1;
-#define POWER_OFF      0;
+#define GET_TDO                0x20
 
 /* type definitions */
 typedef unsigned char u8;
 typedef unsigned short u16;
 typedef unsigned int u32;
 
-/* fx2 register */
-xdata at 0xb5 volatile u8 OED;
-xdata at 0xb0 volatile u8 IOD;
+/*
+ * fx2 register
+ */
+
+/* general configuration */
+xdata at 0xe600 volatile u8 CPUCS;
+xdata at 0xe601 volatile u8 IFCONFIG;
+
+/* endpoint configuration */
+xdata at 0xe604 volatile u8 FIFORESET;
+xdata at 0xe60b volatile u8 REVCTL;
+xdata at 0xe610 volatile u8 EP1OUTCFG;
+xdata at 0xe611 volatile u8 EP1INCFG;
+xdata at 0xe612 volatile u8 EP2CFG;
+xdata at 0xe613 volatile u8 EP4CFG;
+xdata at 0xe614 volatile u8 EP6CFG;
+xdata at 0xe615 volatile u8 EP8CFG;
+xdata at 0xe618 volatile u8 EP2FIFOCFG;
+xdata at 0xe619 volatile u8 EP4FIFOCFG;
+xdata at 0xe61a volatile u8 EP6FIFOCFG;
+xdata at 0xe61b volatile u8 EP8FIFOCFG;
+xdata at 0xe620 volatile u8 EP2AUTOINLENH;
+xdata at 0xe621 volatile u8 EP2AUTOINLENL;
+xdata at 0xe624 volatile u8 EP6AUTOINLENH;
+xdata at 0xe625 volatile u8 EP6AUTOINLENL;
+
+/* endpoint control/status */
+xdata at 0xe6a1 volatile u8 EP1OUTCS;
+xdata at 0xe6a2 volatile u8 EP1INCS;
+xdata at 0xe68d volatile u16 EP1OUTBC;
+xdata at 0xe68f volatile u16 EP1INBC;
+
+#define STALL  0x01
+#define BUSY   0x02
+
+/* access to endpoint buffers */
+xdata at 0xe780 volatile u8 EP1OUTBUF[64];
+xdata at 0xe7c0 volatile u8 EP1INBUF[64];
+
+/* special funtion registers */
+sfr at 0xb5 OED;
+sfr at 0xb0 IOD;
 
-void power_on() {
+/* synchronization delay after writing/reading to registers 0xe600 - 0xe6ff
+ * and some others (p. 438).
+ * maximum delay necessary at highest cpu speed: 16 cycles => 17 nops */
+#define SYNCDELAY _asm \
+       nop; nop; nop; nop; nop; nop; nop; nop; \
+       nop; nop; nop; nop; nop; nop; nop; nop; \
+       nop; _endasm
 
+void power_init() {
+
+       /* pin 7 of port d connected to mosfet gate controlling the board power
+        *
+        * ref: http://digilentinc.com/Data/Products/NEXYS/Nexys_sch.pdf
+        */
+
+       /* configure pin 7 of port d as output */
        OED|=(1<<7);
-       IOD|=(1<<7);
+       SYNCDELAY;
+
 }
 
-void main() {
+void toggle_power() {
+
+       /* toggle high/low state of the mosfet gate */
+
+       if((IOD&(1<<7)))
+               IOD&=~(1<<7);
+       else
+               IOD|=(1<<7);
+
+       SYNCDELAY;
 
-       power_on;
 }
 
+void jtag_init() {
+
+       /* pin 5 of port d disables tdi -> tdo forward */
+       OED|=(1<<5);
+       IOD|=(1<<5);
+
+       /* jtag pins:
+        * tdi - pin 0 (input)
+        * tdo - pin 2 (output)
+        * tms - pin 3 (output)
+        * tck - pin 4 (output)
+        */
+       OED|=((1<<2)|(1<<3)|(1<<4));
+       OED&=~(1<<0);
+
+}
+
+void cpu_init() {
+
+       /* cpu initialization: (0x10)
+        * - 48 mhz
+        * - none inverted signal
+        * - no clk out
+        */
+
+       CPUCS=(1<<4);
+       SYNCDELAY;
+
+}
+
+void slave_fifo_init() {
+
+       /* initialization of the slave fifo, used by external logic (the fpga)
+        * to do usb communication with the host */
+
+       /* enable dyn_out and enhanced packet handling (p. 189) */
+       REVCTL=0x03;
+       SYNCDELAY;
+
+       /* internal 48 mhz clock, async, slave fifo */
+       IFCONFIG=0xcb;
+       SYNCDELAY;
+
+       /* endpoint setup:
+        *
+        * ep2: bulk out 2x512
+        * ep4: bulk out 2x512
+        * ep6: bulk in 2x512
+        * ep8: bulk in 2x512
+        */
+       EP2CFG=0xa2;
+       EP4CFG=0xa0;
+       EP6CFG=0xc2;
+       EP8CFG=0xc0;
+       SYNCDELAY;
+
+       /* reset the fifo */
+       FIFORESET=0x80; /* nak all transfers */
+       SYNCDELAY;
+       FIFORESET=0x02; /* reset ep2 */
+       SYNCDELAY;
+       FIFORESET=0x04; /* reset ep4 */
+       SYNCDELAY;
+       FIFORESET=0x06; /* reset ep6 */
+       SYNCDELAY;
+       FIFORESET=0x08; /* reset ep8 */
+       SYNCDELAY;
+       FIFORESET=0x00; /* restore normal operation */
+       SYNCDELAY;
+
+       /* 8 bit fifo to all endpoints */
+       EP2FIFOCFG=;
+       SYNCDELAY;
+       EP4FIFOCFG=;
+       SYNCDELAY;
+       EP6FIFOCFG=;
+       SYNCDELAY;
+       EP8FIFOCFG=;
+       SYNCDELAY;
+
+       /* default indexed flag configuration:
+        *
+        * flag a: programmable level
+        * flag b: full
+        * flag c: empty
+        *
+        * todo: -> fixed configuration
+        */
+
+       /* auto in/out, no cpu interaction! auto in len = 512 */
+       EP2FIFOCFG|=(1<<4);
+       SYNCDELAY;
+       EP6FIFOCFG|=(1<<3);
+       SYNCDELAY;
+       EP6AUTOINLENH=(1<<1);
+       SYNCDELAY;
+       EP6AUTOINLENL=0;
+       SYNCDELAY;
+
+}
+
+void ep1_init() {
+
+       /* initialize endpoint 1
+        *
+        * used for jtag & control
+        */
+
+       /* endpoint 1 configuration:
+        *
+        * default (valid, bulk) fits!
+        */
+
+       /* arm ep1out, clear ep1out and ep1in stall bit */
+       EP1OUTBC=0;
+       EP1OUTCS&=~STALL;
+       EP1INCS&=~STALL;
+
+}
+
+void fx2_init() {
+
+       /* syncdelay */
+       SYNCDELAY;
+
+       /* cpu init */
+       cpu_init();
+
+       /* power init & power on */
+       power_init();
+       toggle_power();
+
+       /* slave fifo init */
+       slave_fifo_init();
+
+       /* ep1 init */
+       ep1_init();
+
+       /* jtag init */
+       jtag_init();
+}
+
+void main() {
+
+       u8 buf,set;
+
+       /* initialize the fx2 */
+       fx2_init();
+
+       /* jtag by polling ep1 */
+
+       while(1) {
+               if(!(EP1OUTCS&BUSY)) {
+                       set=IOD;
+                       buf=EP1OUTBUF[0];
+                       IOD=(IOD&(~0x1c))|(buf&0x1c);
+                       EP1OUTBC=1;
+               }
+               if(!(EP1INCS&BUSY)) {
+                       EP1INBUF[0]=IOD&0x01;
+                       EP1INBC=1;
+               }
+       }
+
+}
 
-