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.qtpy_u2if:
67 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import I2C_QTPY as _I2C
69 self._i2c = _I2C(scl, sda, frequency=frequency)
71 if detector.board.qt2040_trinkey_u2if:
72 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import I2C_QT2040_Trinkey as _I2C
74 self._i2c = _I2C(scl, sda, frequency=frequency)
76 if detector.chip.id == ap_chip.RP2040:
77 from adafruit_blinka.microcontroller.rp2040.i2c import I2C as _I2C
79 self._i2c = _I2C(scl, sda, frequency=frequency)
81 if detector.board.any_embedded_linux:
82 from adafruit_blinka.microcontroller.generic_linux.i2c import I2C as _I2C
83 elif detector.board.ftdi_ft2232h:
84 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.i2c import I2C as _I2C
86 from adafruit_blinka.microcontroller.generic_micropython.i2c import (
89 from microcontroller.pin import i2cPorts
91 for portId, portScl, portSda in i2cPorts:
93 # pylint: disable=unexpected-keyword-arg
94 if scl == portScl and sda == portSda:
95 self._i2c = _I2C(portId, mode=_I2C.MASTER, baudrate=frequency)
97 # pylint: enable=unexpected-keyword-arg
102 "No Hardware I2C on (scl,sda)={}\nValid I2C ports: {}".format(
106 if threading is not None:
107 self._lock = threading.RLock()
110 """Deinitialization"""
113 except AttributeError:
117 if threading is not None:
121 def __exit__(self, exc_type, exc_value, traceback):
122 if threading is not None:
127 """Scan for attached devices"""
128 return self._i2c.scan()
130 def readfrom_into(self, address, buffer, *, start=0, end=None):
131 """Read from a device at specified address into a buffer"""
132 if start != 0 or end is not None:
135 buffer = memoryview(buffer)[start:end]
136 stop = True # remove for efficiency later
137 return self._i2c.readfrom_into(address, buffer, stop=stop)
139 def writeto(self, address, buffer, *, start=0, end=None, stop=True):
140 """Write to a device at specified address from a buffer"""
141 if isinstance(buffer, str):
142 buffer = bytes([ord(x) for x in buffer])
143 if start != 0 or end is not None:
145 return self._i2c.writeto(address, memoryview(buffer)[start:], stop=stop)
146 return self._i2c.writeto(address, memoryview(buffer)[start:end], stop=stop)
147 return self._i2c.writeto(address, buffer, stop=stop)
149 def writeto_then_readfrom(
161 """ "Write to a device at specified address from a buffer then read
162 from a device at specified address into a buffer
164 return self._i2c.writeto_then_readfrom(
178 Busio SPI Class for CircuitPython Compatibility. Used
179 for both MicroPython and Linux.
182 def __init__(self, clock, MOSI=None, MISO=None):
184 if detector.board.ftdi_ft232h:
185 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
186 from adafruit_blinka.microcontroller.ftdi_mpsse.ft232h.pin import (
193 self._pins = (SCK, MOSI, MISO)
195 if detector.board.binho_nova:
196 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
197 from adafruit_blinka.microcontroller.nova.pin import SCK, MOSI, MISO
199 self._spi = _SPI(clock)
200 self._pins = (SCK, MOSI, MISO)
202 if detector.board.greatfet_one:
203 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
204 from adafruit_blinka.microcontroller.nxp_lpc4330.pin import SCK, MOSI, MISO
207 self._pins = (SCK, MOSI, MISO)
209 if detector.board.pico_u2if:
210 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
212 self._spi = _SPI(clock) # this is really all that's needed
213 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
215 if detector.board.feather_u2if:
216 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Feather as _SPI
218 self._spi = _SPI(clock) # this is really all that's needed
219 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
221 if detector.board.qtpy_u2if:
222 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY 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.chip.id == ap_chip.RP2040:
228 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
230 self._spi = _SPI(clock, MOSI, MISO) # Pins configured on instantiation
231 self._pins = (clock, clock, clock) # These don't matter, they're discarded
233 if detector.board.any_embedded_linux:
234 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
235 elif detector.board.ftdi_ft2232h:
236 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
238 from adafruit_blinka.microcontroller.generic_micropython.spi import (
241 from microcontroller.pin import spiPorts
243 for portId, portSck, portMosi, portMiso in spiPorts:
246 and MOSI in (portMosi, None) # Clock is required!
247 and MISO in (portMiso, None) # But can do with just output
249 self._spi = _SPI(portId)
250 self._pins = (portSck, portMosi, portMiso)
254 "No Hardware SPI on (SCLK, MOSI, MISO)={}\nValid SPI ports:{}".format(
255 (clock, MOSI, MISO), spiPorts
259 def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
260 """Update the configuration"""
261 if detector.board.any_raspberry_pi or detector.board.any_raspberry_pi_40_pin:
262 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
263 elif detector.board.BEAGLEBONE_AI:
264 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
265 elif detector.board.any_beaglebone:
266 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
267 elif detector.board.any_orange_pi:
268 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
269 elif detector.board.any_nanopi and detector.chip.id == ap_chip.SUN8I:
270 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
271 elif board_id == ap_board.GIANT_BOARD:
272 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
273 elif board_id == ap_board.CORAL_EDGE_TPU_DEV:
274 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
275 elif board_id == ap_board.CORAL_EDGE_TPU_DEV_MINI:
276 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
277 elif board_id == ap_board.ODROID_C2:
278 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
279 elif board_id == ap_board.ODROID_C4:
280 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
281 elif board_id == ap_board.ODROID_XU4:
282 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
283 elif board_id == ap_board.DRAGONBOARD_410C:
284 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
285 elif board_id == ap_board.JETSON_NANO:
286 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
287 elif board_id == ap_board.JETSON_TX1:
288 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
289 elif board_id == ap_board.JETSON_TX2:
290 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
291 elif board_id == ap_board.JETSON_XAVIER:
292 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
293 elif board_id == ap_board.JETSON_NX:
294 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
295 elif detector.board.ROCK_PI_S:
296 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
297 elif detector.board.ROCK_PI_4:
298 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
299 elif detector.board.ROCK_PI_E:
300 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
301 elif detector.board.SIFIVE_UNLEASHED:
302 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
303 elif detector.board.ftdi_ft232h:
304 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
307 elif detector.board.ftdi_ft2232h:
308 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
311 elif detector.board.binho_nova:
312 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
313 elif detector.board.greatfet_one:
314 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
321 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
322 elif board_id == ap_board.PINEH64:
323 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
324 elif board_id == ap_board.CLOCKWORK_CPI3:
325 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
326 elif board_id == ap_board.ONION_OMEGA2:
327 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
328 elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
329 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
330 elif detector.board.pico_u2if:
331 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
332 elif detector.board.feather_u2if:
333 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Feather as _SPI
334 elif detector.chip.id == ap_chip.RP2040:
335 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
337 from adafruit_blinka.microcontroller.generic_micropython.spi import (
342 # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
351 raise RuntimeError("First call try_lock()")
354 """Deinitialization"""
360 """Return the baud rate if implemented"""
362 return self._spi.frequency
363 except AttributeError:
364 raise NotImplementedError(
365 "Frequency attribute not implemented for this platform"
366 ) from AttributeError
368 def write(self, buf, start=0, end=None):
369 """Write to the SPI device"""
370 return self._spi.write(buf, start, end)
372 def readinto(self, buf, start=0, end=None, write_value=0):
373 """Read from the SPI device into a buffer"""
374 return self._spi.readinto(buf, start, end, write_value=write_value)
377 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
379 """Write to the SPI device and read from the SPI device into a buffer"""
380 return self._spi.write_readinto(
381 buffer_out, buffer_in, out_start, out_end, in_start, in_end
385 class UART(Lockable):
387 Busio UART Class for CircuitPython Compatibility. Used
388 for MicroPython and a few other non-Linux boards.
392 """Parity Enumeration"""
394 pass # pylint: disable=unnecessary-pass
396 Parity.ODD = Parity()
397 Parity.EVEN = Parity()
408 receiver_buffer_size=64,
411 if detector.board.any_embedded_linux:
413 "busio.UART not supported on this platform. Please use pyserial instead."
415 if detector.board.binho_nova:
416 from adafruit_blinka.microcontroller.nova.uart import UART as _UART
417 elif detector.board.greatfet_one:
418 from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
419 elif detector.chip.id == ap_chip.RP2040:
420 from adafruit_blinka.microcontroller.rp2040.uart import UART as _UART
422 from machine import UART as _UART
424 from microcontroller.pin import uartPorts
426 self.baudrate = baudrate
428 if flow is not None: # default 0
429 raise NotImplementedError(
430 "Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
433 # translate parity flag for Micropython
434 if parity is UART.Parity.ODD:
436 elif parity is UART.Parity.EVEN:
441 raise ValueError("Invalid parity")
443 if detector.chip.id == ap_chip.RP2040:
453 # check tx and rx have hardware support
454 for portId, portTx, portRx in uartPorts: #
455 if portTx == tx and portRx == rx:
463 read_buf_len=receiver_buffer_size,
468 "No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
474 """Deinitialization"""
475 if detector.board.binho_nova:
479 def read(self, nbytes=None):
480 """Read from the UART"""
481 return self._uart.read(nbytes)
483 def readinto(self, buf, nbytes=None):
484 """Read from the UART into a buffer"""
485 return self._uart.readinto(buf, nbytes)
488 """Read a line of characters up to a newline charater from the UART"""
489 return self._uart.readline()
491 def write(self, buf):
492 """Write to the UART from a buffer"""
493 return self._uart.write(buf)
498 Stub class for OneWire, which is currently not implemented
501 def __init__(self, pin):
502 raise NotImplementedError("OneWire has not been implemented")
506 Deinitialize the OneWire bus and release any hardware resources for reuse.
508 raise NotImplementedError("OneWire has not been implemented")
512 Reset the OneWire bus and read presence
514 raise NotImplementedError("OneWire has not been implemented")
520 raise NotImplementedError("OneWire has not been implemented")
522 def write_bit(self, value):
524 Write out a bit based on value.
526 raise NotImplementedError("OneWire has not been implemented")