use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::mutex::Mutex;
use embedded_hal_async::i2c;
use crate::shared_bus::I2cDeviceError;
use crate::SetConfig;
pub struct I2cDevice<'a, M: RawMutex, BUS> {
bus: &'a Mutex<M, BUS>,
}
impl<'a, M: RawMutex, BUS> I2cDevice<'a, M, BUS> {
pub fn new(bus: &'a Mutex<M, BUS>) -> Self {
Self { bus }
}
}
impl<'a, M: RawMutex, BUS> i2c::ErrorType for I2cDevice<'a, M, BUS>
where
BUS: i2c::ErrorType,
{
type Error = I2cDeviceError<BUS::Error>;
}
impl<M, BUS> i2c::I2c for I2cDevice<'_, M, BUS>
where
M: RawMutex + 'static,
BUS: i2c::I2c + 'static,
{
async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), I2cDeviceError<BUS::Error>> {
let mut bus = self.bus.lock().await;
bus.read(address, read).await.map_err(I2cDeviceError::I2c)?;
Ok(())
}
async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), I2cDeviceError<BUS::Error>> {
let mut bus = self.bus.lock().await;
bus.write(address, write).await.map_err(I2cDeviceError::I2c)?;
Ok(())
}
async fn write_read(
&mut self,
address: u8,
write: &[u8],
read: &mut [u8],
) -> Result<(), I2cDeviceError<BUS::Error>> {
let mut bus = self.bus.lock().await;
bus.write_read(address, write, read)
.await
.map_err(I2cDeviceError::I2c)?;
Ok(())
}
async fn transaction(
&mut self,
address: u8,
operations: &mut [embedded_hal_async::i2c::Operation<'_>],
) -> Result<(), I2cDeviceError<BUS::Error>> {
let mut bus = self.bus.lock().await;
bus.transaction(address, operations)
.await
.map_err(I2cDeviceError::I2c)?;
Ok(())
}
}
pub struct I2cDeviceWithConfig<'a, M: RawMutex, BUS: SetConfig> {
bus: &'a Mutex<M, BUS>,
config: BUS::Config,
}
impl<'a, M: RawMutex, BUS: SetConfig> I2cDeviceWithConfig<'a, M, BUS> {
pub fn new(bus: &'a Mutex<M, BUS>, config: BUS::Config) -> Self {
Self { bus, config }
}
pub fn set_config(&mut self, config: BUS::Config) {
self.config = config;
}
}
impl<'a, M, BUS> i2c::ErrorType for I2cDeviceWithConfig<'a, M, BUS>
where
BUS: i2c::ErrorType,
M: RawMutex,
BUS: SetConfig,
{
type Error = I2cDeviceError<BUS::Error>;
}
impl<M, BUS> i2c::I2c for I2cDeviceWithConfig<'_, M, BUS>
where
M: RawMutex + 'static,
BUS: i2c::I2c + SetConfig + 'static,
{
async fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), I2cDeviceError<BUS::Error>> {
let mut bus = self.bus.lock().await;
bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
bus.read(address, buffer).await.map_err(I2cDeviceError::I2c)?;
Ok(())
}
async fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), I2cDeviceError<BUS::Error>> {
let mut bus = self.bus.lock().await;
bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
bus.write(address, bytes).await.map_err(I2cDeviceError::I2c)?;
Ok(())
}
async fn write_read(
&mut self,
address: u8,
wr_buffer: &[u8],
rd_buffer: &mut [u8],
) -> Result<(), I2cDeviceError<BUS::Error>> {
let mut bus = self.bus.lock().await;
bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
bus.write_read(address, wr_buffer, rd_buffer)
.await
.map_err(I2cDeviceError::I2c)?;
Ok(())
}
async fn transaction(&mut self, address: u8, operations: &mut [i2c::Operation<'_>]) -> Result<(), Self::Error> {
let mut bus = self.bus.lock().await;
bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?;
bus.transaction(address, operations)
.await
.map_err(I2cDeviceError::I2c)?;
Ok(())
}
}