#include <fx2regs.h>
#include <fx2macros.h>
#include <delay.h>
-#include <autovector.h>
#include <setupdat.h>
#include <eputils.h>
#include <gpif.h>
-/* Protocol commands */
-#define CMD_SET_SAMPLERATE 0xb0
-#define CMD_START 0xb1
-#define CMD_STOP 0xb2
-#define CMD_GET_FW_VERSION 0xb3
-/* ... */
-
-#define SYNCDELAY() SYNCDELAY4
+#include <command.h>
+#include <fx2lafw.h>
+#include <gpif-acquisition.h>
/* ... */
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();
-}
+BYTE vendor_command;
static void setup_endpoints(void)
{
#endif
SYNCDELAY();
- /* Disable all other EPs (EP4 and EP8). */
+ /* Disable all other EPs (EP1, EP4, and EP8). */
EP1INCFG &= ~bmVALID;
SYNCDELAY();
EP1OUTCFG &= ~bmVALID;
/* EP2: Reset the FIFOs. */
/* Note: RESETFIFO() gets the EP number WITHOUT bit 7 set/cleared. */
RESETFIFO(0x02)
+
#ifdef DEBUG
/* Reset the FIFOs of EP6 when in debug mode. */
RESETFIFO(0x06)
#endif
/* EP2: Enable AUTOIN mode. Set FIFO width to 8bits. */
- EP2FIFOCFG = bmAUTOIN | ~bmWORDWIDE;
+ EP2FIFOCFG = bmAUTOIN;
SYNCDELAY();
/* EP2: Auto-commit 512 (0x200) byte packets (due to AUTOIN = 1). */
BOOL handle_vendorcommand(BYTE cmd)
{
/* Protocol implementation */
-
switch (cmd) {
- case CMD_SET_SAMPLERATE:
- /* TODO */
- break;
case CMD_START:
- /* TODO */
- break;
- case CMD_STOP:
- GPIFABORT = 0xff;
- /* TODO */
- return TRUE;
- break;
+ /* There is data to receive - arm EP0 */
+ EP0BCL = 0;
case CMD_GET_FW_VERSION:
- /* TODO */
- break;
+ vendor_command = cmd;
+ return TRUE;
default:
/* Unimplemented command. */
break;
/* (2) Reset data toggles of the EPs in the interface. */
/* Note: RESETTOGGLE() gets the EP number WITH bit 7 set/cleared. */
RESETTOGGLE(0x82);
- RESETTOGGLE(0x76);
+#ifdef DEBUG
+ RESETTOGGLE(0x86);
+#endif
/* (3) Restore EPs to their default conditions. */
/* Note: RESETFIFO() gets the EP number WITHOUT bit 7 set/cleared. */
RESETFIFO(0x02);
/* TODO */
-
+#ifdef DEBUG
RESETFIFO(0x06);
+#endif
/* (4) Clear the HSNAK bit. Not needed, fx2lib does this. */
CLEAR_HISPEED();
}
-void main(void)
+void fx2lafw_init(void)
{
/* Set DYN_OUT and ENH_PKT bits, as recommended by the TRM. */
REVCTL = bmNOAUTOARM | bmSKIPCOMMIT;
got_sud = FALSE;
+ vendor_command = 0;
/* Renumerate. */
RENUMERATE_UNCOND();
/* Put the FX2 into GPIF master mode and setup the GPIF. */
gpif_init_la();
+}
+
+void fx2lafw_poll(void)
+{
+ if (got_sud) {
+ handle_setupdata();
+ got_sud = FALSE;
+ }
+
+ if (vendor_command) {
+ switch (vendor_command) {
+ case CMD_GET_FW_VERSION:
+ /* TODO */
+
+ /* Acknowledge the vendor command. */
+ vendor_command = 0;
+ break;
- /* Perform the initial GPIF read. */
- gpif_fifo_read(GPIF_EP2);
+ case CMD_START:
+ if((EP0CS & bmEPBUSY) != 0)
+ break;
- while (1) {
- if (got_sud) {
- handle_setupdata();
- got_sud = FALSE;
+ if(EP0BCL == 2) {
+ gpif_acquisition_start(
+ (const struct cmd_start_acquisition*)EP0BUF);
+ }
+
+ /* Acknowledge the vendor command. */
+ vendor_command = 0;
+ break;
+
+ default:
+ /* Unimplemented command. */
+ vendor_command = 0;
+ break;
}
}
+
+ gpif_poll();
}