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 */
57 static const BYTE wavedata[128] = {
60 /* TODO: This is just a dummy entry, fill with useful data. */
62 /* S0-S6: LENGTH/BRANCH */
63 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
64 /* TRM says "reserved", but GPIF designer always puts a 0x07 here. */
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 /* S0-S6: LOGIC FUNCTION (not used for NDPs) */
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 /* TRM says "reserved", but GPIF designer always puts a 0x3f here. */
79 /* TODO: Must unused waveforms be "valid"? */
81 /* Waveform 1 (unused): */
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 /* Waveform 2 (unused): */
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 /* Waveform 3 (unused): */
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 static void gpif_setup_registers(void)
102 /* TODO. Value probably irrelevant, as we don't use RDY* signals? */
106 * Set TRICTL = 0, thus CTL0-CTL5 are CMOS outputs.
107 * TODO: Probably irrelevant, as we don't use CTL0-CTL5?
111 /* When GPIF is idle, tri-state the data bus. */
112 /* Bit 7: DONE, bit 0: IDLEDRV. TODO: Set/clear DONE bit? */
113 GPIFIDLECS = (1 << 0);
115 /* When GPIF is idle, set CTL0-CTL5 to 0. */
119 * Map index 0 in wavedata[] to FIFORD. The rest is assigned too,
120 * but not used by us.
122 * GPIFWFSELECT: [7:6] = SINGLEWR index, [5:4] = SINGLERD index,
123 * [3:2] = FIFOWR index, [1:0] = FIFORD index
125 GPIFWFSELECT = (0x3 << 6) | (0x2 << 4) | (0x1 << 2) | (0x0 << 0);
127 /* Contains RDY* pin values. Read-only according to TRM. */
131 static void gpif_write_waveforms(void)
136 * Write the four waveforms into the respective WAVEDATA register
137 * locations (0xe400 - 0xe47f) using the FX2's autopointer feature.
139 AUTOPTRSETUP = 0x07; /* Increment autopointers 1 & 2. */
140 AUTOPTRH1 = MSB((WORD)wavedata); /* Source is the 'wavedata' array. */
141 AUTOPTRL1 = LSB((WORD)wavedata);
142 AUTOPTRH2 = 0xe4; /* Dest is WAVEDATA (0xe400). */
144 for (i = 0; i < 128; i++)
145 EXTAUTODAT2 = EXTAUTODAT1;
148 static void gpif_init_addr_pins(void)
151 * Configure the 9 GPIF address pins (GPIFADR[8:0], which consist of
152 * PORTC[7:0] and PORTE[7]), and output an initial address (zero).
153 * TODO: Probably irrelevant, the 56pin FX2 has no ports C and E.
155 PORTCCFG = 0xff; /* Set PORTC[7:0] as alt. func. (GPIFADR[7:0]). */
156 OEC = 0xff; /* Configure PORTC[7:0] as outputs. */
157 PORTECFG |= 0x80; /* Set PORTE[7] as alt. func. (GPIFADR[8]). */
158 OEE |= 0x80; /* Configure PORTE[7] as output. */
160 GPIFADRL = 0x00; /* Clear GPIFADR[7:0]. */
162 GPIFADRH = 0x00; /* Clear GPIFADR[8]. */
165 static void gpif_init_flowstates(void)
167 /* Clear all flowstate registers, we don't use this functionality. */
178 static void gpif_init_la(void)
181 * Setup the FX2 in GPIF master mode, using the internal clock
182 * (non-inverted) at 48MHz, and using async sampling.
186 /* Abort currently executing GPIF waveform (if any). */
189 /* Setup the GPIF registers. */
190 gpif_setup_registers();
192 /* Write the four GPIF waveforms into the WAVEDATA register. */
193 gpif_write_waveforms();
195 /* Initialize GPIF address pins, output initial values. */
196 gpif_init_addr_pins();
198 /* Initialize flowstate registers (not used by us). */
199 gpif_init_flowstates();
202 static void setup_endpoints(void)
204 /* Setup EP1 (OUT). */
205 EP1OUTCFG = (1 << 7) | /* EP is valid/activated */
206 (0 << 6) | /* Reserved */
207 (1 << 5) | (0 << 4) | /* EP Type: bulk */
208 (0 << 3) | /* Reserved */
209 (0 << 2) | /* Reserved */
210 (0 << 1) | (0 << 0); /* Reserved */
213 /* Setup EP2 (IN). */
214 EP2CFG = (1 << 7) | /* EP is valid/activated */
215 (1 << 6) | /* EP direction: IN */
216 (1 << 5) | (0 << 4) | /* EP Type: bulk */
217 (0 << 3) | /* EP buffer size: 512 */
218 (0 << 2) | /* Reserved. */
219 (0 << 1) | (0 << 0); /* EP buffering: quad buffering */
222 /* Disable all other EPs (EP4, EP6, and EP8). */
230 /* Reset the FIFOs of EP1 and EP2. */
231 /* Note: RESETFIFO() gets the EP number WITHOUT bit 7 set/cleared. */
235 /* Set the GPIF flag for EP2 to 'empty'. */
236 EP2GPIFFLGSEL = (0 << 1) | (1 << 1);
240 BOOL handle_vendorcommand(BYTE cmd)
246 BOOL handle_get_interface(BYTE ifc, BYTE *alt_ifc)
248 /* We only support interface 0, alternate interface 0. */
256 BOOL handle_set_interface(BYTE ifc, BYTE alt_ifc)
258 /* We only support interface 0, alternate interface 0. */
259 if (ifc != 0 || alt_ifc != 0)
262 /* Perform procedure from TRM, section 2.3.7: */
266 /* (2) Reset data toggles of the EPs in the interface. */
267 /* Note: RESETTOGGLE() gets the EP number WITH bit 7 set/cleared. */
271 /* (3) Restore EPs to their default conditions. */
272 /* Note: RESETFIFO() gets the EP number WITHOUT bit 7 set/cleared. */
278 /* (4) Clear the HSNAK bit. Not needed, fx2lib does this. */
283 BYTE handle_get_configuration(void)
285 /* We only support configuration 1. */
289 BOOL handle_set_configuration(BYTE cfg)
291 /* We only support configuration 1. */
292 return (cfg == 1) ? TRUE : FALSE;
295 void sudav_isr(void) interrupt SUDAV_ISR
301 void sof_isr(void) interrupt SOF_ISR using 1
306 void usbreset_isr(void) interrupt USBRESET_ISR
308 handle_hispeed(FALSE);
312 void hispeed_isr(void) interrupt HISPEED_ISR
314 handle_hispeed(TRUE);
320 /* Set DYN_OUT and ENH_PKT bits, as recommended by the TRM. */
321 REVCTL = (1 << 1) | (1 << 0);
332 /* TODO: Does the order of the following lines matter? */
338 /* Global (8051) interrupt enable. */
341 /* Setup the endpoints. */
344 /* Put the FX2 into GPIF master mode and setup the GPIF. */
348 /* Initiate a GPIF read. */
351 /* TODO: This seems to hang? */
352 gpif_fifo_read(GPIF_EP2);