1use embedded_hal::i2c::I2c;
2use embedded_hal::spi::{Operation, SpiDevice};
3use embedded_hal_async::i2c::I2c as AsyncI2c;
4use embedded_hal_async::spi::SpiDevice as AsyncSpiDevice;
5
6use crate::{Bmi323, Bmi323Async};
7
8pub struct SyncI2cTransport<I2C> {
13 pub(crate) bus: I2C,
14 pub(crate) address: u8,
15}
16
17pub struct SyncSpiTransport<SPI> {
22 pub(crate) bus: SPI,
23}
24
25pub struct AsyncI2cTransport<I2C> {
30 pub(crate) bus: I2C,
31 pub(crate) address: u8,
32}
33
34pub struct AsyncSpiTransport<SPI> {
39 pub(crate) bus: SPI,
40}
41
42pub trait SyncAccess {
47 type BusError;
49
50 fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError>;
52
53 fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError>;
55
56 fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError>;
58}
59
60#[allow(async_fn_in_trait)]
61pub trait AsyncAccess {
66 type BusError;
68
69 async fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError>;
71
72 async fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError>;
74
75 async fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError>;
77}
78
79impl<I2C> SyncAccess for Bmi323<SyncI2cTransport<I2C>>
80where
81 I2C: I2c,
82{
83 type BusError = I2C::Error;
84
85 fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError> {
86 let mut bytes = [0u8; 4];
87 self.transport
88 .bus
89 .write_read(self.transport.address, &[reg], &mut bytes)?;
90 Ok(u16::from_le_bytes([bytes[2], bytes[3]]))
91 }
92
93 fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError> {
94 let [lo, hi] = word.to_le_bytes();
95 self.transport
96 .bus
97 .write(self.transport.address, &[reg, lo, hi])
98 }
99
100 fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError> {
101 let mut bytes = [0u8; 2 * 64 + 2];
102 let byte_len = words.len() * 2 + 2;
103 self.transport
104 .bus
105 .write_read(self.transport.address, &[reg], &mut bytes[..byte_len])?;
106 for (index, word) in words.iter_mut().enumerate() {
107 let offset = 2 + index * 2;
108 *word = u16::from_le_bytes([bytes[offset], bytes[offset + 1]]);
109 }
110 Ok(())
111 }
112}
113
114impl<SPI> SyncAccess for Bmi323<SyncSpiTransport<SPI>>
115where
116 SPI: SpiDevice<u8>,
117{
118 type BusError = SPI::Error;
119
120 fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError> {
121 let cmd = 0x80 | (reg & 0x7F);
122 let mut bytes = [0u8; 3];
123 let mut ops = [Operation::Write(&[cmd]), Operation::Read(&mut bytes)];
124 self.transport.bus.transaction(&mut ops)?;
125 Ok(u16::from_le_bytes([bytes[1], bytes[2]]))
126 }
127
128 fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError> {
129 let [lo, hi] = word.to_le_bytes();
130 let payload = [reg & 0x7F, lo, hi];
131 self.transport.bus.write(&payload)
132 }
133
134 fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError> {
135 let cmd = 0x80 | (reg & 0x7F);
136 let mut bytes = [0u8; 2 * 64 + 1];
137 let byte_len = words.len() * 2 + 1;
138 let mut ops = [
139 Operation::Write(&[cmd]),
140 Operation::Read(&mut bytes[..byte_len]),
141 ];
142 self.transport.bus.transaction(&mut ops)?;
143 for (index, word) in words.iter_mut().enumerate() {
144 let offset = 1 + index * 2;
145 *word = u16::from_le_bytes([bytes[offset], bytes[offset + 1]]);
146 }
147 Ok(())
148 }
149}
150
151impl<I2C> AsyncAccess for Bmi323Async<AsyncI2cTransport<I2C>>
152where
153 I2C: AsyncI2c,
154{
155 type BusError = I2C::Error;
156
157 async fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError> {
158 let mut bytes = [0u8; 4];
159 self.transport
160 .bus
161 .write_read(self.transport.address, &[reg], &mut bytes)
162 .await?;
163 Ok(u16::from_le_bytes([bytes[2], bytes[3]]))
164 }
165
166 async fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError> {
167 let [lo, hi] = word.to_le_bytes();
168 self.transport
169 .bus
170 .write(self.transport.address, &[reg, lo, hi])
171 .await
172 }
173
174 async fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError> {
175 let mut bytes = [0u8; 2 * 64 + 2];
176 let byte_len = words.len() * 2 + 2;
177 self.transport
178 .bus
179 .write_read(self.transport.address, &[reg], &mut bytes[..byte_len])
180 .await?;
181 for (index, word) in words.iter_mut().enumerate() {
182 let offset = 2 + index * 2;
183 *word = u16::from_le_bytes([bytes[offset], bytes[offset + 1]]);
184 }
185 Ok(())
186 }
187}
188
189impl<SPI> AsyncAccess for Bmi323Async<AsyncSpiTransport<SPI>>
190where
191 SPI: AsyncSpiDevice<u8>,
192{
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);
197 let mut bytes = [0u8; 3];
198 let mut ops = [Operation::Write(&[cmd]), Operation::Read(&mut bytes)];
199 self.transport.bus.transaction(&mut ops).await?;
200 Ok(u16::from_le_bytes([bytes[1], bytes[2]]))
201 }
202
203 async fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError> {
204 let [lo, hi] = word.to_le_bytes();
205 let payload = [reg & 0x7F, lo, hi];
206 self.transport.bus.write(&payload).await
207 }
208
209 async fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError> {
210 let cmd = 0x80 | (reg & 0x7F);
211 let mut bytes = [0u8; 2 * 64 + 1];
212 let byte_len = words.len() * 2 + 1;
213 let mut ops = [
214 Operation::Write(&[cmd]),
215 Operation::Read(&mut bytes[..byte_len]),
216 ];
217 self.transport.bus.transaction(&mut ops).await?;
218 for (index, word) in words.iter_mut().enumerate() {
219 let offset = 1 + index * 2;
220 *word = u16::from_le_bytes([bytes[offset], bytes[offset + 1]]);
221 }
222 Ok(())
223 }
224}