stm_32/peripherals/dlhrl20g.rs
1// ******************************************************************************
2// * File : platforms/stm_32/src/peripherals/dlhrl20g.rs
3// * Date : June 28, 2026
4// ******************************************************************************
5// *
6// * Copyright (c) 2023, AeroVironment, Inc.
7// * All rights reserved.
8// *
9// * Redistribution and use in source and binary forms, with or without
10// * modification, are permitted provided that the following conditions are met:
11// *
12// * 1.Redistributions of source code must retain the above copyright notice, this
13// * list of conditions and the following disclaimer.
14// *
15// * 2.Redistributions in binary form must reproduce the above copyright notice,
16// * this list of conditions and the following disclaimer in the documentation
17// * and/or other materials provided with the distribution.
18// *
19// * 3.Neither the name of the copyright holder nor the names of its
20// * contributors may be used to endorse or promote products derived from
21// * this software without specific prior written permission.
22// *
23// * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24// * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25// * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26// * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
27// * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28// * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29// * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30// * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31// * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32// * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33// *
34// ******************************************************************************
35
36use crate::synch_at;
37use embassy_embedded_hal::shared_bus::asynch::i2c::I2cDevice;
38use embassy_stm32::exti::ExtiInput;
39use embassy_stm32::i2c::I2c;
40use embassy_stm32::mode::Async;
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::i2c::I2c as _;
47use veloxity_core::{errors, packets};
48
49pub static PITOT_SIGNAL: Signal<
50 CriticalSectionRawMutex,
51 Result<packets::PitotPacket, errors::SensorError>,
52> = Signal::<CriticalSectionRawMutex, Result<packets::PitotPacket, errors::SensorError>>::new();
53
54pub struct DlhrL20GSensor {
55 pub dev: I2cDevice<
56 'static,
57 CriticalSectionRawMutex,
58 I2c<'static, Async, embassy_stm32::i2c::mode::Master>,
59 >,
60 pub drdy: ExtiInput<'static, Async>,
61}
62
63impl DlhrL20GSensor {
64 pub async fn run(&mut self) {
65 const ADDRESS: u8 = 0x29;
66 const START: u8 = 0xAC;
67
68 let sample_period = Duration::from_hz(100);
69
70 loop {
71 let timestamp = synch_at(sample_period);
72 Timer::at(timestamp).await; // Wait for top of 100 Hz timer
73
74 let write_res = self.dev.write(ADDRESS, &[START]).await;
75 if let Err(_e) = write_res {
76 PITOT_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
77 "Pitot failed: write_register",
78 )))
79 }
80
81 if let Ok(()) =
82 with_timeout(Duration::from_millis(100), self.drdy.wait_for_rising_edge()).await
83 {
84 let mut data = [0u8; 7];
85 if self.dev.read(ADDRESS, &mut data).await.is_err() {
86 PITOT_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
87 "Pitot failed: reading problem",
88 )));
89 continue;
90 }
91 let status = data[0] as u16;
92 let u32_pressure =
93 u32::from(data[1]) << 16 | u32::from(data[2]) << 8 | u32::from(data[3]);
94 let u32_temperature =
95 u32::from(data[4]) << 16 | u32::from(data[5]) << 8 | u32::from(data[6]);
96
97 let fs = 5000.0; // Pa, Full Scale pressure
98
99 let pressure = 1.25 * fs * (f64::from(u32_pressure) / 16777216.0 - 0.1); // Pa
100 let temperature = 125.0 * f64::from(u32_temperature) / 16777216.0 - 40.0; // C
101 {
102 let header = packets::RosflightPacketHeader {
103 timestamp: timestamp.as_micros(),
104 status,
105 };
106 let pitot_packet = packets::PitotPacket {
107 header,
108 differential_pressure: pressure as f32,
109 temperature: temperature as f32,
110 ..Default::default()
111 };
112 PITOT_SIGNAL.signal(Ok(pitot_packet)); // make data available for other tasks.
113 }
114 }
115 }
116 }
117}
118
119#[embassy_executor::task]
120pub async fn task(mut dlhr: DlhrL20GSensor) {
121 dlhr.run().await;
122}