CircuitPython APIs for non-CircuitPython versions of Python such as CPython on Linux and MicroPython.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Software implementations of I2C and SPI communication protocols using bit-banging techniques. These implementations work on platforms without dedicated hardware communication peripherals or when hardware peripherals are already in use.
Bit-banged I2C implementation using GPIO pins for clock and data lines. Provides the same interface as hardware I2C but implemented in software.
class I2C(Lockable):
def __init__(self, scl, sda, frequency: int = 400000):
"""
Initialize software I2C interface.
Parameters:
- scl: Pin to use for I2C clock line
- sda: Pin to use for I2C data line
- frequency: I2C frequency in Hz (default 400000)
Raises:
- NotImplementedError: On Pyboard or Linux platforms
"""
def scan(self) -> list[int]:
"""
Scan I2C bus for connected devices.
Returns:
List of device addresses found on the bus
"""
def readfrom_into(self, address: int, buffer: bytearray, start: int = 0, end: int = None) -> None:
"""
Read data from I2C device into existing buffer.
Parameters:
- address: 7-bit I2C device address
- buffer: Buffer to read data into
- start: Starting index in buffer (default 0)
- end: Ending index in buffer (default None for full buffer)
"""
def writeto(self, address: int, buffer: bytes, start: int = 0, end: int = None, stop: bool = True) -> int:
"""
Write data to I2C device from buffer.
Parameters:
- address: 7-bit I2C device address
- buffer: Data to write
- start: Starting index in buffer (default 0)
- end: Ending index in buffer (default None for full buffer)
- stop: Send I2C stop condition (default True)
Returns:
Number of bytes written
"""Bit-banged SPI implementation using GPIO pins for clock, MOSI, and MISO lines. Provides SPI communication when hardware SPI is unavailable.
class SPI(Lockable):
def __init__(self, clock, MOSI=None, MISO=None):
"""
Initialize software SPI interface.
Parameters:
- clock: Pin to use for SPI clock
- MOSI: Pin to use for Master Out Slave In (optional)
- MISO: Pin to use for Master In Slave Out (optional)
Raises:
- NotImplementedError: On Linux platforms
"""
def configure(self, baudrate: int = 100000, polarity: int = 0, phase: int = 0, bits: int = 8) -> None:
"""
Configure SPI communication parameters.
Parameters:
- baudrate: SPI clock frequency in Hz (default 100000)
- polarity: Clock polarity (0 or 1, default 0)
- phase: Clock phase (0 or 1, default 0)
- bits: Bits per transfer (default 8)
Raises:
- RuntimeError: If try_lock() has not been called
"""
def write(self, buf: bytes) -> None:
"""
Write data to SPI device.
Parameters:
- buf: Data buffer to write
"""
def readinto(self, buf: bytearray) -> None:
"""
Read data from SPI device into buffer.
Parameters:
- buf: Buffer to read data into
"""
def write_readinto(self, buffer_out: bytes, buffer_in: bytearray) -> None:
"""
Simultaneously write and read data over SPI.
Parameters:
- buffer_out: Data to write
- buffer_in: Buffer to read data into
"""import bitbangio
import board
# Initialize software I2C
i2c = bitbangio.I2C(board.SCL, board.SDA, frequency=100000)
# Scan for devices
devices = i2c.scan()
print(f"Found devices: {[hex(d) for d in devices]}")
# Read from device
if devices:
data = bytearray(4)
i2c.readfrom_into(devices[0], data)
print(f"Data: {list(data)}")
i2c.deinit()import bitbangio
import board
# Initialize software SPI
spi = bitbangio.SPI(board.SCLK, MOSI=board.MOSI, MISO=board.MISO)
# Configure SPI parameters
if spi.try_lock():
try:
spi.configure(baudrate=1000000, polarity=0, phase=0)
# Write data
spi.write(b'\x01\x02\x03\x04')
# Read data
buffer = bytearray(4)
spi.readinto(buffer)
print(f"Read: {list(buffer)}")
finally:
spi.unlock()
spi.deinit()Install with Tessl CLI
npx tessl i tessl/pypi-adafruit-blinka