moved a bunch of garbage (things that have nothing to do in root) to _trash

This commit is contained in:
mia 2025-06-15 22:42:02 +02:00
parent d094982b2c
commit 3226ed29ec
2610 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,69 @@
.. include:: ../defs.rst
:mod:`eeprom` - EEPROM API
--------------------------
.. module :: pyftdi.eeprom
Quickstart
~~~~~~~~~~
Example: dump the EEPROM content
.. code-block:: python
# Instantiate an EEPROM manager
eeprom = FtdiEeprom()
# Select the FTDI device to access (the interface is mandatory but any
# valid interface for the device fits)
eeprom.open('ftdi://ftdi:2232h/1')
# Show the EEPROM content
eeprom.dump_config()
# Show the raw EEPROM content
from pyftdi.misc import hexdump
print(hexdump(eeprom.data))
Example: update the serial number
.. code-block:: python
# Instantiate an EEPROM manager
eeprom = FtdiEeprom()
# Select the FTDI device to access
eeprom.open('ftdi://ftdi:2232h/1')
# Change the serial number
eeprom.set_serial_number('123456')
# Commit the change to the EEPROM
eeprom.commit(dry_run=False)
Classes
~~~~~~~
.. autoclass :: FtdiEeprom
:members:
Exceptions
~~~~~~~~~~
.. autoexception :: FtdiEepromError
Tests
~~~~~
.. code-block:: shell
# optional: specify an alternative FTDI device
export FTDI_DEVICE=ftdi://ftdi:2232h/1
PYTHONPATH=. python3 pyftdi/tests/eeprom.py

View file

@ -0,0 +1,26 @@
.. -*- coding: utf-8 -*-
.. include:: ../defs.rst
:mod:`ftdi` - FTDI low-level driver
-----------------------------------
.. module :: pyftdi.ftdi
This module implements access to the low level FTDI hardware. There are very
few reasons to use this module directly. Most of PyFtdi_ features are available
through the dedicated :doc:`APIs <index>`.
Classes
~~~~~~~
.. autoclass :: Ftdi
:members:
Exceptions
~~~~~~~~~~
.. autoexception :: FtdiError
.. autoexception :: FtdiMpsseError
.. autoexception :: FtdiFeatureError

View file

@ -0,0 +1,56 @@
.. -*- coding: utf-8 -*-
.. include:: ../defs.rst
:mod:`gpio` - GPIO API
----------------------
.. module :: pyftdi.gpio
Direct drive GPIO pins of FTDI device.
.. note::
This mode is mutually exclusive with advanced serial MPSSE features, such as
|I2C|, SPI, JTAG, ...
If you need to use GPIO pins and MPSSE interface on the same port, you need
to use the dedicated API. This shared mode is supported with the
:doc:`SPI API <spi>` and the :doc:`I2C API <i2c>`.
.. warning::
This API does not provide access to the special CBUS port of FT232R, FT232H,
FT230X and FT231X devices. See :ref:`cbus_gpio` for details.
Quickstart
~~~~~~~~~~
See ``tests/gpio.py`` example
Classes
~~~~~~~
.. autoclass :: GpioPort
.. autoclass :: GpioAsyncController
:members:
.. autoclass :: GpioSyncController
:members:
.. autoclass :: GpioMpsseController
:members:
Exceptions
~~~~~~~~~~
.. autoexception :: GpioException
Info about GPIO API
~~~~~~~~~~~~~~~~~~~
See :doc:`../gpio` for details

View file

@ -0,0 +1,191 @@
.. include:: ../defs.rst
:mod:`i2c` - |I2C| API
----------------------
.. module :: pyftdi.i2c
Quickstart
~~~~~~~~~~
Example: communication with an |I2C| GPIO expander
.. code-block:: python
# Instantiate an I2C controller
i2c = I2cController()
# Configure the first interface (IF/1) of the FTDI device as an I2C master
i2c.configure('ftdi://ftdi:2232h/1')
# Get a port to an I2C slave device
slave = i2c.get_port(0x21)
# Send one byte, then receive one byte
slave.exchange([0x04], 1)
# Write a register to the I2C slave
slave.write_to(0x06, b'\x00')
# Read a register from the I2C slave
slave.read_from(0x00, 1)
Example: mastering the |I2C| bus with a complex transaction
.. code-block:: python
from time import sleep
port = I2cController().get_port(0x56)
# emit a START sequence is read address, but read no data and keep the bus
# busy
port.read(0, relax=False)
# wait for ~1ms
sleep(0.001)
# write 4 bytes, without neither emitting the start or stop sequence
port.write(b'\x00\x01', relax=False, start=False)
# read 4 bytes, without emitting the start sequence, and release the bus
port.read(4, start=False)
See also pyi2cflash_ module and ``tests/i2c.py``, which provide more detailed
examples on how to use the |I2C| API.
Classes
~~~~~~~
.. autoclass :: I2cPort
:members:
.. autoclass :: I2cGpioPort
:members:
.. autoclass :: I2cController
:members:
Exceptions
~~~~~~~~~~
.. autoexception :: I2cIOError
.. autoexception :: I2cNackError
.. autoexception:: I2cTimeoutError
GPIOs
~~~~~
See :doc:`../gpio` for details
Tests
~~~~~
|I2C| sample tests expect:
* TCA9555 device on slave address 0x21
* ADXL345 device on slave address 0x53
Checkout a fresh copy from PyFtdi_ github repository.
See :doc:`../pinout` for FTDI wiring.
.. code-block:: shell
# optional: specify an alternative FTDI device
export FTDI_DEVICE=ftdi://ftdi:2232h/1
# optional: increase log level
export FTDI_LOGLEVEL=DEBUG
# be sure to connect the appropriate I2C slaves to the FTDI I2C bus and run
PYTHONPATH=. python3 pyftdi/tests/i2c.py
.. _i2c_limitations:
Caveats
~~~~~~~
Open-collector bus
``````````````````
|I2C| uses only two bidirectional open collector (or open drain) lines, pulled
up with resistors. These resistors are also required on an |I2C| bus when an
FTDI master is used.
However, most FTDI devices do not use open collector outputs. Some software
tricks are used to fake open collector mode when possible, for example to
sample for slave ACK/NACK, but most communication (R/W, addressing, data)
cannot use open collector mode. This means that most FTDI devices source
current to the SCL and SDA lines. FTDI HW is able to cope with conflicting
signalling, where FTDI HW forces a line the high logical level while a slave
forces it to the low logical level, and limits the sourced current. You may
want to check your schematics if the slave is not able to handle 4 .. 16 mA
input current in SCL and SDA, for example. The maximal source current depends
on the FTDI device and the attached EEPROM configuration which may be used to
limit further down the sourced current.
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, FT4232H and FT4232HA do not support open
collector mode, and source current to SCL and SDA lines.
Clock streching
```````````````
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, 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
`````
Due to the FTDI MPSSE engine limitations, the actual bitrate for write
operations over I2C is very slow. As the I2C protocol enforces that each I2C
exchanged byte needs to be acknowledged by the peer, a I2C byte cannot be
written to the slave before the previous byte has been acknowledged by the
slave and read back by the I2C master, that is the host. This requires several
USB transfer for each byte, on top of each latency of the USB stack may add up.
With the introduction of PyFtdi_ v0.51, read operations have been optimized so
that long read operations are now much faster thanwith previous PyFtdi_
versions, and exhibits far shorter latencies.
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.
.. _i2c_wiring:
Wiring
~~~~~~
.. figure:: ../images/i2c_wiring.png
:scale: 50 %
:alt: I2C wiring
:align: right
Fig.1: FT2232H with clock stretching
* ``AD0`` should be connected to the SCL bus
* ``AD1`` and ``AD2`` should be both connected to the SDA bus
* ``AD7`` should be connected to the SCL bus, if clock streching is required
* remaining pins can be freely used as regular GPIOs.
*Fig.1*:
* ``D1`` is only required when clock streching is used along with
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.

View file

@ -0,0 +1,20 @@
API documentation
=================
.. include:: ../defs.rst
|release|
---------
.. toctree::
:maxdepth: 1
:glob:
ftdi
gpio
i2c
spi
uart
usbtools
misc
eeprom

View file

@ -0,0 +1,11 @@
.. -*- coding: utf-8 -*-
:mod:`misc` - Miscellaneous helpers
-----------------------------------
Functions
~~~~~~~~~
.. automodule:: pyftdi.misc
:members:

View file

@ -0,0 +1,203 @@
.. include:: ../defs.rst
:mod:`spi` - SPI API
--------------------
.. module :: pyftdi.spi
Quickstart
~~~~~~~~~~
Example: communication with a SPI data flash (half-duplex example)
.. code-block:: python
# Instantiate a SPI controller
spi = SpiController()
# Configure the first interface (IF/1) of the FTDI device as a SPI master
spi.configure('ftdi://ftdi:2232h/1')
# Get a port to a SPI slave w/ /CS on A*BUS3 and SPI mode 0 @ 12MHz
slave = spi.get_port(cs=0, freq=12E6, mode=0)
# Request the JEDEC ID from the SPI slave
jedec_id = slave.exchange([0x9f], 3)
Example: communication with a remote SPI device using full-duplex mode
.. code-block:: python
# Instantiate a SPI controller
# We need want to use A*BUS4 for /CS, so at least 2 /CS lines should be
# reserved for SPI, the remaining IO are available as GPIOs.
spi = SpiController(cs_count=2)
# Configure the first interface (IF/1) of the FTDI device as a SPI master
spi.configure('ftdi://ftdi:2232h/1')
# Get a port to a SPI slave w/ /CS on A*BUS4 and SPI mode 2 @ 10MHz
slave = spi.get_port(cs=1, freq=10E6, mode=2)
# Synchronous exchange with the remote SPI slave
write_buf = b'\x01\x02\x03'
read_buf = slave.exchange(write_buf, duplex=True)
Example: communication with a SPI device and an extra GPIO
.. code-block:: python
# Instantiate a SPI controller
spi = SpiController()
# Configure the first interface (IF/1) of the first FTDI device as a
# SPI master
spi.configure('ftdi://::/1')
# Get a SPI port to a SPI slave w/ /CS on A*BUS3 and SPI mode 0 @ 12MHz
slave = spi.get_port(cs=0, freq=12E6, mode=0)
# Get GPIO port to manage extra pins, use A*BUS4 as GPO, A*BUS4 as GPI
gpio = spi.get_gpio()
gpio.set_direction(0x30, 0x10)
# Assert GPO pin
gpio.write(0x10)
# Write to SPI slace
slave.write(b'hello world!')
# Release GPO pin
gpio.write(0x00)
# Test GPI pin
pin = bool(gpio.read() & 0x20)
Example: managing non-byte aligned transfers
.. code-block:: python
# Instantiate a SPI controller
spi = SpiController()
# Configure the first interface (IF/1) of the first FTDI device as a
# SPI master
spi.configure('ftdi://::/1')
# Get a SPI port to a SPI slave w/ /CS on A*BUS3
slave = spi.get_port(cs=0)
# write 6 first bits of a byte buffer
slave.write(b'\xff', droptail=2)
# read only 13 bits from a slave (13 clock cycles)
# only the 5 MSBs of the last byte are valid, 3 LSBs are force to zero
slave.read(2, droptail=3)
See also pyspiflash_ module and ``tests/spi.py``, which provide more detailed
examples on how to use the SPI API.
Classes
~~~~~~~
.. autoclass :: SpiPort
:members:
.. autoclass :: SpiGpioPort
:members:
.. autoclass :: SpiController
:members:
Exceptions
~~~~~~~~~~
.. autoexception :: SpiIOError
GPIOs
~~~~~
See :doc:`../gpio` for details
Tests
~~~~~
SPI sample tests expect:
* MX25L1606E device on /CS 0, SPI mode 0
* ADXL345 device on /CS 1, SPI mode 2
* RFDA2125 device on /CS 2, SPI mode 0
Checkout a fresh copy from PyFtdi_ github repository.
See :doc:`../pinout` for FTDI wiring.
.. code-block:: shell
# optional: specify an alternative FTDI device
export FTDI_DEVICE=ftdi://ftdi:2232h/1
# optional: increase log level
export FTDI_LOGLEVEL=DEBUG
# be sure to connect the appropriate SPI slaves to the FTDI SPI bus and run
PYTHONPATH=. python3 pyftdi/tests/spi.py
.. _spi_limitations:
Limitations
~~~~~~~~~~~
SPI Modes 1 & 3
```````````````
FTDI hardware does not support cpha=1 (mode 1 and mode 3). As stated in
Application Node 114:
"*It is recommended that designers review the SPI Slave
data sheet to determine the SPI mode implementation. FTDI device can only
support mode 0 and mode 2 due to the limitation of MPSSE engine.*".
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, 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
consequence of this workaround is that SCLK duty cycle is not longer 50% but
25% (mode 1) or 75% (mode 3). Again, support for mode 1 and mode 3 should be
considered as a kludge, you've been warned.
Time-sensitive usage
````````````````````
Due to the MPSSE engine limitation, it is not possible to achieve
time-controlled request sequence. In other words, if the SPI slave needs to
receive command sequences at precise instants - for example ADC or DAC
devices - PyFtdi_ use is not recommended. This limitation is likely to apply
to any library that relies on FTDI device. The USB bus latency and the lack
of timestamped commands always add jitter and delays, with no easy known
workaround.
.. _spi_wiring:
Wiring
~~~~~~
.. figure:: ../images/spi_wiring.png
:scale: 50 %
:alt: SPI wiring
:align: right
Fig.1: FT2232H with two SPI slaves
* ``AD0`` should be connected to SCLK
* ``AD1`` should be connected to MOSI
* ``AD2`` should be connected to MISO
* ``AD3`` should be connected to the first slave /CS.
* ``AD4`` should be connected to the second slave /CS, if any
* remaining pins can be freely used as regular GPIOs.
*Fig.1*:
* ``AD4`` may be used as a regular GPIO if a single SPI slave is used
* ``AD5`` may be used as another /CS signal for a third slave, in this case
the first available GPIO is ``AD6``, etc.

View file

@ -0,0 +1,228 @@
.. include:: ../defs.rst
:mod:`serialext` - UART API
---------------------------
There is no dedicated module for the UART API, as PyFtdi_ acts as a backend of
the well-known pyserial_ module.
The pyserial_ backend module is implemented as the `serialext.protocol_ftdi`
module. It is not documented here as no direct call to this module is required,
as the UART client should use the regular pyserial_ API.
Usage
~~~~~
To enable PyFtdi_ as a pyserial_ backend, use the following import:
.. code-block:: python
import pyftdi.serialext
Then use
.. code-block:: python
pyftdi.serialext.serial_for_url(url, **options)
to open a pyserial_ serial port instance.
Quickstart
~~~~~~~~~~
.. code-block:: python
# Enable pyserial extensions
import pyftdi.serialext
# Open a serial port on the second FTDI device interface (IF/2) @ 3Mbaud
port = pyftdi.serialext.serial_for_url('ftdi://ftdi:2232h/2', baudrate=3000000)
# Send bytes
port.write(b'Hello World')
# Receive bytes
data = port.read(1024)
.. _uart_gpio:
GPIO access
~~~~~~~~~~~
UART mode, the primary function of FTDI \*232\* devices, is somewhat limited
when it comes to GPIO management, as opposed to alternative mode such as |I2C|,
SPI and JTAG. It is not possible to assign the unused pins of an UART mode to
arbitrary GPIO functions.
All the 8 lower pins of an UART port are dedicated to the UART function,
although most of them are seldomely used, as dedicated to manage a modem or a
legacy DCE_ device. Upper pins (b\ :sub:`7`\ ..b\ :sub:`15`\ ), on devices that
have ones, cannot be driven while UART port is enabled.
It is nevertheless possible to have limited access to the lower pins as GPIO,
with many limitations:
- the GPIO direction of each pin is hardcoded and cannot be changed
- GPIO pins cannot be addressed atomically: it is possible to read the state
of an input GPIO, or to change the state of an output GPIO, one after
another. This means than obtaining the state of several input GPIOs or
changing the state of several output GPIO at once is not possible.
- some pins cannot be used as GPIO is hardware flow control is enabled.
Keep in mind However that HW flow control with FTDI is not reliable, see the
:ref:`hardware_flow_control` section.
Accessing those GPIO pins is done through the UART extended pins, using their
UART assigned name, as PySerial port attributes. See the table below:
+---------------+------+-----------+-------------------------------+
| Bit | UART | Direction | API |
+===============+======+===========+===============================+
| b\ :sub:`0`\ | TX | Out | ``port.write(buffer)`` |
+---------------+------+-----------+-------------------------------+
| b\ :sub:`1`\ | RX | In | ``buffer = port.read(count)`` |
+---------------+------+-----------+-------------------------------+
| b\ :sub:`2`\ | RTS | Out | ``port.rts = state`` |
+---------------+------+-----------+-------------------------------+
| b\ :sub:`3`\ | CTS | In | ``state = port.cts`` |
+---------------+------+-----------+-------------------------------+
| b\ :sub:`4`\ | DTR | Out | ``port.dtr = state`` |
+---------------+------+-----------+-------------------------------+
| b\ :sub:`5`\ | DSR | In | ``state = port.dsr`` |
+---------------+------+-----------+-------------------------------+
| b\ :sub:`6`\ | DCD | In | ``state = port.dcd`` |
+---------------+------+-----------+-------------------------------+
| b\ :sub:`7`\ | RI | In | ``state = port.ri`` |
+---------------+------+-----------+-------------------------------+
CBUS support
````````````
Some FTDI devices (FT232R, FT232H, FT230X, FT231X) support additional CBUS
pins, which can be used as regular GPIOs pins. See :ref:`CBUS GPIO<cbus_gpio>`
for details.
.. _pyterm:
Mini serial terminal
~~~~~~~~~~~~~~~~~~~~
``pyterm.py`` is a simple serial terminal that can be used to test the serial
port feature. See the :ref:`tools` chapter to locate this tool.
::
Usage: pyterm.py [-h] [-f] [-b BAUDRATE] [-w] [-e] [-r] [-l] [-s] [-P VIDPID]
[-V VIRTUAL] [-v] [-d]
[device]
Simple Python serial terminal
positional arguments:
device serial port device name (default: ftdi:///1)
optional arguments:
-h, --help show this help message and exit
-f, --fullmode use full terminal mode, exit with [Ctrl]+B
-b BAUDRATE, --baudrate BAUDRATE
serial port baudrate (default: 115200)
-w, --hwflow hardware flow control
-e, --localecho local echo mode (print all typed chars)
-r, --crlf prefix LF with CR char, use twice to replace all LF
with CR chars
-l, --loopback loopback mode (send back all received chars)
-s, --silent silent mode
-P VIDPID, --vidpid VIDPID
specify a custom VID:PID device ID, may be repeated
-V VIRTUAL, --virtual VIRTUAL
use a virtual device, specified as YaML
-v, --verbose increase verbosity
-d, --debug enable debug mode
If the PyFtdi module is not yet installed and ``pyterm.py`` is run from the
archive directory, ``PYTHONPATH`` should be defined to the current directory::
PYTHONPATH=$PWD pyftdi/bin/pyterm.py ftdi:///?
The above command lists all the available FTDI device ports. To avoid conflicts
with some shells such as `zsh`, escape the `?` char as ``ftdi:///\?``.
To start up a serial terminal session, specify the FTDI port to use, for
example:
.. code-block:: shell
# detect all FTDI connected devices
PYTHONPATH=. python3 pyftdi/bin/ftdi_urls.py
# use the first interface of the first FT2232H as a serial port
PYTHONPATH=$PWD pyftdi/bin/pyterm.py ftdi://ftdi:2232/1
.. _uart-limitations:
Limitations
~~~~~~~~~~~
Although the FTDI H series are in theory capable of 12 MBps baudrate, baudrates
above 6 Mbps are barely usable.
See the following table for details.
+------------+-------------+------------+-------------+------------+--------+
| Requ. bps |HW capability| 9-bit time | Real bps | Duty cycle | Stable |
+============+=============+============+=============+============+========+
| 115.2 Kbps | 115.2 Kbps | 78.08 µs | 115.26 Kbps | 49.9% | Yes |
+------------+-------------+------------+-------------+------------+--------+
| 460.8 Kbps | 461.54 Kbps | 19.49 µs | 461.77 Kbps | 49.9% | Yes |
+------------+-------------+------------+-------------+------------+--------+
| 1 Mbps | 1 Mbps | 8.98 µs | 1.002 Mbps | 49.5% | Yes |
+------------+-------------+------------+-------------+------------+--------+
| 4 Mbps | 4 Mbps | 2.24 µs | 4.018 Mbps | 48% | Yes |
+------------+-------------+------------+-------------+------------+--------+
| 5 Mbps | 5.052 Mbps | 1.78 µs | 5.056 Mbps | 50% | Yes |
+------------+-------------+------------+-------------+------------+--------+
| 6 Mbps | 6 Mbps | 1.49 µs | 6.040 Mbps | 48.5% | Yes |
+------------+-------------+------------+-------------+------------+--------+
| 7 Mbps | 6.857 Mbps | 1.11 µs | 8.108 Mbps | 44% | No |
+------------+-------------+------------+-------------+------------+--------+
| 8 Mbps | 8 Mbps | 1.11 µs | 8.108 Mbps | 44%-48% | No |
+------------+-------------+------------+-------------+------------+--------+
| 8.8 Mbps | 8.727 Mbps | 1.13 µs | 7.964 Mbps | 44% | No |
+------------+-------------+------------+-------------+------------+--------+
| 9.6 Mbps | 9.6 Mbps | 1.12 µs | 8.036 Mbps | 48% | No |
+------------+-------------+------------+-------------+------------+--------+
| 10.5 Mbps | 10.667 Mbps | 1.11 µs | 8.108 Mbps | 44% | No |
+------------+-------------+------------+-------------+------------+--------+
| 12 Mbps | 12 Mbps | 0.75 µs | 12 Mbps | 43% | Yes |
+------------+-------------+------------+-------------+------------+--------+
* 9-bit time is the measured time @ FTDI output pins for a 8-bit character
(start bit + 8 bit data)
* Duty cycle is the ratio between a low-bit duration and a high-bit duration,
a good UART should exhibit the same duration for low bits and high bits,
*i.e.* a duty cycle close to 50%.
* Stability reports whether subsequent runs, with the very same HW settings,
produce the same timings.
Achieving a reliable connection over 6 Mbps has proven difficult, if not
impossible: Any baudrate greater than 6 Mbps (except the upper 12 Mbps limit)
results into an actual baudrate of about 8 Mbps, and suffer from clock
fluterring [7.95 .. 8.1Mbps].
.. _hardware_flow_control:
Hardware flow control
`````````````````````
Moreover, as the hardware flow control of the FTDI device is not a true HW
flow control. Quoting FTDI application note:
*If CTS# is logic 1 it is indicating the external device cannot accept more
data. the FTxxx will stop transmitting within 0~3 characters, depending on
what is in the buffer.*
**This potential 3 character overrun does occasionally present problems.**
*Customers shoud be made aware the FTxxx is a USB device and not a "normal"
RS232 device as seen on a PC. As such the device operates on a packet
basis as opposed to a byte basis.*

View file

@ -0,0 +1,19 @@
.. -*- coding: utf-8 -*-
:mod:`usbtools` - USB tools
---------------------------
.. module :: pyftdi.usbtools
Classes
~~~~~~~
.. autoclass :: UsbTools
:members:
Exceptions
~~~~~~~~~~
.. autoexception :: UsbToolsError

View file

@ -0,0 +1,55 @@
Authors
-------
Main developers
~~~~~~~~~~~~~~~
* Emmanuel Blot <emmanuel.blot@free.fr>
* Emmanuel Bouaziz <ebouaziz@free.fr>
Contributors
~~~~~~~~~~~~
* Nikus-V
* Dave McCoy
* Adam Feuer
* endlesscoil
* humm (Fabien Benureau)
* dlharmon
* DavidWC
* Sebastian
* Anders (anders-code)
* Andrea Concil
* Darren Garnier
* Michael Leonard
* nopeppermint (Stefan)
* hannesweisbach
* Vianney le Clément de Saint-Marcq
* Pete Schwamb
* Will Richey
* sgoadhouse
* tavip (Octavian Purdila)
* Tim Legrand
* vestom
* meierphil
* etherfi
* sgoadhouse
* jnmacd
* naushir
* markmelvin (Mark Melvin)
* stiebrs
* mpratt14
* alexforencich
* TedKus
* Amanita-muscaria
* len0rd
* Rod Whitby
* Kornel Swierzy
* Taisuke Yamada
* Michael Niewöhner
* Kalofin
* Henry Au-Yeung
* Roman Dobrodii
* Mark Mentovai
* Alessandro Zini
* Sjoerd Simons

View file

@ -0,0 +1,49 @@
.. |I2C| replace:: I\ :sup:`2`\ C
.. _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: 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: 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: 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
.. _DCE: https://en.wikipedia.org/wiki/Data_circuit-terminating_equipment
.. _PEP_498: https://www.python.org/dev/peps/pep-0498
.. _PEP_526: https://www.python.org/dev/peps/pep-0526
.. _ruamel.yaml: https://pypi.org/project/ruamel.yaml
.. Restructured Text levels
.. Level 1
.. -------
.. Level 2
.. ~~~~~~~
.. Level 3
.. ```````
.. Level 4
.. .......
.. Level 5
.. +++++++

View file

@ -0,0 +1,401 @@
.. include:: defs.rst
EEPROM management
-----------------
.. warning::
Writing to the EEPROM can cause very **undesired** effects if the wrong
value is written in the wrong place. You can even essentially **brick** your
FTDI device. Use this function only with **extreme** caution.
It is not recommended to use this application with devices that use an
internal EEPROM such as FT232R or FT-X series, as if something goes wrong,
recovery options are indeed limited. FT232R internal EEPROM seems to be
unstable, even the official FT_PROG_ tool from FTDI may fail to fix it on
some conditions.
If using a Hi-Speed Mini Module and you brick for FTDI device, see
FTDI_Recovery_
Supported features
~~~~~~~~~~~~~~~~~~
EEPROM support is under active development.
Some features may be wrongly decoded, as each FTDI model implements a different
feature map, and more test/validation are required.
The :doc:`EEPROM API <api/eeprom>` implements the upper API to access the
EEPROM content.
.. _ftconf:
EEPROM configuration tool
~~~~~~~~~~~~~~~~~~~~~~~~~
``ftconf.py`` is a companion script to help managing the content of the FTDI
EEPROM from the command line. See the :ref:`tools` chapter to locate this tool.
::
usage: ftconf.py [-h] [-i INPUT] [-l {all,raw,values}] [-o OUTPUT] [-V VIRTUAL]
[-P VIDPID] [-M EEPROM] [-S {128,256,1024}] [-x] [-X HEXBLOCK]
[-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
-l {all,raw,values}, --load {all,raw,values}
section(s) to load from input file
-o OUTPUT, --output OUTPUT
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
-m MANUFACTURER, --manufacturer MANUFACTURER
set manufacturer name
-p PRODUCT, --product PRODUCT
set product name
-c CONFIG, --config CONFIG
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
**Again, please read the** :doc:`license` **terms before using the EEPROM API
or this script. You may brick your device if something goes wrong, and there
may be no way to recover your device.**
Note that to protect the EEPROM content of unexpected modification, it is
mandatory to specify the :ref:`-u <option_u>` flag along any alteration/change
of the EEPROM content. Without this flag, the script performs a dry-run
execution of the changes, *i.e.* all actions but the write request to the
EEPROM are executed.
Once updated, you need to unplug/plug back the device to use the new EEPROM
configuration.
It is recommended to first save the current content of the EEPROM, using the
:ref:`-o <option_o>` flag, to have a working copy of the EEPROM data before any
attempt to modify it. It can help restoring the EEPROM if something gets wrong
during a subsequence update, thanks to the :ref:`-i <option_i>` option switch.
Most FTDI device can run without an EEPROM. If something goes wrong, try to
erase the EEPROM content, then restore the original content.
Option switches
```````````````
In addition to the :ref:`common_option_switches` for PyFtdi_ tools,
``ftconf.py`` support the following arguments:
.. _option_c:
``-c name=value``
Change a configuration in the EEPROM. This flag can be repeated as many times
as required to change several configuration parameter at once. Note that
without option ``-u``, the EEPROM content is not actually modified, the
script runs in dry-run mode.
The name should be separated from the value with an equal ``=`` sign or
alternatively a full column ``:`` character.
* To obtain the list of supported name, use the `?` wildcard: ``-c ?``, or
`-c help` to avoid conflicts with some shells
* To obtain the list of supported values for a name, use the `?` or the `help`
wildcard:
``-c name=help``, where *name* is a supported name.
See :ref:`cbus_func` table for the alternate function associated with each
name.
.. _option_E_:
``-E``
Erase the full EEPROM content including the CRC. As the CRC no longer
validates the EEPROM content, the EEPROM configuration is ignored on the next
power cycle of the device, so the default FTDI configuration is used.
This may be useful to recover from a corrupted EEPROM, as when no EEPROM or a
blank EEPROM is detected, the FTDI falls back to a default configuration.
Note that without option :ref:`-u <option_u>`, the EEPROM content is not
actually modified, the script runs in dry-run mode.
.. _option_e:
``-e``
Erase the whole EEPROM and regenerates a valid CRC.
Beware that as `-e` option generates a valid CRC for the erased EEPROM
content, the FTDI device may identified itself as VID:PID FFFF:FFFF on next
reboot. You should likely use the `--vid` and `--pid` option to define a
valid FDTI device USB identifier with this option to ensure the device
identifies itself as a FTDI device on next power cycle.
Note that without option :ref:`-u <option_u>`, the EEPROM content is not
actually modified, the script runs in dry-run mode.
Alternatively, use `-E` option that erase the full EEPROM content including
the CRC.
.. _option_i:
``-i``
Load a INI file (as generated with the :ref:`-o <option_o>` option switch. It
is possible to select which section(s) from the INI file are loaded, using
:ref:`-l <option_l>` option switch. The ``values`` section may be modified,
as it takes precedence over the ``raw`` section. Note that without option
:ref:`-u <option_u>`, the EEPROM content is not actually modified, the script
runs in dry-run mode.
.. _option_l:
``-l <all|raw|values>``
Define which section(s) of the INI file are used to update the EEPROM content
along with the :ref:`-i <option_i>` option switch. Defaults to ``all``.
The supported feature set of the ``values`` is the same as the one exposed
through the :ref:`-c <option_c>` option switch. Unsupported feature are
ignored, and a warning is emitted for each unsupported feature.
.. _option_M_:
``-M <model>``
Specify the EEPROM model (93c46, 93c56, 93c66) that is connected to the FTDI
device. There is no reason to use this option except for recovery purposes,
see option `-E`. It is mutually exclusive with the `-S` option.
.. _option_m:
``-m <manufacturer>``
Assign a new manufacturer name to the device. Note that without option
:ref:`-u <option_u>`, the EEPROM content is not actually modified, the script
runs in dry-run mode. Manufacturer names with ``/`` or ``:`` characters are
rejected, to avoid parsing issues with FTDI :ref:`URLs <url_scheme>`.
.. _option_o:
``-o <output>``
Generate and write to the specified file the EEPROM content as decoded
values and a hexa dump. The special ``-`` file can be used as the output file
to print to the standard output. The output file contains two sections:
* ``[values]`` that contain the decoded EEPROM configuration as key, value
pair. Note that the keys and values can be used as configuration input, see
option :ref:`-c <option_c>`.
* ``[raw]`` that contains a compact representation of the EEPROM raw content,
encoded as hexadecimal strings.
.. _option_p:
``-p <product>``
Assign a new product name to the device. Note that without option :ref:`-u
<option_u>`, the EEPROM content is not actually modified, the script runs in
dry-run mode. Product names with ``/`` or ``:`` characters are rejected, to
avoid parsing issues with FTDI :ref:`URLs <url_scheme>`.
.. _option_pid:
``--pid``
Define the USB product identifier - as an hexadecimal number. This is a
shortcut for `-c product_id`
.. _option_S_:
``-S <size>``
Specify the EEPROM size -in bytes- that is connected to the FTDI device.
There is no reason to use this option except for recovery purposes,
see option `-E`. It is mutually exclusive with the `-M` option.
.. _option_s:
``-s <serial>``
Assign a new serial number to the device. Note that without option :ref:`-u
<option_u>`, the EEPROM content is not actually modified, the script runs in
dry-run mode. Serial number with ``/`` or ``:`` characters are rejected, to
avoid parsing issues with FTDI :ref:`URLs <url_scheme>`.
.. _option_u:
``-u``
Update the EEPROM with the new settings. Without this flag, the script runs
in dry-run mode, so no change is made to the EEPROM. Whenever this flag is
used, the EEPROM is actually updated and its checksum regenerated. If
something goes wrong at this point, you may brick you board, you've been
warned. PyFtdi_ offers neither guarantee whatsoever than altering the EEPROM
content is safe, nor that it is possible to recover from a bricked device.
.. _option_vid:
``--vid``
Define the USB vendor identifier - as an hexadecimal number. This is a
shortcut for `-c vendor_id`.
.. _option_x:
``-x``
Generate and print a hexadecimal raw dump of the EEPROM content, similar to
the output of the `hexdump -Cv` tool.
.. _cbus_func:
CBUS function
`````````````
The following table describes the CBUS pin alternate functions. Note that
depending on the actual device, some alternate function may not be available.
+-----------------+--------+--------------------------------------------------------------------------------+
| Name | Active | Description |
+=================+========+================================================================================+
| ``TRISTATE`` | Hi-Z | IO Pad is tri-stated |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``TXLED`` | Low | TX activity, can be used as status for LED |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``RXLED`` | Low | RX activity, can be used as status for LED |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``TXRXLED`` | Low | TX & RX activity, can be used as status for LED |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``PWREN`` | Low | USB configured, USB suspend: high |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``SLEEP`` | Low | USB suspend, typically used to power down external devices. |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``DRIVE0`` | Low | Drive a constant (FT232H and FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``DRIVE1`` | High | Drive a constant (FT232H and FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``GPIO`` | | IO port for CBUS bit bang mode |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``TXDEN`` | High | Enable transmit for RS485 mode |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``CLK48`` | | Output 48 MHz clock (FT232R only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``CLK30`` | | Output 30 MHz clock (FT232H only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``CLK24`` | | Output 24 MHz clock (FT232R and FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``CLK15`` | | Output 12 MHz clock (FT232H only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``CLK12`` | | Output 12 MHz clock (FT232R and FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``CLK7_5`` | | Output 7.5 MHz clock (FT232H only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``CLK6`` | | Output 6 MHz clock (FT232R and FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``BAT_DETECT`` | High | Battery Charger Detect (FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``BAT_NDETECT`` | Low | Inverse signal of BAT_DETECT (FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``I2C_TXE`` | Low | Transmit buffer empty (FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``I2C_RXF`` | Low | Receive buffer full (FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``VBUS_SENSE`` | High | Detect when VBUS is present via the appropriate AC IO pad (FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``BB_WR`` | Low | Synchronous Bit Bang Write strobe (FT232R and FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``BB_RD`` | Low | Synchronous Bit Bang Read strobe (FT232R and FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``TIMESTAMP`` | | Toggle signal each time a USB SOF is received (FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
| ``AWAKE`` | Low | Do not suspend when unplugged/disconnect/suspsend (FT-X only) |
+-----------------+--------+--------------------------------------------------------------------------------+
Examples
````````
* Change product name and serial number
::
pyftdi/bin/ftconf.py ftdi:///1 -p UartBridge -s abcd1234 -u
* List supported configuration parameters
::
pyftdi/bin/ftconf.py ftdi:///1 -c ?
cbus_func_0, cbus_func_1, cbus_func_2, cbus_func_3, cbus_func_4,
cbus_func_5, cbus_func_6, cbus_func_7, cbus_func_8, cbus_func_9,
channel_a_driver, channel_a_type, chip, clock_polarity,
flow_control, group_0_drive, group_0_schmitt, group_0_slew,
group_1_drive, group_1_schmitt, group_1_slew, has_serial,
has_usb_version, in_isochronous, lsb_data, out_isochronous,
power_max, powersave, product_id, remote_wakeup, self_powered,
suspend_pull_down, type, usb_version, vendor_id
* List supported configuration values for CBUS0
::
pyftdi/bin/ftconf.py ftdi:///1 -c cbus_func_0:?
AWAKE, BAT_DETECT, BAT_NDETECT, BB_RD, BB_WR, CLK12, CLK24, CLK6,
DRIVE0, DRIVE1, I2C_RXF, I2C_TXE, GPIO, PWREN, RXLED, SLEEP,
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.
::
pyftdi/bin/ftconf.py -P ffff:ffff ftdi://ffff:ffff/1 -E -u
* Recover from an erased EEPROM with a valid CRC
::
# for a FT4232 device
# note that ffff matches an erased EEPROM, other corrupted values may
# exist, such device can be identified with system tools such as lsusb
pyftdi/bin/ftconf.py -P ffff:ffff ftdi://ffff:ffff/1 -e -u \
--vid 0403 --pid 6011
.. _eeprom_cbus:
* Configure CBUS: 0 and 3 as GPIOs, then show the device configuration
::
pyftdi/bin/ftconf.py ftdi:///1 -v
-c cbus_func_0:GPIO -c cbus_func_3:GPIO

View file

@ -0,0 +1,98 @@
.. include:: defs.rst
Features
--------
Devices
~~~~~~~
* All FTDI device ports (UART, MPSSE) can be used simultaneously.
* SPI and |I2C| SPI support simultaneous GPIO R/W access for all pins that
are not used for SPI/|I2C| feature.
* Several FTDI adapters can be accessed simultaneously from the same Python
runtime instance.
Supported features
~~~~~~~~~~~~~~~~~~
UART
````
Serial port, up to 6 Mbps. PyFtdi_ includes a pyserial_ emulation layer that
offers transparent access to the FTDI serial ports through a pyserial_-
compliant API. The ``serialext`` directory contains a minimal serial terminal
demonstrating the use of this extension, and a dispatcher automatically
selecting the serial backend (pyserial_, PyFtdi_), based on the serial port
name.
See also :ref:`uart-limitations`.
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_/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
several common devices.
Both Half-duplex (write or read) and full-duplex (synchronous write and read)
communication modes are supported.
Experimental support for non-byte aligned access, where up to 7 trailing bits
can be discarded: no clock pulse is generated for those bits, so that SPI
transfer of non byte-sized can be performed.
See :ref:`spi_wiring` and :ref:`spi_limitations`.
Note: FTDI*232* devices cannot be used as an SPI slave.
|I2C| master
````````````
Supported devices: FT232H_, FT2232H_, FT4232H_, FT4232HA_
For now, only 7-bit addresses are supported.
GPIOs can be used while |I2C| mode is enabled.
The ``i2cscan.py`` script helps to discover which I2C devices are connected to
the FTDI I2C bus. See the :ref:`tools` chapter to locate this tool.
The pyi2cflash_ module demonstrates how to use the FTDI |I2C| master to access
serial EEPROMS.
See :ref:`i2c_wiring` and :ref:`i2c_limitations`.
Note: FTDI*232* devices cannot be used as an |I2C| slave.
JTAG
````
JTAG API is limited to low-level access. It is not intented to be used for
any flashing or debugging purpose, but may be used as a base to perform SoC
tests and boundary scans.
EEPROM
``````
The ``pyftdi/bin/ftconf.py`` script helps to manage the content of the FTDI
companion EEPROM.
Status
~~~~~~
This project is still in beta development stage. PyFtdi_ is developed as an
open-source solution.

View file

@ -0,0 +1,451 @@
.. include:: defs.rst
GPIOs
-----
Overview
~~~~~~~~
Many PyFtdi APIs give direct access to the IO pins of the FTDI devices:
* *GpioController*, implemented as ``GpioAsyncController``,
``GpioSyncController`` and ``GpioMpsseController`` (see :doc:`api/gpio`)
gives full access to the FTDI pins as raw I/O pins,
* ``SpiGpioPort`` (see :doc:`api/spi`) gives access to all free pins of an
FTDI interface, which are not reserved for the SPI feature,
* ``I2cGpioPort`` (see :doc:`api/i2c`) gives access to all free pins of an
FTDI interface, which are not reserved for the I2C feature
Other modes
```````````
* Gpio raw access is not yet supported with JTAG feature.
* It is not possible to use GPIO along with UART mode on the same interface.
However, UART mode still provides (very) limited access to GPIO pins, see
UART :ref:`uart_gpio` for details.
This document presents the common definitions for these APIs and explain how to
drive those pins.
Definitions
~~~~~~~~~~~
Interfaces
``````````
An FTDI *interface* follows the definition of a *USB interface*: it is an
independent hardware communication port with an FTDI device. Each interface can
be configured independently from the other interfaces on the same device, e.g.
one interface may be configured as an UART, the other one as |I2C| + GPIO.
It is possible to access two distinct interfaces of the same FTDI device
from a multithreaded application, and even from different applications, or
Python interpreters. However two applications cannot access the same interface
at the same time.
.. warning::
Performing a USB device reset affects all the interfaces of an FTDI device,
this is the rationale for not automatically performing a device reset when
an interface is initialiazed and configured from PyFtdi_.
.. _ftdi_ports:
Ports
`````
An FTDI port is ofter used in PyFtdi as a synonym for an interface. This may
differ from the FTDI datasheets that sometimes show an interface with several
ports (A\*BUS, B\*BUS). From a software standpoint, ports and interfaces are
equivalent: APIs access all the HW port from the same interface at once. From a
pure hardware standpoint, a single interface may be depicted as one or two
*ports*.
With PyFtdi_, *ports* and *interfaces* should be considered as synomyms.
Each port can be accessed as raw input/output pins. At a given time, a pin is
either configured as an input or an output function.
The width of a port, that is the number of pins of the interface, depending on
the actual hardware, *i.e.* the FTDI model:
* FT232R features a single port, which is 8-bit wide: `DBUS`,
* FT232H features a single port, which is 16-bit wide: `ADBUS/ACBUS`,
* FT2232D features two ports, which are 12-bit wide each: `ADBUS/ACBUS` and
`BDBUS/BCBUS`,
* FT2232H features two ports, which are 16-bit wide each: `ADBUS/ACBUS` and
`BDBUS/BCBUS`,
* 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
For historical reasons, 16-bit ports used to be named *wide* ports and 8-bit
ports used to be called *narrow* with PyFtdi_. This terminology and APIs are
no longer used, but are kept to prevent API break. Please only use the port
``width`` rather than these legacy port types.
GPIO value
``````````
* A logical ``0`` bit represents a low level value on a pin, that is *GND*
* A logical ``1`` bit represents a high level value on a pin, that is *Vdd*
which is typically 3.3 volts on most FTDIs
Please refers to the FTDI datasheet of your device for the tolerance and
supported analog levels for more details
.. hint::
FT232H supports a specific feature, which is dedicated to better supporting
the |I2C| feature. This specific devices enables an open-collector mode:
* Setting a pin to a low level drains it to *GND*
* Setting a pin to a high level sets the pin as High-Z
This feature is automatically activated when |I2C| feature is enabled on a
port, for the two first pins, i.e. `SCL` and `SDA out`.
However, PyFTDI does not yet provide an API to enable this mode to the
other pins of a port, *i.e.* for the pins used as GPIOs.
Direction
`````````
An FTDI pin should either be configured as an input or an ouput. It is
mandatory to (re)configure the direction of a pin before changing the way it is
used.
* A logical ``0`` bit represents an input pin, *i.e.* a pin whose value can be
sampled and read via the PyFTDI APIs
* A logical ``1`` bit represents an output pin, *i.e.* a pin whose value can be
set/written with the PyFTDI APIs
.. _cbus_gpio:
CBUS GPIOs
~~~~~~~~~~
FT232R, FT232H and FT230X/FT231X support an additional port denoted CBUS:
* FT232R provides an additional 5-bit wide port, where only 4 LSBs can be
used as programmable GPIOs: ``CBUS0`` to ``CBUS3``,
* FT232H provices an additional 10-bit wide port, where only 4 pins can be
used as programmable GPIOs: ``CBUS5``, ``CBUS6``, ``CBUS8``, ``CBUS9``
* FT230X/FT231X provides an additional 4-bit wide port: ``CBUS0`` to ``CBUS3``
Note that CBUS access is slower than regular asynchronous bitbang mode.
CBUS EEPROM configuration
`````````````````````````
Accessing this extra port requires a specific EEPROM configuration.
The EEPROM needs to be configured so that the CBUS pins that need to be used
as GPIOs are defined as ``GPIO``. Without this special configuration, CBUS
pins are used for other functions, such as driving leds when data is exchanged
over the UART port. Remember to power-cycle the FTDI device after changing its
EEPROM configuration to force load the new configuration.
The :ref:`ftconf` tool can be used to query and change the EEPROM
configuration. See the EEPROM configuration :ref:`example <eeprom_cbus>`.
CBUS GPIO API
`````````````
PyFtdi_ starting from v0.47 supports CBUS pins as special GPIO port. This port
is *not* mapped as regular GPIO, a dedicated API is reserved to drive those
pins:
* :py:meth:`pyftdi.ftdi.Ftdi.has_cbus` to report whether the device supports
CBUS gpios,
* :py:meth:`pyftdi.ftdi.Ftdi.set_cbus_direction` to configure the port,
* :py:meth:`pyftdi.ftdi.Ftdi.get_cbus_gpio` to get the logical values from the
port,
* :py:meth:`pyftdi.ftdi.Ftdi.set_cbus_gpio` to set new logical values to the
port
Additionally, the EEPROM configuration can be queried to retrieve which CBUS
pins have been assigned to GPIO functions:
* :py:meth:`pyftdi.eeprom.FtdiEeprom.cbus_pins` to report CBUS GPIO pins
The CBUS port is **not** available through the
:py:class:`pyftdi.gpio.GpioController` API, as it cannot be considered as a
regular GPIO port.
.. warning::
CBUS GPIO feature has only be tested with the virtual test framework and a
real FT231X HW device. It should be considered as an experimental feature
for now.
Configuration
~~~~~~~~~~~~~
GPIO bitmap
```````````
The GPIO pins of a port are always accessed as an integer, whose supported
width depends on the width of the port. These integers should be considered as
a bitmap of pins, and are always assigned the same mapping, whatever feature is
enabled:
* b\ :sub:`0`\ (``0x01``) represents the first pin of a port, *i.e.* AD0/BD0
* b\ :sub:`1`\ (``0x02``) represents the second pin of a port, *i.e.* AD1/BD1
* ...
* b\ :sub:`7`\ (``0x80``) represents the eighth pin of a port, *i.e.* AD7/BD7
* b\ :sub:`N`\ represents the highest pin of a port, *i.e.* AD7/BD7 for an
8-bit port, AD15/BD15 for a 16-bit port, etc.
Pins reserved for a specific feature (|I2C|, SPI, ...) cannot be accessed as
a regular GPIO. They cannot be arbitrarily written and should be masked out
when the GPIO output value is set. See :ref:`reserved_pins` for details.
FT232H CBUS exception
.....................
Note that there is an exception to this rule for FT232H CBUS port: FTDI has
decided to map non-contiguous CBUS pins as GPIO-capable CBUS pins, that is
``CBUS5``, ``CBUS6``, ``CBUS8``, ``CBUS9``, where other CBUS-enabled devices
use ``CBUS0``, ``CBUS1``, ``CBUS2``, ``CBUS3``.
If the CBUS GPIO feature is used with an FT232H device, the pin positions for
the GPIO port are not b\ :sub:`5`\ .. b\ :sub:`9`\ but b\ :sub:`0`\ to
b\ :sub:`3`\ . This may sounds weird, but CBUS feature is somewhat hack-ish
even with FTDI commands, so it did not deserve a special treatment for the sake
of handling the weird implementation of FT232H.
Direction bitmap
````````````````
Before using a port as GPIO, the port must be configured as GPIO. This is
achieved by either instanciating one of the *GpioController* or by requesting
the GPIO port from a specific serial bus controller:
``I2cController.get_gpio()`` and ``SpiController.get_gpio()``. All instances
provide a similar API (duck typing API) to configure, read and write to GPIO
pins.
Once a GPIO port is instanciated, the direction of each pin should be defined.
The direction can be changed at any time. It is not possible to write to /
read from a pin before the proper direction has been defined.
To configure the direction, use the `set_direction` API with a bitmap integer
value that defines the direction to use of each pin.
Direction example
.................
A 8-bit port, dedicated to GPIO, is configured as follows:
* BD0, BD3, BD7: input, `I` for short
* BD1-BD2, BD4-BD6: output, `O` for short
That is, MSB to LSB: *I O O O I O O I*.
This translates to 0b ``0111 0110`` as output is ``1`` and input is ``0``,
that is ``0x76`` as an hexa value. This is the direction value to use to
``configure()`` the port.
See also the ``set_direction()`` API to reconfigure the direction of GPIO pins
at any time. This method accepts two arguments. This first arguments,
``pins``, defines which pins - the ones with the maching bit set - to consider
in the second ``direction`` argument, so there is no need to
preserve/read-modify-copy the configuration of other pins. Pins with their
matching bit reset are not reconfigured, whatever their direction bit.
.. code-block:: python
gpio = GpioAsyncController()
gpio.configure('ftdi:///1', direction=0x76)
# later, reconfigure BD2 as input and BD7 as output
gpio.set_direction(0x84, 0x80)
Using GPIO APIs
~~~~~~~~~~~~~~~
There are 3 variant of *GpioController*, depending on which features are needed
and how the GPIO port usage is intended. :doc:`api/gpio` gives in depth details
about those controllers. Those controllers are mapped onto FTDI HW features.
* ``GpioAsyncController`` is likely the most useful API to drive GPIOs.
It enables reading current GPIO input pin levels and to change GPIO output
pin levels. When vector values (byte buffers) are used instead of scalar
value (single byte), GPIO pins are samples/updated at a regular pace, whose
frequency can be configured. It is however impossible to control the exact
time when input pins start to be sampled, which can be tricky to use with
most applications. See :doc:`api/gpio` for details.
* ``GpioSyncController`` is a variant of the previous API.
It is aimed at precise time control of sampling/updating the GPIO: a new
GPIO input sample is captured once every time GPIO output pins are updated.
With byte buffers, GPIO pins are samples/updated at a regular pace, whose
frequency can be configured as well. The API of ``GpioSyncController``
slightly differ from the other GPIO APIs, as the usual ``read``/``write``
method are replaced with a single ``exchange`` method.
Both ``GpioAsyncController`` and ``GpioSyncController`` are restricted to only
access the 8 LSB pins of a port, which means that FTDI device with wider port
(12- and 16- pins) cannot be fully addressed, as only b\ :sub:`0`\ to b\
:sub:`7`\ can be addressed.
* ``GpioMpsseController`` enables access to the MSB pins of wide ports.
However LSB and MSB pins cannot be addressed in a true atomic manner, which
means that there is a short delay between sampling/updating the LSB and MSB
part of the same wide port. Byte buffer can also be sampled/updated at a
regular pace, but the achievable frequency range may differ from the other
controllers.
It is recommened to read the ``tests/gpio.py`` files - available from GitHub -
to get some examples on how to use these API variants.
Setting GPIO pin state
``````````````````````
To write to a GPIO, use the `write()` method. The caller needs to mask out
the bits configured as input, or an exception is triggered:
* writing ``0`` to an input pin is ignored
* writing ``1`` to an input pin raises an exception
.. code-block:: python
gpio = GpioAsyncController()
gpio.configure('ftdi:///1', direction=0x76)
# all output set low
gpio.write(0x00)
# all output set high
gpio.write(0x76)
# all output set high, apply direction mask
gpio.write(0xFF & gpio.direction)
# all output forced to high, writing to input pins is illegal
gpio.write(0xFF) # raises an IOError
gpio.close()
Retrieving GPIO pin state
`````````````````````````
To read a GPIO, use the `read()` method.
.. code-block:: python
gpio = GpioAsyncController()
gpio.configure('ftdi:///1', direction=0x76)
# read whole port
pins = gpio.read()
# ignore output values (optional)
pins &= ~gpio.direction
gpio.close()
Modifying GPIO pin state
````````````````````````
A read-modify-write sequence is required.
.. code-block:: python
gpio = GpioAsyncController()
gpio.configure('ftdi:///1', direction=0x76)
# read whole port
pins = gpio.read()
# clearing out AD1 and AD2
pins &= ~((1 << 1) | (1 << 2)) # or 0x06
# want AD2=0, AD1=1
pins |= 1 << 1
# update GPIO output
gpio.write(pins)
gpio.close()
Synchronous GPIO access
```````````````````````
.. code-block:: python
gpio = GpioSyncController()
gpio.configure('ftdi:///1', direction=0x0F, frequency=1e6)
outs = bytes(range(16))
ins = gpio.exchange(outs)
# ins contains as many bytes as outs
gpio.close()
CBUS GPIO access
````````````````
.. code-block:: python
ftdi = Ftdi()
ftdi.open_from_url('ftdi:///1')
# validate CBUS feature with the current device
assert ftdi.has_cbus
# validate CBUS EEPROM configuration with the current device
eeprom = FtdiEeprom()
eeprom.connect(ftdi)
# here we use CBUS0 and CBUS3 (or CBUS5 and CBUS9 on FT232H)
assert eeprom.cbus_mask & 0b1001 == 0b1001
# configure CBUS0 as output and CBUS3 as input
ftdi.set_cbus_direction(0b1001, 0b0001)
# set CBUS0
ftdi.set_cbus_gpio(0x1)
# get CBUS3
cbus3 = ftdi.get_cbus_gpio() >> 3
.. code-block:: python
# it is possible to open the ftdi object from an existing serial connection:
port = serial_for_url('ftdi:///1')
ftdi = port.ftdi
ftdi.has_cbus
# etc...
.. _reserved_pins:
Reserved pins
~~~~~~~~~~~~~
GPIO pins vs. feature pins
``````````````````````````
It is important to note that the reserved pins do not change the pin
assignment, *i.e.* the lowest pins of a port may become unavailable as regular
GPIO when the feature is enabled:
Example
.......
|I2C| feature reserves
the three first pins, as *SCL*, *SDA output*, *SDA input* (w/o clock stretching
feature which also reserves another pin). This means that AD0, AD1 and AD2,
that is b\ :sub:`0`\ , b\ :sub:`1`\ , b\ :sub:`2`\ cannot be directly
accessed.
The first accessible GPIO pin in this case is no longer AD0 but AD3, which
means that b\ :sub:`3`\ becomes the lowest bit which can be read/written.
.. code-block:: python
# use I2C feature
i2c = I2cController()
# configure the I2C feature, and predefines the direction of the GPIO pins
i2c.configure('ftdi:///1', direction=0x78)
gpio = i2c.get_gpio()
# read whole port
pins = gpio.read()
# clearing out I2C bits (SCL, SDAo, SDAi)
pins &= 0x07
# set AD4
pins |= 1 << 4
# update GPIO output
gpio.write(pins)

View file

@ -0,0 +1,125 @@
PyFtdi
======
.. cannot use defs.rst here, as PyPi wants a standalone file.
.. |I2C| replace:: I\ :sup:`2`\ C
Documentation
-------------
The latest PyFtdi online documentation is always available from
`here <https://eblot.github.io/pyftdi>`_.
Beware the online version may be more recent than the PyPI hosted version, as
intermediate development versions are not published to
`PyPi <https://pypi.org/project/pyftdi>`_.
PyFtdi documentation can be locally build with Sphinx, see the installation
instructions.
Source code
-----------
PyFtdi releases are available from the Python Package Index from
`PyPi <https://pypi.org/project/pyftdi>`_.
PyFtdi development code is available from
`GitHub <https://github.com/eblot/pyftdi>`_.
Overview
--------
PyFtdi aims at providing a user-space driver for popular FTDI devices,
implemented in pure Python language.
Supported FTDI devices include:
* UART and GPIO bridges
* FT232R (single port, 3Mbps)
* FT230X/FT231X/FT234X (single port, 3Mbps)
* UART and multi-serial protocols (SPI, |I2C|, JTAG) bridges
* FT2232C/D (dual port, clock up to 6 MHz)
* 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
--------
PyFtdi currently supports the following features:
* UART/Serial USB converter, up to 12Mbps (depending on the FTDI device
capability)
* GPIO/Bitbang support, with 8-bit asynchronous, 8-bit synchronous and
8-/16-bit MPSSE variants
* SPI master, with simultanous GPIO support, up to 12 pins per port,
with support for non-byte sized transfer
* |I2C| master, with simultanous GPIO support, up to 14 pins per port
* Basic JTAG master capabilities
* EEPROM support (some parameters cannot yet be modified, only retrieved)
* Experimental CBUS support on selected devices, 4 pins per port
Supported host OSes
-------------------
* macOS
* Linux
* FreeBSD
* Windows, although not officially supported
.. EOT
Warning
-------
Starting with version *v0.40.0*, several API changes are being introduced.
While PyFtdi tries to maintain backward compatibility with previous versions,
some of these changes may require existing clients to update calls to PyFtdi.
Do not upgrade to *v0.40.0* or above without testing your client against the
new PyFtdi releases. PyFtdi versions up to *v0.39.9* keep a stable API
with *v0.22+* series.
See the *Major Changes* section on the online documentation for details about
potential API breaks.
Major changes
~~~~~~~~~~~~~
* *read* methods now return ``bytearray`` instead of `Array('B')` so that
pyserial ``readline()`` may be used. It also brings some performance
improvements.
* PyFtdi URLs now supports ``bus:address`` alternative specifiers, which
required to augment the ``open_*()`` methods with new, optional parameters.
* ``SpiController`` reserves only one slave line (*/CS*) where it used to
reserve 4 slave lines in previous releases. This frees more GPIOs when
default value is used - it is nevertheless still possible to reserve up to 5
slave lines.
* type hinting is used for most, if not all, public methods.
* simplified baudrate divider calculation.
PyFTDI in details
-----------------
.. toctree::
:maxdepth: 1
:glob:
features
requirements
installation
urlscheme
tools
api/index
pinout
gpio
eeprom
testing
troubleshooting
authors
license

View file

@ -0,0 +1,274 @@
.. include:: defs.rst
Installation
------------
Prerequisites
~~~~~~~~~~~~~
PyFTDI_ relies on PyUSB_, which requires a native dependency: libusb 1.x.
The actual command to install depends on your OS and/or your distribution,
see below
.. _install_linux:
Debian/Ubuntu Linux
```````````````````
.. code-block:: shell
apt-get install libusb-1.0
On Linux, you also need to create a `udev` configuration file to allow
user-space processes to access to the FTDI devices. There are many ways to
configure `udev`, here is a typical setup:
::
# /etc/udev/rules.d/11-ftdi.rules
# FT232AM/FT232BM/FT232R
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6001", GROUP="plugdev", MODE="0664"
# FT2232C/FT2232D/FT2232H
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6010", GROUP="plugdev", MODE="0664"
# FT4232/FT4232H
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6011", GROUP="plugdev", MODE="0664"
# FT232H
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**
You need to add a line for each device with a custom VID / PID pair you
declare, see :ref:`custom_vid_pid` for details.
You need to unplug / plug back the FTDI device once this file has been
created so that `udev` loads the rules for the matching device, or
alternatively, inform the ``udev`` daemon about the changes:
.. code-block:: shell
sudo udevadm control --reload-rules
sudo udevadm trigger
With this setup, be sure to add users that want to run PyFtdi_ to the
`plugdev` group, *e.g.*
.. code-block:: shell
sudo adduser $USER plugdev
Remember that you need to log out / log in to get the above command
effective, or start a subshell to try testing PyFtdi_:
.. code-block:: shell
newgrp plugdev
.. _install_macos:
Homebrew macOS
``````````````
.. code-block:: shell
brew install libusb
.. _install_windows:
Windows
```````
Windows is not officially supported (*i.e.* not tested) but some users have
reported successful installations. Windows requires a specific libusb backend
installation.
Zadig
.....
The probably easiest way to deal with libusb on Windows is to use Zadig_
1. Start up the Zadig utility
2. Select ``Options/List All Devices``, then select the FTDI devices you want
to communicate with. Its names depends on your hardware, *i.e.* the name
stored in the FTDI EEPROM.
* With FTDI devices with multiple channels, such as FT2232 (2 channels) and
FT4232 (4 channels), you **must** install the driver for the composite
parent, **not** for the individual interfaces. If you install the driver
for each interface, each interface will be presented as a unique FTDI
device and you may have difficulties to select a specific FTDI device port
once the installation is completed. To make the composite parents to appear
in the device list, uncheck the ``Options/Ignore Hubs or Composite Parents``
menu item.
* Be sure to select the parent device, *i.e.* the device name should not end
with *(Interface N)*, where *N* is the channel number.
* for example *Dual RS232-HS* represents the composite parent, while
*Dual RS232-HS (Interface 0)* represents a single channel of the FTDI
device. Always select the former.
3. Select ``libusb-win32`` (not ``WinUSB``) in the driver list.
4. Click on ``Replace Driver``
See also `Libusb on Windows`_
.. _install_python:
Python
~~~~~~
Python dependencies
```````````````````
Dependencies should be automatically installed with PIP.
* pyusb >= 1.0.0, != 1.2.0
* pyserial >= 3.0
Do *not* install PyUSB_ from GitHub development branch (``master``, ...).
Always prefer a stable, tagged release.
PyUSB 1.2.0 also broke the backward compatibility of the Device API, so it will
not work with PyFtdi.
Installing with PIP
```````````````````
PIP should automatically install the missing dependencies.
.. code-block:: shell
pip3 install pyftdi
.. _install_from_source:
Installing from source
``````````````````````
If you prefer to install from source, check out a fresh copy from PyFtdi_
github repository.
.. code-block:: shell
git clone https://github.com/eblot/pyftdi.git
cd pyftdi
# note: 'pip3' may simply be 'pip' on some hosts
pip3 install -r requirements.txt
python3 setup.py install
.. _generate_doc:
Generating the documentation
````````````````````````````
Follow :ref:`install_from_source` then:
.. code-block:: shell
pip3 install setuptools wheel sphinx sphinx_autodoc_typehints
# Shpinx Read the Doc theme seems to never get a release w/ fixed issues
pip3 install -U -e git+https://github.com/readthedocs/sphinx_rtd_theme.git@2b8717a3647cc650625c566259e00305f7fb60aa#egg=sphinx_rtd_theme
sphinx-build -b html pyftdi/doc .
The documentation may be accessed from the generated ``index.html`` entry file.
Post-installation sanity check
``````````````````````````````
Open a *shell*, or a *CMD* on Windows
.. code-block:: shell
python3 # or 'python' on Windows
from pyftdi.ftdi import Ftdi
Ftdi.show_devices()
should list all the FTDI devices available on your host.
Alternatively, you can invoke ``ftdi_urls.py`` script that lists all detected
FTDI devices. See the :doc:`tools` chapter for details.
* Example with 1 FT232H device with a serial number and 1 FT2232 device
with no serial number, connected to the host:
.. code-block::
Available interfaces:
ftdi://ftdi:232h:FT1PWZ0Q/1 (C232HD-DDHSP-0)
ftdi://ftdi:2232/1 (Dual RS232-HS)
ftdi://ftdi:2232/2 (Dual RS232-HS)
Note that FTDI devices with custom VID/PID are not listed with this simple
command, please refer to the PyFtdi_ API to add custom identifiers, *i.e.* see
:py:meth:`pyftdi.ftdi.Ftdi.add_custom_vendor` and
:py:meth:`pyftdi.ftdi.Ftdi.add_custom_product` APIs.
.. _custom_vid_pid:
Custom USB vendor and product IDs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PyFtdi only recognizes FTDI official vendor and product IDs.
If you have an FTDI device with an EEPROM with customized IDs, you need to tell
PyFtdi to support those custom USB identifiers.
Custom PID
``````````
To support a custom product ID (16-bit integer) with the official FTDI ID, add
the following code **before** any call to an FTDI ``open()`` method.
.. code-block:: python
from pyftdi.ftdi import Ftdi
Ftdi.add_custom_product(Ftdi.DEFAULT_VENDOR, product_id)
Custom VID
``````````
To support a custom vendor ID and product ID (16-bit integers), add the
following code **before** any call to an FTDI ``open()`` method.
.. code-block:: python
from pyftdi.ftdi import Ftdi
Ftdi.add_custom_vendor(vendor_id)
Ftdi.add_custom_product(vendor_id, product_id)
You may also specify an arbitrary string to each method if you want to specify
a URL by custom vendor and product names instead of their numerical values:
.. code-block:: python
from pyftdi.ftdi import Ftdi
Ftdi.add_custom_vendor(0x1234, 'myvendor')
Ftdi.add_custom_product(0x1234, 0x5678, 'myproduct')
f1 = Ftdi.create_from_url('ftdi://0x1234:0x5678/1')
f2 = Ftdi.create_from_url('ftdi://myvendor:myproduct/2')
.. note::
Remember that on OSes that require per-device access permissions such as
Linux, you also need to add the custom VID/PID entry to the configuration
file, see :ref:`Linux installation <install_linux>` ``udev`` rule file.

View file

@ -0,0 +1,44 @@
License
-------
.. include:: defs.rst
For historical reasons (PyFtdi has been initially developed as a compatibility
layer with libftdi_), the main ``ftdi.py`` file had originally been licensed
under the same license as the libftdi_ project, the GNU Lesser General Public
License LGPL v2 license. It does not share code from this project anymore, but
implements a similar API.
From my perspective, you may use it freely in open source or close source, free
or commercial projects as long as you comply with the BSD 3-clause license.
BSD 3-clause
~~~~~~~~~~~~
::
Copyright (c) 2008-2021 Emmanuel Blot <emmanuel.blot@free.fr>
All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL NEOTION BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,39 @@
.. include:: defs.rst
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
``ADBUS3`` ``BDBUS3`` GPIO3 CTS GPIO3 CS0 TMS Brown
``ADBUS4`` ``BDBUS4`` GPIO4 DTR GPIO4 CS1/GPIO4 Grey
``ADBUS5`` ``BDBUS5`` GPIO5 DSR GPIO5 CS2/GPIO5 Purple
``ADBUS6`` ``BDBUS6`` GPIO6 DCD GPIO6 CS3/GPIO6 White
``ADBUS7`` ``BDBUS7`` GPIO7 RI RSCK [#rck]_ CS4/GPIO7 RCLK Blue
``ACBUS0`` ``BCBUS0`` GPIO8 GPIO8
``ACBUS1`` ``BCBUS1`` GPIO9 GPIO9
``ACBUS2`` ``BCBUS2`` GPIO10 GPIO10
``ACBUS3`` ``BCBUS3`` GPIO11 GPIO11
``ACBUS4`` ``BCBUS4`` GPIO12 GPIO12
``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_,
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.

View file

@ -0,0 +1,54 @@
.. include:: defs.rst
Requirements
------------
Python_ 3.9 or above is required.
* PyFtdi *v0.55* is the last PyFtdi version to support Python 3.8.
* Python 3.7 has reached end-of-life on June 27rd, 2023.
* PyFtdi *v0.53* is the last PyFtdi version to support Python 3.6.
* Python 3.6 has reached end-of-life on December 23rd, 2021.
* PyFtdi *v0.52* is the last PyFtdi version to support Python 3.5.
* Python 3.5 has reached end-of-life on September 5th, 2020.
PyFtdi_ relies on PyUSB_, which itself depends on one of the following native
libraries:
* libusb_, currently tested with 1.0.23
PyFtdi_ does not depend on any other native library, and only uses standard
Python modules along with PyUSB_ and pyserial_.
PyFtdi_ is beeing tested with PyUSB_ 1.1.0.
Development
~~~~~~~~~~~
PyFtdi_ is developed on macOS platforms (64-bit kernel), and is validated on a
regular basis on Linux hosts.
As it contains no native code, it should work on any PyUSB_ and libusb_
supported platforms. However, M$ Windows is a seamless source of issues and is
not officially supported, although users have reported successful installation
with Windows 7 for example. Your mileage may vary.
API breaks
~~~~~~~~~~
Starting with version *v0.40.0*, several API changes are being introduced.
While PyFtdi tries to maintain backward compatibility with previous versions,
some of these changes may require existing clients to update calls to PyFtdi.
Do not upgrade to *v0.40.0* or above without testing your client against the
new PyFtdi releases. PyFtdi versions up to *v0.39.9* keep a stable API
with *v0.22+* series.
See the *Major Changes* section for details about potential API breaks.

View file

@ -0,0 +1,126 @@
Testing
-------
.. include:: defs.rst
Overview
~~~~~~~~
Testing PyFTDI is challenging because it relies on several pieces of hardware:
* one or more FTDI device
* |I2C|, SPI, JTAG bus slaves or communication equipment for UART
The ``tests`` directory contain several tests files, which are primarily aimed
at demonstrating usage of PyFTDI in common use cases.
Most unit tests are disabled, as they require specific slaves, with a dedicated
HW wiring. Reproducing such test environments can be challenging, as it
requires dedicated test benchs.
This is a growing concern as PyFTDI keeps evolving, and up to now, regression
tests were hard to run.
Hardware tests
~~~~~~~~~~~~~~
Please refer to the ``pyftdi/tests`` directory. There is one file dedicated to
each feature to test. Note that you need to read and edit these tests files to
fit your actual test environment, and enable the proper unit test cases, as
most are actually disabled by default.
You need specific bus slaves to perform most of these tests.
.. _virtual_framework:
Virtual test framework
~~~~~~~~~~~~~~~~~~~~~~
With PyFTDI v0.45, a new test module enables PyFTDI API partial testing using a
pure software environment with no hardware. This also eases automatic testing
within a continuous integration environment.
This new module implements a virtual USB backend for PyUSB, which creates some
kind of virtual, limited USB stack. The PyUSB can be told to substitute the
native platform's libusb with this module.
This module, ``usbvirt`` can be dynamically confifured with the help of YaML
definition files to create one or more virtual FTDI devices on a virtual USB
bus topology. This enables to test ``usbtools`` module to enumerate, detect,
report and access FTDI devices using the regular :doc:`urlscheme` syntax.
``usbvirt`` also routes all vendor-specific USB API calls to a secondary
``ftdivirt`` module, which is in charge of handling all FTDI USB requests.
This module enables testing PyFtdi_ APIs. It also re-uses the MPSSE tracker
engine to decode and verify MPSSE requests used to support |I2C|, SPI and UART
features.
For now, it is able to emulate most of GPIO requests (async, sync and MPSSE)
and UART input/output. It also manages the frequency and baudrate settings.
It is not able to emulate the MPSSE commands (with the exception of set and get
GPIO values), as it represents a massive workload...
Beware: WIP
```````````
This is an experimental work in progress, which is its early inception stage.
It has nevertheless already revealed a couple of bugs that had been hiding
within PyFtdi_ for years.
There is a large work effort ahead to be able to support more use cases and
tests more APIs, and many unit tests to write.
It cannot replace hardware tests with actual boards and slaves, but should
simplify test setup and help avoiding regression issues.
Usage
`````
No hardware is required to run these tests, to even a single FTDI device.
The test configuration files are described in YaML file format, therefore the
ruamel.yaml_ package is required.
.. code-block:: python
pip3 install ruamel.yaml
PYTHONPATH=. FTDI_LOGLEVEL=info pyftdi/tests/mockusb.py
Configuration
`````````````
The ``pyftdi/tests/resources`` directory contains definition files which are
loaded by the mock unit tests.
Although it is possible to create fine grained USB device definitions, the
configuration loader tries to automatically define missing parts to match the
USB device topology of FTDI devices.
This enables to create simple definition files without having to mess with low
level USB definitions whenever possible.
EEPROM content
..............
The :ref:`ftconf` tool can be used to load, modify and generate the content of
a virtual EEPROM, see :doc:`eeprom`.
Examples
........
* An example of a nearly comprehensive syntax can be found in ``ft232h.yaml``.
* Another, much more simple example with only mandatory settings can be found
in ``ft230x.yaml``.
* An example of multiple FTDI device definitions can be found in
``ftmany.yaml``
Availability
~~~~~~~~~~~~
Note that unit tests and the virtual infrastructure are not included in the
distributed Python packages, they are only available from the git repository.

View file

@ -0,0 +1,137 @@
.. include:: defs.rst
.. _tools:
Tools
-----
Overview
~~~~~~~~
PyFtdi_ comes with a couple of scripts designed to help using PyFtdi_ APIs,
and can be useful to quick start working with PyFtdi_.
Scripts
~~~~~~~
.. _ftdi_urls:
``ftdi_urls``
`````````````
This tiny script ``ftdi_urls.py`` to list the available, *i.e.* detected,
FTDI devices connected to the host, and the URLs than can be used to open a
:py:class:`pyftdi.ftdi.Ftdi` instance with the
:py:class:`pyftdi.ftdi.Ftdi.open_from_url` family and ``configure`` methods.
``ftconf``
``````````
``ftconf.py`` is a companion script to help managing the content of
the FTDI EEPROM from the command line. See the :ref:`ftconf` documentation.
.. _i2cscan:
``i2cscan``
```````````
The ``i2cscan.py`` script helps to discover which I2C devices
are connected to the FTDI I2C bus.
.. _pyterm.py:
``pyterm``
``````````
``pyterm.py`` is a simple serial terminal that can be used to test the serial
port feature, see the :ref:`pyterm` documentation.
Where to find these tools?
~~~~~~~~~~~~~~~~~~~~~~~~~~
These scripts can be downloaded from PyFtdiTools_, and are also installed along
with the PyFtdi_ module on the local host.
The location of the scripts depends on how PyFtdi_ has been installed and the
type of hosts:
* on linux and macOS, there are located in the ``bin/`` directory, that is the
directory where the Python interpreter is installed.
* on Windows, there are located in the ``Scripts/`` directory, which is a
subdirectory of the directory where the Python interpreter is installed.
.. _common_option_switches:
Common options switches
~~~~~~~~~~~~~~~~~~~~~~~
PyFtdi_ tools share many common option switches:
.. _option_d:
``-d``
Enable debug mode, which emits Python traceback on exceptions
.. _option_h:
``-h``
Show quick help and exit
.. _option_P_:
``-P <vidpid>``
Add custom vendor and product identifiers.
PyFtdi_ only recognizes FTDI official USB vendor identifier (*0x403*) and
the USB identifiers of their products.
In order to use alternative VID/PID values, the PyFtdi_ tools accept the
``-P`` option to describe those products
The ``vidpid`` argument should match the following format:
``[vendor_name=]<vendor_id>:[product_name=]<product_id>``
* ``vendor_name`` and ``product_name`` are optional strings, they may be
omitted as they only serve as human-readable aliases for the vendor and
product names. See example below.
* ``vendor_id`` and ``product_id`` are mandatory strings that should resolve
into 16-bit integers (USB VID and PID values). Integer values are always
interpreted as hexadecimal values, *e.g.* `-P 1234:6789` is parsed as
`-P 0x1234:0x6789`.
This option may be repeated as many times as required to add support for
several custom devices.
examples:
* ``0x403:0x9999``, *vid:pid* short syntax, with no alias names;
a matching FTDI :ref:`URL <url_scheme>` would be ``ftdi://ftdi:0x9999/1``
* ``mycompany=0x666:myproduct=0xcafe``, *vid:pid* complete syntax with
aliases; matching FTDI :ref:`URLs <url_scheme>` could be:
* ``ftdi://0x666:0x9999/1``
* ``ftdi://mycompany:myproduct/1``
* ``ftdi://mycompany:0x9999/1``
* ...
.. _option_v:
``-v``
Increase verbosity, useful for debugging the tool. It can be repeated to
increase more the verbosity.
.. _option_V_:
``-V <virtual>``
Load a virtual USB device configuration, to use a virtualized FTDI/EEPROM
environment. This is useful for PyFtdi_ development, and to test EEPROM
configuration with a virtual setup. This option is not useful for regular
usage. See :ref:`virtual_framework`.

View file

@ -0,0 +1,122 @@
.. include:: defs.rst
Troubleshooting
---------------
Reporting a bug
~~~~~~~~~~~~~~~
Please do not contact the author by email. The preferered method to report bugs
and/or enhancement requests is through
`GitHub <https://github.com/eblot/pyftdi/issues>`_.
Please be sure to read the next sections before reporting a new issue.
Logging
~~~~~~~
FTDI uses the `pyftdi` logger.
It emits log messages with raw payload bytes at DEBUG level, and data loss
at ERROR level.
Common error messages
~~~~~~~~~~~~~~~~~~~~~
"Error: No backend available"
`````````````````````````````
libusb native library cannot be loaded. Try helping the dynamic loader:
* On Linux: ``export LD_LIBRARY_PATH=<path>``
where ``<path>`` is the directory containing the ``libusb-1.*.so``
library file
* On macOS: ``export DYLD_LIBRARY_PATH=.../lib``
where ``<path>`` is the directory containing the ``libusb-1.*.dylib``
library file
* On Windows:
Try to copy the USB dll where the Python executable is installed, along
with the other Python DLLs.
If this happens while using an exe created by pyinstaller:
``copy C:\Windows\System32\libusb0.dll <path>``
where ``<path>`` is the directory containing the executable created
by pyinstaller. This assumes you have installed libusb (using a tool
like Zadig) as referenced in the installation guide for Windows.
"Error: Access denied (insufficient permissions)"
`````````````````````````````````````````````````
The system may already be using the device.
* On macOS: starting with 10.9 "*Mavericks*", macOS ships with a native FTDI
kernel extension that preempts access to the FTDI device.
Up to 10.13 "*High Sierra*", this driver can be unloaded this way:
.. code-block:: shell
sudo kextunload [-v] -bundle com.apple.driver.AppleUSBFTDI
You may want to use an alias or a tiny script such as
``pyftdi/bin/uphy.sh``
Please note that the system automatically reloads the driver, so it may be
useful to move the kernel extension so that the system never loads it.
.. warning::
From macOS 10.14 "*Mojave*", the Apple kernel extension peacefully
co-exists with libusb_ and PyFtdi_, so you no longer need - and **should
not attempt** - to unload the kernel extension. If you still experience
this error, please verify you have not installed another driver from FTDI,
such as FTDI's D2XX.
* On Linux: it may indicate a missing or invalid udev configuration. See
the :doc:`installation` section.
* This error message may also be triggered whenever the communication port is
already in use.
"Error: The device has no langid"
`````````````````````````````````
* On Linux, it usually comes from the same installation issue as the
``Access denied`` error: the current user is not granted the permissions to
access the FTDI device, therefore pyusb cannot read the FTDI registers. Check
out the :doc:`installation` section.
"Bus error / Access violation"
``````````````````````````````
PyFtdi does not use any native library, but relies on PyUSB_ and libusb_. The
latter uses native code that may trigger OS error. Some early development
versions of libusb_, for example 1.0.22-b…, have been reported to trigger
such issues. Please ensure you use a stable/final versions of libusb_ if you
experience this kind of fatal error.
"serial.serialutil.SerialException: Unable to open USB port"
````````````````````````````````````````````````````````````
May be caused by a conflict with the FTDI virtual COM port (VCOM). Try
uninstalling the driver. On macOS, refer to this `FTDI macOS guide`_.
Slow initialisation on OS X El Capitan
``````````````````````````````````````
It may take several seconds to open or enumerate FTDI devices.
If you run libusb <= v1.0.20, be sure to read the `Libusb issue on macOS`_
with OS X 10.11+.

View file

@ -0,0 +1,125 @@
.. include:: defs.rst
.. _url_scheme:
URL Scheme
----------
There are two ways to open a connection to an `Ftdi` object.
The recommended way to open a connection is to specify connection details
using a URL. The URL scheme is defined as:
::
ftdi://[vendor][:[product][:serial|:bus:address|:index]]/interface
where:
* vendor: the USB vendor ID of the manufacturer
* ex: ``ftdi`` or ``0x403``
* product: the USB product ID of the device
* ex: ``232h`` or ``0x6014``
* Supported product IDs: ``0x6001``, ``0x6010``, ``0x6011``, ``0x6014``,
``0x6015``
* Supported product aliases:
* ``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
uniquely identify a specific FTDI device. However, some FTDI device are not
fitted with an EEPROM, or the EEPROM is either corrupted or erased. In this
case, FTDI devices report no serial number
Examples:
* ``ftdi://ftdi:232h:FT0FMF6V/1``
* ``ftdi://:232h:FT0FMF6V/1``
* ``ftdi://::FT0FMF6V/1``
* ``bus:addess``: it is possible to select a FTDI device through a bus:address
pair, specified as *hexadecimal* integer values.
Examples:
* ``ftdi://ftdi:232h:10:22/1``
* ``ftdi://ftdi:232h:10:22/1``
* ``ftdi://::10:22/1``
Here, bus ``(0x)10`` = 16 (decimal) and address ``(0x)22`` = 34 (decimal)
* ``index``: an integer - not particularly useful, as it depends on the
enumeration order on the USB buses, and may vary from on session to another.
* ``interface``: the interface of FTDI device, starting from 1
* ``1`` for 230x and 232\* devices,
* ``1`` or ``2`` for 2232\* devices,
* ``1``, ``2``, ``3`` or ``4`` for 4232\* devices
All parameters but the interface are optional, PyFtdi tries to find the best
match. Therefore, if you have a single FTDI device connected to your system,
``ftdi:///1`` should be enough.
You can also ask PyFtdi to enumerate all the compatible devices with the
special ``ftdi:///?`` syntax. This syntax is useful to retrieve the available
FTDI URLs with serial number and/or bus:address selectors. To avoid conflicts
with some shells such as `zsh`, escape the `?` char as ``ftdi:///\?``.
There are several APIs available to enumerate/filter available FTDI device.
See :doc:`api/ftdi`.
Note that opening an FTDI connection with a URL ending with `?` is interpreted
as a query for matching FTDI devices and immediately stop. With this special
URL syntax, the avaialble devices are printed out to the standard output, and
the Python interpreter is forced to exit (`SystemExit` is raised).
When simple enumeration of the available FTDI devices is needed - so that
execution is not interrupted, two helper methods are available as
:py:meth:`pyftdi.ftdi.Ftdi.list_devices` and
:py:meth:`pyftdi.ftdi.Ftdi.show_devices` and accept the same URL syntax.
Opening a connection
~~~~~~~~~~~~~~~~~~~~
URL-based methods to open a connection
``````````````````````````````````````
.. code-block:: python
open_from_url()
open_mpsse_from_url()
open_bitbang_from_url()
Device-based methods to open a connection
`````````````````````````````````````````
You may also open an Ftdi device from an existing PyUSB_ device, with the help
of the ``open_from_device()`` helper method.
.. code-block:: python
open_from_device()
open_mpsse_from_device()
open_bitbang_from_device()
Legacy methods to open a connection
```````````````````````````````````
The old, deprecated method to open a connection is to use the ``open()``
methods without the ``_from_url`` suffix, which accept VID, PID, and serial
parameters (among others).
.. code-block:: python
open()
open_mpsse()
open_bitbang()
See the :ref:`ftdi_urls` tool to obtain the URLs for the connected FTDI
devices.