test commit
[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         /* set bit 0 and 1 - fifo slave config */       
134         IFCONFIG|=0x03;
135         SYNCDELAY;
136
137         /* async mode */
138         IFCONFIG|=0x04;
139         SYNCDELAY;
140
141         /* p. 180: must be set to 1 */
142         REVCTL|=((1<<0)|(1<<1));
143         SYNCDELAY;
144
145         /* 8 bit fifo to all endpoints
146          *
147          * ('or' of all these bits define port d functionality)
148          */
149         EP2FIFOCFG&=~(1<<0);
150         SYNCDELAY;
151         EP4FIFOCFG&=~(1<<0);
152         SYNCDELAY;
153         EP6FIFOCFG&=~(1<<0);
154         SYNCDELAY;
155         EP8FIFOCFG&=~(1<<0);
156         SYNCDELAY;
157
158         /* default indexed flag configuration:
159          *
160          * flag a: programmable level
161          * flag b: full
162          * flag c: empty
163          *
164          * todo: -> fixed configuration
165          */
166
167         /* endpoint configuration:
168          *
169          * ep2: bulk out 4x512
170          * ep6: bulk in 4x512
171          *
172          * 0xa0 = 1 0 1 0 0 0 0 0 = bulk out 4x512
173          * 0xe0 = 1 1 1 0 0 0 0 0 = bulk in 4x512
174          */
175         EP2CFG=0xa0;
176         SYNCDELAY;
177         EP4CFG&=(~0x80);
178         SYNCDELAY;
179         EP6CFG=0xe0;
180         SYNCDELAY;
181         EP8CFG&=(~0x80);
182         SYNCDELAY;
183
184         /* reset the fifo */
185         FIFORESET=0x80; /* nak all transfers */
186         SYNCDELAY;
187         FIFORESET=0x02; /* reset ep2 */
188         SYNCDELAY;
189         FIFORESET=0x06; /* reset ep6 */
190         SYNCDELAY;
191         FIFORESET=0x00; /* restore normal operation */
192         SYNCDELAY;
193
194         /* auto in/out, no cpu interaction! auto in len = 512 */
195         EP2FIFOCFG|=(1<<4);
196         SYNCDELAY;
197         EP6FIFOCFG|=(1<<3);
198         SYNCDELAY;
199         EP6AUTOINLENH=(1<<1);
200         SYNCDELAY;
201         EP6AUTOINLENL=0;
202         SYNCDELAY;
203
204 }
205
206 void ep1_init() {
207
208         /* initialize endpoint 1
209          *
210          * used for jtag & control
211          */
212
213         /* endpoint 1 configuration:
214          *
215          * default (valid, bulk) fits!
216          */
217
218         /* arm ep1out, clear ep1out and ep1in stall bit */
219         EP1OUTBC=1;
220         EP1OUTCS&=~STALL;
221         EP1INCS&=~STALL;
222
223 }
224
225 void fx2_init() {
226
227         /* syncdelay */
228         SYNCDELAY;
229
230         /* cpu init */
231         cpu_init();
232
233         /* power init & power on */
234         power_init();
235         toggle_power();
236
237         /* slave fifo init */
238         slave_fifo_init();
239
240         /* ep1 init */
241         ep1_init();
242
243         /* jtag init */
244         jtag_init();
245 }
246
247 void main() {
248
249         u8 buf,set;
250
251         /* initialize the fx2 */
252         fx2_init();
253
254         /* jtag by polling ep1 */
255         while(1) {
256                 if(!(EP1OUTCS&BUSY)) {
257                         buf=EP1OUTBUF[0];
258                         if(buf!=GET_TDO) {
259                                 set=(IOD&(~0x1c))|(buf&0x1c);
260                                 IOD=set;
261                                 EP1OUTBC=1;
262                         }
263                         else {
264                                 while(EP1INCS&BUSY)
265                                         continue;
266                                 buf=IOD&0x01?1:0;
267                                 EP1INBUF[0]=buf;
268                                 EP1INBC=1;
269                         }
270                 }
271         }
272
273 }
274