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,consider-using-with
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 I2C_Feather as _I2C
64 self._i2c = _I2C(scl, sda, frequency=frequency)
66 if detector.board.qt2040_trinkey_u2if:
67 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import I2C_QT2040_Trinkey as _I2C
69 self._i2c = _I2C(scl, sda, frequency=frequency)
71 if detector.chip.id == ap_chip.RP2040:
72 from adafruit_blinka.microcontroller.rp2040.i2c import I2C as _I2C
74 self._i2c = _I2C(scl, sda, frequency=frequency)
76 if detector.board.any_embedded_linux:
77 from adafruit_blinka.microcontroller.generic_linux.i2c import I2C as _I2C
78 elif detector.board.ftdi_ft2232h:
79 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.i2c import I2C as _I2C
81 from adafruit_blinka.microcontroller.generic_micropython.i2c import (
84 from microcontroller.pin import i2cPorts
86 for portId, portScl, portSda in i2cPorts:
88 # pylint: disable=unexpected-keyword-arg
89 if scl == portScl and sda == portSda:
90 self._i2c = _I2C(portId, mode=_I2C.MASTER, baudrate=frequency)
92 # pylint: enable=unexpected-keyword-arg
97 "No Hardware I2C on (scl,sda)={}\nValid I2C ports: {}".format(
101 if threading is not None:
102 self._lock = threading.RLock()
105 """Deinitialization"""
108 except AttributeError:
112 if threading is not None:
116 def __exit__(self, exc_type, exc_value, traceback):
117 if threading is not None:
122 """Scan for attached devices"""
123 return self._i2c.scan()
125 def readfrom_into(self, address, buffer, *, start=0, end=None):
126 """Read from a device at specified address into a buffer"""
127 if start != 0 or end is not None:
130 buffer = memoryview(buffer)[start:end]
131 stop = True # remove for efficiency later
132 return self._i2c.readfrom_into(address, buffer, stop=stop)
134 def writeto(self, address, buffer, *, start=0, end=None, stop=True):
135 """Write to a device at specified address from a buffer"""
136 if isinstance(buffer, str):
137 buffer = bytes([ord(x) for x in buffer])
138 if start != 0 or end is not None:
140 return self._i2c.writeto(address, memoryview(buffer)[start:], stop=stop)
141 return self._i2c.writeto(address, memoryview(buffer)[start:end], stop=stop)
142 return self._i2c.writeto(address, buffer, stop=stop)
144 def writeto_then_readfrom(
156 """ "Write to a device at specified address from a buffer then read
157 from a device at specified address into a buffer
159 return self._i2c.writeto_then_readfrom(
173 Busio SPI Class for CircuitPython Compatibility. Used
174 for both MicroPython and Linux.
177 def __init__(self, clock, MOSI=None, MISO=None):
179 if detector.board.ftdi_ft232h:
180 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
181 from adafruit_blinka.microcontroller.ftdi_mpsse.ft232h.pin import (
188 self._pins = (SCK, MOSI, MISO)
190 if detector.board.binho_nova:
191 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
192 from adafruit_blinka.microcontroller.nova.pin import SCK, MOSI, MISO
194 self._spi = _SPI(clock)
195 self._pins = (SCK, MOSI, MISO)
197 if detector.board.greatfet_one:
198 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
199 from adafruit_blinka.microcontroller.nxp_lpc4330.pin import SCK, MOSI, MISO
202 self._pins = (SCK, MOSI, MISO)
204 if detector.board.pico_u2if:
205 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
207 self._spi = _SPI(clock) # this is really all that's needed
208 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
210 if detector.board.feather_u2if:
211 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Feather as _SPI
213 self._spi = _SPI(clock) # this is really all that's needed
214 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
216 if detector.chip.id == ap_chip.RP2040:
217 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
219 self._spi = _SPI(clock, MOSI, MISO) # Pins configured on instantiation
220 self._pins = (clock, clock, clock) # These don't matter, they're discarded
222 if detector.board.any_embedded_linux:
223 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
224 elif detector.board.ftdi_ft2232h:
225 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
227 from adafruit_blinka.microcontroller.generic_micropython.spi import (
230 from microcontroller.pin import spiPorts
232 for portId, portSck, portMosi, portMiso in spiPorts:
235 and MOSI in (portMosi, None) # Clock is required!
236 and MISO in (portMiso, None) # But can do with just output
238 self._spi = _SPI(portId)
239 self._pins = (portSck, portMosi, portMiso)
243 "No Hardware SPI on (SCLK, MOSI, MISO)={}\nValid SPI ports:{}".format(
244 (clock, MOSI, MISO), spiPorts
248 def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
249 """Update the configuration"""
250 if detector.board.any_raspberry_pi or detector.board.any_raspberry_pi_40_pin:
251 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
252 elif detector.board.BEAGLEBONE_AI:
253 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
254 elif detector.board.any_beaglebone:
255 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
256 elif detector.board.any_orange_pi:
257 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
258 elif detector.board.any_nanopi and detector.chip.id == ap_chip.SUN8I:
259 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
260 elif board_id == ap_board.GIANT_BOARD:
261 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
262 elif board_id == ap_board.CORAL_EDGE_TPU_DEV:
263 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
264 elif board_id == ap_board.CORAL_EDGE_TPU_DEV_MINI:
265 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
266 elif board_id == ap_board.ODROID_C2:
267 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
268 elif board_id == ap_board.ODROID_C4:
269 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
270 elif board_id == ap_board.ODROID_XU4:
271 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
272 elif board_id == ap_board.DRAGONBOARD_410C:
273 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
274 elif board_id == ap_board.JETSON_NANO:
275 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
276 elif board_id == ap_board.JETSON_TX1:
277 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
278 elif board_id == ap_board.JETSON_TX2:
279 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
280 elif board_id == ap_board.JETSON_XAVIER:
281 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
282 elif board_id == ap_board.JETSON_NX:
283 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
284 elif detector.board.ROCK_PI_S:
285 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
286 elif detector.board.ROCK_PI_4:
287 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
288 elif detector.board.ROCK_PI_E:
289 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
290 elif detector.board.SIFIVE_UNLEASHED:
291 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
292 elif detector.board.ftdi_ft232h:
293 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
296 elif detector.board.ftdi_ft2232h:
297 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
300 elif detector.board.binho_nova:
301 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
302 elif detector.board.greatfet_one:
303 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
310 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
311 elif board_id == ap_board.PINEH64:
312 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
313 elif board_id == ap_board.CLOCKWORK_CPI3:
314 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
315 elif board_id == ap_board.ONION_OMEGA2:
316 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
317 elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
318 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
319 elif detector.board.pico_u2if:
320 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
321 elif detector.board.feather_u2if:
322 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Feather as _SPI
323 elif detector.chip.id == ap_chip.RP2040:
324 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
326 from adafruit_blinka.microcontroller.generic_micropython.spi import (
331 # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
340 raise RuntimeError("First call try_lock()")
343 """Deinitialization"""
349 """Return the baud rate if implemented"""
351 return self._spi.frequency
352 except AttributeError:
353 raise NotImplementedError(
354 "Frequency attribute not implemented for this platform"
355 ) from AttributeError
357 def write(self, buf, start=0, end=None):
358 """Write to the SPI device"""
359 return self._spi.write(buf, start, end)
361 def readinto(self, buf, start=0, end=None, write_value=0):
362 """Read from the SPI device into a buffer"""
363 return self._spi.readinto(buf, start, end, write_value=write_value)
366 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
368 """Write to the SPI device and read from the SPI device into a buffer"""
369 return self._spi.write_readinto(
370 buffer_out, buffer_in, out_start, out_end, in_start, in_end
374 class UART(Lockable):
376 Busio UART Class for CircuitPython Compatibility. Used
377 for MicroPython and a few other non-Linux boards.
381 """Parity Enumeration"""
383 pass # pylint: disable=unnecessary-pass
385 Parity.ODD = Parity()
386 Parity.EVEN = Parity()
397 receiver_buffer_size=64,
400 if detector.board.any_embedded_linux:
402 "busio.UART not supported on this platform. Please use pyserial instead."
404 if detector.board.binho_nova:
405 from adafruit_blinka.microcontroller.nova.uart import UART as _UART
406 elif detector.board.greatfet_one:
407 from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
408 elif detector.chip.id == ap_chip.RP2040:
409 from adafruit_blinka.microcontroller.rp2040.uart import UART as _UART
411 from machine import UART as _UART
413 from microcontroller.pin import uartPorts
415 self.baudrate = baudrate
417 if flow is not None: # default 0
418 raise NotImplementedError(
419 "Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
422 # translate parity flag for Micropython
423 if parity is UART.Parity.ODD:
425 elif parity is UART.Parity.EVEN:
430 raise ValueError("Invalid parity")
432 if detector.chip.id == ap_chip.RP2040:
442 # check tx and rx have hardware support
443 for portId, portTx, portRx in uartPorts: #
444 if portTx == tx and portRx == rx:
452 read_buf_len=receiver_buffer_size,
457 "No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
463 """Deinitialization"""
464 if detector.board.binho_nova:
468 def read(self, nbytes=None):
469 """Read from the UART"""
470 return self._uart.read(nbytes)
472 def readinto(self, buf, nbytes=None):
473 """Read from the UART into a buffer"""
474 return self._uart.readinto(buf, nbytes)
477 """Read a line of characters up to a newline charater from the UART"""
478 return self._uart.readline()
480 def write(self, buf):
481 """Write to the UART from a buffer"""
482 return self._uart.write(buf)
487 Stub class for OneWire, which is currently not implemented
490 def __init__(self, pin):
491 raise NotImplementedError("OneWire has not been implemented")
495 Deinitialize the OneWire bus and release any hardware resources for reuse.
497 raise NotImplementedError("OneWire has not been implemented")
501 Reset the OneWire bus and read presence
503 raise NotImplementedError("OneWire has not been implemented")
509 raise NotImplementedError("OneWire has not been implemented")
511 def write_bit(self, value):
513 Write out a bit based on value.
515 raise NotImplementedError("OneWire has not been implemented")