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.ft232h.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.pico_u2if.i2c import I2C as _I2C
59 self._i2c = _I2C(scl, sda, frequency=frequency)
61 if detector.chip.id == ap_chip.RP2040:
62 from adafruit_blinka.microcontroller.rp2040.i2c import I2C as _I2C
64 self._i2c = _I2C(scl, sda, frequency=frequency)
66 if detector.board.any_embedded_linux:
67 from adafruit_blinka.microcontroller.generic_linux.i2c import I2C as _I2C
69 from adafruit_blinka.microcontroller.generic_micropython.i2c import (
72 from microcontroller.pin import i2cPorts
74 for portId, portScl, portSda in i2cPorts:
76 # pylint: disable=unexpected-keyword-arg
77 if scl == portScl and sda == portSda:
78 self._i2c = _I2C(portId, mode=_I2C.MASTER, baudrate=frequency)
80 # pylint: enable=unexpected-keyword-arg
85 "No Hardware I2C on (scl,sda)={}\nValid I2C ports: {}".format(
89 if threading is not None:
90 self._lock = threading.RLock()
93 """Deinitialization"""
96 except AttributeError:
100 if threading is not None:
104 def __exit__(self, exc_type, exc_value, traceback):
105 if threading is not None:
110 """Scan for attached devices"""
111 return self._i2c.scan()
113 def readfrom_into(self, address, buffer, *, start=0, end=None):
114 """Read from a device at specified address into a buffer"""
115 if start != 0 or end is not None:
118 buffer = memoryview(buffer)[start:end]
119 stop = True # remove for efficiency later
120 return self._i2c.readfrom_into(address, buffer, stop=stop)
122 def writeto(self, address, buffer, *, start=0, end=None, stop=True):
123 """Write to a device at specified address from a buffer"""
124 if isinstance(buffer, str):
125 buffer = bytes([ord(x) for x in buffer])
126 if start != 0 or end is not None:
128 return self._i2c.writeto(address, memoryview(buffer)[start:], stop=stop)
129 return self._i2c.writeto(address, memoryview(buffer)[start:end], stop=stop)
130 return self._i2c.writeto(address, buffer, stop=stop)
132 def writeto_then_readfrom(
144 """ "Write to a device at specified address from a buffer then read
145 from a device at specified address into a buffer
147 return self._i2c.writeto_then_readfrom(
161 Busio SPI Class for CircuitPython Compatibility. Used
162 for both MicroPython and Linux.
165 def __init__(self, clock, MOSI=None, MISO=None):
167 if detector.board.ftdi_ft232h:
168 from adafruit_blinka.microcontroller.ft232h.spi import SPI as _SPI
169 from adafruit_blinka.microcontroller.ft232h.pin import SCK, MOSI, MISO
172 self._pins = (SCK, MOSI, MISO)
174 if detector.board.binho_nova:
175 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
176 from adafruit_blinka.microcontroller.nova.pin import SCK, MOSI, MISO
178 self._spi = _SPI(clock)
179 self._pins = (SCK, MOSI, MISO)
181 if detector.board.greatfet_one:
182 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
183 from adafruit_blinka.microcontroller.nxp_lpc4330.pin import SCK, MOSI, MISO
186 self._pins = (SCK, MOSI, MISO)
188 if detector.board.pico_u2if:
189 from adafruit_blinka.microcontroller.pico_u2if.spi import SPI as _SPI
191 self._spi = _SPI(clock) # this is really all that's needed
192 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
194 if detector.chip.id == ap_chip.RP2040:
195 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
197 self._spi = _SPI(clock, MOSI, MISO) # Pins configured on instantiation
198 self._pins = (clock, clock, clock) # These don't matter, they're discarded
200 if detector.board.any_embedded_linux:
201 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
203 from adafruit_blinka.microcontroller.generic_micropython.spi import (
206 from microcontroller.pin import spiPorts
208 for portId, portSck, portMosi, portMiso in spiPorts:
211 and MOSI in (portMosi, None) # Clock is required!
212 and MISO in (portMiso, None) # But can do with just output
214 self._spi = _SPI(portId)
215 self._pins = (portSck, portMosi, portMiso)
219 "No Hardware SPI on (SCLK, MOSI, MISO)={}\nValid SPI ports:{}".format(
220 (clock, MOSI, MISO), spiPorts
224 def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
225 """Update the configuration"""
226 if detector.board.any_raspberry_pi or detector.board.any_raspberry_pi_40_pin:
227 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
228 elif detector.board.BEAGLEBONE_AI:
229 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
230 elif detector.board.any_beaglebone:
231 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
232 elif detector.board.any_orange_pi:
233 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
234 elif detector.board.any_nanopi and detector.chip.id == ap_chip.SUN8I:
235 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
236 elif board_id == ap_board.GIANT_BOARD:
237 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
238 elif board_id == ap_board.CORAL_EDGE_TPU_DEV:
239 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
240 elif board_id == ap_board.CORAL_EDGE_TPU_DEV_MINI:
241 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
242 elif board_id == ap_board.ODROID_C2:
243 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
244 elif board_id == ap_board.ODROID_C4:
245 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
246 elif board_id == ap_board.ODROID_XU4:
247 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
248 elif board_id == ap_board.DRAGONBOARD_410C:
249 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
250 elif board_id == ap_board.JETSON_NANO:
251 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
252 elif board_id == ap_board.JETSON_TX1:
253 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
254 elif board_id == ap_board.JETSON_TX2:
255 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
256 elif board_id == ap_board.JETSON_XAVIER:
257 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
258 elif board_id == ap_board.JETSON_NX:
259 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
260 elif detector.board.ROCK_PI_S:
261 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
262 elif detector.board.ROCK_PI_4:
263 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
264 elif detector.board.SIFIVE_UNLEASHED:
265 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
266 elif detector.board.ftdi_ft232h:
267 from adafruit_blinka.microcontroller.ft232h.spi import SPI as _SPI
268 elif detector.board.binho_nova:
269 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
270 elif detector.board.greatfet_one:
271 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
278 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
279 elif board_id == ap_board.CLOCKWORK_CPI3:
280 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
281 elif board_id == ap_board.ONION_OMEGA2:
282 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
283 elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
284 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
285 elif detector.board.pico_u2if:
286 from adafruit_blinka.microcontroller.pico_u2if.spi import SPI as _SPI
287 elif detector.chip.id == ap_chip.RP2040:
288 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
290 from adafruit_blinka.microcontroller.generic_micropython.spi import (
295 # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
304 raise RuntimeError("First call try_lock()")
307 """Deinitialization"""
313 """Return the baud rate if implemented"""
315 return self._spi.frequency
316 except AttributeError:
317 raise NotImplementedError(
318 "Frequency attribute not implemented for this platform"
319 ) from AttributeError
321 def write(self, buf, start=0, end=None):
322 """Write to the SPI device"""
323 return self._spi.write(buf, start, end)
325 def readinto(self, buf, start=0, end=None, write_value=0):
326 """Read from the SPI device into a buffer"""
327 return self._spi.readinto(buf, start, end, write_value=write_value)
330 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
332 """Write to the SPI device and read from the SPI device into a buffer"""
333 return self._spi.write_readinto(
334 buffer_out, buffer_in, out_start, out_end, in_start, in_end
338 class UART(Lockable):
340 Busio UART Class for CircuitPython Compatibility. Used
341 for MicroPython and a few other non-Linux boards.
345 """Parity Enumeration"""
347 pass # pylint: disable=unnecessary-pass
349 Parity.ODD = Parity()
350 Parity.EVEN = Parity()
361 receiver_buffer_size=64,
364 if detector.board.any_embedded_linux:
366 "busio.UART not supported on this platform. Please use pyserial instead."
368 if detector.board.binho_nova:
369 from adafruit_blinka.microcontroller.nova.uart import UART as _UART
370 elif detector.board.greatfet_one:
371 from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
372 elif detector.chip.id == ap_chip.RP2040:
373 from adafruit_blinka.microcontroller.rp2040.uart import UART as _UART
375 from machine import UART as _UART
377 from microcontroller.pin import uartPorts
379 self.baudrate = baudrate
381 if flow is not None: # default 0
382 raise NotImplementedError(
383 "Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
386 # translate parity flag for Micropython
387 if parity is UART.Parity.ODD:
389 elif parity is UART.Parity.EVEN:
394 raise ValueError("Invalid parity")
396 if detector.chip.id == ap_chip.RP2040:
406 # check tx and rx have hardware support
407 for portId, portTx, portRx in uartPorts: #
408 if portTx == tx and portRx == rx:
416 read_buf_len=receiver_buffer_size,
421 "No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
427 """Deinitialization"""
428 if detector.board.binho_nova:
432 def read(self, nbytes=None):
433 """Read from the UART"""
434 return self._uart.read(nbytes)
436 def readinto(self, buf, nbytes=None):
437 """Read from the UART into a buffer"""
438 return self._uart.readinto(buf, nbytes)
441 """Read a line of characters up to a newline charater from the UART"""
442 return self._uart.readline()
444 def write(self, buf):
445 """Write to the UART from a buffer"""
446 return self._uart.write(buf)
451 Stub class for OneWire, which is currently not implemented
454 def __init__(self, pin):
455 raise NotImplementedError("OneWire has not been implemented")
459 Deinitialize the OneWire bus and release any hardware resources for reuse.
461 raise NotImplementedError("OneWire has not been implemented")
465 Reset the OneWire bus and read presence
467 raise NotImplementedError("OneWire has not been implemented")
473 raise NotImplementedError("OneWire has not been implemented")
475 def write_bit(self, value):
477 Write out a bit based on value.
479 raise NotImplementedError("OneWire has not been implemented")