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_nanopi and detector.chip.id == ap_chip.SUN8I:
283 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
284 elif detector.board.ftdi_ft232h:
285 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
288 elif detector.board.ftdi_ft2232h:
289 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
292 elif detector.board.binho_nova:
293 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
294 elif detector.board.greatfet_one:
295 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
296 elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
297 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
298 elif detector.board.pico_u2if:
299 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
300 elif detector.board.feather_u2if:
301 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
304 elif detector.board.itsybitsy_u2if:
305 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
306 SPI_ItsyBitsy as _SPI,
308 elif detector.board.qtpy_u2if:
309 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI
310 elif detector.chip.id == ap_chip.RP2040:
311 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
312 elif detector.board.any_embedded_linux:
313 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
315 from adafruit_blinka.microcontroller.generic_micropython.spi import (
320 # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
329 raise RuntimeError("First call try_lock()")
332 """Deinitialization"""
338 """Return the baud rate if implemented"""
340 return self._spi.frequency
341 except AttributeError as error:
342 raise NotImplementedError(
343 "Frequency attribute not implemented for this platform"
346 def write(self, buf, start=0, end=None):
347 """Write to the SPI device"""
348 return self._spi.write(buf, start, end)
350 def readinto(self, buf, start=0, end=None, write_value=0):
351 """Read from the SPI device into a buffer"""
352 return self._spi.readinto(buf, start, end, write_value=write_value)
355 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
357 """Write to the SPI device and read from the SPI device into a buffer"""
358 return self._spi.write_readinto(
359 buffer_out, buffer_in, out_start, out_end, in_start, in_end
363 class UART(Lockable):
365 Busio UART Class for CircuitPython Compatibility. Used
366 for MicroPython and a few other non-Linux boards.
370 """Parity Enumeration"""
372 pass # pylint: disable=unnecessary-pass
374 Parity.ODD = Parity()
375 Parity.EVEN = Parity()
386 receiver_buffer_size=64,
389 if detector.board.any_embedded_linux:
391 "busio.UART not supported on this platform. Please use pyserial instead."
393 if detector.board.binho_nova:
394 from adafruit_blinka.microcontroller.nova.uart import UART as _UART
395 elif detector.board.greatfet_one:
396 from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
397 elif detector.chip.id == ap_chip.RP2040:
398 from adafruit_blinka.microcontroller.rp2040.uart import UART as _UART
400 from machine import UART as _UART
402 from microcontroller.pin import uartPorts
404 self.baudrate = baudrate
406 if flow is not None: # default 0
407 raise NotImplementedError(
408 "Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
411 # translate parity flag for Micropython
412 if parity is UART.Parity.ODD:
414 elif parity is UART.Parity.EVEN:
419 raise ValueError("Invalid parity")
421 if detector.chip.id == ap_chip.RP2040:
431 # check tx and rx have hardware support
432 for portId, portTx, portRx in uartPorts: #
433 if portTx == tx and portRx == rx:
441 read_buf_len=receiver_buffer_size,
446 "No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
452 """Deinitialization"""
453 if detector.board.binho_nova:
457 def read(self, nbytes=None):
458 """Read from the UART"""
459 return self._uart.read(nbytes)
461 def readinto(self, buf, nbytes=None):
462 """Read from the UART into a buffer"""
463 return self._uart.readinto(buf, nbytes)
466 """Read a line of characters up to a newline charater from the UART"""
467 return self._uart.readline()
469 def write(self, buf):
470 """Write to the UART from a buffer"""
471 return self._uart.write(buf)
476 Stub class for OneWire, which is currently not implemented
479 def __init__(self, pin):
480 raise NotImplementedError("OneWire has not been implemented")
484 Deinitialize the OneWire bus and release any hardware resources for reuse.
486 raise NotImplementedError("OneWire has not been implemented")
490 Reset the OneWire bus and read presence
492 raise NotImplementedError("OneWire has not been implemented")
498 raise NotImplementedError("OneWire has not been implemented")
500 def write_bit(self, value):
502 Write out a bit based on value.
504 raise NotImplementedError("OneWire has not been implemented")