//! Asynchronous shared I2C bus //! //! # Example (nrf52) //! //! ```rust //! use embassy_embedded_hal::shared_bus::i2c::I2cBusDevice; //! use embassy::mutex::Mutex; //! use embassy::blocking_mutex::raw::ThreadModeRawMutex; //! //! static I2C_BUS: Forever>> = Forever::new(); //! let config = twim::Config::default(); //! let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); //! let i2c = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config); //! let i2c_bus = Mutex::::new(i2c); //! let i2c_bus = I2C_BUS.put(i2c_bus); //! //! // Device 1, using embedded-hal-async compatible driver for QMC5883L compass //! let i2c_dev1 = I2cBusDevice::new(i2c_bus); //! let compass = QMC5883L::new(i2c_dev1).await.unwrap(); //! //! // Device 2, using embedded-hal-async compatible driver for Mpu6050 accelerometer //! let i2c_dev2 = I2cBusDevice::new(i2c_bus); //! let mpu = Mpu6050::new(i2c_dev2); //! ``` use core::fmt::Debug; use core::future::Future; use embassy::blocking_mutex::raw::RawMutex; use embassy::mutex::Mutex; use embedded_hal_async::i2c; use crate::shared_bus::I2cBusDeviceError; use crate::SetConfig; pub struct I2cBusDevice<'a, M: RawMutex, BUS> { bus: &'a Mutex, } impl<'a, M: RawMutex, BUS> I2cBusDevice<'a, M, BUS> { pub fn new(bus: &'a Mutex) -> Self { Self { bus } } } impl i2c::Error for I2cBusDeviceError where BUS: i2c::Error + Debug, { fn kind(&self) -> i2c::ErrorKind { match self { Self::I2c(e) => e.kind(), } } } impl<'a, M: RawMutex, BUS> i2c::ErrorType for I2cBusDevice<'a, M, BUS> where BUS: i2c::ErrorType, { type Error = I2cBusDeviceError; } impl i2c::I2c for I2cBusDevice<'_, M, BUS> where M: RawMutex + 'static, BUS: i2c::I2c + 'static, { type ReadFuture<'a> = impl Future> + 'a where Self: 'a; fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { async move { let mut bus = self.bus.lock().await; bus.read(address, buffer).await.map_err(I2cBusDeviceError::I2c)?; Ok(()) } } type WriteFuture<'a> = impl Future> + 'a where Self: 'a; fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> { async move { let mut bus = self.bus.lock().await; bus.write(address, bytes).await.map_err(I2cBusDeviceError::I2c)?; Ok(()) } } type WriteReadFuture<'a> = impl Future> + 'a where Self: 'a; fn write_read<'a>( &'a mut self, address: u8, wr_buffer: &'a [u8], rd_buffer: &'a mut [u8], ) -> Self::WriteReadFuture<'a> { async move { let mut bus = self.bus.lock().await; bus.write_read(address, wr_buffer, rd_buffer) .await .map_err(I2cBusDeviceError::I2c)?; Ok(()) } } type TransactionFuture<'a, 'b> = impl Future> + 'a where Self: 'a, 'b: 'a; fn transaction<'a, 'b>( &'a mut self, address: u8, operations: &'a mut [embedded_hal_async::i2c::Operation<'b>], ) -> Self::TransactionFuture<'a, 'b> { let _ = address; let _ = operations; async move { todo!() } } } pub struct I2cBusDeviceWithConfig<'a, M: RawMutex, BUS: SetConfig> { bus: &'a Mutex, config: BUS::Config, } impl<'a, M: RawMutex, BUS: SetConfig> I2cBusDeviceWithConfig<'a, M, BUS> { pub fn new(bus: &'a Mutex, config: BUS::Config) -> Self { Self { bus, config } } } impl<'a, M, BUS> i2c::ErrorType for I2cBusDeviceWithConfig<'a, M, BUS> where BUS: i2c::ErrorType, M: RawMutex, BUS: SetConfig, { type Error = I2cBusDeviceError; } impl i2c::I2c for I2cBusDeviceWithConfig<'_, M, BUS> where M: RawMutex + 'static, BUS: i2c::I2c + SetConfig + 'static, { type ReadFuture<'a> = impl Future> + 'a where Self: 'a; fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { async move { let mut bus = self.bus.lock().await; bus.set_config(&self.config); bus.read(address, buffer).await.map_err(I2cBusDeviceError::I2c)?; Ok(()) } } type WriteFuture<'a> = impl Future> + 'a where Self: 'a; fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> { async move { let mut bus = self.bus.lock().await; bus.set_config(&self.config); bus.write(address, bytes).await.map_err(I2cBusDeviceError::I2c)?; Ok(()) } } type WriteReadFuture<'a> = impl Future> + 'a where Self: 'a; fn write_read<'a>( &'a mut self, address: u8, wr_buffer: &'a [u8], rd_buffer: &'a mut [u8], ) -> Self::WriteReadFuture<'a> { async move { let mut bus = self.bus.lock().await; bus.set_config(&self.config); bus.write_read(address, wr_buffer, rd_buffer) .await .map_err(I2cBusDeviceError::I2c)?; Ok(()) } } type TransactionFuture<'a, 'b> = impl Future> + 'a where Self: 'a, 'b: 'a; fn transaction<'a, 'b>( &'a mut self, address: u8, operations: &'a mut [embedded_hal_async::i2c::Operation<'b>], ) -> Self::TransactionFuture<'a, 'b> { let _ = address; let _ = operations; async move { todo!() } } }