1use embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice;
37use embassy_stm32::exti::ExtiInput;
38use embassy_stm32::gpio::Output;
39use embassy_stm32::mode::Async;
40use embassy_stm32::spi;
41use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
42use embassy_sync::signal::Signal;
43use embassy_time::Duration;
44use embassy_time::Timer;
45use embassy_time::with_timeout;
46use embedded_hal_async::spi::SpiDevice as _;
47
48use crate::synch_at;
49use veloxity_core::errors;
50use veloxity_core::packets;
51
52const SPI_READ: u8 = 0x80;
54const SPI_WRITE: u8 = 0x00;
55
56pub static BARO_SIGNAL: Signal<
57 CriticalSectionRawMutex,
58 Result<packets::BaroPacket, errors::SensorError>,
59> = Signal::<CriticalSectionRawMutex, Result<packets::BaroPacket, errors::SensorError>>::new();
60
61pub struct Dps310Sensor {
62 pub dev: SpiDevice<
63 'static,
64 CriticalSectionRawMutex,
65 spi::Spi<'static, Async, spi::mode::Master>,
66 Output<'static>,
67 >,
68 pub drdy: ExtiInput<'static, Async>,
69 pub three_wire: bool,
70}
71
72fn compliment(x: u32, bits: u32) -> f64 {
73 let mut x = x as i32;
74 if (x & (1i32 << (bits - 1))) != 0 {
75 x -= 1i32 << bits;
76 }
77 f64::from(x)
78}
79
80const MEAS_CFG_REG: u8 = 0x08;
81const ISR_REG: u8 = 0x0A;
82const DPS310_READ_P_CMD: u8 = 0x00;
83const DPS310_READ_T_CMD: u8 = 0x03;
84
85const K1: f64 = 524288.0;
86const K8: f64 = 7864320.0; impl Dps310Sensor {
89 async fn read_register(&mut self, reg_addr: u8) -> Result<u8, errors::SensorError> {
90 let tx = [reg_addr | SPI_READ, 0x00];
91 let mut rx = [0u8; 2];
92 self.dev.transfer(&mut rx, &tx).await.map_err(|e| match e {
93 _ => errors::SensorError::GenericSensorError("SPI failed: read_register"),
94 })?;
95 Ok(rx[1])
96 }
97
98 async fn write_register(&mut self, reg_addr: u8, value: u8) -> Result<(), errors::SensorError> {
99 let tx = [reg_addr | SPI_WRITE, value];
100 self.dev.write(&tx).await.map_err(|e| match e {
102 _ => errors::SensorError::GenericSensorError("SPI failed: write_register"),
103 })?;
104 Ok(())
105 }
106
107 async fn initialize_sensor(&mut self) -> Result<[f64; 9], errors::SensorError> {
108 const RESET_REG: u8 = 0x0C;
110 self.write_register(RESET_REG, 0x09).await?;
111 Timer::after_millis(52).await; const CFG_REG: u8 = 0x09;
125 let three_wire_mode: u8 = if self.three_wire { 0x01 } else { 0x00 };
126 self.write_register(CFG_REG, three_wire_mode | 0xB0).await?;
127
128 const PRODUCT_ID_REG: u8 = 0x0D;
131 const PRODUCT_ID: u8 = 0x10;
132 let id = self.read_register(PRODUCT_ID_REG).await?;
133 if id != PRODUCT_ID {
134 return Err(errors::SensorError::GenericSensorError("ID mismatch"));
139 }
140
141 const COEF_READY: u8 = 0x80;
144 let coef_rdy = self.read_register(MEAS_CFG_REG).await?;
145 if (coef_rdy & COEF_READY) == 0x00 {
146 return Err(errors::SensorError::GenericSensorError(
147 "Calibration coefficients not ready",
148 ));
149 }
150
151 let cal = self.read_calibration_coefficients().await?;
152 Ok(cal)
153 }
154
155 async fn read_calibration_coefficients(&mut self) -> Result<[f64; 9], errors::SensorError> {
156 const COEF_REG: u8 = 0x10;
157 let mut tx = [0u8; 19];
158 tx[0] = COEF_REG | SPI_READ;
159
160 let mut rx = [0u8; 19];
161 self.dev.transfer(&mut rx, &tx).await.map_err(|e| match e {
162 _ => {
163 errors::SensorError::GenericSensorError("SPI failed: read_calibration_coefficients")
164 }
165 })?;
166
167 let buf = rx.map(|x| x as u32);
169 let mut cal = [0f64; 9];
171 cal[0] = compliment((buf[1] << 4) | ((buf[2] >> 4) & 0x0F), 12); cal[1] = compliment(((buf[2] & 0x0F) << 8) | buf[3], 12); cal[2] = compliment((buf[4] << 12) | (buf[5] << 4) | ((buf[6] >> 4) & 0x0F), 20); cal[3] = compliment(((buf[6] & 0x0F) << 16) | (buf[7] << 8) | buf[8], 20); cal[6] = compliment((buf[9] << 8) | buf[10], 16); cal[7] = compliment((buf[11] << 8) | buf[12], 16); cal[4] = compliment((buf[13] << 8) | buf[14], 16); cal[8] = compliment((buf[15] << 8) | buf[16], 16); cal[5] = compliment((buf[17] << 8) | buf[18], 16); Ok(cal)
182 }
183
184 async fn pressure_config(&mut self) -> Result<(), errors::SensorError> {
185 const PRS_CFG_REG: u8 = 0x06;
187 self.write_register(PRS_CFG_REG, 0x03).await?; Ok(())
190 }
191
192 async fn temperature_config(&mut self) -> Result<(), errors::SensorError> {
193 const COEF_SRCE_REG: u8 = 0x28;
195 let temp_source = self.read_register(COEF_SRCE_REG).await? & 0x80;
196
197 const TMP_CFG_REG: u8 = 0x07;
199 self.write_register(TMP_CFG_REG, temp_source | 0x00).await?; Ok(())
202 }
203
204 async fn measurement_configuration(&mut self) -> Result<(), errors::SensorError> {
205 self.write_register(MEAS_CFG_REG, 0x00).await?;
214
215 Ok(())
216 }
217
218 async fn get_sensor_data(&mut self, cmd: u8) -> Result<i32, errors::SensorError> {
219 let mut rx = [0u8; 4];
220 self.dev
221 .transfer(&mut rx, &[cmd | SPI_READ, 0, 0, 0])
222 .await
223 .map_err(|e| match e {
224 _ => errors::SensorError::GenericSensorError("SPI failed: get_sensor_data"),
225 })?;
226
227 self.read_register(ISR_REG).await?;
229
230 let raw = (((rx[1] as u32) << 24 | (rx[2] as u32) << 16 | (rx[3] as u32) << 8) as i32) >> 8;
231
232 Ok(raw)
233 }
234
235 async fn get_pressure_data(&mut self) -> Result<(i32, u16), errors::SensorError> {
236 self.write_register(MEAS_CFG_REG, 0x01).await?;
238
239 let _drdy_result = with_timeout(
242 Duration::from_micros(14_000),
243 self.drdy.wait_for_rising_edge(),
244 )
245 .await
246 .is_ok();
247 Timer::after_micros(20).await; let status = (self.read_register(MEAS_CFG_REG).await? as u16) << 8;
251
252 let raw_p = self.get_sensor_data(DPS310_READ_P_CMD).await?;
254 Ok((raw_p, status))
255 }
256
257 async fn get_temperature_data(&mut self) -> Result<(i32, u16), errors::SensorError> {
258 self.write_register(MEAS_CFG_REG, 0x02).await?;
260
261 let _drdy_result = with_timeout(
264 Duration::from_micros(3_000),
265 self.drdy.wait_for_rising_edge(),
266 )
267 .await
268 .is_ok();
269
270 let status_low = self.read_register(MEAS_CFG_REG).await? as u16;
272
273 let raw_t = self.get_sensor_data(DPS310_READ_T_CMD).await?;
275 Ok((raw_t, status_low))
276 }
277
278 fn process_temperature_data(
279 &mut self,
280 raw_t: i32,
281 raw_t_previous: &mut i32,
282 cal: &[f64; 9],
283 ) -> (f64, f64) {
284 *raw_t_previous += (raw_t - *raw_t_previous) / 16; let raw_t_f64 = f64::from(*raw_t_previous) / K1;
286 let temperature = cal[0] * 0.5 + cal[1] * raw_t_f64; (raw_t_f64, temperature)
289 }
290
291 fn process_pressure_data(&mut self, raw_p: i32, raw_t_f64: f64, cal: &[f64; 9]) -> (f64, f64) {
292 let raw_p_f64 = f64::from(raw_p) / K8;
293 let pressure = cal[2]
294 + raw_p_f64 * (cal[3] + raw_p_f64 * (cal[4] + raw_p_f64 * cal[5]))
295 + raw_t_f64 * (cal[6] + raw_p_f64 * (cal[7] + raw_p_f64 * cal[8])); (raw_p_f64, pressure)
297 }
298
299 pub async fn run(&mut self) {
300 let mut cal = match self.initialize_sensor().await {
302 Ok(cal) => cal,
303 Err(e) => {
304 BARO_SIGNAL.signal(Err(e));
305 return;
306 }
307 };
308 if let Err(e) = self.pressure_config().await {
309 BARO_SIGNAL.signal(Err(e));
310 return;
311 }
312 if let Err(e) = self.temperature_config().await {
313 BARO_SIGNAL.signal(Err(e));
314 return;
315 }
316 if let Err(e) = self.measurement_configuration().await {
317 BARO_SIGNAL.signal(Err(e));
318 return;
319 }
320 let mut raw_t_previous = 0_i32;
323 let sample_period = Duration::from_hz(50);
324
325 loop {
326 let timestamp = synch_at(sample_period);
327 Timer::at(timestamp).await;
328
329 let (raw_p, status_high) = match self.get_pressure_data().await {
331 Ok(data) => data,
332 Err(e) => {
333 BARO_SIGNAL.signal(Err(e));
334 continue;
335 }
336 };
337 let (raw_t, status_low) = match self.get_temperature_data().await {
338 Ok(data) => data,
339 Err(e) => {
340 BARO_SIGNAL.signal(Err(e));
341 continue;
342 }
343 };
344
345 let status_combined = (status_high & 0xFF00) | (status_low & 0x00FF);
347
348 let (raw_t_f64, temperature) =
349 self.process_temperature_data(raw_t, &mut raw_t_previous, &mut cal);
350 let (_raw_p_f64, pressure) = self.process_pressure_data(raw_p, raw_t_f64, &mut cal);
351
352 if status_combined == 0xD0E0 {
353 let header = packets::RosflightPacketHeader {
354 timestamp: timestamp.as_micros(),
355 status: status_combined,
356 };
357 let baro_packet = packets::BaroPacket {
358 header,
359 pressure: pressure as f32,
360 temperature: temperature as f32,
361 ..Default::default()
362 };
363 BARO_SIGNAL.signal(Ok(baro_packet)); } else {
365 BARO_SIGNAL.signal(Err(errors::SensorError::GenericSensorError("Bad status")));
366 }
367 }
368 }
369}
370
371#[embassy_executor::task]
372pub async fn task(mut dps: Dps310Sensor) {
373 dps.run().await;
374}