2 `busio` - Bus protocol support like I2C and SPI
3 =================================================
5 See `CircuitPython:busio` in CircuitPython for more details.
15 import adafruit_platformdetect.constants.boards as ap_board
16 import adafruit_platformdetect.constants.chips as ap_chip
17 from adafruit_blinka import Enum, Lockable, agnostic
18 from adafruit_blinka.agnostic import board_id, detector
20 # pylint: disable=import-outside-toplevel,too-many-branches,too-many-statements
21 # pylint: disable=too-many-arguments,too-many-function-args,too-many-return-statements
26 Busio I2C Class for CircuitPython Compatibility. Used
27 for both MicroPython and Linux.
30 def __init__(self, scl, sda, frequency=100000):
31 self.init(scl, sda, frequency)
33 def init(self, scl, sda, frequency):
36 if detector.board.ftdi_ft232h:
37 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.i2c import I2C as _I2C
39 self._i2c = _I2C(frequency=frequency)
41 if detector.board.binho_nova:
42 from adafruit_blinka.microcontroller.nova.i2c import I2C as _I2C
44 self._i2c = _I2C(frequency=frequency)
46 if detector.board.microchip_mcp2221:
47 from adafruit_blinka.microcontroller.mcp2221.i2c import I2C as _I2C
49 self._i2c = _I2C(frequency=frequency)
51 if detector.board.greatfet_one:
52 from adafruit_blinka.microcontroller.nxp_lpc4330.i2c import I2C as _I2C
54 self._i2c = _I2C(frequency=frequency)
56 if detector.board.pico_u2if:
57 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import I2C_Pico as _I2C
59 self._i2c = _I2C(scl, sda, frequency=frequency)
61 if detector.board.feather_u2if:
62 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
66 self._i2c = _I2C(scl, sda, frequency=frequency)
68 if detector.board.qtpy_u2if:
69 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import I2C_QTPY as _I2C
71 self._i2c = _I2C(scl, sda, frequency=frequency)
73 if detector.board.itsybitsy_u2if:
74 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
75 I2C_ItsyBitsy as _I2C,
78 self._i2c = _I2C(scl, sda, frequency=frequency)
80 if detector.board.qt2040_trinkey_u2if:
81 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
82 I2C_QT2040_Trinkey as _I2C,
85 self._i2c = _I2C(scl, sda, frequency=frequency)
87 if detector.chip.id == ap_chip.RP2040:
88 from adafruit_blinka.microcontroller.rp2040.i2c import I2C as _I2C
90 self._i2c = _I2C(scl, sda, frequency=frequency)
92 if detector.board.any_embedded_linux:
93 from adafruit_blinka.microcontroller.generic_linux.i2c import I2C as _I2C
94 elif detector.board.ftdi_ft2232h:
95 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.i2c import I2C as _I2C
97 from adafruit_blinka.microcontroller.generic_micropython.i2c import (
100 from microcontroller.pin import i2cPorts
102 for portId, portScl, portSda in i2cPorts:
104 # pylint: disable=unexpected-keyword-arg
105 if scl == portScl and sda == portSda:
106 self._i2c = _I2C(portId, mode=_I2C.MASTER, baudrate=frequency)
108 # pylint: enable=unexpected-keyword-arg
113 "No Hardware I2C on (scl,sda)={}\nValid I2C ports: {}".format(
117 if threading is not None:
118 self._lock = threading.RLock()
121 """Deinitialization"""
124 except AttributeError:
128 if threading is not None:
132 def __exit__(self, exc_type, exc_value, traceback):
133 if threading is not None:
138 """Scan for attached devices"""
139 return self._i2c.scan()
141 def readfrom_into(self, address, buffer, *, start=0, end=None):
142 """Read from a device at specified address into a buffer"""
143 if start != 0 or end is not None:
146 buffer = memoryview(buffer)[start:end]
147 stop = True # remove for efficiency later
148 return self._i2c.readfrom_into(address, buffer, stop=stop)
150 def writeto(self, address, buffer, *, start=0, end=None, stop=True):
151 """Write to a device at specified address from a buffer"""
152 if isinstance(buffer, str):
153 buffer = bytes([ord(x) for x in buffer])
154 if start != 0 or end is not None:
156 return self._i2c.writeto(address, memoryview(buffer)[start:], stop=stop)
157 return self._i2c.writeto(address, memoryview(buffer)[start:end], stop=stop)
158 return self._i2c.writeto(address, buffer, stop=stop)
160 def writeto_then_readfrom(
172 """ "Write to a device at specified address from a buffer then read
173 from a device at specified address into a buffer
175 return self._i2c.writeto_then_readfrom(
189 Busio SPI Class for CircuitPython Compatibility. Used
190 for both MicroPython and Linux.
193 def __init__(self, clock, MOSI=None, MISO=None):
195 if detector.board.ftdi_ft232h:
196 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
197 from adafruit_blinka.microcontroller.ftdi_mpsse.ft232h.pin import (
204 self._pins = (SCK, MOSI, MISO)
206 if detector.board.binho_nova:
207 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
208 from adafruit_blinka.microcontroller.nova.pin import SCK, MOSI, MISO
210 self._spi = _SPI(clock)
211 self._pins = (SCK, MOSI, MISO)
213 if detector.board.greatfet_one:
214 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
215 from adafruit_blinka.microcontroller.nxp_lpc4330.pin import SCK, MOSI, MISO
218 self._pins = (SCK, MOSI, MISO)
220 if detector.board.pico_u2if:
221 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
223 self._spi = _SPI(clock) # this is really all that's needed
224 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
226 if detector.board.feather_u2if:
227 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
231 self._spi = _SPI(clock) # this is really all that's needed
232 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
234 if detector.board.itsybitsy_u2if:
235 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
236 SPI_ItsyBitsy as _SPI,
239 self._spi = _SPI(clock) # this is really all that's needed
240 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
242 if detector.board.qtpy_u2if:
243 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI
245 self._spi = _SPI(clock) # this is really all that's needed
246 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
248 if detector.chip.id == ap_chip.RP2040:
249 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
251 self._spi = _SPI(clock, MOSI, MISO) # Pins configured on instantiation
252 self._pins = (clock, clock, clock) # These don't matter, they're discarded
254 if detector.board.any_embedded_linux:
255 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
256 elif detector.board.ftdi_ft2232h:
257 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
259 from adafruit_blinka.microcontroller.generic_micropython.spi import (
262 from microcontroller.pin import spiPorts
264 for portId, portSck, portMosi, portMiso in spiPorts:
267 and MOSI in (portMosi, None) # Clock is required!
268 and MISO in (portMiso, None) # But can do with just output
270 self._spi = _SPI(portId)
271 self._pins = (portSck, portMosi, portMiso)
275 "No Hardware SPI on (SCLK, MOSI, MISO)={}\nValid SPI ports:{}".format(
276 (clock, MOSI, MISO), spiPorts
280 def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
281 """Update the configuration"""
282 if detector.board.any_raspberry_pi or detector.board.any_raspberry_pi_40_pin:
283 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
284 elif detector.board.BEAGLEBONE_AI:
285 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
286 elif detector.board.any_beaglebone:
287 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
288 elif detector.board.any_orange_pi:
289 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
290 elif detector.board.any_nanopi and detector.chip.id == ap_chip.SUN8I:
291 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
292 elif board_id == ap_board.GIANT_BOARD:
293 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
294 elif board_id == ap_board.CORAL_EDGE_TPU_DEV:
295 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
296 elif board_id == ap_board.CORAL_EDGE_TPU_DEV_MINI:
297 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
298 elif board_id == ap_board.ODROID_C2:
299 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
300 elif board_id == ap_board.ODROID_C4:
301 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
302 elif board_id == ap_board.ODROID_XU4:
303 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
304 elif board_id == ap_board.DRAGONBOARD_410C:
305 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
306 elif board_id == ap_board.JETSON_NANO:
307 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
308 elif board_id == ap_board.JETSON_TX1:
309 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
310 elif board_id == ap_board.JETSON_TX2:
311 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
312 elif board_id == ap_board.JETSON_XAVIER:
313 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
314 elif board_id == ap_board.JETSON_NX:
315 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
316 elif detector.board.ROCK_PI_S:
317 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
318 elif detector.board.ROCK_PI_4:
319 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
320 elif detector.board.ROCK_PI_E:
321 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
322 elif detector.board.SIFIVE_UNLEASHED:
323 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
324 elif detector.board.ftdi_ft232h:
325 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
328 elif detector.board.ftdi_ft2232h:
329 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
332 elif detector.board.binho_nova:
333 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
334 elif detector.board.greatfet_one:
335 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
342 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
343 elif board_id == ap_board.PINEH64:
344 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
345 elif board_id == ap_board.CLOCKWORK_CPI3:
346 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
347 elif board_id == ap_board.ONION_OMEGA2:
348 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
349 elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
350 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
351 elif detector.board.pico_u2if:
352 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
353 elif detector.board.feather_u2if:
354 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
357 elif detector.board.itsybitsy_u2if:
358 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
359 SPI_ItsyBitsy as _SPI,
361 elif detector.board.qtpy_u2if:
362 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI
363 elif detector.chip.id == ap_chip.RP2040:
364 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
366 from adafruit_blinka.microcontroller.generic_micropython.spi import (
371 # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
380 raise RuntimeError("First call try_lock()")
383 """Deinitialization"""
389 """Return the baud rate if implemented"""
391 return self._spi.frequency
392 except AttributeError:
393 raise NotImplementedError(
394 "Frequency attribute not implemented for this platform"
395 ) from AttributeError
397 def write(self, buf, start=0, end=None):
398 """Write to the SPI device"""
399 return self._spi.write(buf, start, end)
401 def readinto(self, buf, start=0, end=None, write_value=0):
402 """Read from the SPI device into a buffer"""
403 return self._spi.readinto(buf, start, end, write_value=write_value)
406 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
408 """Write to the SPI device and read from the SPI device into a buffer"""
409 return self._spi.write_readinto(
410 buffer_out, buffer_in, out_start, out_end, in_start, in_end
414 class UART(Lockable):
416 Busio UART Class for CircuitPython Compatibility. Used
417 for MicroPython and a few other non-Linux boards.
421 """Parity Enumeration"""
423 pass # pylint: disable=unnecessary-pass
425 Parity.ODD = Parity()
426 Parity.EVEN = Parity()
437 receiver_buffer_size=64,
440 if detector.board.any_embedded_linux:
442 "busio.UART not supported on this platform. Please use pyserial instead."
444 if detector.board.binho_nova:
445 from adafruit_blinka.microcontroller.nova.uart import UART as _UART
446 elif detector.board.greatfet_one:
447 from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
448 elif detector.chip.id == ap_chip.RP2040:
449 from adafruit_blinka.microcontroller.rp2040.uart import UART as _UART
451 from machine import UART as _UART
453 from microcontroller.pin import uartPorts
455 self.baudrate = baudrate
457 if flow is not None: # default 0
458 raise NotImplementedError(
459 "Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
462 # translate parity flag for Micropython
463 if parity is UART.Parity.ODD:
465 elif parity is UART.Parity.EVEN:
470 raise ValueError("Invalid parity")
472 if detector.chip.id == ap_chip.RP2040:
482 # check tx and rx have hardware support
483 for portId, portTx, portRx in uartPorts: #
484 if portTx == tx and portRx == rx:
492 read_buf_len=receiver_buffer_size,
497 "No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
503 """Deinitialization"""
504 if detector.board.binho_nova:
508 def read(self, nbytes=None):
509 """Read from the UART"""
510 return self._uart.read(nbytes)
512 def readinto(self, buf, nbytes=None):
513 """Read from the UART into a buffer"""
514 return self._uart.readinto(buf, nbytes)
517 """Read a line of characters up to a newline charater from the UART"""
518 return self._uart.readline()
520 def write(self, buf):
521 """Write to the UART from a buffer"""
522 return self._uart.write(buf)
527 Stub class for OneWire, which is currently not implemented
530 def __init__(self, pin):
531 raise NotImplementedError("OneWire has not been implemented")
535 Deinitialize the OneWire bus and release any hardware resources for reuse.
537 raise NotImplementedError("OneWire has not been implemented")
541 Reset the OneWire bus and read presence
543 raise NotImplementedError("OneWire has not been implemented")
549 raise NotImplementedError("OneWire has not been implemented")
551 def write_bit(self, value):
553 Write out a bit based on value.
555 raise NotImplementedError("OneWire has not been implemented")