stm_32/peripherals/
ist8308.rs1pub use embassy_stm32::mode::Async;
37pub use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
38pub use embassy_sync::signal::Signal;
39use veloxity_core::{errors, packets};
40
41use embassy_embedded_hal::shared_bus::asynch::i2c::I2cDevice;
43use embassy_stm32::i2c::I2c;
44use embedded_hal_async::i2c::I2c as _;
45
46use crate::synch_at;
48use embassy_time::Duration;
49use embassy_time::Timer;
50
51pub static MAG_SIGNAL: Signal<
54 CriticalSectionRawMutex,
55 Result<packets::MagPacket, errors::SensorError>,
56> = Signal::<CriticalSectionRawMutex, Result<packets::MagPacket, errors::SensorError>>::new();
57
58pub struct Ist8308Sensor {
59 pub dev: I2cDevice<
60 'static,
61 CriticalSectionRawMutex,
62 I2c<'static, Async, embassy_stm32::i2c::mode::Master>,
63 >,
64}
65
66impl Ist8308Sensor {
67 async fn write_read(
68 &mut self,
69 address: u8,
70 register: &[u8],
71 data: &mut [u8],
72 ) -> Result<(), ()> {
73 match self.dev.write(address, register).await {
74 Err(_e) => return Err(()),
75 Ok(_) => {}
76 }
77
78 Timer::after(Duration::from_micros(0)).await;
79
80 match self.dev.read(address, data).await {
82 Err(_e) => return Err(()),
83 Ok(_) => {}
84 }
85
86 Ok(())
87 }
88
89 pub async fn run(&mut self) {
90 const ADDRESS: u8 = 0x0C;
91
92 const WAI_REG: u8 = 0x00;
95 let mut device_id = [0u8; 1];
96 if self
97 .write_read(ADDRESS, &[WAI_REG], &mut device_id)
98 .await
99 .is_err()
100 {
101 MAG_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
102 "IST8308 Mag failed: reading WAI_REG",
103 )));
104 return;
105 }
106 const DEVICE_ID: u8 = 0x08;
107 if device_id[0] != DEVICE_ID {
108 MAG_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
109 "IST8308 Mag failed: bad device ID",
110 )));
111 return;
112 }
113
114 const CNTL3_REG: u8 = 0x32;
117 const CNTL3_VAL_SRST: u8 = 1;
118 if self
119 .dev
120 .write(ADDRESS, &[CNTL3_REG, CNTL3_VAL_SRST])
121 .await
122 .is_err()
123 {
124 MAG_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
125 "IST8308 Mag failed: writing CNTL3_REG",
126 )));
127 return;
128 }
129 Timer::after(Duration::from_millis(20)).await; let mut cntrl3 = [0u8; 1];
133 if self
134 .write_read(ADDRESS, &[CNTL3_REG], &mut cntrl3)
135 .await
136 .is_err()
137 {
138 MAG_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
139 "IST8308 Mag failed: reading CNTL3_REG",
140 )));
141 return;
142 }
143 if (cntrl3[0] & 0x01) != 0 {
144 MAG_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
145 "IST8308 Mag failed: bad status CNTL3_REG",
146 )));
147 return;
148 }
149
150 const CNTL3_VAL_DRDY_EN: u8 = 1 << 3;
154
155 if self
156 .dev
157 .write(ADDRESS, &[CNTL3_REG, CNTL3_VAL_DRDY_EN])
158 .await
159 .is_err()
160 {
161 MAG_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
162 "IST8308 Mag failed: writing CNTL4_REG",
163 )));
164 return;
165 }
166
167 const CNTL4_REG: u8 = 0x34;
168 const CNTL4_VAL_DYNAMIC_RANGE_500: u8 = 0;
169
170 if self
171 .dev
172 .write(ADDRESS, &[CNTL4_REG, CNTL4_VAL_DYNAMIC_RANGE_500])
173 .await
174 .is_err()
175 {
176 MAG_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
177 "IST8308 Mag failed: writing CNTL4_REG",
178 )));
179 return;
180 }
181
182 const OSRCNTL_REG: u8 = 0x41;
183 const OSRCNTL_VAL_Y_16: u8 = 4 << 3;
184 const OSRCNTL_VAL_XZ_16: u8 = 4;
185
186 if self
187 .dev
188 .write(
189 ADDRESS,
190 &[OSRCNTL_REG, OSRCNTL_VAL_Y_16 | OSRCNTL_VAL_XZ_16],
191 )
192 .await
193 .is_err()
194 {
195 MAG_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
196 "IST8308 Mag failed: writing OSRCNTL_REG",
197 )));
198 return;
199 }
200
201 const CNTL2_REG: u8 = 0x31;
203 const CNTL2_VAL_CONT_ODR100_MODE: u8 = 0x08; if self
205 .dev
206 .write(ADDRESS, &[CNTL2_REG, CNTL2_VAL_CONT_ODR100_MODE])
207 .await
208 .is_err()
209 {
210 MAG_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
211 "IST8308 Mag failed: writing CNTL2_REG",
212 )));
213 return;
214 }
215
216 let loop_period = Duration::from_hz(100);
217 loop {
218 let timestamp = synch_at(loop_period) + Duration::from_micros(900);
219 Timer::at(timestamp).await;
220
221 const STAT1_REG: u8 = 0x10;
223 let mut data = [0u8; 7];
224 if self
225 .write_read(ADDRESS, &[STAT1_REG], &mut data)
226 .await
227 .is_err()
228 {
229 MAG_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
230 "IST8308 Mag failed: reading STAT1_REG",
231 )));
232 continue;
233 }
234
235 const STAT1_VAL_DRDY: u8 = 0x01;
236 let status = data[0];
237 let data_ready = (status & STAT1_VAL_DRDY) != 0;
238 if data_ready {
239 let flux = [
240 f32::from((((data[2] as u16) << 8) | (data[1] as u16)) as i16) * 1.5e-7,
241 f32::from((((data[4] as u16) << 8) | (data[3] as u16)) as i16) * 1.5e-7,
242 f32::from((((data[6] as u16) << 8) | (data[5] as u16)) as i16) * 1.5e-7,
243 ]; let timestamp_us = timestamp.as_micros();
246
247 let header = packets::RosflightPacketHeader {
248 timestamp: timestamp_us,
249 status: status as u16,
250 };
251
252 let mag_packet = packets::MagPacket {
253 header,
254 flux,
255 temperature: 0.0f32,
256 };
257 MAG_SIGNAL.signal(Ok(mag_packet)); }
260 }
261 }
262}
263
264#[embassy_executor::task]
265pub async fn task(mut ist: Ist8308Sensor) {
266 ist.run().await;
267}