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.PINEH64:
280 from adafruit_blinka.microcontroller.allwinner.h6.pin import Pin
281 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
282 elif board_id == ap_board.CLOCKWORK_CPI3:
283 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
284 elif board_id == ap_board.ONION_OMEGA2:
285 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
286 elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
287 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
288 elif detector.board.pico_u2if:
289 from adafruit_blinka.microcontroller.pico_u2if.spi import SPI as _SPI
290 elif detector.chip.id == ap_chip.RP2040:
291 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
293 from adafruit_blinka.microcontroller.generic_micropython.spi import (
298 # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
307 raise RuntimeError("First call try_lock()")
310 """Deinitialization"""
316 """Return the baud rate if implemented"""
318 return self._spi.frequency
319 except AttributeError:
320 raise NotImplementedError(
321 "Frequency attribute not implemented for this platform"
322 ) from AttributeError
324 def write(self, buf, start=0, end=None):
325 """Write to the SPI device"""
326 return self._spi.write(buf, start, end)
328 def readinto(self, buf, start=0, end=None, write_value=0):
329 """Read from the SPI device into a buffer"""
330 return self._spi.readinto(buf, start, end, write_value=write_value)
333 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
335 """Write to the SPI device and read from the SPI device into a buffer"""
336 return self._spi.write_readinto(
337 buffer_out, buffer_in, out_start, out_end, in_start, in_end
341 class UART(Lockable):
343 Busio UART Class for CircuitPython Compatibility. Used
344 for MicroPython and a few other non-Linux boards.
348 """Parity Enumeration"""
350 pass # pylint: disable=unnecessary-pass
352 Parity.ODD = Parity()
353 Parity.EVEN = Parity()
364 receiver_buffer_size=64,
367 if detector.board.any_embedded_linux:
369 "busio.UART not supported on this platform. Please use pyserial instead."
371 if detector.board.binho_nova:
372 from adafruit_blinka.microcontroller.nova.uart import UART as _UART
373 elif detector.board.greatfet_one:
374 from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
375 elif detector.chip.id == ap_chip.RP2040:
376 from adafruit_blinka.microcontroller.rp2040.uart import UART as _UART
378 from machine import UART as _UART
380 from microcontroller.pin import uartPorts
382 self.baudrate = baudrate
384 if flow is not None: # default 0
385 raise NotImplementedError(
386 "Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
389 # translate parity flag for Micropython
390 if parity is UART.Parity.ODD:
392 elif parity is UART.Parity.EVEN:
397 raise ValueError("Invalid parity")
399 if detector.chip.id == ap_chip.RP2040:
409 # check tx and rx have hardware support
410 for portId, portTx, portRx in uartPorts: #
411 if portTx == tx and portRx == rx:
419 read_buf_len=receiver_buffer_size,
424 "No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
430 """Deinitialization"""
431 if detector.board.binho_nova:
435 def read(self, nbytes=None):
436 """Read from the UART"""
437 return self._uart.read(nbytes)
439 def readinto(self, buf, nbytes=None):
440 """Read from the UART into a buffer"""
441 return self._uart.readinto(buf, nbytes)
444 """Read a line of characters up to a newline charater from the UART"""
445 return self._uart.readline()
447 def write(self, buf):
448 """Write to the UART from a buffer"""
449 return self._uart.write(buf)
454 Stub class for OneWire, which is currently not implemented
457 def __init__(self, pin):
458 raise NotImplementedError("OneWire has not been implemented")
462 Deinitialize the OneWire bus and release any hardware resources for reuse.
464 raise NotImplementedError("OneWire has not been implemented")
468 Reset the OneWire bus and read presence
470 raise NotImplementedError("OneWire has not been implemented")
476 raise NotImplementedError("OneWire has not been implemented")
478 def write_bit(self, value):
480 Write out a bit based on value.
482 raise NotImplementedError("OneWire has not been implemented")