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.chip.id == ap_chip.RP2040:
67 from adafruit_blinka.microcontroller.rp2040.i2c import I2C as _I2C
69 self._i2c = _I2C(scl, sda, frequency=frequency)
71 if detector.board.any_embedded_linux:
72 from adafruit_blinka.microcontroller.generic_linux.i2c import I2C as _I2C
73 elif detector.board.ftdi_ft2232h:
74 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.i2c import I2C as _I2C
76 from adafruit_blinka.microcontroller.generic_micropython.i2c import (
79 from microcontroller.pin import i2cPorts
81 for portId, portScl, portSda in i2cPorts:
83 # pylint: disable=unexpected-keyword-arg
84 if scl == portScl and sda == portSda:
85 self._i2c = _I2C(portId, mode=_I2C.MASTER, baudrate=frequency)
87 # pylint: enable=unexpected-keyword-arg
92 "No Hardware I2C on (scl,sda)={}\nValid I2C ports: {}".format(
96 if threading is not None:
97 self._lock = threading.RLock()
100 """Deinitialization"""
103 except AttributeError:
107 if threading is not None:
111 def __exit__(self, exc_type, exc_value, traceback):
112 if threading is not None:
117 """Scan for attached devices"""
118 return self._i2c.scan()
120 def readfrom_into(self, address, buffer, *, start=0, end=None):
121 """Read from a device at specified address into a buffer"""
122 if start != 0 or end is not None:
125 buffer = memoryview(buffer)[start:end]
126 stop = True # remove for efficiency later
127 return self._i2c.readfrom_into(address, buffer, stop=stop)
129 def writeto(self, address, buffer, *, start=0, end=None, stop=True):
130 """Write to a device at specified address from a buffer"""
131 if isinstance(buffer, str):
132 buffer = bytes([ord(x) for x in buffer])
133 if start != 0 or end is not None:
135 return self._i2c.writeto(address, memoryview(buffer)[start:], stop=stop)
136 return self._i2c.writeto(address, memoryview(buffer)[start:end], stop=stop)
137 return self._i2c.writeto(address, buffer, stop=stop)
139 def writeto_then_readfrom(
151 """ "Write to a device at specified address from a buffer then read
152 from a device at specified address into a buffer
154 return self._i2c.writeto_then_readfrom(
168 Busio SPI Class for CircuitPython Compatibility. Used
169 for both MicroPython and Linux.
172 def __init__(self, clock, MOSI=None, MISO=None):
174 if detector.board.ftdi_ft232h:
175 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
176 from adafruit_blinka.microcontroller.ftdi_mpsse.ft232h.pin import (
183 self._pins = (SCK, MOSI, MISO)
185 if detector.board.binho_nova:
186 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
187 from adafruit_blinka.microcontroller.nova.pin import SCK, MOSI, MISO
189 self._spi = _SPI(clock)
190 self._pins = (SCK, MOSI, MISO)
192 if detector.board.greatfet_one:
193 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
194 from adafruit_blinka.microcontroller.nxp_lpc4330.pin import SCK, MOSI, MISO
197 self._pins = (SCK, MOSI, MISO)
199 if detector.board.pico_u2if:
200 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
202 self._spi = _SPI(clock) # this is really all that's needed
203 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
205 if detector.board.feather_u2if:
206 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Feather as _SPI
208 self._spi = _SPI(clock) # this is really all that's needed
209 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
211 if detector.chip.id == ap_chip.RP2040:
212 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
214 self._spi = _SPI(clock, MOSI, MISO) # Pins configured on instantiation
215 self._pins = (clock, clock, clock) # These don't matter, they're discarded
217 if detector.board.any_embedded_linux:
218 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
219 elif detector.board.ftdi_ft2232h:
220 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
222 from adafruit_blinka.microcontroller.generic_micropython.spi import (
225 from microcontroller.pin import spiPorts
227 for portId, portSck, portMosi, portMiso in spiPorts:
230 and MOSI in (portMosi, None) # Clock is required!
231 and MISO in (portMiso, None) # But can do with just output
233 self._spi = _SPI(portId)
234 self._pins = (portSck, portMosi, portMiso)
238 "No Hardware SPI on (SCLK, MOSI, MISO)={}\nValid SPI ports:{}".format(
239 (clock, MOSI, MISO), spiPorts
243 def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
244 """Update the configuration"""
245 if detector.board.any_raspberry_pi or detector.board.any_raspberry_pi_40_pin:
246 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
247 elif detector.board.BEAGLEBONE_AI:
248 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
249 elif detector.board.any_beaglebone:
250 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
251 elif detector.board.any_orange_pi:
252 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
253 elif detector.board.any_nanopi and detector.chip.id == ap_chip.SUN8I:
254 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
255 elif board_id == ap_board.GIANT_BOARD:
256 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
257 elif board_id == ap_board.CORAL_EDGE_TPU_DEV:
258 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
259 elif board_id == ap_board.CORAL_EDGE_TPU_DEV_MINI:
260 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
261 elif board_id == ap_board.ODROID_C2:
262 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
263 elif board_id == ap_board.ODROID_C4:
264 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
265 elif board_id == ap_board.ODROID_XU4:
266 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
267 elif board_id == ap_board.DRAGONBOARD_410C:
268 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
269 elif board_id == ap_board.JETSON_NANO:
270 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
271 elif board_id == ap_board.JETSON_TX1:
272 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
273 elif board_id == ap_board.JETSON_TX2:
274 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
275 elif board_id == ap_board.JETSON_XAVIER:
276 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
277 elif board_id == ap_board.JETSON_NX:
278 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
279 elif detector.board.ROCK_PI_S:
280 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
281 elif detector.board.ROCK_PI_4:
282 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
283 elif detector.board.ROCK_PI_E:
284 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
285 elif detector.board.SIFIVE_UNLEASHED:
286 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
287 elif detector.board.ftdi_ft232h:
288 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
291 elif detector.board.ftdi_ft2232h:
292 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
295 elif detector.board.binho_nova:
296 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
297 elif detector.board.greatfet_one:
298 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
305 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
306 elif board_id == ap_board.PINEH64:
307 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
308 elif board_id == ap_board.CLOCKWORK_CPI3:
309 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
310 elif board_id == ap_board.ONION_OMEGA2:
311 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
312 elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
313 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
314 elif detector.board.pico_u2if:
315 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
316 elif detector.board.feather_u2if:
317 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Feather as _SPI
318 elif detector.chip.id == ap_chip.RP2040:
319 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
321 from adafruit_blinka.microcontroller.generic_micropython.spi import (
326 # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
335 raise RuntimeError("First call try_lock()")
338 """Deinitialization"""
344 """Return the baud rate if implemented"""
346 return self._spi.frequency
347 except AttributeError:
348 raise NotImplementedError(
349 "Frequency attribute not implemented for this platform"
350 ) from AttributeError
352 def write(self, buf, start=0, end=None):
353 """Write to the SPI device"""
354 return self._spi.write(buf, start, end)
356 def readinto(self, buf, start=0, end=None, write_value=0):
357 """Read from the SPI device into a buffer"""
358 return self._spi.readinto(buf, start, end, write_value=write_value)
361 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
363 """Write to the SPI device and read from the SPI device into a buffer"""
364 return self._spi.write_readinto(
365 buffer_out, buffer_in, out_start, out_end, in_start, in_end
369 class UART(Lockable):
371 Busio UART Class for CircuitPython Compatibility. Used
372 for MicroPython and a few other non-Linux boards.
376 """Parity Enumeration"""
378 pass # pylint: disable=unnecessary-pass
380 Parity.ODD = Parity()
381 Parity.EVEN = Parity()
392 receiver_buffer_size=64,
395 if detector.board.any_embedded_linux:
397 "busio.UART not supported on this platform. Please use pyserial instead."
399 if detector.board.binho_nova:
400 from adafruit_blinka.microcontroller.nova.uart import UART as _UART
401 elif detector.board.greatfet_one:
402 from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
403 elif detector.chip.id == ap_chip.RP2040:
404 from adafruit_blinka.microcontroller.rp2040.uart import UART as _UART
406 from machine import UART as _UART
408 from microcontroller.pin import uartPorts
410 self.baudrate = baudrate
412 if flow is not None: # default 0
413 raise NotImplementedError(
414 "Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
417 # translate parity flag for Micropython
418 if parity is UART.Parity.ODD:
420 elif parity is UART.Parity.EVEN:
425 raise ValueError("Invalid parity")
427 if detector.chip.id == ap_chip.RP2040:
437 # check tx and rx have hardware support
438 for portId, portTx, portRx in uartPorts: #
439 if portTx == tx and portRx == rx:
447 read_buf_len=receiver_buffer_size,
452 "No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
458 """Deinitialization"""
459 if detector.board.binho_nova:
463 def read(self, nbytes=None):
464 """Read from the UART"""
465 return self._uart.read(nbytes)
467 def readinto(self, buf, nbytes=None):
468 """Read from the UART into a buffer"""
469 return self._uart.readinto(buf, nbytes)
472 """Read a line of characters up to a newline charater from the UART"""
473 return self._uart.readline()
475 def write(self, buf):
476 """Write to the UART from a buffer"""
477 return self._uart.write(buf)
482 Stub class for OneWire, which is currently not implemented
485 def __init__(self, pin):
486 raise NotImplementedError("OneWire has not been implemented")
490 Deinitialize the OneWire bus and release any hardware resources for reuse.
492 raise NotImplementedError("OneWire has not been implemented")
496 Reset the OneWire bus and read presence
498 raise NotImplementedError("OneWire has not been implemented")
504 raise NotImplementedError("OneWire has not been implemented")
506 def write_bit(self, value):
508 Write out a bit based on value.
510 raise NotImplementedError("OneWire has not been implemented")