embedded_registers/i2c/codecs/
simple_codec.rs1use crate::{ReadableRegister, WritableRegister};
2use bytemuck::Zeroable;
3
4#[derive(Default)]
24pub struct SimpleCodec<const HEADER_SIZE: usize> {}
25
26#[maybe_async_cfg::maybe(
27 idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), Codec, I2cBoundBus),
28 sync(feature = "sync"),
29 async(feature = "async"),
30 keep_self
31)]
32impl<const HEADER_SIZE: usize> crate::i2c::Codec for SimpleCodec<HEADER_SIZE> {
33 #[inline]
34 async fn read_register<R, I, A>(bound_bus: &mut crate::i2c::I2cBoundBus<I, A>) -> Result<R, I::Error>
35 where
36 R: ReadableRegister,
37 I: hal::i2c::I2c<A> + hal::i2c::ErrorType,
38 A: hal::i2c::AddressMode + Copy,
39 {
40 let header = &R::ADDRESS.to_be_bytes()[core::mem::size_of_val(&R::ADDRESS) - HEADER_SIZE..];
41 let mut register = R::zeroed();
42
43 bound_bus
44 .interface
45 .write_read(bound_bus.address, header, register.data_mut())
46 .await?;
47 Ok(register)
48 }
49
50 #[inline]
51 async fn write_register<R, I, A>(
52 bound_bus: &mut crate::i2c::I2cBoundBus<I, A>,
53 register: impl AsRef<R>,
54 ) -> Result<(), I::Error>
55 where
56 R: WritableRegister,
57 I: hal::i2c::I2c<A> + hal::i2c::ErrorType,
58 A: hal::i2c::AddressMode + Copy,
59 {
60 #[repr(C, packed(1))]
61 #[derive(Copy, Clone, bytemuck::Pod, Zeroable)]
62 struct Buffer<const HEADER_SIZE: usize, R> {
63 header: [u8; HEADER_SIZE],
64 register: R,
65 }
66
67 let mut buffer = Buffer::<{ HEADER_SIZE }, R> {
68 header: R::ADDRESS.to_be_bytes()[core::mem::size_of_val(&R::ADDRESS) - HEADER_SIZE..]
69 .try_into()
70 .expect("Unexpected compile-time header address size. This is a bug in the chosen Codec or embedded-registers."),
71 register: *register.as_ref(),
72 };
73
74 let data = bytemuck::bytes_of_mut(&mut buffer);
75 bound_bus.interface.write(bound_bus.address, data).await
76 }
77}