FT8U232A and FT8U245A

The first generation of fixed-function D2xx devices. The devices are:

  • FT8U232AM: UART mode, 32-pin MQFP
  • FT8U245AM: FIFO mode, 32-pin MQFP

Both devices look exactly the same from the software perspective, and in fact may or may not be the same silicon.

Features:

  • is a full-speed USB 1.1 peripherial
  • single channel D2xx device, hardwired to either UART or FIFO mode
    • no alternate bit modes
  • 384-byte IN FIFO, 128-byte OUT FIFO
  • 48MHz internal base clock, generated from 6MHz crystal
  • 5V VCC supply (used for internal circuitry and business-end IO)
  • separate AGND and AVCC supply for the clock multiplier
  • internal 3.3V LDO
  • required external support circuitry:
    • USB D+ pullup
    • power-on reset circuit
    • decoupling capacitor for internal LDO
    • RC timer for oscillator bootstrap
    • 6MHz crystal
    • optionally, a 93C46 64×16-bit EEPROM

The default VID:PID of the device is 0403:6001, unless configured otherwise by the EEPROM. The bcdDevice value is 0x0200.

Pinout

MQFP pincategoryFT8U232AFT8U245A
1EEPROMEESKEESK
2EEPROMEEDATAEEDATA
3powerVCCVCC
4controlRESET#RESET#
5controlTESTTEST
6power3V3OUT3V3OUT
7USBUSBDPUSBDP
8USBUSBDMUSBDM
9powerGNDGND
10IOSLEEP#EEGNT#
11IORXLED#EEREQ#
12IOTXLED#RXF#
13powerVCCVCC
14IOPWRCTLTXE#
15IOUSBENWR
16IOTXDENRD#
17powerGNDGND
18IORI#D7
19IODCD#D6
20IODSR#D5
21IODTR#D4
22IOCTS#D3
23IORTS#D2
24IORXDD1
25IOTXDD0
26powerVCCVCC
27clockXTINXTIN
28clockXTOUTXTOUT
29powerAGNDAGND
30powerAVCCAVCC
31clockRCCLKRCCLK
32EEPROMEECSEECS

UART-mode IO pins have the following functions:

  • TXD, RXD, RTS#, CTS#, DTR#, DSR#, DCD#, RI#: standard UART pins
  • SLEEP#: device output, goes low when in USB suspend mode
  • RXLED#, TXLED#: active-low LED outputs
  • PWRCTL: device input, used to generate USB descriptors when EEPROM not present or not functional
    • 0: bus-powered
    • 1: self-powered
  • TXDEN: device output, high while TXD is actively transmitting data; can be used as transmitter enable for RS485 transceivers
  • USBEN: device output, high after the host configures the device

FIFO-mode IO pins have the following functions:

  • D0-D7, TXE#, RXF#, RD#, WR: standard FIFO-mode pins
  • EEREQ#: device input, requests access to EEPROM via data bus
  • EEGNT#: device output, grants access to EEPROM via data bus

The semantics of EEREQ# and EEGNT# are unclear. They were removed from all subsequent devices.

TODO: wtf is this exactly

The EEPROM interface is 3-pin at the FTDI chip, while the EEPROM itself has a 4-pin interface. This is because the FTDI device uses a single tied data line. To connect the EEPROM, connect the FTDI EEDATA pin directly to the ROM's data input, and to the data output via a 2.2kΩ resistor.

EEPROM data format

  • word 0x00: always 0
  • word 0x01: idVendor (USB VID)
  • word 0x02: idProduct (USB PID)
  • word 0x03: bcdDevice (should be 0x200)
  • 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)
  • words 0x05, 0x06: always 0
  • word 0x07: manufacturer string pointer
  • word 0x08: product description string pointer
  • word 0x09: serial number string pointer
  • words 0x0a..0x3f: string / user area
  • word 0x3f: checksum

String pointers are formatted as follows:

  • bits 0-6: pointer to descriptor within EEPROM (counted in bytes)
  • bit 7: always set to 1
  • bits 8-15: total length of descriptor in bytes

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; 0x40]) -> u16 {
    let mut res: u16 = 0xaaaa;
    for pos in 0..0x3f { // checksum word is NOT included — we're calculating it
        res ^= eeprom[pos];
        res = res.rotate_left(1);
    }
    res
}
}