pub mod codecs;
use core::{any::TypeId, marker::PhantomData};
use codecs::NoCodec;
use crate::{ReadableRegister, WritableRegister};
#[maybe_async_cfg::maybe(
idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), I2cBoundBus),
sync(feature = "sync"),
async(feature = "async")
)]
#[allow(async_fn_in_trait)]
pub trait Codec: Default + 'static {
async fn read_register<R, I, A>(bound_bus: &mut I2cBoundBus<I, A>) -> Result<R, I::Error>
where
R: ReadableRegister,
I: hal::i2c::I2c<A> + hal::i2c::ErrorType,
A: hal::i2c::AddressMode + Copy;
async fn write_register<R, I, A>(
bound_bus: &mut I2cBoundBus<I, A>,
register: impl AsRef<R>,
) -> Result<(), I::Error>
where
R: WritableRegister,
I: hal::i2c::I2c<A> + hal::i2c::ErrorType,
A: hal::i2c::AddressMode + Copy;
}
#[maybe_async_cfg::maybe(
idents(hal(sync = "embedded_hal", async = "embedded_hal_async")),
sync(feature = "sync"),
async(feature = "async")
)]
pub struct I2cBoundBus<I, A>
where
I: hal::i2c::I2c<A> + hal::i2c::ErrorType,
A: hal::i2c::AddressMode + Copy,
{
pub interface: I,
pub address: A,
}
#[maybe_async_cfg::maybe(
idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), Codec, I2cBoundBus),
sync(feature = "sync"),
async(feature = "async")
)]
pub struct I2cDevice<I, A, C>
where
I: hal::i2c::I2c<A> + hal::i2c::ErrorType,
A: hal::i2c::AddressMode + Copy,
C: Codec,
{
pub bound_bus: I2cBoundBus<I, A>,
pub default_codec: PhantomData<C>,
}
#[maybe_async_cfg::maybe(
idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), Codec, I2cBoundBus),
sync(feature = "sync"),
async(feature = "async")
)]
impl<I, A, C> I2cDevice<I, A, C>
where
I: hal::i2c::I2c<A> + hal::i2c::ErrorType,
A: hal::i2c::AddressMode + Copy,
C: Codec,
{
pub fn new(interface: I, address: A) -> Self {
Self {
bound_bus: I2cBoundBus { interface, address },
default_codec: Default::default(),
}
}
}
#[maybe_async_cfg::maybe(
idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), Codec, RegisterInterface),
sync(feature = "sync"),
async(feature = "async")
)]
impl<I, A, C> crate::RegisterInterface for I2cDevice<I, A, C>
where
I: hal::i2c::I2c<A> + hal::i2c::ErrorType,
A: hal::i2c::AddressMode + Copy,
C: Codec,
{
type Error = I::Error;
#[inline]
async fn read_register<R>(&mut self) -> Result<R, I::Error>
where
R: ReadableRegister,
{
if TypeId::of::<R::I2cCodec>() == TypeId::of::<NoCodec>() {
C::read_register::<R, _, A>(&mut self.bound_bus).await
} else {
<R::I2cCodec as Codec>::read_register::<R, _, A>(&mut self.bound_bus).await
}
}
#[inline]
async fn write_register<R>(&mut self, register: impl AsRef<R>) -> Result<(), I::Error>
where
R: WritableRegister,
{
if TypeId::of::<R::I2cCodec>() == TypeId::of::<NoCodec>() {
C::write_register(&mut self.bound_bus, register).await
} else {
<R::I2cCodec as Codec>::write_register(&mut self.bound_bus, register).await
}
}
}