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