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.ftdi_mpsse.mpsse.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
68 elif detector.board.ftdi_ft2232h:
69 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.i2c import I2C as _I2C
71 from adafruit_blinka.microcontroller.generic_micropython.i2c import (
74 from microcontroller.pin import i2cPorts
76 for portId, portScl, portSda in i2cPorts:
78 # pylint: disable=unexpected-keyword-arg
79 if scl == portScl and sda == portSda:
80 self._i2c = _I2C(portId, mode=_I2C.MASTER, baudrate=frequency)
82 # pylint: enable=unexpected-keyword-arg
87 "No Hardware I2C on (scl,sda)={}\nValid I2C ports: {}".format(
91 if threading is not None:
92 self._lock = threading.RLock()
95 """Deinitialization"""
98 except AttributeError:
102 if threading is not None:
106 def __exit__(self, exc_type, exc_value, traceback):
107 if threading is not None:
112 """Scan for attached devices"""
113 return self._i2c.scan()
115 def readfrom_into(self, address, buffer, *, start=0, end=None):
116 """Read from a device at specified address into a buffer"""
117 if start != 0 or end is not None:
120 buffer = memoryview(buffer)[start:end]
121 stop = True # remove for efficiency later
122 return self._i2c.readfrom_into(address, buffer, stop=stop)
124 def writeto(self, address, buffer, *, start=0, end=None, stop=True):
125 """Write to a device at specified address from a buffer"""
126 if isinstance(buffer, str):
127 buffer = bytes([ord(x) for x in buffer])
128 if start != 0 or end is not None:
130 return self._i2c.writeto(address, memoryview(buffer)[start:], stop=stop)
131 return self._i2c.writeto(address, memoryview(buffer)[start:end], stop=stop)
132 return self._i2c.writeto(address, buffer, stop=stop)
134 def writeto_then_readfrom(
146 """ "Write to a device at specified address from a buffer then read
147 from a device at specified address into a buffer
149 return self._i2c.writeto_then_readfrom(
163 Busio SPI Class for CircuitPython Compatibility. Used
164 for both MicroPython and Linux.
167 def __init__(self, clock, MOSI=None, MISO=None):
169 if detector.board.ftdi_ft232h:
170 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
171 from adafruit_blinka.microcontroller.ftdi_mpsse.ft232h.pin import (
178 self._pins = (SCK, MOSI, MISO)
180 if detector.board.binho_nova:
181 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
182 from adafruit_blinka.microcontroller.nova.pin import SCK, MOSI, MISO
184 self._spi = _SPI(clock)
185 self._pins = (SCK, MOSI, MISO)
187 if detector.board.greatfet_one:
188 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
189 from adafruit_blinka.microcontroller.nxp_lpc4330.pin import SCK, MOSI, MISO
192 self._pins = (SCK, MOSI, MISO)
194 if detector.board.pico_u2if:
195 from adafruit_blinka.microcontroller.pico_u2if.spi import SPI as _SPI
197 self._spi = _SPI(clock) # this is really all that's needed
198 self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock
200 if detector.chip.id == ap_chip.RP2040:
201 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
203 self._spi = _SPI(clock, MOSI, MISO) # Pins configured on instantiation
204 self._pins = (clock, clock, clock) # These don't matter, they're discarded
206 if detector.board.any_embedded_linux:
207 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
208 elif detector.board.ftdi_ft2232h:
209 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import SPI as _SPI
211 from adafruit_blinka.microcontroller.generic_micropython.spi import (
214 from microcontroller.pin import spiPorts
216 for portId, portSck, portMosi, portMiso in spiPorts:
219 and MOSI in (portMosi, None) # Clock is required!
220 and MISO in (portMiso, None) # But can do with just output
222 self._spi = _SPI(portId)
223 self._pins = (portSck, portMosi, portMiso)
227 "No Hardware SPI on (SCLK, MOSI, MISO)={}\nValid SPI ports:{}".format(
228 (clock, MOSI, MISO), spiPorts
232 def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
233 """Update the configuration"""
234 if detector.board.any_raspberry_pi or detector.board.any_raspberry_pi_40_pin:
235 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
236 elif detector.board.BEAGLEBONE_AI:
237 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
238 elif detector.board.any_beaglebone:
239 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
240 elif detector.board.any_orange_pi:
241 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
242 elif detector.board.any_nanopi and detector.chip.id == ap_chip.SUN8I:
243 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
244 elif board_id == ap_board.GIANT_BOARD:
245 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
246 elif board_id == ap_board.CORAL_EDGE_TPU_DEV:
247 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
248 elif board_id == ap_board.CORAL_EDGE_TPU_DEV_MINI:
249 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
250 elif board_id == ap_board.ODROID_C2:
251 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
252 elif board_id == ap_board.ODROID_C4:
253 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
254 elif board_id == ap_board.ODROID_XU4:
255 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
256 elif board_id == ap_board.DRAGONBOARD_410C:
257 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
258 elif board_id == ap_board.JETSON_NANO:
259 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
260 elif board_id == ap_board.JETSON_TX1:
261 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
262 elif board_id == ap_board.JETSON_TX2:
263 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
264 elif board_id == ap_board.JETSON_XAVIER:
265 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
266 elif board_id == ap_board.JETSON_NX:
267 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
268 elif detector.board.ROCK_PI_S:
269 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
270 elif detector.board.ROCK_PI_4:
271 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
272 elif detector.board.ROCK_PI_E:
273 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
274 elif detector.board.SIFIVE_UNLEASHED:
275 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
276 elif detector.board.ftdi_ft232h:
277 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
280 elif detector.board.ftdi_ft2232h:
281 from adafruit_blinka.microcontroller.ftdi_mpsse.mpsse.spi import (
284 elif detector.board.binho_nova:
285 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
286 elif detector.board.greatfet_one:
287 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
294 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
295 elif board_id == ap_board.PINEH64:
296 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
297 elif board_id == ap_board.CLOCKWORK_CPI3:
298 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
299 elif board_id == ap_board.ONION_OMEGA2:
300 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
301 elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
302 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
303 elif detector.board.pico_u2if:
304 from adafruit_blinka.microcontroller.pico_u2if.spi import SPI as _SPI
305 elif detector.chip.id == ap_chip.RP2040:
306 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
308 from adafruit_blinka.microcontroller.generic_micropython.spi import (
313 # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
322 raise RuntimeError("First call try_lock()")
325 """Deinitialization"""
331 """Return the baud rate if implemented"""
333 return self._spi.frequency
334 except AttributeError:
335 raise NotImplementedError(
336 "Frequency attribute not implemented for this platform"
337 ) from AttributeError
339 def write(self, buf, start=0, end=None):
340 """Write to the SPI device"""
341 return self._spi.write(buf, start, end)
343 def readinto(self, buf, start=0, end=None, write_value=0):
344 """Read from the SPI device into a buffer"""
345 return self._spi.readinto(buf, start, end, write_value=write_value)
348 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
350 """Write to the SPI device and read from the SPI device into a buffer"""
351 return self._spi.write_readinto(
352 buffer_out, buffer_in, out_start, out_end, in_start, in_end
356 class UART(Lockable):
358 Busio UART Class for CircuitPython Compatibility. Used
359 for MicroPython and a few other non-Linux boards.
363 """Parity Enumeration"""
365 pass # pylint: disable=unnecessary-pass
367 Parity.ODD = Parity()
368 Parity.EVEN = Parity()
379 receiver_buffer_size=64,
382 if detector.board.any_embedded_linux:
384 "busio.UART not supported on this platform. Please use pyserial instead."
386 if detector.board.binho_nova:
387 from adafruit_blinka.microcontroller.nova.uart import UART as _UART
388 elif detector.board.greatfet_one:
389 from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
390 elif detector.chip.id == ap_chip.RP2040:
391 from adafruit_blinka.microcontroller.rp2040.uart import UART as _UART
393 from machine import UART as _UART
395 from microcontroller.pin import uartPorts
397 self.baudrate = baudrate
399 if flow is not None: # default 0
400 raise NotImplementedError(
401 "Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
404 # translate parity flag for Micropython
405 if parity is UART.Parity.ODD:
407 elif parity is UART.Parity.EVEN:
412 raise ValueError("Invalid parity")
414 if detector.chip.id == ap_chip.RP2040:
424 # check tx and rx have hardware support
425 for portId, portTx, portRx in uartPorts: #
426 if portTx == tx and portRx == rx:
434 read_buf_len=receiver_buffer_size,
439 "No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
445 """Deinitialization"""
446 if detector.board.binho_nova:
450 def read(self, nbytes=None):
451 """Read from the UART"""
452 return self._uart.read(nbytes)
454 def readinto(self, buf, nbytes=None):
455 """Read from the UART into a buffer"""
456 return self._uart.readinto(buf, nbytes)
459 """Read a line of characters up to a newline charater from the UART"""
460 return self._uart.readline()
462 def write(self, buf):
463 """Write to the UART from a buffer"""
464 return self._uart.write(buf)
469 Stub class for OneWire, which is currently not implemented
472 def __init__(self, pin):
473 raise NotImplementedError("OneWire has not been implemented")
477 Deinitialize the OneWire bus and release any hardware resources for reuse.
479 raise NotImplementedError("OneWire has not been implemented")
483 Reset the OneWire bus and read presence
485 raise NotImplementedError("OneWire has not been implemented")
491 raise NotImplementedError("OneWire has not been implemented")
493 def write_bit(self, value):
495 Write out a bit based on value.
497 raise NotImplementedError("OneWire has not been implemented")