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.generic_linux.spi import SPI as _SPI
281 elif board_id == ap_board.CLOCKWORK_CPI3:
282 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
283 elif board_id == ap_board.ONION_OMEGA2:
284 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
285 elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
286 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
287 elif detector.board.pico_u2if:
288 from adafruit_blinka.microcontroller.pico_u2if.spi import SPI as _SPI
289 elif detector.chip.id == ap_chip.RP2040:
290 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
292 from adafruit_blinka.microcontroller.generic_micropython.spi import (
297 # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
306 raise RuntimeError("First call try_lock()")
309 """Deinitialization"""
315 """Return the baud rate if implemented"""
317 return self._spi.frequency
318 except AttributeError:
319 raise NotImplementedError(
320 "Frequency attribute not implemented for this platform"
321 ) from AttributeError
323 def write(self, buf, start=0, end=None):
324 """Write to the SPI device"""
325 return self._spi.write(buf, start, end)
327 def readinto(self, buf, start=0, end=None, write_value=0):
328 """Read from the SPI device into a buffer"""
329 return self._spi.readinto(buf, start, end, write_value=write_value)
332 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
334 """Write to the SPI device and read from the SPI device into a buffer"""
335 return self._spi.write_readinto(
336 buffer_out, buffer_in, out_start, out_end, in_start, in_end
340 class UART(Lockable):
342 Busio UART Class for CircuitPython Compatibility. Used
343 for MicroPython and a few other non-Linux boards.
347 """Parity Enumeration"""
349 pass # pylint: disable=unnecessary-pass
351 Parity.ODD = Parity()
352 Parity.EVEN = Parity()
363 receiver_buffer_size=64,
366 if detector.board.any_embedded_linux:
368 "busio.UART not supported on this platform. Please use pyserial instead."
370 if detector.board.binho_nova:
371 from adafruit_blinka.microcontroller.nova.uart import UART as _UART
372 elif detector.board.greatfet_one:
373 from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
374 elif detector.chip.id == ap_chip.RP2040:
375 from adafruit_blinka.microcontroller.rp2040.uart import UART as _UART
377 from machine import UART as _UART
379 from microcontroller.pin import uartPorts
381 self.baudrate = baudrate
383 if flow is not None: # default 0
384 raise NotImplementedError(
385 "Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
388 # translate parity flag for Micropython
389 if parity is UART.Parity.ODD:
391 elif parity is UART.Parity.EVEN:
396 raise ValueError("Invalid parity")
398 if detector.chip.id == ap_chip.RP2040:
408 # check tx and rx have hardware support
409 for portId, portTx, portRx in uartPorts: #
410 if portTx == tx and portRx == rx:
418 read_buf_len=receiver_buffer_size,
423 "No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
429 """Deinitialization"""
430 if detector.board.binho_nova:
434 def read(self, nbytes=None):
435 """Read from the UART"""
436 return self._uart.read(nbytes)
438 def readinto(self, buf, nbytes=None):
439 """Read from the UART into a buffer"""
440 return self._uart.readinto(buf, nbytes)
443 """Read a line of characters up to a newline charater from the UART"""
444 return self._uart.readline()
446 def write(self, buf):
447 """Write to the UART from a buffer"""
448 return self._uart.write(buf)
453 Stub class for OneWire, which is currently not implemented
456 def __init__(self, pin):
457 raise NotImplementedError("OneWire has not been implemented")
461 Deinitialize the OneWire bus and release any hardware resources for reuse.
463 raise NotImplementedError("OneWire has not been implemented")
467 Reset the OneWire bus and read presence
469 raise NotImplementedError("OneWire has not been implemented")
475 raise NotImplementedError("OneWire has not been implemented")
477 def write_bit(self, value):
479 Write out a bit based on value.
481 raise NotImplementedError("OneWire has not been implemented")