2 `busio` - Bus protocol support like I2C and SPI
3 =================================================
5 See `CircuitPython:busio` in CircuitPython for more details.
15 # pylint: disable=unused-import
16 import adafruit_platformdetect.constants.boards as ap_board
17 import adafruit_platformdetect.constants.chips as ap_chip
18 from adafruit_blinka import Enum, Lockable, agnostic
19 from adafruit_blinka.agnostic import board_id, detector
21 # pylint: disable=import-outside-toplevel,too-many-branches,too-many-statements
22 # pylint: disable=too-many-arguments,too-many-function-args,too-many-return-statements
27 Busio I2C Class for CircuitPython Compatibility. Used
28 for both MicroPython and Linux.
31 def __init__(self, scl, sda, frequency=100000):
32 self.init(scl, sda, frequency)
34 def init(self, scl, sda, frequency):
37 if detector.board.ftdi_ft232h:
38 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.i2c import I2C as _I2C
40 self._i2c = _I2C(frequency=frequency)
42 if detector.board.binho_nova:
43 from adafruit_blinka.microcontroller.nova.i2c import I2C as _I2C
45 self._i2c = _I2C(frequency=frequency)
47 if detector.board.microchip_mcp2221:
48 from adafruit_blinka.microcontroller.mcp2221.i2c import I2C as _I2C
50 self._i2c = _I2C(frequency=frequency)
52 if detector.board.greatfet_one:
53 from adafruit_blinka.microcontroller.nxp_lpc4330.i2c import I2C as _I2C
55 self._i2c = _I2C(frequency=frequency)
57 if detector.board.pico_u2if:
58 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import I2C_Pico as _I2C
60 self._i2c = _I2C(scl, sda, frequency=frequency)
62 if detector.board.feather_u2if:
63 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
67 self._i2c = _I2C(scl, sda, frequency=frequency)
69 if detector.board.qtpy_u2if:
70 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import I2C_QTPY as _I2C
72 self._i2c = _I2C(scl, sda, frequency=frequency)
74 if detector.board.itsybitsy_u2if:
75 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
76 I2C_ItsyBitsy as _I2C,
79 self._i2c = _I2C(scl, sda, frequency=frequency)
81 if detector.board.qt2040_trinkey_u2if:
82 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
83 I2C_QT2040_Trinkey as _I2C,
86 self._i2c = _I2C(scl, sda, frequency=frequency)
88 if detector.chip.id == ap_chip.RP2040:
89 from adafruit_blinka.microcontroller.rp2040.i2c import I2C as _I2C
91 self._i2c = _I2C(scl, sda, frequency=frequency)
93 if detector.board.any_embedded_linux:
94 from adafruit_blinka.microcontroller.generic_linux.i2c import I2C as _I2C
95 elif detector.board.ftdi_ft2232h:
96 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.i2c import I2C as _I2C
98 from adafruit_blinka.microcontroller.generic_micropython.i2c import (
101 from microcontroller.pin import i2cPorts
103 for portId, portScl, portSda in i2cPorts:
105 # pylint: disable=unexpected-keyword-arg
106 if scl == portScl and sda == portSda:
107 self._i2c = _I2C(portId, mode=_I2C.MASTER, baudrate=frequency)
109 # pylint: enable=unexpected-keyword-arg
114 "No Hardware I2C on (scl,sda)={}\nValid I2C ports: {}".format(
118 if threading is not None:
119 self._lock = threading.RLock()
122 """Deinitialization"""
125 except AttributeError:
129 if threading is not None:
133 def __exit__(self, exc_type, exc_value, traceback):
134 if threading is not None:
139 """Scan for attached devices"""
140 return self._i2c.scan()
142 def readfrom_into(self, address, buffer, *, start=0, end=None):
143 """Read from a device at specified address into a buffer"""
144 if start != 0 or end is not None:
147 buffer = memoryview(buffer)[start:end]
148 stop = True # remove for efficiency later
149 return self._i2c.readfrom_into(address, buffer, stop=stop)
151 def writeto(self, address, buffer, *, start=0, end=None, stop=True):
152 """Write to a device at specified address from a buffer"""
153 if isinstance(buffer, str):
154 buffer = bytes([ord(x) for x in buffer])
155 if start != 0 or end is not None:
157 return self._i2c.writeto(address, memoryview(buffer)[start:], stop=stop)
158 return self._i2c.writeto(address, memoryview(buffer)[start:end], stop=stop)
159 return self._i2c.writeto(address, buffer, stop=stop)
161 def writeto_then_readfrom(
173 """ "Write to a device at specified address from a buffer then read
174 from a device at specified address into a buffer
176 return self._i2c.writeto_then_readfrom(
190 Busio SPI Class for CircuitPython Compatibility. Used
191 for both MicroPython and Linux.
194 def __init__(self, clock, MOSI=None, MISO=None):
196 if detector.board.ftdi_ft232h:
197 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
198 from adafruit_blinka.microcontroller.ftdi_mpsse.ft232h.pin import (
205 self._pins = (SCK, MOSI, MISO)
207 if detector.board.binho_nova:
208 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
209 from adafruit_blinka.microcontroller.nova.pin import SCK, MOSI, MISO
211 self._spi = _SPI(clock)
212 self._pins = (SCK, MOSI, MISO)
214 if detector.board.greatfet_one:
215 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
216 from adafruit_blinka.microcontroller.nxp_lpc4330.pin import SCK, MOSI, MISO
219 self._pins = (SCK, MOSI, MISO)
221 if detector.board.pico_u2if:
222 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
224 self._spi = _SPI(clock) # this is really all that's needed
225 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
227 if detector.board.feather_u2if:
228 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
232 self._spi = _SPI(clock) # this is really all that's needed
233 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
235 if detector.board.itsybitsy_u2if:
236 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
237 SPI_ItsyBitsy as _SPI,
240 self._spi = _SPI(clock) # this is really all that's needed
241 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
243 if detector.board.qtpy_u2if:
244 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI
246 self._spi = _SPI(clock) # this is really all that's needed
247 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
249 if detector.chip.id == ap_chip.RP2040:
250 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
252 self._spi = _SPI(clock, MOSI, MISO) # Pins configured on instantiation
253 self._pins = (clock, clock, clock) # These don't matter, they're discarded
255 if detector.board.any_embedded_linux:
256 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
257 elif detector.board.ftdi_ft2232h:
258 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
260 from adafruit_blinka.microcontroller.generic_micropython.spi import (
263 from microcontroller.pin import spiPorts
265 for portId, portSck, portMosi, portMiso in spiPorts:
268 and MOSI in (portMosi, None) # Clock is required!
269 and MISO in (portMiso, None) # But can do with just output
271 self._spi = _SPI(portId)
272 self._pins = (portSck, portMosi, portMiso)
276 "No Hardware SPI on (SCLK, MOSI, MISO)={}\nValid SPI ports:{}".format(
277 (clock, MOSI, MISO), spiPorts
281 def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
282 """Update the configuration"""
283 if detector.board.any_nanopi and detector.chip.id == ap_chip.SUN8I:
284 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
285 elif detector.board.ftdi_ft232h:
286 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
289 elif detector.board.ftdi_ft2232h:
290 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
293 elif detector.board.binho_nova:
294 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
295 elif detector.board.greatfet_one:
296 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
297 elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
298 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
299 elif detector.board.pico_u2if:
300 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
301 elif detector.board.feather_u2if:
302 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
305 elif detector.board.itsybitsy_u2if:
306 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
307 SPI_ItsyBitsy as _SPI,
309 elif detector.board.qtpy_u2if:
310 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI
311 elif detector.chip.id == ap_chip.RP2040:
312 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
313 elif detector.board.any_embedded_linux:
314 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
316 from adafruit_blinka.microcontroller.generic_micropython.spi import (
321 # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
330 raise RuntimeError("First call try_lock()")
333 """Deinitialization"""
339 """Return the baud rate if implemented"""
341 return self._spi.frequency
342 except AttributeError as error:
343 raise NotImplementedError(
344 "Frequency attribute not implemented for this platform"
347 def write(self, buf, start=0, end=None):
348 """Write to the SPI device"""
349 return self._spi.write(buf, start, end)
351 def readinto(self, buf, start=0, end=None, write_value=0):
352 """Read from the SPI device into a buffer"""
353 return self._spi.readinto(buf, start, end, write_value=write_value)
356 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
358 """Write to the SPI device and read from the SPI device into a buffer"""
359 return self._spi.write_readinto(
360 buffer_out, buffer_in, out_start, out_end, in_start, in_end
364 class UART(Lockable):
366 Busio UART Class for CircuitPython Compatibility. Used
367 for MicroPython and a few other non-Linux boards.
371 """Parity Enumeration"""
373 pass # pylint: disable=unnecessary-pass
375 Parity.ODD = Parity()
376 Parity.EVEN = Parity()
387 receiver_buffer_size=64,
390 if detector.board.any_embedded_linux:
392 "busio.UART not supported on this platform. Please use pyserial instead."
394 if detector.board.binho_nova:
395 from adafruit_blinka.microcontroller.nova.uart import UART as _UART
396 elif detector.board.greatfet_one:
397 from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
398 elif detector.chip.id == ap_chip.RP2040:
399 from adafruit_blinka.microcontroller.rp2040.uart import UART as _UART
401 from machine import UART as _UART
403 from microcontroller.pin import uartPorts
405 self.baudrate = baudrate
407 if flow is not None: # default 0
408 raise NotImplementedError(
409 "Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
412 # translate parity flag for Micropython
413 if parity is UART.Parity.ODD:
415 elif parity is UART.Parity.EVEN:
420 raise ValueError("Invalid parity")
422 if detector.chip.id == ap_chip.RP2040:
432 # check tx and rx have hardware support
433 for portId, portTx, portRx in uartPorts: #
434 if portTx == tx and portRx == rx:
442 read_buf_len=receiver_buffer_size,
447 "No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
453 """Deinitialization"""
454 if detector.board.binho_nova:
458 def read(self, nbytes=None):
459 """Read from the UART"""
460 return self._uart.read(nbytes)
462 def readinto(self, buf, nbytes=None):
463 """Read from the UART into a buffer"""
464 return self._uart.readinto(buf, nbytes)
467 """Read a line of characters up to a newline charater from the UART"""
468 return self._uart.readline()
470 def write(self, buf):
471 """Write to the UART from a buffer"""
472 return self._uart.write(buf)
477 Stub class for OneWire, which is currently not implemented
480 def __init__(self, pin):
481 raise NotImplementedError("OneWire has not been implemented")
485 Deinitialize the OneWire bus and release any hardware resources for reuse.
487 raise NotImplementedError("OneWire has not been implemented")
491 Reset the OneWire bus and read presence
493 raise NotImplementedError("OneWire has not been implemented")
499 raise NotImplementedError("OneWire has not been implemented")
501 def write_bit(self, value):
503 Write out a bit based on value.
505 raise NotImplementedError("OneWire has not been implemented")