bitbangio
– Digital protocols implemented by the CPU¶
The bitbangio
module contains classes to provide digital bus protocol
support regardless of whether the underlying hardware exists to use the
protocol.
First try to use busio
module instead which may utilize peripheral
hardware to implement the protocols. Native implementations will be faster
than bitbanged versions and have more capabilities.
All classes change hardware state and should be deinitialized when they
are no longer needed if the program continues after use. To do so, either
call deinit()
or use a context manager. See
Lifetime and ContextManagers for more info.
For example:
import bitbangio
from board import *
i2c = bitbangio.I2C(SCL, SDA)
print(i2c.scan())
i2c.deinit()
This example will initialize the the device, run
scan()
and then deinit()
the
hardware. The last step is optional because CircuitPython automatically
resets hardware after a program finishes.
-
class
bitbangio.
I2C
(scl: microcontroller.Pin, sda: microcontroller.Pin, *, frequency: int = 400000, timeout: int = 255)¶ Two wire serial protocol
I2C is a two-wire protocol for communicating between devices. At the physical level it consists of 2 wires: SCL and SDA, the clock and data lines respectively.
See also
Using this class directly requires careful lock management. Instead, use
I2CDevice
to manage locks.See also
Using this class to directly read registers requires manual bit unpacking. Instead, use an existing driver or make one with Register data descriptors.
- Parameters
-
__enter__
(self) → I2C¶ No-op used in Context Managers.
-
__exit__
(self) → None¶ Automatically deinitializes the hardware on context exit. See Lifetime and ContextManagers for more info.
-
scan
(self) → List[int]¶ Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of those that respond. A device responds if it pulls the SDA line low after its address (including a read bit) is sent on the bus.
-
readfrom_into
(self, address: int, buffer: WriteableBuffer, *, start: int = 0, end: Optional[int] = None) → None¶ Read into
buffer
from the device selected byaddress
. The number of bytes read will be the length ofbuffer
. At least one byte must be read.If
start
orend
is provided, then the buffer will be sliced as ifbuffer[start:end]
. This will not cause an allocation likebuf[start:end]
will so it saves memory.- Parameters
address (int) – 7-bit device address
buffer (WriteableBuffer) – buffer to write into
start (int) – Index to start writing at
end (int) – Index to write up to but not include
-
writeto
(self, address: int, buffer: ReadableBuffer, *, start: int = 0, end: Optional[int] = None, stop: bool = True) → None¶ Write the bytes from
buffer
to the device selected byaddress
and then transmits a stop bit. Usewriteto_then_readfrom
when needing a write, no stop and repeated start before a read.If
start
orend
is provided, then the buffer will be sliced as ifbuffer[start:end]
. This will not cause an allocation likebuffer[start:end]
will so it saves memory.Writing a buffer or slice of length zero is permitted, as it can be used to poll for the existence of a device.
- Parameters
address (int) – 7-bit device address
buffer (ReadableBuffer) – buffer containing the bytes to write
start (int) – Index to start writing from
end (int) – Index to read up to but not include
-
writeto_then_readfrom
(self, address: int, out_buffer: ReadableBuffer, in_buffer: ReadableBuffer, *, out_start: int = 0, out_end: Optional[int] = None, in_start: int = 0, in_end: Optional[int] = None) → None¶ Write the bytes from
out_buffer
to the device selected byaddress
, generate no stop bit, generate a repeated start and read intoin_buffer
.out_buffer
andin_buffer
can be the same buffer because they are used sequentially.If
start
orend
is provided, then the corresponding buffer will be sliced as ifbuffer[start:end]
. This will not cause an allocation likebuf[start:end]
will so it saves memory.- Parameters
address (int) – 7-bit device address
out_buffer (ReadableBuffer) – buffer containing the bytes to write
in_buffer (WriteableBuffer) – buffer to write into
out_start (int) – Index to start writing from
out_end (int) – Index to read up to but not include. Defaults to
len(buffer)
in_start (int) – Index to start writing at
in_end (int) – Index to write up to but not include. Defaults to
len(buffer)
-
class
bitbangio.
OneWire
(pin: microcontroller.Pin)¶ Lowest-level of the Maxim OneWire protocol
OneWire
implements the timing-sensitive foundation of the Maxim (formerly Dallas Semi) OneWire protocol.Protocol definition is here: https://www.maximintegrated.com/en/app-notes/index.mvp/id/126
Create a OneWire object associated with the given pin. The object implements the lowest level timing-sensitive bits of the protocol.
- Parameters
pin (Pin) – Pin to read pulses from.
Read a short series of pulses:
import bitbangio import board onewire = bitbangio.OneWire(board.D7) onewire.reset() onewire.write_bit(True) onewire.write_bit(False) print(onewire.read_bit())
-
__enter__
(self) → OneWire¶ No-op used by Context Managers.
-
__exit__
(self) → None¶ Automatically deinitializes the hardware when exiting a context. See Lifetime and ContextManagers for more info.
-
class
bitbangio.
SPI
(clock: microcontroller.Pin, MOSI: Optional[microcontroller.Pin] = None, MISO: Optional[microcontroller.Pin] = None)¶ A 3-4 wire serial protocol
SPI is a serial protocol that has exclusive pins for data in and out of the main device. It is typically faster than
I2C
because a separate pin is used to select a device rather than a transmitted address. This class only manages three of the four SPI lines:clock
,MOSI
,MISO
. Its up to the client to manage the appropriate select line, often abbreviatedCS
orSS
. (This is common because multiple secondaries can share theclock
,MOSI
andMISO
lines and therefore the hardware.)Construct an SPI object on the given pins.
See also
Using this class directly requires careful lock management. Instead, use
SPIDevice
to manage locks.See also
Using this class to directly read registers requires manual bit unpacking. Instead, use an existing driver or make one with Register data descriptors.
- Parameters
-
__enter__
(self) → SPI¶ No-op used by Context Managers.
-
__exit__
(self) → None¶ Automatically deinitializes the hardware when exiting a context. See Lifetime and ContextManagers for more info.
-
configure
(self, *, baudrate: int = 100000, polarity: int = 0, phase: int = 0, bits: int = 8) → None¶ Configures the SPI bus. Only valid when locked.
-
try_lock
(self) → bool¶ Attempts to grab the SPI lock. Returns True on success.
- Returns
True when lock has been grabbed
- Return type
-
write
(self, buf: ReadableBuffer) → None¶ Write the data contained in
buf
. Requires the SPI being locked. If the buffer is empty, nothing happens.
-
readinto
(self, buf: WriteableBuffer) → None¶ Read into the buffer specified by
buf
while writing zeroes. Requires the SPI being locked. If the number of bytes to read is 0, nothing happens.
-
write_readinto
(self, buffer_out: ReadableBuffer, buffer_in: WriteableBuffer, *, out_start: int = 0, out_end: Optional[int] = None, in_start: int = 0, in_end: Optional[int] = None) → None¶ Write out the data in
buffer_out
while simultaneously reading data intobuffer_in
. The lengths of the slices defined bybuffer_out[out_start:out_end]
andbuffer_in[in_start:in_end]
must be equal. If buffer slice lengths are both 0, nothing happens.- Parameters
buffer_out (ReadableBuffer) – Write out the data in this buffer
buffer_in (WriteableBuffer) – Read data into this buffer
out_start (int) – Start of the slice of buffer_out to write out:
buffer_out[out_start:out_end]
out_end (int) – End of the slice; this index is not included. Defaults to
len(buffer_out)
in_start (int) – Start of the slice of
buffer_in
to read into:buffer_in[in_start:in_end]
in_end (int) – End of the slice; this index is not included. Defaults to
len(buffer_in)