embedded_registers/spi/codecs/
simple_codec.rs1use crate::{ReadableRegister, Register, WritableRegister};
2use bytemuck::Zeroable;
3
4pub struct SimpleCodec<
31 const HEADER_SIZE: usize,
32 const ADDR_MSB: u8,
33 const ADDR_LSB: u8,
34 const RW_BIT: u8,
35 const RW_1_IS_READ: bool,
36 const READ_DELAY: usize,
37> {}
38
39impl<
40 const HEADER_SIZE: usize,
41 const ADDR_MSB: u8,
42 const ADDR_LSB: u8,
43 const RW_BIT: u8,
44 const RW_1_IS_READ: bool,
45 const READ_DELAY: usize,
46 > SimpleCodec<HEADER_SIZE, ADDR_MSB, ADDR_LSB, RW_BIT, RW_1_IS_READ, READ_DELAY>
47{
48 #[inline]
49 pub fn fill_addr_header<R>(header: &mut [u8])
50 where
51 R: Register,
52 {
53 let addr_mask = u64::checked_shl(1, ADDR_MSB as u32 + 1).unwrap_or(0).wrapping_sub(1);
57 let addr_shifted = (R::ADDRESS << ADDR_LSB) & addr_mask;
59 let addr_bytes = addr_shifted.to_le_bytes();
61 let affected_bytes = ((ADDR_MSB - ADDR_LSB) / 8) as usize;
62 for i in 0..=affected_bytes {
63 header[HEADER_SIZE - 1 - i] |= addr_bytes[i];
64 }
65 }
66}
67
68#[maybe_async_cfg::maybe(
69 idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), Codec),
70 sync(feature = "sync"),
71 async(feature = "async"),
72 keep_self
73)]
74impl<
75 const HEADER_SIZE: usize,
76 const ADDR_MSB: u8,
77 const ADDR_LSB: u8,
78 const RW_BIT: u8,
79 const RW_1_IS_READ: bool,
80 const READ_DELAY: usize,
81 > crate::spi::Codec for SimpleCodec<HEADER_SIZE, ADDR_MSB, ADDR_LSB, RW_BIT, RW_1_IS_READ, READ_DELAY>
82{
83 #[inline]
84 async fn read_register<R, I>(interface: &mut I) -> Result<R, I::Error>
85 where
86 R: ReadableRegister,
87 I: hal::spi::r#SpiDevice,
88 {
89 #[repr(C, packed(1))]
90 #[derive(Copy, Clone, bytemuck::Pod, Zeroable)]
91 struct Buffer<const HEADER_SIZE: usize, const READ_DELAY: usize, R> {
92 header: [u8; HEADER_SIZE],
93 delay: [u8; READ_DELAY],
94 register: R,
95 }
96
97 let mut buffer = Buffer::<{ HEADER_SIZE }, { READ_DELAY }, R>::zeroed();
98 let data = bytemuck::bytes_of_mut(&mut buffer);
99 data[HEADER_SIZE - 1 - (RW_BIT as usize) / 8] |= (RW_1_IS_READ as u8) << (RW_BIT % 8);
101 Self::fill_addr_header::<R>(data);
102 interface.transfer_in_place(data).await?;
103 Ok(buffer.register)
104 }
105
106 #[inline]
107 async fn write_register<R, I>(interface: &mut I, register: impl AsRef<R>) -> Result<(), I::Error>
108 where
109 R: WritableRegister,
110 I: hal::spi::r#SpiDevice,
111 {
112 #[repr(C, packed(1))]
113 #[derive(Copy, Clone, bytemuck::Pod, Zeroable)]
114 struct Buffer<const HEADER_SIZE: usize, R> {
115 header: [u8; HEADER_SIZE],
116 register: R,
117 }
118
119 let mut buffer = Buffer::<{ HEADER_SIZE }, R> {
120 header: [0u8; HEADER_SIZE],
121 register: *register.as_ref(),
122 };
123
124 let data = bytemuck::bytes_of_mut(&mut buffer);
125 data[HEADER_SIZE - 1 - (RW_BIT as usize) / 8] |= ((!RW_1_IS_READ) as u8) << (RW_BIT % 8);
127 Self::fill_addr_header::<R>(data);
128 interface.write(data).await
129 }
130}