From: Joel Holdsworth Date: Wed, 29 Feb 2012 20:45:02 +0000 (+0000) Subject: Moved gpif code out to separate source file X-Git-Tag: sigrok-firmware-fx2lafw-0.1.0~59 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=e41576ec531630354c5b48ed0caa83caa1a4c14e;p=sigrok-firmware-fx2lafw.git Moved gpif code out to separate source file --- diff --git a/fx2lafw.c b/fx2lafw.c index 2a64b84a..ab6d55fa 100644 --- a/fx2lafw.c +++ b/fx2lafw.c @@ -44,210 +44,19 @@ #include #include #include + #include +#include /* Protocol commands */ #define CMD_SET_SAMPLERATE 0xb0 #define CMD_START 0xb1 #define CMD_STOP 0xb2 #define CMD_GET_FW_VERSION 0xb3 -/* ... */ - -#define SYNCDELAY() SYNCDELAY4 /* ... */ volatile bit got_sud; -/* GPIF terminology: DP = decision point, NDP = non-decision-point */ - -/* - * GPIF waveforms. - * - * See section "10.3.4 State Instructions" in the TRM for details. - */ -static const BYTE wavedata[128] = { - /* Waveform 0: */ - - /* - * This is the basic algorithm implemented in our GPIF state machine: - * - * State 0: NDP: Sample the FIFO data bus. - * State 1: DP: If EP2 is full, go to state 7 (the IDLE state), i.e., - * end the current waveform. Otherwise, go to state 0 again, - * i.e., sample data until EP2 is full. - * State 2: Unused. - * State 3: Unused. - * State 4: Unused. - * State 5: Unused. - * State 6: Unused. - */ - - /* S0-S6: LENGTH/BRANCH */ - /* - * For NDPs (LENGTH): Number of IFCLK cycles to stay in this state. - * For DPs (BRANCH): [7] ReExec, [5:3]: BRANCHON1, [2:0]: BRANCHON0. - * - * 0x01: Stay one IFCLK cycle in this state. - * 0x38: No Re-execution, BRANCHON1 = state 7, BRANCHON0 = state 0. - */ - // 0x01, 0x38, 0x01, 0x01, 0x01, 0x01, 0x01, - // FIXME: For now just loop over the "sample data" state forever. - 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - /* TRM says "reserved", but GPIF designer always puts a 0x07 here. */ - 0x07, - - /* S0-S6: OPCODE */ - /* - * 0x02: NDP, sample the FIFO data bus. - * 0x01: DP, don't sample the FIFO data bus. - */ - 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - /* Reserved */ - 0x00, - - /* S0-S6: OUTPUT */ - /* Unused, we don't output anything, we only sample the pins. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* Reserved */ - 0x00, - - /* S0-S6: LOGIC FUNCTION (not used for NDPs) */ - /* - * 0x36: LFUNC = "A AND B", A = FIFO flag, B = FIFO flag. - * The FIFO flag (FF == full flag, in our case) is configured via - * EP2GPIFFLGSEL. - * - * So: If the EP2 FIFO is full and the EP2 FIFO is full, go to - * the state specified by BRANCHON1 (state 7), otherwise BRANCHON0 - * (state 0). See the LENGTH/BRANCH value above for details. - */ - 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, - /* TRM says "reserved", but GPIF designer always puts a 0x3f here. */ - 0x3f, - - /* TODO: Must unused waveforms be "valid"? */ - - /* Waveform 1 (unused): */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* Waveform 2 (unused): */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* Waveform 3 (unused): */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -static void gpif_setup_registers(void) -{ - /* TODO. Value probably irrelevant, as we don't use RDY* signals? */ - GPIFREADYCFG = 0; - - /* - * Set TRICTL = 0, thus CTL0-CTL5 are CMOS outputs. - * TODO: Probably irrelevant, as we don't use CTL0-CTL5? - */ - GPIFCTLCFG = 0; - - /* When GPIF is idle, tri-state the data bus. */ - /* Bit 7: DONE, bit 0: IDLEDRV. TODO: Set/clear DONE bit? */ - GPIFIDLECS = (1 << 0); - - /* When GPIF is idle, set CTL0-CTL5 to 0. */ - GPIFIDLECTL = 0; - - /* - * Map index 0 in wavedata[] to FIFORD. The rest is assigned too, - * but not used by us. - * - * GPIFWFSELECT: [7:6] = SINGLEWR index, [5:4] = SINGLERD index, - * [3:2] = FIFOWR index, [1:0] = FIFORD index - */ - GPIFWFSELECT = (0x3 << 6) | (0x2 << 4) | (0x1 << 2) | (0x0 << 0); - - /* Contains RDY* pin values. Read-only according to TRM. */ - GPIFREADYSTAT = 0; -} - -static void gpif_write_waveforms(void) -{ - int i; - - /* - * Write the four waveforms into the respective WAVEDATA register - * locations (0xe400 - 0xe47f) using the FX2's autopointer feature. - */ - AUTOPTRSETUP = 0x07; /* Increment autopointers 1 & 2. */ - AUTOPTRH1 = MSB((WORD)wavedata); /* Source is the 'wavedata' array. */ - AUTOPTRL1 = LSB((WORD)wavedata); - AUTOPTRH2 = 0xe4; /* Dest is WAVEDATA (0xe400). */ - AUTOPTRL2 = 0x00; - for (i = 0; i < 128; i++) - EXTAUTODAT2 = EXTAUTODAT1; -} - -static void gpif_init_addr_pins(void) -{ - /* - * Configure the 9 GPIF address pins (GPIFADR[8:0], which consist of - * PORTC[7:0] and PORTE[7]), and output an initial address (zero). - * TODO: Probably irrelevant, the 56pin FX2 has no ports C and E. - */ - PORTCCFG = 0xff; /* Set PORTC[7:0] as alt. func. (GPIFADR[7:0]). */ - OEC = 0xff; /* Configure PORTC[7:0] as outputs. */ - PORTECFG |= 0x80; /* Set PORTE[7] as alt. func. (GPIFADR[8]). */ - OEE |= 0x80; /* Configure PORTE[7] as output. */ - SYNCDELAY(); - GPIFADRL = 0x00; /* Clear GPIFADR[7:0]. */ - SYNCDELAY(); - GPIFADRH = 0x00; /* Clear GPIFADR[8]. */ -} - -static void gpif_init_flowstates(void) -{ - /* Clear all flowstate registers, we don't use this functionality. */ - FLOWSTATE = 0; - FLOWLOGIC = 0; - FLOWEQ0CTL = 0; - FLOWEQ1CTL = 0; - FLOWHOLDOFF = 0; - FLOWSTB = 0; - FLOWSTBEDGE = 0; - FLOWSTBHPERIOD = 0; -} - -static void gpif_init_la(void) -{ - /* - * Setup the FX2 in GPIF master mode, using the internal clock - * (non-inverted) at 48MHz, and using async sampling. - */ - IFCONFIG = 0xee; - - /* Abort currently executing GPIF waveform (if any). */ - GPIFABORT = 0xff; - - /* Setup the GPIF registers. */ - gpif_setup_registers(); - - /* Write the four GPIF waveforms into the WAVEDATA register. */ - gpif_write_waveforms(); - - /* Initialize GPIF address pins, output initial values. */ - gpif_init_addr_pins(); - - /* Initialize flowstate registers (not used by us). */ - gpif_init_flowstates(); -} - static void setup_endpoints(void) { /* Setup EP2 (IN). */ @@ -314,8 +123,8 @@ BOOL handle_vendorcommand(BYTE cmd) /* TODO */ break; case CMD_START: - /* TODO */ - break; + gpif_acquisition_start(); + return TRUE; case CMD_STOP: GPIFABORT = 0xff; /* TODO */ @@ -435,9 +244,6 @@ void fx2lafw_init(void) /* Put the FX2 into GPIF master mode and setup the GPIF. */ gpif_init_la(); - - /* Perform the initial GPIF read. */ - gpif_fifo_read(GPIF_EP2); } void fx2lafw_run(void) diff --git a/gpif-acquisition.c b/gpif-acquisition.c new file mode 100644 index 00000000..9eedfbfd --- /dev/null +++ b/gpif-acquisition.c @@ -0,0 +1,224 @@ +/* + * This file is part of the fx2lafw project. + * + * Copyright (C) 2011-2012 Uwe Hermann + * Copyright (C) 2012 Joel Holdsworth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +/* GPIF terminology: DP = decision point, NDP = non-decision-point */ + +/* + * GPIF waveforms. + * + * See section "10.3.4 State Instructions" in the TRM for details. + */ +static const BYTE wavedata[128] = { + /* Waveform 0: */ + + /* + * This is the basic algorithm implemented in our GPIF state machine: + * + * State 0: NDP: Sample the FIFO data bus. + * State 1: DP: If EP2 is full, go to state 7 (the IDLE state), i.e., + * end the current waveform. Otherwise, go to state 0 again, + * i.e., sample data until EP2 is full. + * State 2: Unused. + * State 3: Unused. + * State 4: Unused. + * State 5: Unused. + * State 6: Unused. + */ + + /* S0-S6: LENGTH/BRANCH */ + /* + * For NDPs (LENGTH): Number of IFCLK cycles to stay in this state. + * For DPs (BRANCH): [7] ReExec, [5:3]: BRANCHON1, [2:0]: BRANCHON0. + * + * 0x01: Stay one IFCLK cycle in this state. + * 0x38: No Re-execution, BRANCHON1 = state 7, BRANCHON0 = state 0. + */ + // 0x01, 0x38, 0x01, 0x01, 0x01, 0x01, 0x01, + // FIXME: For now just loop over the "sample data" state forever. + 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + /* TRM says "reserved", but GPIF designer always puts a 0x07 here. */ + 0x07, + + /* S0-S6: OPCODE */ + /* + * 0x02: NDP, sample the FIFO data bus. + * 0x01: DP, don't sample the FIFO data bus. + */ + 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Reserved */ + 0x00, + + /* S0-S6: OUTPUT */ + /* Unused, we don't output anything, we only sample the pins. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Reserved */ + 0x00, + + /* S0-S6: LOGIC FUNCTION (not used for NDPs) */ + /* + * 0x36: LFUNC = "A AND B", A = FIFO flag, B = FIFO flag. + * The FIFO flag (FF == full flag, in our case) is configured via + * EP2GPIFFLGSEL. + * + * So: If the EP2 FIFO is full and the EP2 FIFO is full, go to + * the state specified by BRANCHON1 (state 7), otherwise BRANCHON0 + * (state 0). See the LENGTH/BRANCH value above for details. + */ + 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, + /* TRM says "reserved", but GPIF designer always puts a 0x3f here. */ + 0x3f, + + /* TODO: Must unused waveforms be "valid"? */ + + /* Waveform 1 (unused): */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* Waveform 2 (unused): */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* Waveform 3 (unused): */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static void gpif_setup_registers(void) +{ + /* TODO. Value probably irrelevant, as we don't use RDY* signals? */ + GPIFREADYCFG = 0; + + /* + * Set TRICTL = 0, thus CTL0-CTL5 are CMOS outputs. + * TODO: Probably irrelevant, as we don't use CTL0-CTL5? + */ + GPIFCTLCFG = 0; + + /* When GPIF is idle, tri-state the data bus. */ + /* Bit 7: DONE, bit 0: IDLEDRV. TODO: Set/clear DONE bit? */ + GPIFIDLECS = (1 << 0); + + /* When GPIF is idle, set CTL0-CTL5 to 0. */ + GPIFIDLECTL = 0; + + /* + * Map index 0 in wavedata[] to FIFORD. The rest is assigned too, + * but not used by us. + * + * GPIFWFSELECT: [7:6] = SINGLEWR index, [5:4] = SINGLERD index, + * [3:2] = FIFOWR index, [1:0] = FIFORD index + */ + GPIFWFSELECT = (0x3 << 6) | (0x2 << 4) | (0x1 << 2) | (0x0 << 0); + + /* Contains RDY* pin values. Read-only according to TRM. */ + GPIFREADYSTAT = 0; +} + +static void gpif_write_waveforms(void) +{ + int i; + + /* + * Write the four waveforms into the respective WAVEDATA register + * locations (0xe400 - 0xe47f) using the FX2's autopointer feature. + */ + AUTOPTRSETUP = 0x07; /* Increment autopointers 1 & 2. */ + AUTOPTRH1 = MSB((WORD)wavedata); /* Source is the 'wavedata' array. */ + AUTOPTRL1 = LSB((WORD)wavedata); + AUTOPTRH2 = 0xe4; /* Dest is WAVEDATA (0xe400). */ + AUTOPTRL2 = 0x00; + for (i = 0; i < 128; i++) + EXTAUTODAT2 = EXTAUTODAT1; +} + +static void gpif_init_addr_pins(void) +{ + /* + * Configure the 9 GPIF address pins (GPIFADR[8:0], which consist of + * PORTC[7:0] and PORTE[7]), and output an initial address (zero). + * TODO: Probably irrelevant, the 56pin FX2 has no ports C and E. + */ + PORTCCFG = 0xff; /* Set PORTC[7:0] as alt. func. (GPIFADR[7:0]). */ + OEC = 0xff; /* Configure PORTC[7:0] as outputs. */ + PORTECFG |= 0x80; /* Set PORTE[7] as alt. func. (GPIFADR[8]). */ + OEE |= 0x80; /* Configure PORTE[7] as output. */ + SYNCDELAY(); + GPIFADRL = 0x00; /* Clear GPIFADR[7:0]. */ + SYNCDELAY(); + GPIFADRH = 0x00; /* Clear GPIFADR[8]. */ +} + +static void gpif_init_flowstates(void) +{ + /* Clear all flowstate registers, we don't use this functionality. */ + FLOWSTATE = 0; + FLOWLOGIC = 0; + FLOWEQ0CTL = 0; + FLOWEQ1CTL = 0; + FLOWHOLDOFF = 0; + FLOWSTB = 0; + FLOWSTBEDGE = 0; + FLOWSTBHPERIOD = 0; +} + +void gpif_init_la(void) +{ + /* + * Setup the FX2 in GPIF master mode, using the internal clock + * (non-inverted) at 48MHz, and using async sampling. + */ + IFCONFIG = 0xee; + + /* Abort currently executing GPIF waveform (if any). */ + GPIFABORT = 0xff; + + /* Setup the GPIF registers. */ + gpif_setup_registers(); + + /* Write the four GPIF waveforms into the WAVEDATA register. */ + gpif_write_waveforms(); + + /* Initialize GPIF address pins, output initial values. */ + gpif_init_addr_pins(); + + /* Initialize flowstate registers (not used by us). */ + gpif_init_flowstates(); +} + +void gpif_acquisition_start(void) +{ + /* Perform the initial GPIF read. */ + gpif_fifo_read(GPIF_EP2); +} diff --git a/hw/cwav-usbeeax/Makefile b/hw/cwav-usbeeax/Makefile index bed8e858..1d773a67 100644 --- a/hw/cwav-usbeeax/Makefile +++ b/hw/cwav-usbeeax/Makefile @@ -18,7 +18,11 @@ ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## -SOURCES = main.c ../../fx2lafw.c ../../debug.c +SOURCES = \ + main.c \ + ../../fx2lafw.c \ + ../../gpif-acquisition.c \ + ../../debug.c A51_SOURCES = dscr.a51 BASENAME = fx2lafw-cwav-usbeeax diff --git a/hw/saleae-logic/Makefile b/hw/saleae-logic/Makefile index 644cf148..76cf65a1 100644 --- a/hw/saleae-logic/Makefile +++ b/hw/saleae-logic/Makefile @@ -18,7 +18,11 @@ ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ## -SOURCES = main.c ../../fx2lafw.c ../../debug.c +SOURCES = \ + main.c \ + ../../fx2lafw.c \ + ../../gpif-capture.c \ + ../../debug.c A51_SOURCES = dscr.a51 BASENAME = fx2lafw-saleae-logic diff --git a/include/fx2lafw.h b/include/fx2lafw.h index 5819b6c6..71f181f4 100644 --- a/include/fx2lafw.h +++ b/include/fx2lafw.h @@ -20,6 +20,8 @@ #include +#define SYNCDELAY() SYNCDELAY4 + /** * Performs setup common to all fx2lafw devices. */ diff --git a/include/gpif-acquisition.h b/include/gpif-acquisition.h new file mode 100644 index 00000000..6ccdc616 --- /dev/null +++ b/include/gpif-acquisition.h @@ -0,0 +1,23 @@ +/* + * This file is part of the fx2lafw project. + * + * Copyright (C) 2012 Joel Holdsworth + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +void gpif_init_la(void); + +void gpif_acquisition_start(void);