Skip to content

Instantly share code, notes, and snippets.

@anarsoul
Created June 6, 2025 00:32
Show Gist options
  • Select an option

  • Save anarsoul/55fcbb90f141266f12a9c85d2aba2176 to your computer and use it in GitHub Desktop.

Select an option

Save anarsoul/55fcbb90f141266f12a9c85d2aba2176 to your computer and use it in GitHub Desktop.
use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::mutex::Mutex;
use embedded_hal_async::i2c;
use core::fmt::Debug;
use core::ops::DerefMut;
use esp_hal::gpio::AnyPin;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum I2cDeviceError {
/// An operation on the inner I2C bus failed.
I2c(esp_hal::i2c::master::Error),
/// Configuration of the inner I2C bus failed.
Config,
}
impl i2c::Error for I2cDeviceError
{
fn kind(&self) -> i2c::ErrorKind {
match self {
Self::I2c(e) => e.kind(),
Self::Config => i2c::ErrorKind::Other,
}
}
}
/// I2C device on a shared bus.
pub struct I2cDevice<'a, M: RawMutex> {
bus: &'a Mutex<M, esp_hal::i2c::master::I2c<'a, esp_hal::Async>>,
scl: AnyPin<'a>,
sda: AnyPin<'a>,
}
impl<'a, M: RawMutex> I2cDevice<'a, M> {
/// Create a new `I2cDevice`.
pub fn new(bus: &'a Mutex<M, esp_hal::i2c::master::I2c<'a, esp_hal::Async>>,
scl: AnyPin<'a>,
sda: AnyPin<'a>) -> Self {
Self { bus, scl, sda }
}
}
impl<'a, M: RawMutex> i2c::ErrorType for I2cDevice<'a, M>
where
{
type Error = I2cDeviceError;
}
impl<M> i2c::I2c for I2cDevice<'_, M>
where
M: RawMutex + 'static,
{
async fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), I2cDeviceError> {
let mut bus = self.bus.lock().await;
bus.read_async(address, read).await.map_err(I2cDeviceError::I2c)?;
Ok(())
}
async fn write(&mut self, address: u8, write: &[u8]) -> Result<(), I2cDeviceError> {
let mut bus = self.bus.lock().await;
bus.write_async(address, write).await.map_err(I2cDeviceError::I2c)?;
Ok(())
}
async fn write_read(
&mut self,
address: u8,
write: &[u8],
read: &mut [u8],
) -> Result<(), I2cDeviceError> {
let mut bus = self.bus.lock().await;
bus.write_read_async(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> {
let mut bus = self.bus.lock().await;
embedded_hal_async::i2c::I2c::transaction(bus.deref_mut(), address, operations)
.await
.map_err(I2cDeviceError::I2c)?;
Ok(())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment