2024-03-03 17:02:33 +00:00
|
|
|
use anyhow::anyhow;
|
2024-03-03 17:05:01 +00:00
|
|
|
use core::fmt::{Display, Formatter};
|
2024-02-27 20:09:16 +00:00
|
|
|
use embedded_hal::i2c::I2c;
|
2024-02-26 20:01:42 +00:00
|
|
|
|
|
|
|
///
|
|
|
|
/// Represents the I2C address of the BME680 Sensor.
|
|
|
|
///
|
2024-02-27 20:12:24 +00:00
|
|
|
#[derive(Debug, Clone, Copy, Default)]
|
2024-02-26 20:01:42 +00:00
|
|
|
pub enum Address {
|
|
|
|
/// Primary Address 0x76
|
2024-02-27 20:12:24 +00:00
|
|
|
#[default]
|
2024-02-26 20:01:42 +00:00
|
|
|
Primary,
|
|
|
|
/// Secondary Address 0x77
|
|
|
|
Secondary,
|
|
|
|
/// Alternative address
|
|
|
|
Other(u8),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Address {
|
|
|
|
pub fn addr(&self) -> u8 {
|
|
|
|
match &self {
|
|
|
|
Address::Primary => 0x76u8,
|
|
|
|
Address::Secondary => 0x77u8,
|
|
|
|
Address::Other(addr) => *addr,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-03 17:02:33 +00:00
|
|
|
impl Display for Address {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
|
|
|
write!(f, "Address={:#01x}", self.addr())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-26 20:01:42 +00:00
|
|
|
/// I2CUtility is a simple wrapper over the I2c trait to make reading and writing data easier.
|
|
|
|
pub(crate) struct I2CUtility {}
|
|
|
|
|
|
|
|
impl I2CUtility {
|
|
|
|
/// Reads a byte from the I2C bus.
|
|
|
|
pub fn read_byte<I2C: I2c>(
|
|
|
|
i2c_handle: &mut I2C,
|
|
|
|
device_address: u8,
|
|
|
|
register_address: u8,
|
2024-03-03 17:02:33 +00:00
|
|
|
) -> Result<u8, anyhow::Error> {
|
2024-02-26 20:01:42 +00:00
|
|
|
let mut buf = [0; 1];
|
|
|
|
|
2024-02-27 20:09:16 +00:00
|
|
|
i2c_handle
|
|
|
|
.write(device_address, &[register_address])
|
2024-03-03 17:05:01 +00:00
|
|
|
.map_err(|e| {
|
|
|
|
anyhow!(
|
|
|
|
"Failed to write a byte {} to device {}: {:?}",
|
|
|
|
register_address,
|
|
|
|
device_address,
|
|
|
|
e
|
|
|
|
)
|
|
|
|
})?;
|
2024-02-26 20:01:42 +00:00
|
|
|
|
|
|
|
match i2c_handle.read(device_address, &mut buf) {
|
|
|
|
Ok(()) => Ok(buf[0]),
|
2024-03-03 17:05:01 +00:00
|
|
|
Err(_e) => Err(anyhow!(
|
|
|
|
"Failed to read byte {} from device {}",
|
|
|
|
register_address,
|
|
|
|
device_address
|
|
|
|
)),
|
2024-02-26 20:01:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Reads bytes from the I2C bus.
|
|
|
|
pub fn read_bytes<I2C: I2c>(
|
|
|
|
i2c_handle: &mut I2C,
|
|
|
|
device_address: u8,
|
|
|
|
register_address: u8,
|
|
|
|
buffer: &mut [u8],
|
2024-03-03 17:02:33 +00:00
|
|
|
) -> Result<(), anyhow::Error> {
|
2024-02-27 20:09:16 +00:00
|
|
|
i2c_handle
|
|
|
|
.write(device_address, &[register_address])
|
2024-03-03 17:05:01 +00:00
|
|
|
.map_err(|_e| {
|
|
|
|
anyhow!(
|
|
|
|
"Failed to write a byte {} from device {}",
|
|
|
|
register_address,
|
|
|
|
device_address
|
|
|
|
)
|
|
|
|
})?;
|
2024-02-26 20:01:42 +00:00
|
|
|
|
|
|
|
match i2c_handle.read(device_address, buffer) {
|
|
|
|
Ok(()) => Ok(()),
|
2024-03-03 17:05:01 +00:00
|
|
|
Err(_e) => Err(anyhow!(
|
|
|
|
"Failed to read bytes from register {} and device {}",
|
|
|
|
register_address,
|
|
|
|
device_address
|
|
|
|
)),
|
2024-02-26 20:01:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Writes bytes to the I2C bus.
|
2024-02-27 20:09:16 +00:00
|
|
|
pub fn write_bytes<I2C: I2c>(
|
|
|
|
i2c_handle: &mut I2C,
|
|
|
|
device_address: u8,
|
|
|
|
buffer: &[u8],
|
2024-03-03 17:02:33 +00:00
|
|
|
) -> Result<(), anyhow::Error> {
|
2024-02-27 20:09:16 +00:00
|
|
|
i2c_handle
|
2024-02-27 20:12:24 +00:00
|
|
|
.write(device_address, buffer)
|
2024-03-03 17:02:33 +00:00
|
|
|
.map_err(|_e| anyhow!("Failed to write bytes to address {}", device_address))
|
2024-02-26 20:01:42 +00:00
|
|
|
}
|
|
|
|
}
|