2 `busio` - Bus protocol support like I2C and SPI
3 =================================================
5 See `CircuitPython:busio` in CircuitPython for more details.
15 # pylint: disable=unused-import
16 import adafruit_platformdetect.constants.boards as ap_board
17 import adafruit_platformdetect.constants.chips as ap_chip
18 from adafruit_blinka import Enum, Lockable, agnostic
19 from adafruit_blinka.agnostic import board_id, detector
21 # pylint: disable=import-outside-toplevel,too-many-branches,too-many-statements
22 # pylint: disable=too-many-arguments,too-many-function-args,too-many-return-statements
27 Busio I2C Class for CircuitPython Compatibility. Used
28 for both MicroPython and Linux.
31 def __init__(self, scl, sda, frequency=100000):
32 self.init(scl, sda, frequency)
34 def init(self, scl, sda, frequency):
37 if detector.board.ftdi_ft232h:
38 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.i2c import I2C as _I2C
40 self._i2c = _I2C(frequency=frequency)
42 if detector.board.binho_nova:
43 from adafruit_blinka.microcontroller.nova.i2c import I2C as _I2C
45 self._i2c = _I2C(frequency=frequency)
47 if detector.board.microchip_mcp2221:
48 from adafruit_blinka.microcontroller.mcp2221.i2c import I2C as _I2C
50 self._i2c = _I2C(frequency=frequency)
52 if detector.board.greatfet_one:
53 from adafruit_blinka.microcontroller.nxp_lpc4330.i2c import I2C as _I2C
55 self._i2c = _I2C(frequency=frequency)
57 if detector.board.pico_u2if:
58 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import I2C_Pico as _I2C
60 self._i2c = _I2C(scl, sda, frequency=frequency)
62 if detector.board.feather_u2if:
63 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
67 self._i2c = _I2C(scl, sda, frequency=frequency)
69 if detector.board.qtpy_u2if:
70 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import I2C_QTPY as _I2C
72 self._i2c = _I2C(scl, sda, frequency=frequency)
74 if detector.board.itsybitsy_u2if:
75 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
76 I2C_ItsyBitsy as _I2C,
79 self._i2c = _I2C(scl, sda, frequency=frequency)
81 if detector.board.macropad_u2if:
82 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
85 self._i2c = _I2C(scl, sda, frequency=frequency)
87 if detector.board.qt2040_trinkey_u2if:
88 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
89 I2C_QT2040_Trinkey as _I2C,
92 self._i2c = _I2C(scl, sda, frequency=frequency)
94 if detector.chip.id == ap_chip.RP2040:
95 from adafruit_blinka.microcontroller.rp2040.i2c import I2C as _I2C
97 self._i2c = _I2C(scl, sda, frequency=frequency)
99 if detector.board.any_embedded_linux:
100 from adafruit_blinka.microcontroller.generic_linux.i2c import I2C as _I2C
101 elif detector.board.ftdi_ft2232h:
102 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.i2c import I2C as _I2C
104 from adafruit_blinka.microcontroller.generic_micropython.i2c import (
107 from microcontroller.pin import i2cPorts
109 for portId, portScl, portSda in i2cPorts:
111 # pylint: disable=unexpected-keyword-arg
112 if scl == portScl and sda == portSda:
113 self._i2c = _I2C(portId, mode=_I2C.MASTER, baudrate=frequency)
115 # pylint: enable=unexpected-keyword-arg
120 "No Hardware I2C on (scl,sda)={}\nValid I2C ports: {}".format(
124 if threading is not None:
125 self._lock = threading.RLock()
128 """Deinitialization"""
131 except AttributeError:
135 if threading is not None:
139 def __exit__(self, exc_type, exc_value, traceback):
140 if threading is not None:
145 """Scan for attached devices"""
146 return self._i2c.scan()
148 def readfrom_into(self, address, buffer, *, start=0, end=None):
149 """Read from a device at specified address into a buffer"""
150 if start != 0 or end is not None:
153 buffer = memoryview(buffer)[start:end]
154 stop = True # remove for efficiency later
155 return self._i2c.readfrom_into(address, buffer, stop=stop)
157 def writeto(self, address, buffer, *, start=0, end=None, stop=True):
158 """Write to a device at specified address from a buffer"""
159 if isinstance(buffer, str):
160 buffer = bytes([ord(x) for x in buffer])
161 if start != 0 or end is not None:
163 return self._i2c.writeto(address, memoryview(buffer)[start:], stop=stop)
164 return self._i2c.writeto(address, memoryview(buffer)[start:end], stop=stop)
165 return self._i2c.writeto(address, buffer, stop=stop)
167 def writeto_then_readfrom(
179 """ "Write to a device at specified address from a buffer then read
180 from a device at specified address into a buffer
182 return self._i2c.writeto_then_readfrom(
196 Busio SPI Class for CircuitPython Compatibility. Used
197 for both MicroPython and Linux.
200 def __init__(self, clock, MOSI=None, MISO=None):
202 if detector.board.ftdi_ft232h:
203 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
204 from adafruit_blinka.microcontroller.ftdi_mpsse.ft232h.pin import (
211 self._pins = (SCK, MOSI, MISO)
213 if detector.board.binho_nova:
214 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
215 from adafruit_blinka.microcontroller.nova.pin import SCK, MOSI, MISO
217 self._spi = _SPI(clock)
218 self._pins = (SCK, MOSI, MISO)
220 if detector.board.greatfet_one:
221 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
222 from adafruit_blinka.microcontroller.nxp_lpc4330.pin import SCK, MOSI, MISO
225 self._pins = (SCK, MOSI, MISO)
227 if detector.board.pico_u2if:
228 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
230 self._spi = _SPI(clock) # this is really all that's needed
231 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
233 if detector.board.feather_u2if:
234 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
238 self._spi = _SPI(clock) # this is really all that's needed
239 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
241 if detector.board.itsybitsy_u2if:
242 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
243 SPI_ItsyBitsy as _SPI,
246 self._spi = _SPI(clock) # this is really all that's needed
247 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
249 if detector.board.macropad_u2if:
250 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
251 SPI_MacroPad as _SPI,
254 self._spi = _SPI(clock) # this is really all that's needed
255 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
257 if detector.board.qtpy_u2if:
258 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI
260 self._spi = _SPI(clock) # this is really all that's needed
261 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
263 if detector.chip.id == ap_chip.RP2040:
264 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
266 self._spi = _SPI(clock, MOSI, MISO) # Pins configured on instantiation
267 self._pins = (clock, clock, clock) # These don't matter, they're discarded
269 if detector.board.any_embedded_linux:
270 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
271 elif detector.board.ftdi_ft2232h:
272 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
274 from adafruit_blinka.microcontroller.generic_micropython.spi import (
277 from microcontroller.pin import spiPorts
279 for portId, portSck, portMosi, portMiso in spiPorts:
282 and MOSI in (portMosi, None) # Clock is required!
283 and MISO in (portMiso, None) # But can do with just output
285 self._spi = _SPI(portId)
286 self._pins = (portSck, portMosi, portMiso)
290 "No Hardware SPI on (SCLK, MOSI, MISO)={}\nValid SPI ports:{}".format(
291 (clock, MOSI, MISO), spiPorts
295 def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
296 """Update the configuration"""
297 if detector.board.any_nanopi and detector.chip.id == ap_chip.SUN8I:
298 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
299 elif detector.board.ftdi_ft232h:
300 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
303 elif detector.board.ftdi_ft2232h:
304 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
307 elif detector.board.binho_nova:
308 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
309 elif detector.board.greatfet_one:
310 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
311 elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
312 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
313 elif detector.board.pico_u2if:
314 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
315 elif detector.board.feather_u2if:
316 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
319 elif detector.board.itsybitsy_u2if:
320 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
321 SPI_ItsyBitsy as _SPI,
323 elif detector.board.macropad_u2if:
324 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
325 SPI_Macropad as _SPI,
327 elif detector.board.qtpy_u2if:
328 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI
329 elif detector.chip.id == ap_chip.RP2040:
330 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
331 elif detector.board.any_embedded_linux:
332 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
334 from adafruit_blinka.microcontroller.generic_micropython.spi import (
339 # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
348 raise RuntimeError("First call try_lock()")
351 """Deinitialization"""
357 """Return the baud rate if implemented"""
359 return self._spi.frequency
360 except AttributeError as error:
361 raise NotImplementedError(
362 "Frequency attribute not implemented for this platform"
365 def write(self, buf, start=0, end=None):
366 """Write to the SPI device"""
367 return self._spi.write(buf, start, end)
369 def readinto(self, buf, start=0, end=None, write_value=0):
370 """Read from the SPI device into a buffer"""
371 return self._spi.readinto(buf, start, end, write_value=write_value)
374 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
376 """Write to the SPI device and read from the SPI device into a buffer"""
377 return self._spi.write_readinto(
378 buffer_out, buffer_in, out_start, out_end, in_start, in_end
382 class UART(Lockable):
384 Busio UART Class for CircuitPython Compatibility. Used
385 for MicroPython and a few other non-Linux boards.
389 """Parity Enumeration"""
391 pass # pylint: disable=unnecessary-pass
393 Parity.ODD = Parity()
394 Parity.EVEN = Parity()
405 receiver_buffer_size=64,
408 if detector.board.any_embedded_linux:
410 "busio.UART not supported on this platform. Please use pyserial instead."
412 if detector.board.binho_nova:
413 from adafruit_blinka.microcontroller.nova.uart import UART as _UART
414 elif detector.board.greatfet_one:
415 from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
416 elif detector.chip.id == ap_chip.RP2040:
417 from adafruit_blinka.microcontroller.rp2040.uart import UART as _UART
419 from machine import UART as _UART
421 from microcontroller.pin import uartPorts
423 self.baudrate = baudrate
425 if flow is not None: # default 0
426 raise NotImplementedError(
427 "Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
430 # translate parity flag for Micropython
431 if parity is UART.Parity.ODD:
433 elif parity is UART.Parity.EVEN:
438 raise ValueError("Invalid parity")
440 if detector.chip.id == ap_chip.RP2040:
450 # check tx and rx have hardware support
451 for portId, portTx, portRx in uartPorts: #
452 if portTx == tx and portRx == rx:
460 read_buf_len=receiver_buffer_size,
465 "No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
471 """Deinitialization"""
472 if detector.board.binho_nova:
476 def read(self, nbytes=None):
477 """Read from the UART"""
478 return self._uart.read(nbytes)
480 def readinto(self, buf, nbytes=None):
481 """Read from the UART into a buffer"""
482 return self._uart.readinto(buf, nbytes)
485 """Read a line of characters up to a newline charater from the UART"""
486 return self._uart.readline()
488 def write(self, buf):
489 """Write to the UART from a buffer"""
490 return self._uart.write(buf)
495 Stub class for OneWire, which is currently not implemented
498 def __init__(self, pin):
499 raise NotImplementedError("OneWire has not been implemented")
503 Deinitialize the OneWire bus and release any hardware resources for reuse.
505 raise NotImplementedError("OneWire has not been implemented")
509 Reset the OneWire bus and read presence
511 raise NotImplementedError("OneWire has not been implemented")
517 raise NotImplementedError("OneWire has not been implemented")
519 def write_bit(self, value):
521 Write out a bit based on value.
523 raise NotImplementedError("OneWire has not been implemented")