2 `busio` - Bus protocol support like I2C and SPI
3 =================================================
5 See `CircuitPython:busio` in CircuitPython for more details.
11 __version__ = "0.0.0-auto.0"
12 __repo__ = "https://github.com/adafruit/Adafruit_Blinka.git"
20 # pylint: disable=unused-import
21 import adafruit_platformdetect.constants.boards as ap_board
22 import adafruit_platformdetect.constants.chips as ap_chip
23 from adafruit_blinka import Enum, Lockable, agnostic
24 from adafruit_blinka.agnostic import board_id, detector
26 # pylint: disable=import-outside-toplevel,too-many-branches,too-many-statements
27 # pylint: disable=too-many-arguments,too-many-function-args,too-many-return-statements
32 Busio I2C Class for CircuitPython Compatibility. Used
33 for both MicroPython and Linux.
36 def __init__(self, scl, sda, frequency=100000):
37 self.init(scl, sda, frequency)
39 def init(self, scl, sda, frequency):
42 if detector.board.ftdi_ft232h:
43 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.i2c import I2C as _I2C
45 self._i2c = _I2C(frequency=frequency)
47 if detector.board.binho_nova:
48 from adafruit_blinka.microcontroller.nova.i2c import I2C as _I2C
50 self._i2c = _I2C(frequency=frequency)
52 if detector.board.microchip_mcp2221:
53 from adafruit_blinka.microcontroller.mcp2221.i2c import I2C as _I2C
55 self._i2c = _I2C(frequency=frequency)
57 if detector.board.greatfet_one:
58 from adafruit_blinka.microcontroller.nxp_lpc4330.i2c import I2C as _I2C
60 self._i2c = _I2C(frequency=frequency)
62 if detector.board.pico_u2if:
63 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import I2C_Pico as _I2C
65 self._i2c = _I2C(scl, sda, frequency=frequency)
67 if detector.board.feather_u2if:
68 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
72 self._i2c = _I2C(scl, sda, frequency=frequency)
74 if detector.board.qtpy_u2if:
75 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import I2C_QTPY as _I2C
77 self._i2c = _I2C(scl, sda, frequency=frequency)
79 if detector.board.itsybitsy_u2if:
80 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
81 I2C_ItsyBitsy as _I2C,
84 self._i2c = _I2C(scl, sda, frequency=frequency)
86 if detector.board.qt2040_trinkey_u2if:
87 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
88 I2C_QT2040_Trinkey as _I2C,
91 self._i2c = _I2C(scl, sda, frequency=frequency)
93 if detector.chip.id == ap_chip.RP2040:
94 from adafruit_blinka.microcontroller.rp2040.i2c import I2C as _I2C
96 self._i2c = _I2C(scl, sda, frequency=frequency)
98 if detector.board.any_embedded_linux:
99 from adafruit_blinka.microcontroller.generic_linux.i2c import I2C as _I2C
100 elif detector.board.ftdi_ft2232h:
101 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.i2c import I2C as _I2C
103 from adafruit_blinka.microcontroller.generic_micropython.i2c import (
106 from microcontroller.pin import i2cPorts
108 for portId, portScl, portSda in i2cPorts:
110 # pylint: disable=unexpected-keyword-arg
111 if scl == portScl and sda == portSda:
112 self._i2c = _I2C(portId, mode=_I2C.MASTER, baudrate=frequency)
114 # pylint: enable=unexpected-keyword-arg
119 "No Hardware I2C on (scl,sda)={}\nValid I2C ports: {}".format(
123 if threading is not None:
124 self._lock = threading.RLock()
127 """Deinitialization"""
130 except AttributeError:
134 if threading is not None:
138 def __exit__(self, exc_type, exc_value, traceback):
139 if threading is not None:
144 """Scan for attached devices"""
145 return self._i2c.scan()
147 def readfrom_into(self, address, buffer, *, start=0, end=None):
148 """Read from a device at specified address into a buffer"""
149 if start != 0 or end is not None:
152 buffer = memoryview(buffer)[start:end]
153 stop = True # remove for efficiency later
154 return self._i2c.readfrom_into(address, buffer, stop=stop)
156 def writeto(self, address, buffer, *, start=0, end=None, stop=True):
157 """Write to a device at specified address from a buffer"""
158 if isinstance(buffer, str):
159 buffer = bytes([ord(x) for x in buffer])
160 if start != 0 or end is not None:
162 return self._i2c.writeto(address, memoryview(buffer)[start:], stop=stop)
163 return self._i2c.writeto(address, memoryview(buffer)[start:end], stop=stop)
164 return self._i2c.writeto(address, buffer, stop=stop)
166 def writeto_then_readfrom(
178 """ "Write to a device at specified address from a buffer then read
179 from a device at specified address into a buffer
181 return self._i2c.writeto_then_readfrom(
195 Busio SPI Class for CircuitPython Compatibility. Used
196 for both MicroPython and Linux.
199 def __init__(self, clock, MOSI=None, MISO=None):
201 if detector.board.ftdi_ft232h:
202 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
203 from adafruit_blinka.microcontroller.ftdi_mpsse.ft232h.pin import (
210 self._pins = (SCK, MOSI, MISO)
212 if detector.board.binho_nova:
213 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
214 from adafruit_blinka.microcontroller.nova.pin import SCK, MOSI, MISO
216 self._spi = _SPI(clock)
217 self._pins = (SCK, MOSI, MISO)
219 if detector.board.greatfet_one:
220 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
221 from adafruit_blinka.microcontroller.nxp_lpc4330.pin import SCK, MOSI, MISO
224 self._pins = (SCK, MOSI, MISO)
226 if detector.board.pico_u2if:
227 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
229 self._spi = _SPI(clock) # this is really all that's needed
230 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
232 if detector.board.feather_u2if:
233 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
237 self._spi = _SPI(clock) # this is really all that's needed
238 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
240 if detector.board.itsybitsy_u2if:
241 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
242 SPI_ItsyBitsy 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.board.qtpy_u2if:
249 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI
251 self._spi = _SPI(clock) # this is really all that's needed
252 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
254 if detector.chip.id == ap_chip.RP2040:
255 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
257 self._spi = _SPI(clock, MOSI, MISO) # Pins configured on instantiation
258 self._pins = (clock, clock, clock) # These don't matter, they're discarded
260 if detector.board.any_embedded_linux:
261 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
262 elif detector.board.ftdi_ft2232h:
263 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
265 from adafruit_blinka.microcontroller.generic_micropython.spi import (
268 from microcontroller.pin import spiPorts
270 for portId, portSck, portMosi, portMiso in spiPorts:
273 and MOSI in (portMosi, None) # Clock is required!
274 and MISO in (portMiso, None) # But can do with just output
276 self._spi = _SPI(portId)
277 self._pins = (portSck, portMosi, portMiso)
281 "No Hardware SPI on (SCLK, MOSI, MISO)={}\nValid SPI ports:{}".format(
282 (clock, MOSI, MISO), spiPorts
286 def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
287 """Update the configuration"""
288 if detector.board.any_nanopi and detector.chip.id == ap_chip.SUN8I:
289 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
290 elif detector.board.ftdi_ft232h:
291 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
294 elif detector.board.ftdi_ft2232h:
295 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
298 elif detector.board.binho_nova:
299 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
300 elif detector.board.greatfet_one:
301 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
302 elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
303 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
304 elif detector.board.pico_u2if:
305 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
306 elif detector.board.feather_u2if:
307 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
310 elif detector.board.itsybitsy_u2if:
311 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
312 SPI_ItsyBitsy as _SPI,
314 elif detector.board.qtpy_u2if:
315 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI
316 elif detector.chip.id == ap_chip.RP2040:
317 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
318 elif detector.board.any_embedded_linux:
319 from adafruit_blinka.microcontroller.generic_linux.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 as error:
348 raise NotImplementedError(
349 "Frequency attribute not implemented for this platform"
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")