Skip to content

Commit 7f8fc0e

Browse files
committed
Add FTDI_PINOUT and FTDI_INTERFACE options
1 parent fe6247a commit 7f8fc0e

File tree

3 files changed

+168
-67
lines changed

3 files changed

+168
-67
lines changed

basics.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#define VARLIST_FTDI_BASE_CLOCK 8
2727
#define VARLIST_FTDI_LOG_LEVEL 9
2828
#define VARLIST_FTDI_LOG_FILE 10
29+
#define VARLIST_FTDI_PINOUT 11
30+
#define VARLIST_FTDI_INTERFACE 12
2931

3032
const SPIVARDEF g_pVarList[]={
3133
{"SPIPORT","1",1},
@@ -38,7 +40,9 @@ const SPIVARDEF g_pVarList[]={
3840
{"SPIMAXCLOCK","1000",0},
3941
{"FTDI_BASE_CLOCK","2000000",0},
4042
{"FTDI_LOG_LEVEL","warn",0},
41-
{"FTDI_LOG_FILE","stderr",0}
43+
{"FTDI_LOG_FILE","stderr",0},
44+
{"FTDI_PINOUT","0",0},
45+
{"FTDI_INTERFACE","A",0}
4246
};
4347

4448
int g_nSpiPort=1;
@@ -386,6 +390,31 @@ static int spifns_sequence_setvar(const char *szName, const char *szValue) {
386390
}
387391
}
388392
break;
393+
case VARLIST_FTDI_PINOUT:
394+
{
395+
enum spi_pinouts pinout;
396+
397+
if (!stricmp(szValue, "default")) {
398+
pinout = SPI_PINOUT_DEFAULT;
399+
} else if (!stricmp(szValue, "noleds")) {
400+
pinout = SPI_PINOUT_NOLEDS;
401+
} else if (!stricmp(szValue, "hwspi+leds")) {
402+
pinout = SPI_PINOUT_HWSPI_LEDS;
403+
} else if (!stricmp(szValue, "hwspi")) {
404+
pinout = SPI_PINOUT_HWSPI;
405+
} else {
406+
const char szError[]="Invalid pinout specified in FTDI_PINOUT";
407+
memcpy(g_szErrorString,szError,sizeof(szError));
408+
return 1;
409+
}
410+
spi_set_pinout(pinout);
411+
}
412+
case VARLIST_FTDI_INTERFACE:
413+
if (spi_set_interface(szValue) < 0) {
414+
const char szError[]="Invalid channel specified in FTDI_INTERFACE";
415+
memcpy(g_szErrorString,szError,sizeof(szError));
416+
return 1;
417+
}
389418
}
390419
}
391420
}

spi.c

Lines changed: 80 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,6 @@
1717
/* Default SPI clock rate, in kHz */
1818
#define SPIMAXCLOCK 1000
1919

20-
21-
/*
22-
* FTDI bitbang pins:
23-
* D0 - TXD
24-
* D1 - RXD
25-
* D2 - RTS#
26-
* D3 - CTS#
27-
* D4 - DTR#
28-
* D5 - DSR#
29-
* D6 - DCD#
30-
* D7 - RI#
31-
*/
32-
33-
/* Pinout. Change it at will. Beware that FTDI adapters provide 5V or 3V3 I/O
34-
* levels, but CSR chips require 3V3 or 1V8 I/O level. */
35-
#define PIN_nCS (1 << 4) /* FT232RL pin 2 (DTR#/D4), output */
36-
#define PIN_CLK (1 << 2) /* FT232RL pin 3 (RTS#/D2), output */
37-
#define PIN_MOSI (1 << 7) /* FT232RL pin 6 (RI#/D7), output */
38-
#define PIN_MISO (1 << 5) /* FT232RL pin 9 (DSR#/D5), input */
39-
#ifdef ENABLE_LEDS
40-
#define PIN_nLED_RD (1 << 6) /* FT232RL pin 10 (DCD#/D6), output */
41-
#define PIN_nLED_WR (1 << 3) /* FT232RL pin 11 (CTS#/D3), output */
42-
#define PINS_OUTPUT (PIN_MOSI | PIN_CLK | PIN_nCS | PIN_nLED_RD | PIN_nLED_WR)
43-
/* Set initial pin state: CS high, MISO high as pullup, MOSI and CLK low, LEDs off */
44-
#define PINS_INIT (PIN_nCS | PIN_MISO | PIN_nLED_WR | PIN_nLED_RD)
45-
#else
46-
#define PINS_OUTPUT (PIN_MOSI | PIN_CLK | PIN_nCS)
47-
#define PINS_INIT (PIN_nCS | PIN_MISO)
48-
#endif
49-
5020
static char *ftdi_type_str = NULL;
5121

5222
static uint8_t *ftdi_out_buf = NULL, *ftdi_in_buf = NULL;
@@ -57,12 +27,11 @@ static int spi_dev_open = 0;
5727
static int spi_nrefs = 0;
5828

5929
static struct ftdi_context ftdic;
30+
static enum ftdi_interface ftdi_intf = INTERFACE_A;
6031
static uint8_t ftdi_pin_state = 0;
6132

62-
#ifdef ENABLE_LEDS
6333
#define SPI_LED_FREQ 10 /* Hz */
6434
static int spi_led_state = 0;
65-
#endif
6635

6736
#ifdef SPI_STATS
6837
static struct spi_stats {
@@ -100,6 +69,10 @@ static struct ftdi_device_ids ftdi_device_ids[] = {
10069
static char *spi_err_buf = NULL;
10170
static size_t spi_err_buf_sz = 0;
10271

72+
static struct spi_pins *spi_pins;
73+
static struct spi_pins spi_pin_presets[] = SPI_PIN_PRESETS;
74+
static enum spi_pinouts spi_pinout = SPI_PINOUT_DEFAULT;
75+
10376
void spi_set_err_buf(char *buf, size_t sz)
10477
{
10578
if (buf && sz) {
@@ -212,14 +185,16 @@ static int spi_ftdi_xfer(uint8_t *out_buf, uint8_t *in_buf, int size)
212185
return 0;
213186
}
214187

215-
#ifdef ENABLE_LEDS
216188
static void spi_led_tick(void)
217189
{
218190
struct timeval tv;
219191

220192
if (spi_led_state == SPI_LED_OFF) {
221193
/* Asked to turn LEDs off */
222-
ftdi_pin_state |= PIN_nLED_WR | PIN_nLED_RD;
194+
if (spi_pins->nledr)
195+
ftdi_pin_state |= spi_pins->nledr;
196+
if (spi_pins->nledw)
197+
ftdi_pin_state |= spi_pins->nledw;
223198
return;
224199
}
225200

@@ -229,12 +204,15 @@ static void spi_led_tick(void)
229204
if (((tv.tv_sec * 1000 + tv.tv_usec / 1000) /
230205
(1000 / SPI_LED_FREQ / 2)) % 2 == 0)
231206
{
232-
if (spi_led_state & SPI_LED_READ)
233-
ftdi_pin_state &= ~PIN_nLED_RD;
234-
if (spi_led_state & SPI_LED_WRITE)
235-
ftdi_pin_state &= ~PIN_nLED_WR;
207+
if (spi_led_state & SPI_LED_READ && spi_pins->nledr)
208+
ftdi_pin_state &= ~spi_pins->nledr;
209+
if (spi_led_state & SPI_LED_WRITE && spi_pins->nledw)
210+
ftdi_pin_state &= ~spi_pins->nledw;
236211
} else {
237-
ftdi_pin_state |= PIN_nLED_WR | PIN_nLED_RD;
212+
if (spi_pins->nledr)
213+
ftdi_pin_state |= spi_pins->nledr;
214+
if (spi_pins->nledw)
215+
ftdi_pin_state |= spi_pins->nledw;
238216
}
239217
}
240218

@@ -243,7 +221,6 @@ void spi_led(int led)
243221
spi_led_state = led;
244222
spi_led_tick();
245223
}
246-
#endif
247224

248225
/*
249226
* spi_xfer_*() use global output and input buffers. Output buffer is flushed
@@ -270,9 +247,7 @@ int spi_xfer_begin(int get_status)
270247
return -1;
271248
}
272249

273-
#ifdef ENABLE_LEDS
274250
spi_led_tick();
275-
#endif
276251

277252
#ifdef SPI_STATS
278253
if (gettimeofday(&spi_stats.tv_xfer_begin, NULL) < 0)
@@ -292,24 +267,24 @@ int spi_xfer_begin(int get_status)
292267
/* BlueCore chip SPI port reset sequence: deassert CS, wait at least two
293268
* clock cycles */
294269

295-
ftdi_pin_state |= PIN_nCS;
270+
ftdi_pin_state |= spi_pins->ncs;
296271
ftdi_out_buf[ftdi_out_buf_offset++] = ftdi_pin_state;
297272

298-
ftdi_pin_state |= PIN_CLK;
273+
ftdi_pin_state |= spi_pins->clk;
299274
ftdi_out_buf[ftdi_out_buf_offset++] = ftdi_pin_state;
300275

301-
ftdi_pin_state &= ~PIN_CLK;
276+
ftdi_pin_state &= ~spi_pins->clk;
302277
ftdi_out_buf[ftdi_out_buf_offset++] = ftdi_pin_state;
303278

304-
ftdi_pin_state |= PIN_CLK;
279+
ftdi_pin_state |= spi_pins->clk;
305280
ftdi_out_buf[ftdi_out_buf_offset++] = ftdi_pin_state;
306281

307-
ftdi_pin_state &= ~PIN_CLK;
282+
ftdi_pin_state &= ~spi_pins->clk;
308283
ftdi_out_buf[ftdi_out_buf_offset++] = ftdi_pin_state;
309284

310285
/* Start transfer */
311286

312-
ftdi_pin_state &= ~PIN_nCS;
287+
ftdi_pin_state &= ~spi_pins->ncs;
313288
ftdi_out_buf[ftdi_out_buf_offset++] = ftdi_pin_state;
314289

315290
if (get_status) {
@@ -330,7 +305,7 @@ int spi_xfer_begin(int get_status)
330305
if (spi_ftdi_xfer(ftdi_out_buf, ftdi_in_buf, ftdi_out_buf_offset) < 0)
331306
return -1;
332307

333-
if (ftdi_in_buf[status_offset] & PIN_MISO)
308+
if (ftdi_in_buf[status_offset] & spi_pins->miso)
334309
status = SPI_CPU_STOPPED;
335310
else
336311
status = SPI_CPU_RUNNING;
@@ -361,7 +336,7 @@ int spi_xfer_end(void)
361336
/* Commit the last ftdi_pin_state after spi_xfer() */
362337
ftdi_out_buf[ftdi_out_buf_offset++] = ftdi_pin_state;
363338

364-
ftdi_pin_state |= PIN_nCS;
339+
ftdi_pin_state |= spi_pins->ncs;
365340
ftdi_out_buf[ftdi_out_buf_offset++] = ftdi_pin_state;
366341

367342
/* Buffer flush is done on close */
@@ -377,9 +352,7 @@ int spi_xfer_end(void)
377352
}
378353
#endif
379354

380-
#ifdef ENABLE_LEDS
381355
spi_led(SPI_LED_OFF);
382-
#endif
383356

384357
return 0;
385358
}
@@ -395,9 +368,7 @@ int spi_xfer(int cmd, int iosize, void *buf, int size)
395368
read_offset = 0;
396369

397370
do {
398-
#ifdef ENABLE_LEDS
399371
spi_led_tick();
400-
#endif
401372

402373
/* In FTDI sync bitbang mode we need to write something to device to
403374
* toggle a read. */
@@ -429,22 +400,22 @@ int spi_xfer(int cmd, int iosize, void *buf, int size)
429400
if (cmd & SPI_XFER_WRITE) {
430401
/* Set output bit */
431402
if (word & bit)
432-
ftdi_pin_state |= PIN_MOSI;
403+
ftdi_pin_state |= spi_pins->mosi;
433404
else
434-
ftdi_pin_state &= ~PIN_MOSI;
405+
ftdi_pin_state &= ~spi_pins->mosi;
435406
} else {
436407
/* Write 0 during a read */
437-
ftdi_pin_state &= ~PIN_MOSI;
408+
ftdi_pin_state &= ~spi_pins->mosi;
438409
}
439410

440411
ftdi_out_buf[ftdi_out_buf_offset++] = ftdi_pin_state;
441412

442413
/* Clock high */
443-
ftdi_pin_state |= PIN_CLK;
414+
ftdi_pin_state |= spi_pins->clk;
444415
ftdi_out_buf[ftdi_out_buf_offset++] = ftdi_pin_state;
445416

446417
/* Clock low */
447-
ftdi_pin_state &= ~PIN_CLK;
418+
ftdi_pin_state &= ~spi_pins->clk;
448419
}
449420
write_offset++;
450421
}
@@ -460,7 +431,7 @@ int spi_xfer(int cmd, int iosize, void *buf, int size)
460431
for (bit = (1 << (iosize - 1)); bit != 0; bit >>= 1) {
461432
/* Input bit */
462433
ftdi_in_buf_offset++;
463-
if (ftdi_in_buf[ftdi_in_buf_offset] & PIN_MISO)
434+
if (ftdi_in_buf[ftdi_in_buf_offset] & spi_pins->miso)
464435
word |= bit;
465436
ftdi_in_buf_offset++;
466437
}
@@ -546,6 +517,33 @@ static int spi_enumerate_ports(void)
546517
return 0;
547518
}
548519

520+
void spi_set_pinout(enum spi_pinouts pinout)
521+
{
522+
spi_pinout = pinout;
523+
}
524+
525+
int spi_set_interface(const char *intf)
526+
{
527+
enum ftdi_interface eintf;
528+
529+
if (intf[1] != '\0')
530+
return -1;
531+
if (intf[0] == 'a' || intf[0] == 'A' || intf[0] == '0') {
532+
eintf = INTERFACE_A;
533+
} else if (intf[0] == 'b' || intf[0] == 'B' || intf[0] == '1') {
534+
eintf = INTERFACE_B;
535+
} else if (intf[0] == 'c' || intf[0] == 'C' || intf[0] == '2') {
536+
eintf = INTERFACE_C;
537+
} else if (intf[0] == 'd' || intf[0] == 'D' || intf[0] == '3') {
538+
eintf = INTERFACE_D;
539+
} else {
540+
return -1;
541+
}
542+
543+
ftdi_intf = eintf;
544+
return 0;
545+
}
546+
549547
int spi_init(void)
550548
{
551549
LOG(DEBUG, "spi_nrefs=%d, spi_dev_open=%d", spi_nrefs, spi_dev_open);
@@ -570,6 +568,8 @@ int spi_init(void)
570568
return -1;
571569
}
572570

571+
spi_pins = &spi_pin_presets[spi_pinout];
572+
573573
return 0;
574574
}
575575

@@ -688,6 +688,7 @@ int spi_open(int nport)
688688
{
689689
int rc;
690690
char *serial;
691+
uint8_t output_pins;
691692

692693
LOG(DEBUG, "(%d) spi_dev_open=%d", nport, spi_dev_open);
693694

@@ -707,7 +708,12 @@ int spi_open(int nport)
707708
LOG(WARN, "gettimeofday failed: %s", strerror(errno));
708709
#endif
709710

710-
/*ftdi_set_interface(&ftdic, INTERFACE_A);*/ /* XXX for multichannel chips */
711+
rc = ftdi_set_interface(&ftdic, ftdi_intf);
712+
if (rc < 0)
713+
{
714+
SPI_ERR("FTDI: ftdi_set_interface() failed: [%d] %s", rc, ftdi_get_error_string(&ftdic));
715+
goto open_err;
716+
}
711717

712718
/* Serial number can be unavailable due to SerNumEnable* settings in FTDI
713719
* EEPROM. Don't try to pass a serial number pointer for such a device to
@@ -752,7 +758,13 @@ int spi_open(int nport)
752758
goto open_err;
753759
}
754760

755-
rc = ftdi_set_bitmode(&ftdic, PINS_OUTPUT, BITMODE_SYNCBB);
761+
/* Set pins direction */
762+
output_pins = spi_pins->mosi | spi_pins->clk | spi_pins->ncs;
763+
if (spi_pins->nledr)
764+
output_pins |= spi_pins->nledr;
765+
if (spi_pins->nledw)
766+
output_pins |= spi_pins->nledw;
767+
rc = ftdi_set_bitmode(&ftdic, output_pins, BITMODE_SYNCBB);
756768
if (rc < 0) {
757769
SPI_ERR("FTDI: set synchronous bitbang mode failed: [%d] %s", rc, ftdi_get_error_string(&ftdic));
758770
goto open_err;
@@ -829,7 +841,12 @@ int spi_open(int nport)
829841
}
830842
ftdi_out_buf_offset = 0;
831843

832-
ftdi_pin_state = PINS_INIT;
844+
/* Set initial pin state: CS high, MISO high as pullup, MOSI and CLK low, LEDs off */
845+
ftdi_pin_state = spi_pins->ncs | spi_pins->miso;
846+
if (spi_pins->nledr)
847+
ftdi_pin_state |= spi_pins->nledr;
848+
if (spi_pins->nledw)
849+
ftdi_pin_state |= spi_pins->nledw;
833850
ftdi_out_buf[ftdi_out_buf_offset++] = ftdi_pin_state;
834851

835852
return 0;
@@ -943,9 +960,7 @@ int spi_close(void)
943960
LOG(DEBUG, "spi_nrefs=%d, spi_dev_open=%d", spi_nrefs, spi_dev_open);
944961

945962
if (spi_dev_open) {
946-
#ifdef ENABLE_LEDS
947963
spi_led(SPI_LED_OFF);
948-
#endif
949964

950965
/* Flush and reset the buffers */
951966
if (ftdi_out_buf_offset) {

0 commit comments

Comments
 (0)