some bits changed during 24c3 (no comments!) :)
[my-code/fpga.git] / fx2 / fx2.c
1 /*
2  * fx2 firmware 
3  *
4  * author: hackbard@hackdaworld.org
5  *
6  * feature list:
7  * - switch on board power (done)
8  * - allow high speed bulk usb transfer
9  * - do jtag
10  * 
11  */
12
13 /* constant definitions */
14 #define GET_TDO         0x20
15
16 /* type definitions */
17 typedef unsigned char u8;
18 typedef unsigned short u16;
19 typedef unsigned int u32;
20
21 /*
22  * fx2 register
23  */
24
25 /* general configuration */
26 xdata at 0xe600 volatile u8 CPUCS;
27 xdata at 0xe601 volatile u8 IFCONFIG;
28
29 /* endpoint configuration */
30 xdata at 0xe604 volatile u8 FIFORESET;
31 xdata at 0xe60b volatile u8 REVCTL;
32 xdata at 0xe610 volatile u8 EP1OUTCFG;
33 xdata at 0xe611 volatile u8 EP1INCFG;
34 xdata at 0xe612 volatile u8 EP2CFG;
35 xdata at 0xe613 volatile u8 EP4CFG;
36 xdata at 0xe614 volatile u8 EP6CFG;
37 xdata at 0xe615 volatile u8 EP8CFG;
38 xdata at 0xe618 volatile u8 EP2FIFOCFG;
39 xdata at 0xe619 volatile u8 EP4FIFOCFG;
40 xdata at 0xe61a volatile u8 EP6FIFOCFG;
41 xdata at 0xe61b volatile u8 EP8FIFOCFG;
42 xdata at 0xe620 volatile u8 EP2AUTOINLENH;
43 xdata at 0xe621 volatile u8 EP2AUTOINLENL;
44 xdata at 0xe624 volatile u8 EP6AUTOINLENH;
45 xdata at 0xe625 volatile u8 EP6AUTOINLENL;
46
47 /* endpoint control/status */
48 xdata at 0xe6a1 volatile u8 EP1OUTCS;
49 xdata at 0xe6a2 volatile u8 EP1INCS;
50 xdata at 0xe68d volatile u16 EP1OUTBC;
51 xdata at 0xe68f volatile u16 EP1INBC;
52
53 #define STALL   0x01
54 #define BUSY    0x02
55
56 /* access to endpoint buffers */
57 xdata at 0xe780 volatile u8 EP1OUTBUF[64];
58 xdata at 0xe7c0 volatile u8 EP1INBUF[64];
59
60 /* special funtion registers */
61 sfr at 0xb5 OED;
62 sfr at 0xb0 IOD;
63
64 /* synchronization delay after writing/reading to registers 0xe600 - 0xe6ff
65  * and some others (p. 438).
66  * maximum delay necessary at highest cpu speed: 16 cycles => 17 nops */
67 #define SYNCDELAY _asm \
68         nop; nop; nop; nop; nop; nop; nop; nop; \
69         nop; nop; nop; nop; nop; nop; nop; nop; \
70         nop; _endasm
71
72 void power_init() {
73
74         /* pin 7 of port d connected to mosfet gate controlling the board power
75          *
76          * ref: http://digilentinc.com/Data/Products/NEXYS/Nexys_sch.pdf
77          */
78
79         /* configure pin 7 of port d as output */
80         OED|=(1<<7);
81         SYNCDELAY;
82
83 }
84
85 void toggle_power() {
86
87         /* toggle high/low state of the mosfet gate */
88
89         if((IOD&(1<<7)))
90                 IOD&=~(1<<7);
91         else
92                 IOD|=(1<<7);
93
94         SYNCDELAY;
95
96 }
97
98 void jtag_init() {
99
100         /* pin 5 of port d disables tdi -> tdo forward */
101         OED|=(1<<5);
102         IOD|=(1<<5);
103
104         /* jtag pins:
105          * tdi - pin 0 (input)
106          * tdo - pin 2 (output)
107          * tms - pin 3 (output)
108          * tck - pin 4 (output)
109          */
110         OED|=((1<<2)|(1<<3)|(1<<4));
111         OED&=~(1<<0);
112
113 }
114
115 void cpu_init() {
116
117         /* cpu initialization: (0x10)
118          * - 48 mhz
119          * - none inverted signal
120          * - no clk out
121          */
122
123         CPUCS=(1<<4);
124         SYNCDELAY;
125
126 }
127
128 void slave_fifo_init() {
129
130         /* initialization of the slave fifo, used by external logic (the fpga)
131          * to do usb communication with the host */
132
133         /* enable dyn_out and enhanced packet handling (p. 189) */
134         REVCTL=0x03;
135         SYNCDELAY;
136
137         /* internal 48 mhz clock, async, slave fifo */
138         IFCONFIG=0xcb;
139         SYNCDELAY;
140
141         /* endpoint setup:
142          *
143          * ep2: bulk out 2x512
144          * ep4: bulk out 2x512
145          * ep6: bulk in 2x512
146          * ep8: bulk in 2x512
147          */
148         EP2CFG=0xa2;
149         EP4CFG=0xa0;
150         EP6CFG=0xc2;
151         EP8CFG=0xc0;
152         SYNCDELAY;
153
154         /* reset the fifo */
155         FIFORESET=0x80; /* nak all transfers */
156         SYNCDELAY;
157         FIFORESET=0x02; /* reset ep2 */
158         SYNCDELAY;
159         FIFORESET=0x04; /* reset ep4 */
160         SYNCDELAY;
161         FIFORESET=0x06; /* reset ep6 */
162         SYNCDELAY;
163         FIFORESET=0x08; /* reset ep8 */
164         SYNCDELAY;
165         FIFORESET=0x00; /* restore normal operation */
166         SYNCDELAY;
167
168         /* 8 bit fifo to all endpoints */
169         EP2FIFOCFG=;
170         SYNCDELAY;
171         EP4FIFOCFG=;
172         SYNCDELAY;
173         EP6FIFOCFG=;
174         SYNCDELAY;
175         EP8FIFOCFG=;
176         SYNCDELAY;
177
178         /* default indexed flag configuration:
179          *
180          * flag a: programmable level
181          * flag b: full
182          * flag c: empty
183          *
184          * todo: -> fixed configuration
185          */
186
187         /* auto in/out, no cpu interaction! auto in len = 512 */
188         EP2FIFOCFG|=(1<<4);
189         SYNCDELAY;
190         EP6FIFOCFG|=(1<<3);
191         SYNCDELAY;
192         EP6AUTOINLENH=(1<<1);
193         SYNCDELAY;
194         EP6AUTOINLENL=0;
195         SYNCDELAY;
196
197 }
198
199 void ep1_init() {
200
201         /* initialize endpoint 1
202          *
203          * used for jtag & control
204          */
205
206         /* endpoint 1 configuration:
207          *
208          * default (valid, bulk) fits!
209          */
210
211         /* arm ep1out, clear ep1out and ep1in stall bit */
212         EP1OUTBC=0;
213         EP1OUTCS&=~STALL;
214         EP1INCS&=~STALL;
215
216 }
217
218 void fx2_init() {
219
220         /* syncdelay */
221         SYNCDELAY;
222
223         /* cpu init */
224         cpu_init();
225
226         /* power init & power on */
227         power_init();
228         toggle_power();
229
230         /* slave fifo init */
231         slave_fifo_init();
232
233         /* ep1 init */
234         ep1_init();
235
236         /* jtag init */
237         jtag_init();
238 }
239
240 void main() {
241
242         u8 buf,set;
243
244         /* initialize the fx2 */
245         fx2_init();
246
247         /* jtag by polling ep1 */
248
249         while(1) {
250                 if(!(EP1OUTCS&BUSY)) {
251                         set=IOD;
252                         buf=EP1OUTBUF[0];
253                         IOD=(IOD&(~0x1c))|(buf&0x1c);
254                         EP1OUTBC=1;
255                 }
256                 if(!(EP1INCS&BUSY)) {
257                         EP1INBUF[0]=IOD&0x01;
258                         EP1INBC=1;
259                 }
260         }
261
262 }
263