2 * This file is part of the fx2lafw project.
4 * Copyright (C) 2011-2012 Uwe Hermann <uwe@hermann-uwe.de>
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.
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.
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
22 * fx2lafw is an open-source firmware for Cypress FX2 based logic analyzers.
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.
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.
38 * - See http://sigrok.org/wiki/Fx2lafw
42 #include <fx2macros.h>
44 #include <autovector.h>
49 #define SYNCDELAY() SYNCDELAY4
54 /* GPIF terminology: DP = decision point, NDP = non-decision-point */
59 * See section "10.3.4 State Instructions" in the TRM for details.
61 static const BYTE wavedata[128] = {
65 * This is the basic algorithm implemented in our GPIF state machine:
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.
78 /* S0-S6: LENGTH/BRANCH */
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.
83 * 0x01: Stay one IFCLK cycle in this state.
84 * 0x38: No Re-execution, BRANCHON1 = state 7, BRANCHON0 = state 0.
86 // 0x01, 0x38, 0x01, 0x01, 0x01, 0x01, 0x01,
87 // FIXME: For now just loop over the "sample data" state forever.
88 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
89 /* TRM says "reserved", but GPIF designer always puts a 0x07 here. */
94 * 0x02: NDP, sample the FIFO data bus.
95 * 0x01: DP, don't sample the FIFO data bus.
97 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
102 /* Unused, we don't output anything, we only sample the pins. */
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 /* S0-S6: LOGIC FUNCTION (not used for NDPs) */
109 * 0x36: LFUNC = "A AND B", A = FIFO flag, B = FIFO flag.
110 * The FIFO flag (FF == full flag, in our case) is configured via
113 * So: If the EP2 FIFO is full and the EP2 FIFO is full, go to
114 * the state specified by BRANCHON1 (state 7), otherwise BRANCHON0
115 * (state 0). See the LENGTH/BRANCH value above for details.
117 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
118 /* TRM says "reserved", but GPIF designer always puts a 0x3f here. */
121 /* TODO: Must unused waveforms be "valid"? */
123 /* Waveform 1 (unused): */
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 /* Waveform 2 (unused): */
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135 /* Waveform 3 (unused): */
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 static void gpif_setup_registers(void)
144 /* TODO. Value probably irrelevant, as we don't use RDY* signals? */
148 * Set TRICTL = 0, thus CTL0-CTL5 are CMOS outputs.
149 * TODO: Probably irrelevant, as we don't use CTL0-CTL5?
153 /* When GPIF is idle, tri-state the data bus. */
154 /* Bit 7: DONE, bit 0: IDLEDRV. TODO: Set/clear DONE bit? */
155 GPIFIDLECS = (1 << 0);
157 /* When GPIF is idle, set CTL0-CTL5 to 0. */
161 * Map index 0 in wavedata[] to FIFORD. The rest is assigned too,
162 * but not used by us.
164 * GPIFWFSELECT: [7:6] = SINGLEWR index, [5:4] = SINGLERD index,
165 * [3:2] = FIFOWR index, [1:0] = FIFORD index
167 GPIFWFSELECT = (0x3 << 6) | (0x2 << 4) | (0x1 << 2) | (0x0 << 0);
169 /* Contains RDY* pin values. Read-only according to TRM. */
173 static void gpif_write_waveforms(void)
178 * Write the four waveforms into the respective WAVEDATA register
179 * locations (0xe400 - 0xe47f) using the FX2's autopointer feature.
181 AUTOPTRSETUP = 0x07; /* Increment autopointers 1 & 2. */
182 AUTOPTRH1 = MSB((WORD)wavedata); /* Source is the 'wavedata' array. */
183 AUTOPTRL1 = LSB((WORD)wavedata);
184 AUTOPTRH2 = 0xe4; /* Dest is WAVEDATA (0xe400). */
186 for (i = 0; i < 128; i++)
187 EXTAUTODAT2 = EXTAUTODAT1;
190 static void gpif_init_addr_pins(void)
193 * Configure the 9 GPIF address pins (GPIFADR[8:0], which consist of
194 * PORTC[7:0] and PORTE[7]), and output an initial address (zero).
195 * TODO: Probably irrelevant, the 56pin FX2 has no ports C and E.
197 PORTCCFG = 0xff; /* Set PORTC[7:0] as alt. func. (GPIFADR[7:0]). */
198 OEC = 0xff; /* Configure PORTC[7:0] as outputs. */
199 PORTECFG |= 0x80; /* Set PORTE[7] as alt. func. (GPIFADR[8]). */
200 OEE |= 0x80; /* Configure PORTE[7] as output. */
202 GPIFADRL = 0x00; /* Clear GPIFADR[7:0]. */
204 GPIFADRH = 0x00; /* Clear GPIFADR[8]. */
207 static void gpif_init_flowstates(void)
209 /* Clear all flowstate registers, we don't use this functionality. */
220 static void gpif_init_la(void)
223 * Setup the FX2 in GPIF master mode, using the internal clock
224 * (non-inverted) at 48MHz, and using async sampling.
228 /* Abort currently executing GPIF waveform (if any). */
231 /* Setup the GPIF registers. */
232 gpif_setup_registers();
234 /* Write the four GPIF waveforms into the WAVEDATA register. */
235 gpif_write_waveforms();
237 /* Initialize GPIF address pins, output initial values. */
238 gpif_init_addr_pins();
240 /* Initialize flowstate registers (not used by us). */
241 gpif_init_flowstates();
244 static void setup_endpoints(void)
246 /* Setup EP1 (OUT). */
247 EP1OUTCFG = (1 << 7) | /* EP is valid/activated */
248 (0 << 6) | /* Reserved */
249 (1 << 5) | (0 << 4) | /* EP Type: bulk */
250 (0 << 3) | /* Reserved */
251 (0 << 2) | /* Reserved */
252 (0 << 1) | (0 << 0); /* Reserved */
255 /* Setup EP2 (IN). */
256 EP2CFG = (1 << 7) | /* EP is valid/activated */
257 (1 << 6) | /* EP direction: IN */
258 (1 << 5) | (0 << 4) | /* EP Type: bulk */
259 (0 << 3) | /* EP buffer size: 512 */
260 (0 << 2) | /* Reserved. */
261 (0 << 1) | (0 << 0); /* EP buffering: quad buffering */
264 /* Disable all other EPs (EP4, EP6, and EP8). */
272 /* Reset the FIFOs of EP1 and EP2. */
273 /* Note: RESETFIFO() gets the EP number WITHOUT bit 7 set/cleared. */
277 /* EP2: Enable AUTOIN mode. Set FIFO width to 8bits. */
278 EP2FIFOCFG = bmAUTOIN | ~bmWORDWIDE;
281 /* EP2: Auto-commit 512 (0x200) byte packets (due to AUTOIN = 1). */
282 EP2AUTOINLENH = 0x02;
284 EP2AUTOINLENL = 0x00;
287 /* Set the GPIF flag for EP2 to 'full'. */
288 EP2GPIFFLGSEL = (1 << 1) | (0 << 1);
292 BOOL handle_vendorcommand(BYTE cmd)
298 BOOL handle_get_interface(BYTE ifc, BYTE *alt_ifc)
300 /* We only support interface 0, alternate interface 0. */
308 BOOL handle_set_interface(BYTE ifc, BYTE alt_ifc)
310 /* We only support interface 0, alternate interface 0. */
311 if (ifc != 0 || alt_ifc != 0)
314 /* Perform procedure from TRM, section 2.3.7: */
318 /* (2) Reset data toggles of the EPs in the interface. */
319 /* Note: RESETTOGGLE() gets the EP number WITH bit 7 set/cleared. */
323 /* (3) Restore EPs to their default conditions. */
324 /* Note: RESETFIFO() gets the EP number WITHOUT bit 7 set/cleared. */
330 /* (4) Clear the HSNAK bit. Not needed, fx2lib does this. */
335 BYTE handle_get_configuration(void)
337 /* We only support configuration 1. */
341 BOOL handle_set_configuration(BYTE cfg)
343 /* We only support configuration 1. */
344 return (cfg == 1) ? TRUE : FALSE;
347 void sudav_isr(void) interrupt SUDAV_ISR
353 void sof_isr(void) interrupt SOF_ISR using 1
358 void usbreset_isr(void) interrupt USBRESET_ISR
360 handle_hispeed(FALSE);
364 void hispeed_isr(void) interrupt HISPEED_ISR
366 handle_hispeed(TRUE);
372 /* Set DYN_OUT and ENH_PKT bits, as recommended by the TRM. */
373 REVCTL = bmNOAUTOARM | bmSKIPCOMMIT;
384 /* TODO: Does the order of the following lines matter? */
390 /* Global (8051) interrupt enable. */
393 /* Setup the endpoints. */
396 /* Put the FX2 into GPIF master mode and setup the GPIF. */
399 /* Perform the initial GPIF read. */
400 gpif_fifo_read(GPIF_EP2);