X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=fx2lafw.c;h=f69955161eb18b88aeda21a5775e7c4658e34a78;hb=8ee491edbe31d980abe261307ef893bce9a16760;hp=0488cb7e83d6bf3d941b969d62af6880dbba7006;hpb=d5f5ea7394647699061f7185c884328defff9b7d;p=sigrok-firmware-fx2lafw.git diff --git a/fx2lafw.c b/fx2lafw.c index 0488cb7e..f6995516 100644 --- a/fx2lafw.c +++ b/fx2lafw.c @@ -46,6 +46,13 @@ #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 /* ... */ @@ -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 (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 - /* Set the GPIF flag for EP2 to 'empty'. */ - EP2GPIFFLGSEL = (0 << 1) | (1 << 1); + /* EP2: Enable AUTOIN mode. Set FIFO width to 8bits. */ + EP2FIFOCFG = bmAUTOIN | ~bmWORDWIDE; + SYNCDELAY(); + + /* 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,16 +354,16 @@ 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); + RESETTOGGLE(0x76); /* (3) Restore EPs to their default conditions. */ /* Note: RESETFIFO() gets the EP number WITHOUT bit 7 set/cleared. */ - RESETFIFO(0x01); - /* TODO */ RESETFIFO(0x02); /* TODO */ + RESETFIFO(0x06); + /* (4) Clear the HSNAK bit. Not needed, fx2lib does this. */ return TRUE; @@ -318,7 +407,7 @@ void hispeed_isr(void) interrupt HISPEED_ISR void main(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,13 +433,8 @@ 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) {