stm_32/peripherals/
llv3hp.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 RANGE_SIGNAL: Signal<
54 CriticalSectionRawMutex,
55 Result<packets::RangePacket, errors::SensorError>,
56> = Signal::<CriticalSectionRawMutex, Result<packets::RangePacket, errors::SensorError>>::new();
57
58pub struct Llv3hpSensor {
59 pub dev: I2cDevice<
60 'static,
61 CriticalSectionRawMutex,
62 I2c<'static, Async, embassy_stm32::i2c::mode::Master>,
63 >,
64}
65
66const ACQ_COMMAND: u8 = 0x00; const STATUS: u8 = 0x01; const SIG_COUNT_VAL: u8 = 0x02; const ACQ_CONFIG_REG: u8 = 0x04; const DATA: u8 = 0x0F; const REF_COUNT_VAL: u8 = 0x12; const THRESHOLD_BYPASS: u8 = 0x1C; const HEALTH_STATUS: u8 = 0x48; impl Llv3hpSensor {
77 async fn write_read(
78 &mut self,
79 address: u8,
80 register: &[u8],
81 data: &mut [u8],
82 ) -> Result<(), ()> {
83 match self.dev.write(address, register).await {
84 Err(_e) => return Err(()),
85 Ok(_) => {}
86 }
87
88 Timer::after(Duration::from_micros(0)).await;
89
90 match self.dev.read(address, data).await {
92 Err(_e) => return Err(()),
93 Ok(_) => {}
94 }
95
96 Ok(())
97 }
98
99 pub async fn run(&mut self) {
100 const ADDRESS: u8 = 0x62;
101
102 let mut status = [0u8; 1];
104 if self
105 .write_read(ADDRESS, &[STATUS], &mut status)
106 .await
107 .is_err()
108 {
109 RANGE_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
110 "LLV3HP Lidar failed: reading STATUS",
111 )));
112 return;
113 }
114 if self
115 .write_read(ADDRESS, &[STATUS], &mut status)
116 .await
117 .is_err()
118 {
119 RANGE_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
120 "LLV3HP Lidar failed: reading STATUS",
121 )));
122 return;
123 }
124
125 if (status[0] & 0x30) != 0x30 {
126 RANGE_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
127 "LLV3HP Lidar failed: bad STATUS",
128 )));
129 return;
130 }
131
132 let mut health = [0u8; 1];
134 if self
135 .write_read(ADDRESS, &[HEALTH_STATUS], &mut health)
136 .await
137 .is_err()
138 {
139 RANGE_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
140 "LLV3HP Lidar failed: reading HEALTH_STATUS",
141 )));
142 return;
143 }
144
145 if (health[0] & 0x17) != 0x17 {
146 RANGE_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
147 "LLV3HP Lidar failed: bad HEALTH_STATUS",
148 )));
149 return;
150 }
151
152 let sig_count_max: u8 = 0x80;
153 let acq_config_reg: u8 = 0x08;
154 let ref_count_max: u8 = 0x05;
155 let threshold_bypass: u8 = 0x00;
156
157 if self
158 .dev
159 .write(ADDRESS, &[SIG_COUNT_VAL, sig_count_max])
160 .await
161 .is_err()
162 {
163 RANGE_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
164 "LLV3HP Lidar failed: writing SIG_COUNT_VAL",
165 )));
166 return;
167 }
168 if self
169 .dev
170 .write(ADDRESS, &[ACQ_CONFIG_REG, acq_config_reg])
171 .await
172 .is_err()
173 {
174 RANGE_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
175 "LLV3HP Lidar failed: writing ACQ_CONFIG_REG",
176 )));
177 return;
178 }
179 if self
180 .dev
181 .write(ADDRESS, &[REF_COUNT_VAL, ref_count_max])
182 .await
183 .is_err()
184 {
185 RANGE_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
186 "LLV3HP Lidar failed: writing REF_COUNT_VAL",
187 )));
188 return;
189 }
190 if self
191 .dev
192 .write(ADDRESS, &[THRESHOLD_BYPASS, threshold_bypass])
193 .await
194 .is_err()
195 {
196 RANGE_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
197 "LLV3HP Lidar failed: writing THRESHOLD_BYPASS",
198 )));
199 return;
200 }
201
202 let loop_period = Duration::from_hz(100);
203 loop {
204 if self
206 .dev
207 .write(ADDRESS, &[ACQ_COMMAND, 0x04u8])
208 .await
209 .is_err()
210 {
211 RANGE_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
212 "LLV3HP Lidar failed: writing ACQ_COMMAND",
213 )));
214 }
215
216 let timestamp = synch_at(loop_period) + Duration::from_micros(5800);
217 Timer::at(timestamp).await;
218
219 let mut data = [0u8; 2];
221 if self.write_read(ADDRESS, &[DATA], &mut data).await.is_err() {
222 RANGE_SIGNAL.signal(Err(errors::SensorError::GenericSensorError(
223 "LLV3HP Lidar failed: reading DATA",
224 )));
225 } else {
226 let urange = (u16::from(data[0]) << 8) | u16::from(data[1]); let range = f32::from(urange) / 100f32;
228
229 let timestamp_us = timestamp.as_micros();
230
231 let header = packets::RosflightPacketHeader {
232 timestamp: timestamp_us,
233 status: status[0] as u16,
234 };
235
236 let range_packet = packets::RangePacket {
237 header,
238 range,
239 min_range: 0f32,
240 max_range: 40f32,
241 range_type: packets::RangeType::Lidar,
242 };
243 RANGE_SIGNAL.signal(Ok(range_packet)); }
245 }
246 }
247}
248
249#[embassy_executor::task]
250pub async fn task(mut llv3hp: Llv3hpSensor) {
251 llv3hp.run().await;
252}