1use embedded_hal::spi::Operation;
2
3#[cfg(feature = "blocking")]
4use embedded_hal::i2c::I2c as HalI2c;
5#[cfg(feature = "blocking")]
6use embedded_hal::spi::SpiDevice as HalSpiDevice;
7#[cfg(not(feature = "blocking"))]
8use embedded_hal_async::i2c::I2c as HalI2c;
9#[cfg(not(feature = "blocking"))]
10use embedded_hal_async::spi::SpiDevice as HalSpiDevice;
11
12use crate::Bmi323;
13
14pub const MAX_WORDS_PER_READ: usize = 64;
19
20pub struct I2cTransport<I2C> {
25 pub(crate) bus: I2C,
26 pub(crate) address: u8,
27}
28
29pub struct SpiTransport<SPI> {
34 pub(crate) bus: SPI,
35}
36
37#[cfg(feature = "blocking")]
45pub trait Access {
46 type BusError;
48 fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError>;
50 fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError>;
52 fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError>;
54}
55
56#[cfg(not(feature = "blocking"))]
57#[allow(async_fn_in_trait)]
58pub trait Access {
59 type BusError;
61 async fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError>;
63 async fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError>;
65 async fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError>;
67}
68
69#[cfg(feature = "blocking")]
72impl<I2C: HalI2c> Access for Bmi323<I2cTransport<I2C>> {
73 type BusError = I2C::Error;
74
75 fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError> {
76 let mut bytes = [0u8; 4];
78 self.transport
79 .bus
80 .write_read(self.transport.address, &[reg], &mut bytes)?;
81 Ok(u16::from_le_bytes([bytes[2], bytes[3]]))
82 }
83
84 fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError> {
85 let [lo, hi] = word.to_le_bytes();
86 self.transport
87 .bus
88 .write(self.transport.address, &[reg, lo, hi])
89 }
90
91 fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError> {
92 let mut bytes = [0u8; 2 + MAX_WORDS_PER_READ * 2];
94 let byte_len = words.len() * 2 + 2;
95 self.transport
96 .bus
97 .write_read(self.transport.address, &[reg], &mut bytes[..byte_len])?;
98 for (index, word) in words.iter_mut().enumerate() {
99 let offset = 2 + index * 2;
100 *word = u16::from_le_bytes([bytes[offset], bytes[offset + 1]]);
101 }
102 Ok(())
103 }
104}
105
106#[cfg(not(feature = "blocking"))]
109impl<I2C: HalI2c> Access for Bmi323<I2cTransport<I2C>> {
110 type BusError = I2C::Error;
111
112 async fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError> {
113 let mut bytes = [0u8; 4];
115 self.transport
116 .bus
117 .write_read(self.transport.address, &[reg], &mut bytes)
118 .await?;
119 Ok(u16::from_le_bytes([bytes[2], bytes[3]]))
120 }
121
122 async fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError> {
123 let [lo, hi] = word.to_le_bytes();
124 self.transport
125 .bus
126 .write(self.transport.address, &[reg, lo, hi])
127 .await
128 }
129
130 async fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError> {
131 let mut bytes = [0u8; 2 + MAX_WORDS_PER_READ * 2];
133 let byte_len = words.len() * 2 + 2;
134 self.transport
135 .bus
136 .write_read(self.transport.address, &[reg], &mut bytes[..byte_len])
137 .await?;
138 for (index, word) in words.iter_mut().enumerate() {
139 let offset = 2 + index * 2;
140 *word = u16::from_le_bytes([bytes[offset], bytes[offset + 1]]);
141 }
142 Ok(())
143 }
144}
145
146#[cfg(feature = "blocking")]
149impl<SPI: HalSpiDevice<u8>> Access for Bmi323<SpiTransport<SPI>> {
150 type BusError = SPI::Error;
151
152 fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError> {
153 let cmd = 0x80 | (reg & 0x7F);
155 let mut bytes = [0u8; 3];
157 let cmd_buf = [cmd];
158 let mut ops = [Operation::Write(&cmd_buf), Operation::Read(&mut bytes)];
159 self.transport.bus.transaction(&mut ops)?;
160 Ok(u16::from_le_bytes([bytes[1], bytes[2]]))
161 }
162
163 fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError> {
164 let [lo, hi] = word.to_le_bytes();
165 let payload = [reg & 0x7F, lo, hi];
166 self.transport.bus.write(&payload)
167 }
168
169 fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError> {
170 let cmd = 0x80 | (reg & 0x7F);
172 let mut bytes = [0u8; 1 + MAX_WORDS_PER_READ * 2];
174 let byte_len = words.len() * 2 + 1;
175 let cmd_buf = [cmd];
176 let mut ops = [
177 Operation::Write(&cmd_buf),
178 Operation::Read(&mut bytes[..byte_len]),
179 ];
180 self.transport.bus.transaction(&mut ops)?;
181 for (index, word) in words.iter_mut().enumerate() {
182 let offset = 1 + index * 2;
183 *word = u16::from_le_bytes([bytes[offset], bytes[offset + 1]]);
184 }
185 Ok(())
186 }
187}
188
189#[cfg(not(feature = "blocking"))]
192impl<SPI: HalSpiDevice<u8>> Access for Bmi323<SpiTransport<SPI>> {
193 type BusError = SPI::Error;
194
195 async fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError> {
196 let cmd = 0x80 | (reg & 0x7F);
198 let mut bytes = [0u8; 3];
200 let cmd_buf = [cmd];
201 let mut ops = [Operation::Write(&cmd_buf), Operation::Read(&mut bytes)];
202 self.transport.bus.transaction(&mut ops).await?;
203 Ok(u16::from_le_bytes([bytes[1], bytes[2]]))
204 }
205
206 async fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError> {
207 let [lo, hi] = word.to_le_bytes();
208 let payload = [reg & 0x7F, lo, hi];
209 self.transport.bus.write(&payload).await
210 }
211
212 async fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError> {
213 let cmd = 0x80 | (reg & 0x7F);
215 let mut bytes = [0u8; 1 + MAX_WORDS_PER_READ * 2];
217 let byte_len = words.len() * 2 + 1;
218 let cmd_buf = [cmd];
219 let mut ops = [
220 Operation::Write(&cmd_buf),
221 Operation::Read(&mut bytes[..byte_len]),
222 ];
223 self.transport.bus.transaction(&mut ops).await?;
224 for (index, word) in words.iter_mut().enumerate() {
225 let offset = 1 + index * 2;
226 *word = u16::from_le_bytes([bytes[offset], bytes[offset + 1]]);
227 }
228 Ok(())
229 }
230}