]> sigrok.org Git - sigrok-firmware-fx2lafw.git/blobdiff - fx2lafw.c
Update README.
[sigrok-firmware-fx2lafw.git] / fx2lafw.c
index 0488cb7e83d6bf3d941b969d62af6880dbba7006..2a64b84ae8db8de497fe95de85279ed4c0926456 100644 (file)
--- a/fx2lafw.c
+++ b/fx2lafw.c
 #include <fx2regs.h>
 #include <fx2macros.h>
 #include <delay.h>
-#include <autovector.h>
 #include <setupdat.h>
 #include <eputils.h>
 #include <gpif.h>
+#include <fx2lafw.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
 
@@ -53,26 +60,68 @@ volatile bit got_sud;
 
 /* GPIF terminology: DP = decision point, NDP = non-decision-point */
 
-/* GPIF waveforms */
+/*
+ * GPIF waveforms.
+ *
+ * See section "10.3.4 State Instructions" in the TRM for details.
+ */
 static const BYTE wavedata[128] = {
        /* Waveform 0: */
 
-       /* TODO: This is just a dummy entry, fill with useful data. */
+       /*
+        * 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 */
-       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       /*
+        * 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 */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       /*
+        * 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) */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       /*
+        * 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,
 
@@ -201,15 +250,6 @@ static void gpif_init_la(void)
 
 static void setup_endpoints(void)
 {
-       /* Setup EP1 (OUT). */
-       EP1OUTCFG = (1 << 7) |            /* EP is valid/activated */
-                   (0 << 6) |            /* Reserved */
-                   (1 << 5) | (0 << 4) | /* EP Type: bulk */
-                   (0 << 3) |            /* Reserved */
-                   (0 << 2) |            /* Reserved */
-                   (0 << 1) | (0 << 0);  /* Reserved */
-       SYNCDELAY();
-
        /* Setup EP2 (IN). */
        EP2CFG = (1 << 7) |               /* EP is valid/activated */
                 (1 << 6) |               /* EP direction: IN */
@@ -219,27 +259,76 @@ static void setup_endpoints(void)
                 (0 << 1) | (0 << 0);     /* EP buffering: quad buffering */
        SYNCDELAY();
 
-       /* Disable all other EPs (EP4, EP6, and EP8). */
-       EP4CFG &= ~bmVALID;
-       SYNCDELAY();
+       /* Setup EP6 (IN) in the debug build. */
+#ifdef DEBUG
+       EP6CFG = (1 << 7) |               /* EP is valid/activated */
+                (1 << 6) |               /* EP direction: IN */
+                (1 << 5) | (0 << 4) |    /* EP Type: bulk */
+                (0 << 3) |               /* EP buffer size: 512 */
+                (0 << 2) |               /* Reserved */
+                (1 << 1) | (0 << 0);     /* EP buffering: double buffering */
+#else
        EP6CFG &= ~bmVALID;
+#endif
+       SYNCDELAY();
+
+       /* Disable all other EPs (EP1, EP4, and EP8). */
+       EP1INCFG &= ~bmVALID;
+       SYNCDELAY();
+       EP1OUTCFG &= ~bmVALID;
+       SYNCDELAY();
+       EP4CFG &= ~bmVALID;
        SYNCDELAY();
        EP8CFG &= ~bmVALID;
        SYNCDELAY();
 
-       /* Reset the FIFOs of EP1 and EP2. */
+       /* EP2: Reset the FIFOs. */
        /* Note: RESETFIFO() gets the EP number WITHOUT bit 7 set/cleared. */
-       RESETFIFO(0x01)
        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;
+       SYNCDELAY();
 
-       /* Set the GPIF flag for EP2 to 'empty'. */
-       EP2GPIFFLGSEL = (0 << 1) | (1 << 1);
+       /* EP2: Auto-commit 512 (0x200) byte packets (due to AUTOIN = 1). */
+       EP2AUTOINLENH = 0x02;
+       SYNCDELAY();
+       EP2AUTOINLENL = 0x00;
+       SYNCDELAY();
+
+       /* EP2: Set the GPIF flag to 'full'. */
+       EP2GPIFFLGSEL = (1 << 1) | (0 << 1);
        SYNCDELAY();
 }
 
 BOOL handle_vendorcommand(BYTE cmd)
 {
-       (void)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;
+       case CMD_GET_FW_VERSION:
+               /* TODO */
+               break;
+       default:
+               /* Unimplemented command. */
+               break;
+       }
+
        return FALSE;
 }
 
@@ -265,15 +354,18 @@ BOOL handle_set_interface(BYTE ifc, BYTE alt_ifc)
 
        /* (2) Reset data toggles of the EPs in the interface. */
        /* Note: RESETTOGGLE() gets the EP number WITH bit 7 set/cleared. */
-       RESETTOGGLE(0x01);
        RESETTOGGLE(0x82);
+#ifdef DEBUG
+       RESETTOGGLE(0x86);
+#endif
 
        /* (3) Restore EPs to their default conditions. */
        /* Note: RESETFIFO() gets the EP number WITHOUT bit 7 set/cleared. */
-       RESETFIFO(0x01);
-       /* TODO */
        RESETFIFO(0x02);
        /* TODO */
+#ifdef DEBUG
+       RESETFIFO(0x06);
+#endif
 
        /* (4) Clear the HSNAK bit. Not needed, fx2lib does this. */
 
@@ -315,10 +407,10 @@ void hispeed_isr(void) interrupt HISPEED_ISR
        CLEAR_HISPEED();
 }
 
-void main(void)
+void fx2lafw_init(void)
 {
        /* Set DYN_OUT and ENH_PKT bits, as recommended by the TRM. */
-       REVCTL = (1 << 1) | (1 << 0);
+       REVCTL = bmNOAUTOARM | bmSKIPCOMMIT;
 
        got_sud = FALSE;
 
@@ -344,18 +436,14 @@ void main(void)
        /* Put the FX2 into GPIF master mode and setup the GPIF. */
        gpif_init_la();
 
-       /* TODO */
-       /* Initiate a GPIF read. */
-       (void)EP2GPIFTRIG;
-#if 0
-       /* TODO: This seems to hang? */
+       /* Perform the initial GPIF read. */
        gpif_fifo_read(GPIF_EP2);
-#endif
+}
 
-       while (1) {
-               if (got_sud) {
-                       handle_setupdata();
-                       got_sud = FALSE;
-               }
+void fx2lafw_run(void)
+{
+       if (got_sud) {
+               handle_setupdata();
+               got_sud = FALSE;
        }
 }