PyFtdi Documentation

repository·main·Indexed 20 days ago

https://github.com/eblot/pyftdi

A pure Python user-space driver for FTDI devices supporting UART, GPIO, SPI, I2C, and JTAG protocols. It provides support for various FTDI bridge chips (including FT232R, FT232H, FT2232H, and FT4232H) and includes CLI tools such as ftconf for EEPROM configuration, ftdi_urls for device discovery, i2cscan for bus scanning, and pyterm for serial terminal emulation. Requires Python 3.9+ and supports macOS, Linux, and FreeBSD.

Tokens
18.2K
Snippets
45
Records
93
Agent score
66%

What's inside PyFtdi

  1. Overview of EEPROM API support

    main

    EEPROM support in pyftdi is under active development. Because different FTDI models implement different feature maps, some features may be incorrectly decoded.

    To interact with the EEPROM, use the high-level EEPROM API.

  2. Overview of PyFtdi capabilities

    main

    PyFtdi is a pure Python user-space driver for popular FTDI devices. It allows you to interface with FTDI chips to implement various communication protocols without needing kernel-level drivers.

    Supported Protocols

    • UART/Serial: Up to 12Mbps (device dependent).
    • GPIO/Bitbang: Supports 8-bit asynchronous, 8-bit synchronous, and 8-/16-bit MPSSE variants.
    • SPI Master: Supports up to 12 pins per port with non-byte sized transfer support.
    • I2C Master: Supports up to 14 pins per port.
    • JTAG: Basic master capabilities.
    • EEPROM: Support for retrieving parameters (modification support is limited).
    • CBUS: Experimental support for up to 4 pins per port on selected devices.
  3. Use the GPIO API to drive FTDI pins

    main

    The pyftdi.gpio module allows for direct driving of GPIO pins on an FTDI device.

    Important Constraints:

    • Mutual Exclusivity: This direct GPIO mode is mutually exclusive with advanced MPSSE features like I2C, SPI, or JTAG.
    • Shared Mode: If you need to use GPIO pins simultaneously with an MPSSE interface (like SPI or I2C), you must use the dedicated shared-mode APIs provided in the SPI API or I2C API documentation instead of this direct GPIO API.
    • CBUS Limitation: This API does not provide access to the special CBUS port on FT232R, FT232H, FT230X, and FT231X devices.
  4. Overview of GPIO access in PyFtdi

    main

    PyFtdi provides several ways to access FTDI IO pins depending on your use case:

    • Raw GPIO Access: Use GpioController implementations (GpioAsyncController, GpioSyncController, or GpioMpsseController) for full, direct access to FTDI pins as raw I/O.
    • SPI/I2C Integrated GPIO: Use SpiGpioPort or I2cGpioPort to access free pins that are not reserved by the SPI or I2C features.

    Limitations:

    • Raw GPIO access is not supported when using the JTAG feature.
    • You cannot use GPIO along with UART mode on the same interface (though UART provides very limited GPIO access).
    • Performing a USB device reset affects all interfaces on an FTDI device; PyFtdi avoids automatic resets during interface initialization to prevent this.
  5. Use the pyftdi.ftdi module for low-level FTDI hardware access

    main

    The pyftdi.ftdi module provides direct access to the low-level FTDI hardware.

    Note: It is highly recommended to use the dedicated high-level APIs instead of this module. Most features required for standard development are available through the specialized API modules (e.g., GPIO, MPSSE, I2C, SPI, etc.). Use this module only if you have specific requirements that the high-level APIs do not support.

  6. Enumerate FTDI devices using URL syntax

    main

    You can use special URL syntax to find and list available FTDI devices:

    Querying via URL

    Using the syntax ftdi:///? (or ftdi:///\? in shells like zsh to escape the question mark) will print available devices to standard output and raise a SystemExit. This is a quick way to see available URLs with serial numbers or bus:address selectors.

    Programmatic Enumeration

    To enumerate devices without interrupting execution (i.e., without raising SystemExit), use the following helper methods on the Ftdi class:

    • pyftdi.ftdi.Ftdi.list_devices(url)
    • pyftdi.ftdi.Ftdi.show_devices(url)

    Both methods accept the same URL syntax used for connections.

    from pyftdi.ftdi import Ftdi
    
    # List devices without exiting the script
    devices = Ftdi.list_devices("ftdi://")
    print(devices)
  7. Hardware Caveats: Open-collector and Speed

    main

    Open-collector Bus

    I2C requires open-collector/open-drain lines with pull-up resistors.

    • FT232H: Supports real open-collector outputs; PyFtdi enables this mode automatically.
    • FT2232H / FT4232H: Do not support open-collector mode and will source current to SCL/SDA lines. Ensure your slave device can handle 4..16 mA input current, or use a diode to prevent current sourcing.

    Speed Limitations

    Due to the MPSSE engine and USB latency, write operations are relatively slow because each byte must be acknowledged by the slave before the next is sent. While read operations are optimized in PyFtdi v0.51+, this library is not recommended for high-speed I2C write requirements. For high-speed needs, consider a dedicated I2C master like the FT4222H.

  8. Understand FTDI Ports and Interfaces

    main

    In PyFtdi, Ports and Interfaces are treated as synonyms. An interface is an independent hardware communication port on an FTDI device. Each interface can be configured independently (e.g., one as UART, another as I2C + GPIO).

    Port Widths by Hardware Model:

    • FT232R: 8-bit (DBUS)
    • FT232H: 16-bit (ADBUS/ACBUS)
    • FT2232D: Two 12-bit ports (ADBUS/ACBUS and BDBUS/BCBUS)
    • FT2232H: Two 16-bit ports (ADBUS/ACBUS and BDBUS/BCBUS)
    • FT4232H/HA/HP: Four 8-bit ports (ADBUS, BDBUS, CDBUS, DDBUS)
    • FT230X: 4-bit (DBUS)
    • FT231X: 8-bit (DBUS)

    Note: Avoid using legacy terms 'wide' or 'narrow'; use the actual port width instead.

  9. How feature-reserved pins affect GPIO access

    main

    When a specific feature (like I2C) is enabled, certain pins are reserved for that feature's protocol (e.g., SCL, SDA). These reserved pins are no longer available as standard GPIOs.

    If a feature reserves the first $N$ pins, the lowest accessible GPIO pin will be bit $N$. For example, if I2C reserves bits 0, 1, and 2, the first available GPIO is bit 3 (AD3). When interacting with the GPIO controller in this state, you must account for these reserved bits in your bitmasks.

    # Example: Using I2C feature which reserves bits 0, 1, 2
    i2c = I2cController()
    i2c.configure('ftdi:///1', direction=0x78)
    gpio = i2c.get_gpio()
    
    # Read current state
    pins = gpio.read()
    
    # Mask out the I2C bits (0x07 = bits 0, 1, 2)
    pins &= 0x07
    
    # Set AD4 (bit 4)
    pins |= 1 << 4
    
    # Update GPIO output
    gpio.write(pins)
  10. Use FTDI as an SPI master

    main

    PyFtdi supports using FTDI devices as SPI masters in both half-duplex (write or read) and full-duplex (synchronous write and read) modes.

    Supported SPI Modes:

    • Mode 0 (CPol 0, CPh 0): Supported on all MPSSE devices.
    • Mode 1 (CPol 0, CPh 1): Workaround available for -H series.
    • Mode 2 (CPol 1, CPh 0): Supported on -H series (FT232H, FT2232H, FT4232H, FT4232HA).
    • Mode 3 (CPol 1, CPh 1): Workaround available for -H series.

    Key Capabilities & Limitations:

    • Non-byte aligned access: Experimental support allows discarding up to 7 trailing bits (no clock pulse generated) to perform non-byte-sized transfers.
    • GPIO: SPI and I2C support simultaneous GPIO R/W access for all pins not used by the protocol.
    • Limitation: FTDI232 devices cannot be used as an SPI slave.
  11. Access GPIO pins via UART port attributes

    main

    In UART mode, you have limited access to the lower 8 pins as GPIO. Note that direction is hardcoded, pins cannot be addressed atomically, and some pins are unavailable if hardware flow control is enabled. You access these pins using their UART assigned names as attributes on the PySerial port object:

    BitUARTDirectionAPI
    b0TXOutport.write(buffer)
    b1RXInbuffer = port.read(count)
    b2RTSOutport.rts = state
    b3CTSInstate = port.cts
    b4DTROutport.dtr = state
    b5DSRInstate = port.dsr
    b6DCDInstate = port.dcd
    b7RIInstate = port.ri
  12. Choose the right GpioController variant

    main

    PyFtdi provides three GpioController variants depending on your hardware requirements and timing needs:

    • GpioAsyncController: The most common API. It allows reading current input levels and changing output levels. When using byte buffers instead of single bytes, pins are sampled/updated at a configurable regular pace. Note that the exact timing of input sampling cannot be controlled.
    • GpioSyncController: Designed for precise timing. A new GPIO input sample is captured exactly when GPIO output pins are updated. It uses an exchange() method instead of separate read() and write() calls. When using byte buffers, pins are sampled/updated at a configurable regular pace.
    • GpioMpsseController: Used to access the MSB pins of wide ports (12- or 16-pin FTDI devices). Note that LSB and MSB pins are not addressed atomically; there is a short delay between sampling/updating the LSB and MSB parts of the same wide port.

    Note on Port Width: Both GpioAsyncController and GpioSyncController are restricted to the 8 LSB pins (bits 0-7). For wider ports, use GpioMpsseController to access the MSB pins.