Skip to content

Commit

Permalink
Support for FTDI FT4232HA added.
Browse files Browse the repository at this point in the history
  • Loading branch information
eblot committed Aug 5, 2023
1 parent 3c0e8d1 commit f73f6ea
Show file tree
Hide file tree
Showing 23 changed files with 159 additions and 107 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Suported FTDI devices include:
* FT232H (single port, clock up to 30 MHz)
* FT2232H (dual port, clock up to 30 MHz)
* FT4232H (quad port, clock up to 30 MHz)
* FT4232HA (quad port, clock up to 30 MHz)

## Features

Expand Down
2 changes: 1 addition & 1 deletion pyftdi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#pylint: disable-msg=missing-docstring

__version__ = '0.54.1'
__version__ = '0.55.0'
__title__ = 'PyFtdi'
__description__ = 'FTDI device driver (pure Python)'
__uri__ = 'http://github.com/eblot/pyftdi'
Expand Down
18 changes: 9 additions & 9 deletions pyftdi/doc/api/i2c.rst
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ Fortunately, FT232H device is fitted with real open collector outputs, and
PyFtdi always enable this mode on SCL and SDA lines when a FT232H device is
used.

Other FTDI devices such as FT2232H and FT4232H do not support open collector
mode, and source current to SCL and SDA lines.
Other FTDI devices such as FT2232H, FT4232H and FT4232HA do not support open
collector mode, and source current to SCL and SDA lines.

Clock streching
```````````````
Expand All @@ -142,11 +142,11 @@ Clock stretching is supported through a hack that re-uses the JTAG adaptative
clock mode designed for ARM devices. FTDI HW drives SCL on ``AD0`` (`BD0`), and
samples the SCL line on : the 8\ :sup:`th` pin of a port ``AD7`` (``BD7``).

When a FTDI device without an open collector capability is used (FT2232H,
FT4232H) the current sourced from AD0 may prevent proper sampling of the SCL
line when the slave attempts to strech the clock. It is therefore recommended
to add a low forward voltage drop diode to `AD0` to prevent AD0 to source
current to the SCL bus. See the wiring section.
When a FTDI device without an open collector capability is used
(FT2232H, FT4232H, FT4232HA) the current sourced from AD0 may prevent proper
sampling ofthe SCL line when the slave attempts to strech the clock. It is
therefore recommended to add a low forward voltage drop diode to `AD0` to
prevent AD0 to source current to the SCL bus. See the wiring section.

Speed
`````
Expand All @@ -165,7 +165,7 @@ Use of PyFtdi_ should nevetherless carefully studied and is not recommended if
you need to achieve medium to high speed write operations with a slave
(relative to the I2C clock...). Dedicated I2C master such as FT4222H device is
likely a better option, but is not currently supported with PyFtdi_ as it uses
a different communication protocol.
a different communication protocol.

.. _i2c_wiring:

Expand All @@ -187,5 +187,5 @@ Wiring
*Fig.1*:

* ``D1`` is only required when clock streching is used along with
FT2232H or FT4232H devices. It should not be fit with an FT232H.
FT2232H, FT4232H or FT4232HA devices. It should not be fit with an FT232H.
* ``AD7`` may be used as a regular GPIO with clock stretching is not required.
2 changes: 1 addition & 1 deletion pyftdi/doc/api/spi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ Application Node 114:

Support for mode 1 and mode 3 is implemented with some workarounds, but
generated signals may not be reliable: YMMV. It is only available with -H
series (232H, 2232H, 4232H).
series (232H, 2232H, 4232H, 4232HA).

The 3-clock phase mode which has initially be designed to cope with |I2C|
signalling is used to delay the data lines from the clock signals. A direct
Expand Down
2 changes: 2 additions & 0 deletions pyftdi/doc/authors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,5 @@ Contributors
* Amanita-muscaria
* len0rd
* Rod Whitby
* Kornel Swierzy

25 changes: 13 additions & 12 deletions pyftdi/doc/defs.rst
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
.. |I2C| replace:: I\ :sup:`2`\ C

.. _FT232R: http://www.ftdichip.com/Products/ICs/FT232R.htm
.. _FT230X: http://www.ftdichip.com/Products/ICs/FT230X.html
.. _FT2232D: http://www.ftdichip.com/Products/ICs/FT2232D.htm
.. _FT232H: http://www.ftdichip.com/Products/ICs/FT232H.htm
.. _FT2232H: http://www.ftdichip.com/Products/ICs/FT2232H.html
.. _FT4232H: http://www.ftdichip.com/Products/ICs/FT4232H.htm
.. _FTDI_Recovery: http://www.ftdichip.com/Support/Documents/AppNotes/AN_136%20Hi%20Speed%20Mini%20Module%20EEPROM%20Disaster%20Recovery.pdf
.. _FT232R: https://www.ftdichip.com/Products/ICs/FT232R.htm
.. _FT230X: https://www.ftdichip.com/Products/ICs/FT230X.html
.. _FT2232D: https://www.ftdichip.com/Products/ICs/FT2232D.htm
.. _FT232H: https://www.ftdichip.com/Products/ICs/FT232H.htm
.. _FT2232H: https://www.ftdichip.com/Products/ICs/FT2232H.html
.. _FT4232H: https://www.ftdichip.com/Products/ICs/FT4232H.htm
.. _FT4232HA: http://ftdichip.com/products/ft4232haq/
.. _FTDI_Recovery: https://www.ftdichip.com/Support/Documents/AppNotes/AN_136%20Hi%20Speed%20Mini%20Module%20EEPROM%20Disaster%20Recovery.pdf
.. _PyFtdi: https://www.github.com/eblot/pyftdi
.. _PyFtdiTools: https://github.com/eblot/pyftdi/tree/master/pyftdi/bin
.. _FTDI: http://www.ftdichip.com/
.. _PyUSB: http://pyusb.github.io/pyusb/
.. _FTDI: https://www.ftdichip.com/
.. _PyUSB: https://pyusb.github.io/pyusb/
.. _Python: https://www.python.org/
.. _pyserial: https://pythonhosted.org/pyserial/
.. _libftdi: https://www.intra2net.com/en/developer/libftdi/
.. _pyspiflash: https://github.com/eblot/pyspiflash/
.. _pyi2cflash: https://github.com/eblot/pyi2cflash/
.. _libusb: http://www.libusb.info/
.. _libusb: https://www.libusb.info/
.. _Libusb on Windows: https://github.com/libusb/libusb/wiki/Windows
.. _Libusb win32: https://sourceforge.net/projects/libusb-win32/files/libusb-win32-releases/
.. _Zadig: http://zadig.akeo.ie/
.. _FTDI macOS guide: http://www.ftdichip.com/Support/Documents/AppNotes/AN_134_FTDI_Drivers_Installation_Guide_for_MAC_OSX.pdf
.. _Zadig: https://zadig.akeo.ie/
.. _FTDI macOS guide: https://www.ftdichip.com/Support/Documents/AppNotes/AN_134_FTDI_Drivers_Installation_Guide_for_MAC_OSX.pdf
.. _Libusb issue on macOs: https://github.com/libusb/libusb/commit/5e45e0741daee4fa295c6cc977edfb986c872152
.. _FT_PROG: https://www.ftdichip.com/Support/Utilities.htm#FT_PROG
.. _fstring: https://www.python.org/dev/peps/pep-0498
Expand Down
20 changes: 10 additions & 10 deletions pyftdi/doc/eeprom.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ EEPROM from the command line. See the :ref:`tools` chapter to locate this tool.
[-s SERIAL_NUMBER] [-m MANUFACTURER] [-p PRODUCT] [-c CONFIG]
[--vid VID] [--pid PID] [-e] [-E] [-u] [-v] [-d]
[device]

Simple FTDI EEPROM configurator.

positional arguments:
device serial port device name

optional arguments:
-h, --help show this help message and exit

Files:
-i INPUT, --input INPUT
input ini file to load EEPROM content
Expand All @@ -62,20 +62,20 @@ EEPROM from the command line. See the :ref:`tools` chapter to locate this tool.
output ini file to save EEPROM content
-V VIRTUAL, --virtual VIRTUAL
use a virtual device, specified as YaML

Device:
-P VIDPID, --vidpid VIDPID
specify a custom VID:PID device ID (search for FTDI devices)
-M EEPROM, --eeprom EEPROM
force an EEPROM model
-S {128,256,1024}, --size {128,256,1024}
force an EEPROM size

Format:
-x, --hexdump dump EEPROM content as ASCII
-X HEXBLOCK, --hexblock HEXBLOCK
dump EEPROM as indented hexa blocks

Configuration:
-s SERIAL_NUMBER, --serial-number SERIAL_NUMBER
set serial number
Expand All @@ -87,12 +87,12 @@ EEPROM from the command line. See the :ref:`tools` chapter to locate this tool.
change/configure a property as key=value pair
--vid VID shortcut to configure the USB vendor ID
--pid PID shortcut to configure the USB product ID

Action:
-e, --erase erase the whole EEPROM content
-E, --full-erase erase the whole EEPROM content, including the CRC
-u, --update perform actual update, use w/ care

Extras:
-v, --verbose increase verbosity
-d, --debug enable debug mode
Expand Down Expand Up @@ -372,7 +372,7 @@ Examples
TIME_STAMP, TRISTATE, TXDEN, TXLED, TXRXLED, VBUS_SENSE

* Erase the whole EEPROM including its CRC.

Once power cycle, the device should run as if no EEPROM was connected.
Do not use this with internal, embedded EEPROMs such as FT230X.

Expand Down
10 changes: 5 additions & 5 deletions pyftdi/doc/features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ SPI master

Supported devices:

===== ===== ====== ====================================================
===== ===== ====== ============================================================
Mode CPol CPha Status
===== ===== ====== ====================================================
===== ===== ====== ============================================================
0 0 0 Supported on all MPSSE devices
1 0 1 Workaround available for on -H series
2 1 0 Supported on -H series (FT232H_/FT2232H_/FT4232H_)
2 1 0 Supported on -H series (FT232H_/FT2232H_/FT4232H_/FT4232HA_)
3 1 1 Workaround available for on -H series
===== ===== ====== ====================================================
===== ===== ====== ============================================================

PyFtdi_ can be used with pyspiflash_ module that demonstrates how to
use the FTDI SPI master with a pure-Python serial flash device driver for
Expand All @@ -61,7 +61,7 @@ Note: FTDI*232* devices cannot be used as an SPI slave.
|I2C| master
````````````

Supported devices: FT232H_, FT2232H_, FT4232H_
Supported devices: FT232H_, FT2232H_, FT4232H_, FT4232HA_

For now, only 7-bit addresses are supported.

Expand Down
4 changes: 2 additions & 2 deletions pyftdi/doc/gpio.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ the actual hardware, *i.e.* the FTDI model:
`BDBUS/BCBUS`,
* FT2232H features two ports, which are 16-bit wide each: `ADBUS/ACBUS` and
`BDBUS/BCBUS`,
* FT4232H features four ports, which are 8-bit wide each: `ADBUS`, `BDBUS`,
`CDBUS` and `DDBUS`,
* FT4232H/FT4232HA features four ports, which are 8-bit wide each: `ADBUS`,
`BDBUS`, `CDBUS` and `DDBUS`,
* FT230X features a single port, which is 4-bit wide,
* FT231X feature a single port, which is 8-bit wide

Expand Down
1 change: 1 addition & 0 deletions pyftdi/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Supported FTDI devices include:
* FT232H (single port, clock up to 30 MHz)
* FT2232H (dual port, clock up to 30 MHz)
* FT4232H (quad port, clock up to 30 MHz)
* FT4232HA (quad port, clock up to 30 MHz)

Features
--------
Expand Down
2 changes: 2 additions & 0 deletions pyftdi/doc/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ configure `udev`, here is a typical setup:
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6014", GROUP="plugdev", MODE="0664"
# FT230X/FT231X/FT234X
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6015", GROUP="plugdev", MODE="0664"
# FT4232HA
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6048", GROUP="plugdev", MODE="0664"

.. note:: **Accessing FTDI devices with custom VID/PID**

Expand Down
14 changes: 7 additions & 7 deletions pyftdi/doc/pinout.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
FTDI device pinout
------------------

============ ============= ======= ====== ============== ========== ====== ============
============ ============= ======= ====== ============== ========== ====== =============
IF/1 [#ih]_ IF/2 [#if2]_ BitBang UART |I2C| SPI JTAG C232HD cable
============ ============= ======= ====== ============== ========== ====== ============
============ ============= ======= ====== ============== ========== ====== =============
``ADBUS0`` ``BDBUS0`` GPIO0 TxD SCK SCLK TCK Orange
``ADBUS1`` ``BDBUS1`` GPIO1 RxD SDA/O [#i2c]_ MOSI TDI Yellow
``ADBUS2`` ``BDBUS2`` GPIO2 RTS SDA/I [#i2c]_ MISO TDO Green
Expand All @@ -22,18 +22,18 @@ FTDI device pinout
``ACBUS5`` ``BCBUS5`` GPIO13 GPIO13
``ACBUS6`` ``BCBUS6`` GPIO14 GPIO14
``ACBUS7`` ``BCBUS7`` GPIO15 GPIO15
============ ============= ======= ====== ============== ========== ====== ============
============ ============= ======= ====== ============== ========== ====== =============

.. [#ih] 16-bit port (ACBUS, BCBUS) is not available with FT4232H_ series, and
FTDI2232C/D only support 12-bit ports.
.. [#i2c] FTDI pins are either configured as input or output. As |I2C| SDA line
is bi-directional, two FTDI pins are required to provide the SDA
feature, and they should be connected together and to the SDA |I2C|
bus line. Pull-up resistors on SCK and SDA lines should be used.
.. [#if2] FT232H_ does not support a secondary MPSSE port, only FT2232H_ and
FT4232H_ do. Note that FT4232H_ has 4 serial ports, but only the
first two interfaces are MPSSE-capable. C232HD cable only exposes
IF/1 (ADBUS).
.. [#if2] FT232H_ does not support a secondary MPSSE port, only FT2232H_,
FT4232H_ and FT4232HA_ do. Note that FT4232H_/FT4232HA_ has 4 serial
ports, but only the first two interfaces are MPSSE-capable. C232HD
cable only exposes IF/1 (ADBUS).
.. [#rck] In order to support I2C clock stretch mode, ADBUS7 should be
connected to SCK. When clock stretching mode is not selected, ADBUS7
may be used as GPIO7.
3 changes: 2 additions & 1 deletion pyftdi/doc/urlscheme.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ where:
``0x6015``
* Supported product aliases:

* ``232``, ``232r``, ``232h``, ``2232d``, ``2232h``, ``4232h``, ``230x``
* ``232``, ``232r``, ``232h``, ``2232d``, ``2232h``, ``4232h``, ``4232ha``,
``230x``
* ``ft`` prefix for all aliases is also accepted, as for example ``ft232h``

* ``serial``: the serial number as a string. This is the preferred method to
Expand Down
13 changes: 7 additions & 6 deletions pyftdi/eeprom.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2019-2022, Emmanuel Blot <emmanuel.blot@free.fr>
# Copyright (c) 2019-2023, Emmanuel Blot <emmanuel.blot@free.fr>
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
Expand Down Expand Up @@ -70,6 +70,7 @@ class FtdiEeprom:
0x0800: _PROPS(256, 0x1A, 0x9A, 0x18), # FT4232H
0x0900: _PROPS(256, 0x1A, 0xA0, 0x1e), # FT232H
0x1000: _PROPS(1024, 0x1A, 0xA0, None), # FT230X/FT231X/FT234X
0x3600: _PROPS(256, 0x1A, 0x9A, 0x18), # FT4232HA
}
"""EEPROM properties."""

Expand Down Expand Up @@ -634,7 +635,7 @@ def commit(self, dry_run: bool = True, no_crc: bool = False) -> bool:
the EEPROM content
:param no_crc: do not compute EEPROM CRC. This should only be used
to perform a full erasure of the EEPROM, as an attempt to recover
from a corrupted config.
from a corrupted config.
:return: True if some changes have been committed to the EEPROM
"""
Expand Down Expand Up @@ -778,7 +779,7 @@ def _update_crc(self):
crc_s1_start = self.mirror_sector - crc_size
self._eeprom[crc_s1_start:crc_s1_start+crc_size] = spack('<H', crc)

def _compute_size(self,
def _compute_size(self,
eeprom: Union[bytes, bytearray]) -> Tuple[int, bool]:
"""
:return: Tuple of:
Expand Down Expand Up @@ -937,7 +938,7 @@ def _set_bus_control(self, bus: str, control: str,
def _set_group(self, group: int, control: str,
value: Union[str, int, bool], out: Optional[TextIO]) \
-> None:
if self.device_version in (0x0700, 0x0800, 0x0900):
if self.device_version in (0x0700, 0x0800, 0x0900, 0x3600):
self._set_group_x232h(group, control, value, out)
return
raise ValueError('Group not implemented for this device')
Expand All @@ -951,7 +952,7 @@ def _set_bus_control_230x(self, bus: str, control: str,

def _set_group_x232h(self, group: int, control: str, value: str,
out: Optional[TextIO]) -> None:
if self.device_version in (0x0700, 0x800): # 2232H/4232H
if self.device_version in (0x0700, 0x800, 0x3600): # 2232H/4232H/4232HA
offset = 0x0c + group//2
nibble = group & 1
else: # 232H
Expand Down Expand Up @@ -1121,7 +1122,7 @@ def _decode_4232h(self):
cfg['channel_%x_rs485' % (0xa+chix)] = bool(conf & (rs485 << chix))

def _decode_x232h(self, cfg):
# common code for 2232h and 4232h
# common code for 2232h, 4232h, 4232ha
cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01]
cfg['channel_a_driver'] = 'VCP' if (cfg0 & (1 << 3)) else 'D2XX'
cfg['channel_b_driver'] = 'VCP' if (cfg1 & (1 << 3)) else 'D2XX'
Expand Down

0 comments on commit f73f6ea

Please sign in to comment.