pub struct I2cBus { /* private fields */ }Expand description
One I2C bus, reached by every clone of this handle.
§Examples
use pamoja_hal::bus::{BusKind, I2cBus};
use pamoja_hal::i2c::I2c;
use pamoja_hal::script::{I2cScript, I2cStep};
// A script of one register read, a BME280 answering its chip id, and a driver that
// makes it.
const BME280: u8 = 0x76;
const CHIP_ID_REGISTER: u8 = 0xD0;
const BME280_CHIP_ID: u8 = 0x60;
let bus = I2cBus::scripted(I2cScript::new([I2cStep::write_read(
BME280,
[CHIP_ID_REGISTER],
[BME280_CHIP_ID],
)]));
let mut driver = bus.clone();
let mut id = [0u8; 1];
driver.write_read(BME280, &[CHIP_ID_REGISTER], &mut id)?;
assert_eq!(bus.kind(), BusKind::Scripted);
assert_eq!(bus.remaining(), Some(0), "the script has been played through");Implementations§
Source§impl I2cBus
impl I2cBus
Sourcepub fn open(path: impl AsRef<Path>) -> Result<I2cBus, OpenError>
pub fn open(path: impl AsRef<Path>) -> Result<I2cBus, OpenError>
Opens the kernel’s I2C adapter, such as /dev/i2c-1 on a Raspberry Pi.
§Arguments
path- the adapter’s device file.
§Returns
The bus, with the real parts wired to it on the other end.
§Errors
OpenError::Unsupported anywhere but Linux, or in a build without the linux
feature, and OpenError::Adapter when the file cannot be opened as an adapter: the
interface is not turned on, or the process may not use it.
§Examples
use pamoja_hal::bus::I2cBus;
let bus = I2cBus::open("/dev/i2c-1")?;Sourcepub fn simulated<P: Into<Part>>(parts: impl IntoIterator<Item = P>) -> I2cBus
pub fn simulated<P: Into<Part>>(parts: impl IntoIterator<Item = P>) -> I2cBus
A bus of simulated parts, each answering at its own address.
§Arguments
parts- the parts on the bus, of any of the three kinds, put on in order asI2cBus::attachputs them, so a part at an address an earlier one holds takes its place.
§Returns
The bus. A transfer to an address no part holds fails with
BusError::NoAcknowledge.
Sourcepub fn attach(
&self,
part: impl Into<Part>,
) -> Result<Option<Part>, NotSimulated>
pub fn attach( &self, part: impl Into<Part>, ) -> Result<Option<Part>, NotSimulated>
Puts a simulated part on the bus, in place of any part already at its address.
A driver keeps working across the change, which is how a test moves a reading on: a part built to report different values takes the old one’s place.
§Arguments
part- the part, of any of the three kinds.
§Returns
The part it replaced, or None when the address was free.
§Errors
NotSimulated when the bus is the kernel’s adapter or a script.
Sourcepub fn scripted(script: I2cScript) -> I2cBus
pub fn scripted(script: I2cScript) -> I2cBus
A bus that plays one conversation and refuses any other.
§Arguments
script- the transfers a driver is expected to make, in order, and the replies.
§Returns
The bus. A transfer that does not match the next step fails with
BusError::Script and consumes nothing.
Sourcepub fn part<P: FromPart>(&self, address: u8) -> Option<P>
pub fn part<P: FromPart>(&self, address: u8) -> Option<P>
What a simulated part holds now, as the kind of part the caller names.
§Arguments
address- the part’s address.
§Returns
A copy of the part, with whatever drivers have written to it, or None when the bus
is not simulated, no part holds the address, or the part there is another kind. Ask
for a Part to take any kind.
§Examples
use pamoja_hal::bus::I2cBus;
use pamoja_hal::i2c::I2c;
use pamoja_hal::sim::{I2cPart, WordPart};
// A driver asks a BME280 for one forced measurement: ctrl_meas takes one temperature
// sample, one pressure sample, and forced mode, in its three fields.
const BME280: u8 = 0x76;
const CTRL_MEAS: u8 = 0xF4;
const FORCED_ONCE: u8 = 0b001_001_01;
let mut bus = I2cBus::simulated([I2cPart::new(BME280)]);
bus.write(BME280, &[CTRL_MEAS, FORCED_ONCE])?;
// The program looks at what the driver left in the part.
let part: I2cPart = bus.part(BME280).expect("a byte-wide part");
assert_eq!(part.register(CTRL_MEAS), FORCED_ONCE);
assert!(bus.part::<WordPart>(BME280).is_none(), "it is not a word-wide one");Sourcepub fn transfers(&self) -> usize
pub fn transfers(&self) -> usize
How many transfers have been made on the bus, by every clone, including any that failed.
§Returns
The count, one per transaction however many operations it held.
Sourcepub fn remaining(&self) -> Option<usize>
pub fn remaining(&self) -> Option<usize>
How many steps a script has left.
§Returns
The steps not yet reached, Some(0) once a driver has made every transfer the script
expected, or None when the bus is not scripted.
Sourcepub fn waited_micros(&self) -> u64
pub fn waited_micros(&self) -> u64
How long the drivers on the bus have asked to wait, through I2cBus::delay.
§Returns
The total in microseconds, counted whether or not the process slept through it.
Sourcepub fn delay(&self) -> BusDelay
pub fn delay(&self) -> BusDelay
The delay a driver on this bus waits with.
§Returns
A delay that sleeps the process when the bus is the kernel’s adapter, returns at once
when it is simulated or scripted, and adds every wait to I2cBus::waited_micros.