FT2232[CDL]
The third generation of fixed-function D2xx devices, now with two channels. The devices are:
- FT2232C: first revision; 48-pin LQFP package
- FT2232L: first revision; 48-pin LQFP package (lead-free version)
- FT2232D: second revision, fixed CPU FIFO mode; 48-pin LQFP package (lead-free version)
The FT2232H is an entirely different device, and is not described here.
Features:
- is a full-speed USB 1.1 peripherial
- dual-channel D2xx device
- each channel can be independently configured to one of several supported modes:
- FT232B-like UART mode (default)
- FT245B-like FIFO mode (selected in EEPROM)
- new CPU FIFO mode (selected in EEPROM; FT2232D only — this mode is present but unusably broken on FT2232C)
- FT2xxB-like async bitbang mode (dynamically selected)
- new sync bitbang mode (dynamically selected)
- new MPSSE mode (dynamically selected; channel A only)
- new fast opto-isolated serial mode (selected in EEPROM)
- new MCU bus controller mode (dynamically selected; uses both channels)
- 384-byte IN FIFOs, 128-byte OUT FIFOs (per channel)
- 48MHz internal base clock, generated from 6MHz crystal
- 5V VCC supply for internal circuitry
- separate 3.3V or 5V VCCIOA supply for channel A business-end IO
- separate 3.3V or 5V VCCIOB supply for channel B business-end IO
- separate AGND and AVCC 5V supply for the clock multiplier
- internal 3.3V LDO
- internal power-on reset circuit
- required external support circuitry:
- USB D+ pullup
- decoupling capacitor for internal LDO
- 6MHz crystal or external clock
- optionally, a 93C46 (64×16-bit), 93C56 (128×16-bit), or 93C66 (256×16-bit) EEPROM
The default VID:PID of the device is 0403:6010, unless configured otherwise by the EEPROM. The bcdDevice value is 0x0500.
Pinout
| pin | category | function |
|---|---|---|
| 1 | EEPROM | EESK |
| 2 | EEPROM | EEDATA |
| 3 | power | VCC |
| 4 | control | RESET# |
| 5 | control | RSTOUT# |
| 6 | power | 3V3OUT |
| 7 | USB | USBDP |
| 8 | USB | USBDM |
| 9 | power | GND |
| 10 | IO-A | SI/WUA |
| 11 | IO-A | ACBUS3 |
| 12 | IO-A | ACBUS2 |
| 13 | IO-A | ACBUS1 |
| 14 | power | VCCIOA |
| 15 | IO-A | ACBUS0 |
| 16 | IO-A | ADBUS7 |
| 17 | IO-A | ADBUS6 |
| 18 | power | GND |
| 19 | IO-A | ADBUS5 |
| 20 | IO-A | ADBUS4 |
| 21 | IO-A | ADBUS3 |
| 22 | IO-A | ADBUS2 |
| 23 | IO-A | ADBUS1 |
| 24 | IO-A | ADBUS0 |
| 25 | power | GND |
| 26 | IO-B | SI/WUB |
| 27 | IO-B | BCBUS3 |
| 28 | IO-B | BCBUS2 |
| 29 | IO-B | BCBUS1 |
| 30 | IO-B | BCBUS0 |
| 31 | power | VCCIOB |
| 32 | IO-B | BDBUS7 |
| 33 | IO-B | BDBUS6 |
| 34 | power | GND |
| 35 | IO-B | BDBUS5 |
| 36 | IO-B | BDBUS4 |
| 37 | IO-B | BDBUS3 |
| 38 | IO-B | BDBUS2 |
| 39 | IO-B | BDBUS1 |
| 40 | IO-B | BDBUS0 |
| 41 | control | PWREN# |
| 42 | power | VCC |
| 43 | clock | XTIN |
| 44 | clock | XTOUT |
| 45 | power | AGND |
| 46 | power | AVCC |
| 47 | control | TEST |
| 48 | EEPROM | EECS |
Pin functions per mode
| pin | UART | FIFO | CPU FIFO | bitbang (U) | bitbang (F) | MPSSE | MCU bus | opto-isolated |
|---|---|---|---|---|---|---|---|---|
| ADBUS0 | TXD | D0 | D0 | D0 | D0 | TCK/SK | AD0 | - |
| ADBUS1 | RXD | D1 | D1 | D1 | D1 | TDI/DO | AD1 | - |
| ADBUS2 | RTS# | D2 | D2 | D2 | D2 | TDO/DI | AD2 | - |
| ADBUS3 | CTS# | D3 | D3 | D3 | D3 | TMS/CS | AD3 | - |
| ADBUS4 | DTR# | D4 | D4 | D4 | D4 | GPIOL0 | AD4 | - |
| ADBUS5 | DSR# | D5 | D5 | D5 | D5 | GPIOL1 | AD5 | - |
| ADBUS6 | DCD# | D6 | D6 | D6 | D6 | GPIOL2 | AD6 | - |
| ADBUS7 | RI# | D7 | D7 | D7 | D7 | GPIOL3 | AD7 | - |
| ACBUS0 | TXDEN | RXF# | CS# | - | WR# | GPIOH0 | I/O0 | - |
| ACBUS1 | SLEEP# | TXE# | A0 | - | RD# | GPIOH1 | I/O1 | - |
| ACBUS2 | RXLED# | RD# | RD# | WR# | - | GPIOH2 | IORDY | - |
| ACBUS3 | TXLED# | WR | WR# | RD# | - | GPIOH3 | OSC | - |
| SI/WUA | SI/WU | SI/WU | - (?) | SI/WU | SI/WU | N/A | - | - |
| BDBUS0 | TXD | D0 | D0 | D0 | D0 | N/A | A8 | FSDI |
| BDBUS1 | RXD | D1 | D1 | D1 | D1 | N/A | A9 | FSCLK |
| BDBUS2 | RTS# | D2 | D2 | D2 | D2 | N/A | A10 | FSDO |
| BDBUS3 | CTS# | D3 | D3 | D3 | D3 | N/A | A11 | FSCTS |
| BDBUS4 | DTR# | D4 | D4 | D4 | D4 | N/A | A12 | - |
| BDBUS5 | DSR# | D5 | D5 | D5 | D5 | N/A | A13 | - |
| BDBUS6 | DCD# | D6 | D6 | D6 | D6 | N/A | A14 | - |
| BDBUS7 | RI# | D7 | D7 | D7 | D7 | N/A | A15 | - |
| BCBUS0 | TXDEN | RXF# | CS# | - | WR# | N/A | CS# | - |
| BCBUS1 | SLEEP# | TXE# | A0 | - | RD# | N/A | ALE | - |
| BCBUS2 | RXLED# | RD# | RD# | WR# | - | N/A | RD# | - |
| BCBUS3 | TXLED# | WR | WR# | RD# | - | N/A | WR# | - |
| SI/WUB | SI/WU | SI/WU | - (?) | SI/WU | SI/WU | N/A | - | SI/WU |
Note: for bitbang modes, the pin assignments in the "bitbang (U)" column apply when the base mode of the channel is UART, and the "bitbang (F)" column applies otherwise.
EEPROM data format
The device will accept 64-word, 128-word, and 256-word EEPROMs. In case of 256-word EEPROMs, only first half is covered by the checksum. The other half can still be used to store user data.
- word 0x00:
- bits 0-2: channel A mode
- 0: UART
- 1: 245-style FIFO
- 2: CPU FIFO
- 4: fast opto-isolated serial
- bit 3: channel A enable bind to VCP driver
- bit 4: channel A high current output drive
- bits 8-10: channel B mode (see above)
- bit 11: channel B enable bind to VCP driver
- bit 12: channel B high current output drive
- bits 0-2: channel A mode
- word 0x01: idVendor (USB VID)
- word 0x02: idProduct (USB PID)
- word 0x03: bcdDevice (0x500)
- word 0x04: USB config (goes straight to configuration descriptor)
- bits 0-7: bmAttributes
- bit 5: remote wakeup enabled
- bit 6: self-powered
- bit 7: always set to 1
- bits 8-15: bMaxPower (max power in units of 2mA)
- bits 0-7: bmAttributes
- word 0x05: device control
- bit 0: channel A IN endpoint is isochronous
- bit 1: channel A OUT endpoint is isochronous
- bit 2: IO pulldown in suspend
- bit 3: serial number enabled
- bit 4: bcdUSB is present
- bit 5: channel B IN endpoint is isochronous
- bit 6: channel B OUT endpoint is isochronous
- word 0x06: bcdUSB
- word 0x07: manufacturer string pointer
- word 0x08: product description string pointer
- word 0x09: serial number string pointer
- word 0x0a: EEPROM type
- 0x46: 93C46 (64-word)
- 0x56: 93C56 (128-word)
- 0x66: 93C66 (256-word)
- for 64-word EEPROM:
- words 0x0b..0x3f: string / user area
- word 0x3f: checksum
- for 128-word and 256-word EEPROM:
- words 0xb..0x4b: user area
- words 0x4b..0x7f: string / user area
- word 0x7f: checksum
- words 0x80..0x100 (256-word EEPROM only): user area (not covered by checksum)
String pointers are formatted as follows:
- for 64-word EEPROM:
- bits 0-6: pointer to descriptor within EEPROM (counted in bytes)
- bit 7: always set to 1
- for 128-word or 256-word EEPROM:
- bits 0-7: pointer to descriptor within EEPROM (counted in bytes); note that FTDI tools will only store string descriptors in the area starting at word 0x4b, ensuring the high bit is always set
- bits 8-15: total length of descriptor in bytes
TODO: figure out wtf it is with the always-set high bit
The string descriptors are stored in ROM with the descriptor header included, as follows:
- word 0: header
- bits 0-7: total length of descriptor in bytes (includes header)
- bits 8-15: descriptor type (always 3 — string)
- words 1 and up: string in UTF-16
The checksum can be computed as follows:
#![allow(unused)] fn main() { fn checksum(eeprom: &[u16]) -> u16 { let checksum_word = match eeprom.len() { 0x40 => 0x3f, 0x80 | 0x100 => 0x7f, }; let mut res: u16 = 0xaaaa; for pos in 0..checksum_word { // checksum word is NOT included — we're calculating it res ^= eeprom[pos]; res = res.rotate_left(1); } res } }