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 (
86 self._i2c = _I2C(scl, sda, frequency=frequency)
88 if detector.board.qt2040_trinkey_u2if:
89 from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
90 I2C_QT2040_Trinkey as _I2C,
93 self._i2c = _I2C(scl, sda, frequency=frequency)
95 if detector.chip.id == ap_chip.RP2040:
96 from adafruit_blinka.microcontroller.rp2040.i2c import I2C as _I2C
98 self._i2c = _I2C(scl, sda, frequency=frequency)
100 if detector.board.any_embedded_linux:
101 from adafruit_blinka.microcontroller.generic_linux.i2c import I2C as _I2C
102 elif detector.board.ftdi_ft2232h:
103 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.i2c import I2C as _I2C
105 from adafruit_blinka.microcontroller.generic_micropython.i2c import (
108 from microcontroller.pin import i2cPorts
110 for portId, portScl, portSda in i2cPorts:
112 # pylint: disable=unexpected-keyword-arg
113 if scl == portScl and sda == portSda:
114 self._i2c = _I2C(portId, mode=_I2C.MASTER, baudrate=frequency)
116 # pylint: enable=unexpected-keyword-arg
121 "No Hardware I2C on (scl,sda)={}\nValid I2C ports: {}".format(
125 if threading is not None:
126 self._lock = threading.RLock()
129 """Deinitialization"""
132 except AttributeError:
136 if threading is not None:
140 def __exit__(self, exc_type, exc_value, traceback):
141 if threading is not None:
146 """Scan for attached devices"""
147 return self._i2c.scan()
149 def readfrom_into(self, address, buffer, *, start=0, end=None):
150 """Read from a device at specified address into a buffer"""
151 if start != 0 or end is not None:
154 buffer = memoryview(buffer)[start:end]
155 stop = True # remove for efficiency later
156 return self._i2c.readfrom_into(address, buffer, stop=stop)
158 def writeto(self, address, buffer, *, start=0, end=None, stop=True):
159 """Write to a device at specified address from a buffer"""
160 if isinstance(buffer, str):
161 buffer = bytes([ord(x) for x in buffer])
162 if start != 0 or end is not None:
164 return self._i2c.writeto(address, memoryview(buffer)[start:], stop=stop)
165 return self._i2c.writeto(address, memoryview(buffer)[start:end], stop=stop)
166 return self._i2c.writeto(address, buffer, stop=stop)
168 def writeto_then_readfrom(
180 """ "Write to a device at specified address from a buffer then read
181 from a device at specified address into a buffer
183 return self._i2c.writeto_then_readfrom(
197 Busio SPI Class for CircuitPython Compatibility. Used
198 for both MicroPython and Linux.
201 def __init__(self, clock, MOSI=None, MISO=None):
203 if detector.board.ftdi_ft232h:
204 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
205 from adafruit_blinka.microcontroller.ftdi_mpsse.ft232h.pin import (
212 self._pins = (SCK, MOSI, MISO)
214 if detector.board.binho_nova:
215 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
216 from adafruit_blinka.microcontroller.nova.pin import SCK, MOSI, MISO
218 self._spi = _SPI(clock)
219 self._pins = (SCK, MOSI, MISO)
221 if detector.board.greatfet_one:
222 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
223 from adafruit_blinka.microcontroller.nxp_lpc4330.pin import SCK, MOSI, MISO
226 self._pins = (SCK, MOSI, MISO)
228 if detector.board.pico_u2if:
229 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI
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.feather_u2if:
235 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
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.itsybitsy_u2if:
243 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
244 SPI_ItsyBitsy as _SPI,
247 self._spi = _SPI(clock) # this is really all that's needed
248 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
250 if detector.board.macropad_u2if:
251 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
252 SPI_MacroPad as _SPI,
255 self._spi = _SPI(clock) # this is really all that's needed
256 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
258 if detector.board.qtpy_u2if:
259 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI
261 self._spi = _SPI(clock) # this is really all that's needed
262 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
264 if detector.chip.id == ap_chip.RP2040:
265 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
267 self._spi = _SPI(clock, MOSI, MISO) # Pins configured on instantiation
268 self._pins = (clock, clock, clock) # These don't matter, they're discarded
270 if detector.board.any_embedded_linux:
271 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
272 elif detector.board.ftdi_ft2232h:
273 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
275 from adafruit_blinka.microcontroller.generic_micropython.spi import (
278 from microcontroller.pin import spiPorts
280 for portId, portSck, portMosi, portMiso in spiPorts:
283 and MOSI in (portMosi, None) # Clock is required!
284 and MISO in (portMiso, None) # But can do with just output
286 self._spi = _SPI(portId)
287 self._pins = (portSck, portMosi, portMiso)
291 "No Hardware SPI on (SCLK, MOSI, MISO)={}\nValid SPI ports:{}".format(
292 (clock, MOSI, MISO), spiPorts
296 def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
297 """Update the configuration"""
298 if detector.board.any_nanopi and detector.chip.id == ap_chip.SUN8I:
299 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
300 elif detector.board.ftdi_ft232h:
301 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
304 elif detector.board.ftdi_ft2232h:
305 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
308 elif detector.board.binho_nova:
309 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
310 elif detector.board.greatfet_one:
311 from adafruit_blinka.microcontroller.nxp_lpc4330.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 (
320 elif detector.board.itsybitsy_u2if:
321 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
322 SPI_ItsyBitsy as _SPI,
324 elif detector.board.macropad_u2if:
325 from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
326 SPI_MacroPad as _SPI,
328 elif detector.board.qtpy_u2if:
329 from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI
330 elif detector.chip.id == ap_chip.RP2040:
331 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
332 elif detector.board.any_embedded_linux:
333 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
335 from adafruit_blinka.microcontroller.generic_micropython.spi import (
340 # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
349 raise RuntimeError("First call try_lock()")
352 """Deinitialization"""
358 """Return the baud rate if implemented"""
360 return self._spi.frequency
361 except AttributeError as error:
362 raise NotImplementedError(
363 "Frequency attribute not implemented for this platform"
366 def write(self, buf, start=0, end=None):
367 """Write to the SPI device"""
368 return self._spi.write(buf, start, end)
370 def readinto(self, buf, start=0, end=None, write_value=0):
371 """Read from the SPI device into a buffer"""
372 return self._spi.readinto(buf, start, end, write_value=write_value)
375 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
377 """Write to the SPI device and read from the SPI device into a buffer"""
378 return self._spi.write_readinto(
379 buffer_out, buffer_in, out_start, out_end, in_start, in_end
383 class UART(Lockable):
385 Busio UART Class for CircuitPython Compatibility. Used
386 for MicroPython and a few other non-Linux boards.
390 """Parity Enumeration"""
392 pass # pylint: disable=unnecessary-pass
394 Parity.ODD = Parity()
395 Parity.EVEN = Parity()
406 receiver_buffer_size=64,
409 if detector.board.any_embedded_linux:
411 "busio.UART not supported on this platform. Please use pyserial instead."
413 if detector.board.binho_nova:
414 from adafruit_blinka.microcontroller.nova.uart import UART as _UART
415 elif detector.board.greatfet_one:
416 from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
417 elif detector.chip.id == ap_chip.RP2040:
418 from adafruit_blinka.microcontroller.rp2040.uart import UART as _UART
420 from machine import UART as _UART
422 from microcontroller.pin import uartPorts
424 self.baudrate = baudrate
426 if flow is not None: # default 0
427 raise NotImplementedError(
428 "Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
431 # translate parity flag for Micropython
432 if parity is UART.Parity.ODD:
434 elif parity is UART.Parity.EVEN:
439 raise ValueError("Invalid parity")
441 if detector.chip.id == ap_chip.RP2040:
451 # check tx and rx have hardware support
452 for portId, portTx, portRx in uartPorts: #
453 if portTx == tx and portRx == rx:
461 read_buf_len=receiver_buffer_size,
466 "No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
472 """Deinitialization"""
473 if detector.board.binho_nova:
477 def read(self, nbytes=None):
478 """Read from the UART"""
479 return self._uart.read(nbytes)
481 def readinto(self, buf, nbytes=None):
482 """Read from the UART into a buffer"""
483 return self._uart.readinto(buf, nbytes)
486 """Read a line of characters up to a newline charater from the UART"""
487 return self._uart.readline()
489 def write(self, buf):
490 """Write to the UART from a buffer"""
491 return self._uart.write(buf)
496 Stub class for OneWire, which is currently not implemented
499 def __init__(self, pin):
500 raise NotImplementedError("OneWire has not been implemented")
504 Deinitialize the OneWire bus and release any hardware resources for reuse.
506 raise NotImplementedError("OneWire has not been implemented")
510 Reset the OneWire bus and read presence
512 raise NotImplementedError("OneWire has not been implemented")
518 raise NotImplementedError("OneWire has not been implemented")
520 def write_bit(self, value):
522 Write out a bit based on value.
524 raise NotImplementedError("OneWire has not been implemented")