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.ROCK_PI_E:
265 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
266 elif detector.board.SIFIVE_UNLEASHED:
267 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
268 elif detector.board.ftdi_ft232h:
269 from adafruit_blinka.microcontroller.ft232h.spi import SPI as _SPI
270 elif detector.board.binho_nova:
271 from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
272 elif detector.board.greatfet_one:
273 from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
280 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
281 elif board_id == ap_board.PINEH64:
282 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
283 elif board_id == ap_board.CLOCKWORK_CPI3:
284 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
285 elif board_id == ap_board.ONION_OMEGA2:
286 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
287 elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL:
288 from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
289 elif detector.board.pico_u2if:
290 from adafruit_blinka.microcontroller.pico_u2if.spi import SPI as _SPI
291 elif detector.chip.id == ap_chip.RP2040:
292 from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
294 from adafruit_blinka.microcontroller.generic_micropython.spi import (
299 # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
308 raise RuntimeError("First call try_lock()")
311 """Deinitialization"""
317 """Return the baud rate if implemented"""
319 return self._spi.frequency
320 except AttributeError:
321 raise NotImplementedError(
322 "Frequency attribute not implemented for this platform"
323 ) from AttributeError
325 def write(self, buf, start=0, end=None):
326 """Write to the SPI device"""
327 return self._spi.write(buf, start, end)
329 def readinto(self, buf, start=0, end=None, write_value=0):
330 """Read from the SPI device into a buffer"""
331 return self._spi.readinto(buf, start, end, write_value=write_value)
334 self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
336 """Write to the SPI device and read from the SPI device into a buffer"""
337 return self._spi.write_readinto(
338 buffer_out, buffer_in, out_start, out_end, in_start, in_end
342 class UART(Lockable):
344 Busio UART Class for CircuitPython Compatibility. Used
345 for MicroPython and a few other non-Linux boards.
349 """Parity Enumeration"""
351 pass # pylint: disable=unnecessary-pass
353 Parity.ODD = Parity()
354 Parity.EVEN = Parity()
365 receiver_buffer_size=64,
368 if detector.board.any_embedded_linux:
370 "busio.UART not supported on this platform. Please use pyserial instead."
372 if detector.board.binho_nova:
373 from adafruit_blinka.microcontroller.nova.uart import UART as _UART
374 elif detector.board.greatfet_one:
375 from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
376 elif detector.chip.id == ap_chip.RP2040:
377 from adafruit_blinka.microcontroller.rp2040.uart import UART as _UART
379 from machine import UART as _UART
381 from microcontroller.pin import uartPorts
383 self.baudrate = baudrate
385 if flow is not None: # default 0
386 raise NotImplementedError(
387 "Parameter '{}' unsupported on {}".format("flow", agnostic.board_id)
390 # translate parity flag for Micropython
391 if parity is UART.Parity.ODD:
393 elif parity is UART.Parity.EVEN:
398 raise ValueError("Invalid parity")
400 if detector.chip.id == ap_chip.RP2040:
410 # check tx and rx have hardware support
411 for portId, portTx, portRx in uartPorts: #
412 if portTx == tx and portRx == rx:
420 read_buf_len=receiver_buffer_size,
425 "No Hardware UART on (tx,rx)={}\nValid UART ports: {}".format(
431 """Deinitialization"""
432 if detector.board.binho_nova:
436 def read(self, nbytes=None):
437 """Read from the UART"""
438 return self._uart.read(nbytes)
440 def readinto(self, buf, nbytes=None):
441 """Read from the UART into a buffer"""
442 return self._uart.readinto(buf, nbytes)
445 """Read a line of characters up to a newline charater from the UART"""
446 return self._uart.readline()
448 def write(self, buf):
449 """Write to the UART from a buffer"""
450 return self._uart.write(buf)
455 Stub class for OneWire, which is currently not implemented
458 def __init__(self, pin):
459 raise NotImplementedError("OneWire has not been implemented")
463 Deinitialize the OneWire bus and release any hardware resources for reuse.
465 raise NotImplementedError("OneWire has not been implemented")
469 Reset the OneWire bus and read presence
471 raise NotImplementedError("OneWire has not been implemented")
477 raise NotImplementedError("OneWire has not been implemented")
479 def write_bit(self, value):
481 Write out a bit based on value.
483 raise NotImplementedError("OneWire has not been implemented")