1 # SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
3 # SPDX-License-Identifier: MIT
4 """SPI Class for FTDI MPSSE"""
5 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.pin import Pin
6 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.url import (
12 # pylint: disable=protected-access
14 """Custom SPI Class for FTDI MPSSE"""
18 def __init__(self, spi_id=None):
19 # pylint: disable=import-outside-toplevel
20 from pyftdi.spi import SpiController
22 # pylint: enable=import-outside-toplevel
24 self._spi = SpiController(cs_count=1)
26 self._spi.configure(get_ft232h_url())
28 self._spi.configure(get_ftx232h_url(spi_id + 1))
29 self._port = self._spi.get_port(0)
30 self._port.set_frequency(100000)
33 # Change GPIO controller to SPI
34 Pin.mpsse_gpio = self._spi.get_gpio()
36 # pylint: disable=too-many-arguments,unused-argument
48 """Initialize the Port"""
49 self._port.set_frequency(baudrate)
50 # FTDI device can only support mode 0 and mode 2
51 # due to the limitation of MPSSE engine.
52 # This means CPHA must = 0
53 self._port._cpol = polarity
55 raise ValueError("Only SPI phase 0 is supported by FT232H.")
56 self._port._cpha = phase
58 # pylint: enable=too-many-arguments
62 """Return the current frequency"""
63 return self._port.frequency
65 def write(self, buf, start=0, end=None):
66 """Write data from the buffer to SPI"""
67 end = end if end else len(buf)
68 chunks, rest = divmod(end - start, self._spi.PAYLOAD_MAX_LENGTH)
69 for i in range(chunks):
70 chunk_start = start + i * self._spi.PAYLOAD_MAX_LENGTH
71 chunk_end = chunk_start + self._spi.PAYLOAD_MAX_LENGTH
72 self._port.write(buf[chunk_start:chunk_end])
74 rest_start = start + chunks * self._spi.PAYLOAD_MAX_LENGTH
75 self._port.write(buf[rest_start:end])
77 # pylint: disable=unused-argument
78 def readinto(self, buf, start=0, end=None, write_value=0):
79 """Read data from SPI and into the buffer"""
80 end = end if end else len(buf)
81 buffer_out = [write_value] * (end - start)
82 result = self._port.exchange(buffer_out, end - start, duplex=True)
83 for i, b in enumerate(result):
86 # pylint: enable=unused-argument
88 # pylint: disable=too-many-arguments
90 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
92 """Perform a half-duplex write from buffer_out and then
93 read data into buffer_in
95 out_end = out_end if out_end else len(buffer_out)
96 in_end = in_end if in_end else len(buffer_in)
97 result = self._port.exchange(
98 buffer_out[out_start:out_end], in_end - in_start, duplex=True
100 for i, b in enumerate(result):
101 buffer_in[in_start + i] = b
103 # pylint: enable=too-many-arguments