]> sigrok.org Git - sigrok-firmware-fx2lafw.git/blob - fx2lafw.c
First attempt at a sampling GPIF waveform (untested!).
[sigrok-firmware-fx2lafw.git] / fx2lafw.c
1 /*
2  * This file is part of the fx2lafw project.
3  *
4  * Copyright (C) 2011-2012 Uwe Hermann <uwe@hermann-uwe.de>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 /*
22  * fx2lafw is an open-source firmware for Cypress FX2 based logic analyzers.
23  *
24  * It is written in C, using fx2lib as helper library, and sdcc as compiler.
25  * The code is licensed under the terms of the GNU GPL, version 2 or later.
26  *
27  * Technical notes:
28  *
29  *  - We use the FX2 in GPIF mode to sample the data (asynchronously).
30  *  - We use the internal 48MHz clock for GPIF.
31  *  - The 8 channels/pins we sample (the GPIF data bus) are PB0-PB7.
32  *    Support for 16 channels is not yet included, but might be added later.
33  *  - Endpoint 2 is used for data transfers from FX2 to host.
34  *  - The endpoint is quad-buffered.
35  *
36  * Documentation:
37  *
38  *  - See http://sigrok.org/wiki/Fx2lafw
39  */
40
41 #include <fx2regs.h>
42 #include <fx2macros.h>
43 #include <delay.h>
44 #include <autovector.h>
45 #include <setupdat.h>
46 #include <eputils.h>
47 #include <gpif.h>
48
49 #define SYNCDELAY() SYNCDELAY4
50
51 /* ... */
52 volatile bit got_sud;
53
54 /* GPIF terminology: DP = decision point, NDP = non-decision-point */
55
56 /*
57  * GPIF waveforms.
58  *
59  * See section "10.3.4 State Instructions" in the TRM for details.
60  */
61 static const BYTE wavedata[128] = {
62         /* Waveform 0: */
63
64         /*
65          * This is the basic algorithm implemented in our GPIF state machine:
66          *
67          * State 0: NDP: Sample the FIFO data bus.
68          * State 1: DP: If EP2 is full, go to state 7 (the IDLE state), i.e.,
69          *          end the current waveform. Otherwise, go to state 0 again,
70          *          i.e., sample data until EP2 is full.
71          * State 2: Unused.
72          * State 3: Unused.
73          * State 4: Unused.
74          * State 5: Unused.
75          * State 6: Unused.
76          */
77
78         /* S0-S6: LENGTH/BRANCH */
79         /*
80          * For NDPs (LENGTH): Number of IFCLK cycles to stay in this state.
81          * For DPs (BRANCH): [7] ReExec, [5:3]: BRANCHON1, [2:0]: BRANCHON0.
82          *
83          * 0x01: Stay one IFCLK cycle in this state.
84          * 0x38: No Re-execution, BRANCHON1 = state 7, BRANCHON0 = state 0.
85          */
86         0x01, 0x38, 0x01, 0x01, 0x01, 0x01, 0x01,
87         /* TRM says "reserved", but GPIF designer always puts a 0x07 here. */
88         0x07,
89
90         /* S0-S6: OPCODE */
91         /*
92          * 0x02: NDP, sample the FIFO data bus.
93          * 0x01: DP, don't sample the FIFO data bus.
94          */
95         0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
96         /* Reserved */
97         0x00,
98
99         /* S0-S6: OUTPUT */
100         /* Unused, we don't output anything, we only sample the pins. */
101         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102         /* Reserved */
103         0x00,
104
105         /* S0-S6: LOGIC FUNCTION (not used for NDPs) */
106         /*
107          * 0x36: LFUNC = "A AND B", A = FIFO flag, B = FIFO flag.
108          * The FIFO flag (FF == full flag, in our case) is configured via
109          * EP2GPIFFLGSEL.
110          *
111          * So: If the EP2 FIFO is full and the EP2 FIFO is full, go to
112          * the state specified by BRANCHON1 (state 7), otherwise BRANCHON0
113          * (state 0). See the LENGTH/BRANCH value above for details.
114          */
115         0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
116         /* TRM says "reserved", but GPIF designer always puts a 0x3f here. */
117         0x3f,
118
119         /* TODO: Must unused waveforms be "valid"? */
120
121         /* Waveform 1 (unused): */
122         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126
127         /* Waveform 2 (unused): */
128         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132
133         /* Waveform 3 (unused): */
134         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 };
139
140 static void gpif_setup_registers(void)
141 {
142         /* TODO. Value probably irrelevant, as we don't use RDY* signals? */
143         GPIFREADYCFG = 0;
144
145         /*
146          * Set TRICTL = 0, thus CTL0-CTL5 are CMOS outputs.
147          * TODO: Probably irrelevant, as we don't use CTL0-CTL5?
148          */
149         GPIFCTLCFG = 0;
150
151         /* When GPIF is idle, tri-state the data bus. */
152         /* Bit 7: DONE, bit 0: IDLEDRV. TODO: Set/clear DONE bit? */
153         GPIFIDLECS = (1 << 0);
154
155         /* When GPIF is idle, set CTL0-CTL5 to 0. */
156         GPIFIDLECTL = 0;
157
158         /*
159          * Map index 0 in wavedata[] to FIFORD. The rest is assigned too,
160          * but not used by us.
161          *
162          * GPIFWFSELECT: [7:6] = SINGLEWR index, [5:4] = SINGLERD index,
163          *               [3:2] = FIFOWR index, [1:0] = FIFORD index
164          */
165         GPIFWFSELECT = (0x3 << 6) | (0x2 << 4) | (0x1 << 2) | (0x0 << 0);
166
167         /* Contains RDY* pin values. Read-only according to TRM. */
168         GPIFREADYSTAT = 0;
169 }
170
171 static void gpif_write_waveforms(void)
172 {
173         int i;
174
175         /*
176          * Write the four waveforms into the respective WAVEDATA register
177          * locations (0xe400 - 0xe47f) using the FX2's autopointer feature.
178          */
179         AUTOPTRSETUP = 0x07;             /* Increment autopointers 1 & 2. */
180         AUTOPTRH1 = MSB((WORD)wavedata); /* Source is the 'wavedata' array. */
181         AUTOPTRL1 = LSB((WORD)wavedata);
182         AUTOPTRH2 = 0xe4;                /* Dest is WAVEDATA (0xe400). */
183         AUTOPTRL2 = 0x00;
184         for (i = 0; i < 128; i++)
185                 EXTAUTODAT2 = EXTAUTODAT1;
186 }
187
188 static void gpif_init_addr_pins(void)
189 {
190         /*
191          * Configure the 9 GPIF address pins (GPIFADR[8:0], which consist of
192          * PORTC[7:0] and PORTE[7]), and output an initial address (zero).
193          * TODO: Probably irrelevant, the 56pin FX2 has no ports C and E.
194          */
195         PORTCCFG = 0xff;    /* Set PORTC[7:0] as alt. func. (GPIFADR[7:0]). */
196         OEC = 0xff;         /* Configure PORTC[7:0] as outputs. */
197         PORTECFG |= 0x80;   /* Set PORTE[7] as alt. func. (GPIFADR[8]). */
198         OEE |= 0x80;        /* Configure PORTE[7] as output. */
199         SYNCDELAY();
200         GPIFADRL = 0x00;    /* Clear GPIFADR[7:0]. */
201         SYNCDELAY();
202         GPIFADRH = 0x00;    /* Clear GPIFADR[8]. */
203 }
204
205 static void gpif_init_flowstates(void)
206 {
207         /* Clear all flowstate registers, we don't use this functionality. */
208         FLOWSTATE = 0;
209         FLOWLOGIC = 0;
210         FLOWEQ0CTL = 0;
211         FLOWEQ1CTL = 0;
212         FLOWHOLDOFF = 0;
213         FLOWSTB = 0;
214         FLOWSTBEDGE = 0;
215         FLOWSTBHPERIOD = 0;
216 }
217
218 static void gpif_init_la(void)
219 {
220         /*
221          * Setup the FX2 in GPIF master mode, using the internal clock
222          * (non-inverted) at 48MHz, and using async sampling.
223          */
224         IFCONFIG = 0xee;
225
226         /* Abort currently executing GPIF waveform (if any). */
227         GPIFABORT = 0xff;
228
229         /* Setup the GPIF registers. */
230         gpif_setup_registers();
231
232         /* Write the four GPIF waveforms into the WAVEDATA register. */
233         gpif_write_waveforms();
234
235         /* Initialize GPIF address pins, output initial values. */
236         gpif_init_addr_pins();
237
238         /* Initialize flowstate registers (not used by us). */
239         gpif_init_flowstates();
240 }
241
242 static void setup_endpoints(void)
243 {
244         /* Setup EP1 (OUT). */
245         EP1OUTCFG = (1 << 7) |            /* EP is valid/activated */
246                     (0 << 6) |            /* Reserved */
247                     (1 << 5) | (0 << 4) | /* EP Type: bulk */
248                     (0 << 3) |            /* Reserved */
249                     (0 << 2) |            /* Reserved */
250                     (0 << 1) | (0 << 0);  /* Reserved */
251         SYNCDELAY();
252
253         /* Setup EP2 (IN). */
254         EP2CFG = (1 << 7) |               /* EP is valid/activated */
255                  (1 << 6) |               /* EP direction: IN */
256                  (1 << 5) | (0 << 4) |    /* EP Type: bulk */
257                  (0 << 3) |               /* EP buffer size: 512 */
258                  (0 << 2) |               /* Reserved. */
259                  (0 << 1) | (0 << 0);     /* EP buffering: quad buffering */
260         SYNCDELAY();
261
262         /* Disable all other EPs (EP4, EP6, and EP8). */
263         EP4CFG &= ~bmVALID;
264         SYNCDELAY();
265         EP6CFG &= ~bmVALID;
266         SYNCDELAY();
267         EP8CFG &= ~bmVALID;
268         SYNCDELAY();
269
270         /* Reset the FIFOs of EP1 and EP2. */
271         /* Note: RESETFIFO() gets the EP number WITHOUT bit 7 set/cleared. */
272         RESETFIFO(0x01)
273         RESETFIFO(0x02)
274
275         /* Set the GPIF flag for EP2 to 'full'. */
276         EP2GPIFFLGSEL = (1 << 1) | (0 << 1);
277         SYNCDELAY();
278 }
279
280 BOOL handle_vendorcommand(BYTE cmd)
281 {
282         (void)cmd;
283         return FALSE;
284 }
285
286 BOOL handle_get_interface(BYTE ifc, BYTE *alt_ifc)
287 {
288         /* We only support interface 0, alternate interface 0. */
289         if (ifc != 0)
290                 return FALSE;
291
292         *alt_ifc = 0;
293         return TRUE;
294 }
295
296 BOOL handle_set_interface(BYTE ifc, BYTE alt_ifc)
297 {
298         /* We only support interface 0, alternate interface 0. */
299         if (ifc != 0 || alt_ifc != 0)
300                 return FALSE;
301         
302         /* Perform procedure from TRM, section 2.3.7: */
303
304         /* (1) TODO. */
305
306         /* (2) Reset data toggles of the EPs in the interface. */
307         /* Note: RESETTOGGLE() gets the EP number WITH bit 7 set/cleared. */
308         RESETTOGGLE(0x01);
309         RESETTOGGLE(0x82);
310
311         /* (3) Restore EPs to their default conditions. */
312         /* Note: RESETFIFO() gets the EP number WITHOUT bit 7 set/cleared. */
313         RESETFIFO(0x01);
314         /* TODO */
315         RESETFIFO(0x02);
316         /* TODO */
317
318         /* (4) Clear the HSNAK bit. Not needed, fx2lib does this. */
319
320         return TRUE;
321 }
322
323 BYTE handle_get_configuration(void)
324 {
325         /* We only support configuration 1. */
326         return 1;
327 }
328
329 BOOL handle_set_configuration(BYTE cfg)
330 {
331         /* We only support configuration 1. */
332         return (cfg == 1) ? TRUE : FALSE;
333 }
334
335 void sudav_isr(void) interrupt SUDAV_ISR
336 {
337         got_sud = TRUE;
338         CLEAR_SUDAV();
339 }
340
341 void sof_isr(void) interrupt SOF_ISR using 1
342 {
343         CLEAR_SOF();
344 }
345
346 void usbreset_isr(void) interrupt USBRESET_ISR
347 {
348         handle_hispeed(FALSE);
349         CLEAR_USBRESET();
350 }
351
352 void hispeed_isr(void) interrupt HISPEED_ISR
353 {
354         handle_hispeed(TRUE);
355         CLEAR_HISPEED();
356 }
357
358 void main(void)
359 {
360         /* Set DYN_OUT and ENH_PKT bits, as recommended by the TRM. */
361         REVCTL = (1 << 1) | (1 << 0);
362
363         got_sud = FALSE;
364
365         /* Renumerate. */
366         RENUMERATE_UNCOND();
367
368         SETCPUFREQ(CLK_48M);
369
370         USE_USB_INTS();
371
372         /* TODO: Does the order of the following lines matter? */
373         ENABLE_SUDAV();
374         ENABLE_SOF();
375         ENABLE_HISPEED();
376         ENABLE_USBRESET();
377
378         /* Global (8051) interrupt enable. */
379         EA = 1;
380
381         /* Setup the endpoints. */
382         setup_endpoints();
383
384         /* Put the FX2 into GPIF master mode and setup the GPIF. */
385         gpif_init_la();
386
387         /* TODO */
388         /* Initiate a GPIF read. */
389         (void)EP2GPIFTRIG;
390 #if 0
391         /* TODO: This seems to hang? */
392         gpif_fifo_read(GPIF_EP2);
393 #endif
394
395         while (1) {
396                 if (got_sud) {
397                         handle_setupdata();
398                         got_sud = FALSE;
399                 }
400         }
401 }