Expand description
One I2C bus, shared by a program and every driver on it.
A driver takes its bus by value, which is the right shape on a microcontroller: the program
owns the peripheral and hands it over once. A program on a host works differently. A gateway
keeps several parts on /dev/i2c-1, gives the same bus to a driver for each, and looks at
the bus itself between reads. A language binding needs the same, since it cannot give a
driver a Rust type at all. I2cBus is a handle to one bus that clones cheaply: every
clone reaches the same bus, and one transfer runs at a time.
Behind the handle is one of three things:
- The kernel’s adapter, opened with
I2cBus::open. Only Linux has one. - Simulated parts,
I2cBus::simulated, each answering at its own address from its registers the way asim::I2cPartdoes. A transfer to an address no part holds is not acknowledged, as on a real bus. - A script,
I2cBus::scripted, that plays one conversation and refuses any other, the way anI2cScriptdoes.
A driver also takes a delay. I2cBus::delay gives it one that suits the bus: the process
sleeps when real parts are on the other end, and carries straight on when simulated or
scripted ones are, since there is nothing to wait for. Either way the wait is counted, and
I2cBus::waited_micros is the total, so a test checks that a driver waited as long as its
datasheet asks without the test taking that long.
§Examples
use pamoja_hal::bus::I2cBus;
use pamoja_hal::i2c::I2c;
use pamoja_hal::sim::I2cPart;
// Two parts on one bus, each holding the id its datasheet gives: a BME280, whose chip
// id register reads 0x60, and a TMP117, whose 16-bit device id register reads 0x0117.
const BME280: u8 = 0x76;
const BME280_CHIP_ID_REGISTER: u8 = 0xD0;
const TMP117: u8 = 0x48;
const TMP117_DEVICE_ID_REGISTER: u8 = 0x0F;
let bus = I2cBus::simulated([
I2cPart::new(BME280).holding(BME280_CHIP_ID_REGISTER, &[0x60]),
I2cPart::new(TMP117).holding(TMP117_DEVICE_ID_REGISTER, &0x0117u16.to_be_bytes()),
]);
// A clone is what a driver is given; the program keeps the original.
let mut driver = bus.clone();
let mut id = [0u8; 1];
driver.write_read(BME280, &[BME280_CHIP_ID_REGISTER], &mut id)?;
assert_eq!(id, [0x60]);
// Nothing answers at the BME280's other address.
assert!(driver.write_read(BME280 + 1, &[BME280_CHIP_ID_REGISTER], &mut id).is_err());
assert_eq!(bus.transfers(), 2);Structs§
- BusDelay
- The delay a driver on an
I2cBuswaits with, fromI2cBus::delay. - I2cBus
- One I2C bus, reached by every clone of this handle.
- NotSimulated
- A part was put on a bus that is not simulated.