use crate::TransportError;
use crate::registers::{ReadableRegister, Register, RegisterCodec, WritableRegister};
use bytemuck::Zeroable;
#[derive(Default)]
pub struct StandardCodec<const HEADER_SIZE: usize> {}
impl<const HEADER_SIZE: usize> RegisterCodec for StandardCodec<HEADER_SIZE> {
type Error = ();
}
#[maybe_async_cfg::maybe(
idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), Codec, I2cBoundBus),
sync(feature = "sync"),
async(feature = "async"),
keep_self
)]
impl<const HEADER_SIZE: usize> crate::registers::i2c::Codec for StandardCodec<HEADER_SIZE> {
#[inline]
async fn read_register<R, I, A>(
bound_bus: &mut crate::i2c::I2cBoundBus<I, A>,
) -> Result<R, TransportError<Self::Error, I::Error>>
where
R: Register<CodecError = Self::Error> + ReadableRegister,
I: hal::i2c::I2c<A> + hal::i2c::ErrorType,
A: hal::i2c::AddressMode + Copy + core::fmt::Debug,
{
let header = &R::ADDRESS.to_be_bytes()[core::mem::size_of_val(&R::ADDRESS) - HEADER_SIZE..];
let mut register = R::zeroed();
let data = bytemuck::bytes_of_mut(&mut register);
bound_bus.interface.write_read(bound_bus.address, header, data).await?;
#[cfg(feature = "trace-communication")]
log::trace!(
"I2C [32mread[m i2c_addr={:?} register_addr={:08x}:\n{}",
bound_bus.address,
R::ADDRESS,
register.bitdump()
);
Ok(register)
}
#[inline]
async fn write_register<R, I, A>(
bound_bus: &mut crate::i2c::I2cBoundBus<I, A>,
register: impl AsRef<R>,
) -> Result<(), TransportError<Self::Error, I::Error>>
where
R: Register<CodecError = Self::Error> + WritableRegister,
I: hal::i2c::I2c<A> + hal::i2c::ErrorType,
A: hal::i2c::AddressMode + Copy + core::fmt::Debug,
{
#[cfg(feature = "trace-communication")]
log::trace!(
"I2C [31mwrite[m i2c_addr={:?} register_addr={:08x}:\n{}",
bound_bus.address,
R::ADDRESS,
register.as_ref().bitdump()
);
#[repr(C, packed(1))]
#[derive(Copy, Clone, bytemuck::Pod, Zeroable)]
struct Buffer<const HEADER_SIZE: usize, R> {
header: [u8; HEADER_SIZE],
register: R,
}
let mut buffer = Buffer::<{ HEADER_SIZE }, R> {
header: R::ADDRESS.to_be_bytes()[core::mem::size_of_val(&R::ADDRESS) - HEADER_SIZE..]
.try_into()
.map_err(|_| TransportError::Unexpected("wrong register address size - should not be able to occur"))?,
register: *register.as_ref(),
};
let data = bytemuck::bytes_of_mut(&mut buffer);
Ok(bound_bus.interface.write(bound_bus.address, data).await?)
}
}