.. 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).

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.
