a121_rs/config.rs
1#![warn(missing_docs)]
2
3use core::num::NonZeroU8;
4
5use num::Zero;
6
7use error::ConfigError;
8use error::ConfigError::ContinuousSweepMode;
9use frame_rate::FrameRate;
10use profile::RadarProfile;
11
12use crate::config::hwaas::Hwaas;
13use crate::config::prf::PulseRepetitionFrequency;
14use crate::config::subsweep::Subsweep;
15use a121_sys::*;
16
17/// Module for radar configuration errors
18mod error;
19/// Module for frame rate values
20pub mod frame_rate;
21/// Module for hardware accelerated average samples (HWAAS) values
22mod hwaas;
23/// Module for Pulse Repetition Frequency (PRF) values
24pub mod prf;
25/// Module for radar profiles
26pub mod profile;
27/// Module for subsweep configuration
28pub mod subsweep;
29
30#[derive(Debug, PartialEq)]
31/// Idle states for the radar sensor between sweeps or frames.
32pub enum RadarIdleState {
33 /// Deep sleep state for maximum power saving.
34 DeepSleep = 0,
35 /// Sleep state with reduced power consumption.
36 Sleep,
37 /// Ready state for quick start of operations.
38 Ready,
39}
40
41/// Enum representing different sweep modes for the radar sensor.
42pub enum SweepMode {
43 /// Continuous sweep mode with specified constraints.
44 Continuous {
45 /// Sweep rate in Hz, must be >= 0
46 sweep_rate: f32,
47 },
48 /// Non-continuous (or discrete) sweep mode with different settings.
49 Discrete {
50 /// Frame rate in Hz
51 frame_rate: FrameRate,
52 /// Number of sweeps per frame
53 sweeps_per_frame: u16,
54 },
55}
56
57#[derive(Debug)]
58/// Radar configuration structure to manage the settings of a radar sensor.
59pub struct RadarConfig {
60 /// Number of subsweeps in the radar configuration.
61 num_subsweep: Option<NonZeroU8>,
62 /// Internal pointer to the radar configuration.
63 inner: *mut acc_config_t,
64}
65
66impl Default for RadarConfig {
67 /// Provides a default instance of `RadarConfig` with an ID of 1.
68 fn default() -> Self {
69 Self::new()
70 }
71}
72
73impl Drop for RadarConfig {
74 /// Destroys the radar configuration instance, freeing any allocated resources.
75 fn drop(&mut self) {
76 unsafe { acc_config_destroy(self.inner) };
77 }
78}
79
80impl RadarConfig {
81 /// Creates a new radar configuration instance with a specified ID.
82 pub fn new() -> Self {
83 #[cfg(feature = "defmt")]
84 defmt::trace!("Creating radar configuration");
85 let inner = unsafe { acc_config_create() };
86 #[cfg(feature = "defmt")]
87 defmt::trace!("Radar configuration created");
88 Self {
89 inner,
90 num_subsweep: None,
91 }
92 }
93
94 /// Returns a mutable pointer to the internal radar configuration structure
95 /// # Safety
96 /// This function is unsafe because it returns a raw pointer.
97 pub unsafe fn mut_ptr(&mut self) -> *mut acc_config_t {
98 self.inner
99 }
100
101 /// Returns a pointer to the internal radar configuration structure
102 pub fn ptr(&self) -> *const acc_config_t {
103 self.inner
104 }
105
106 /// Sets the sweep mode for the radar sensor
107 /// # Arguments
108 /// * `sweep_mode` - The sweep mode to set
109 pub fn set_sweep_mode(&mut self, sweep_mode: SweepMode) -> Result<(), ConfigError> {
110 match sweep_mode {
111 SweepMode::Continuous { sweep_rate } => {
112 self.set_continuous_sweep_mode(true)?;
113 self.set_sweep_rate(sweep_rate)?;
114 }
115 SweepMode::Discrete {
116 frame_rate,
117 sweeps_per_frame,
118 } => {
119 self.set_continuous_sweep_mode(false)?;
120 self.set_frame_rate(frame_rate);
121 self.set_sweeps_per_frame(sweeps_per_frame);
122 }
123 }
124 Ok(())
125 }
126
127 /// Sets the starting point of the sweep.
128 ///
129 /// # Arguments
130 ///
131 /// * `start_point` - The starting point of the sweep in millimeters.
132 pub fn set_start_point(&mut self, start_point: i32) {
133 unsafe { acc_config_start_point_set(self.inner, start_point) };
134 }
135
136 /// Get the starting point of the sweep.
137 pub fn start_point(&self) -> i32 {
138 unsafe { acc_config_start_point_get(self.inner) }
139 }
140
141 /// Set the number of data points to measure in a sweep.
142 ///
143 /// # Arguments
144 ///
145 /// * `num_points` - Number of data points to measure.
146 pub fn set_num_points(&mut self, num_points: u16) {
147 unsafe { acc_config_num_points_set(self.inner, num_points) };
148 }
149
150 /// Get the number of data points set to measure in a sweep.
151 pub fn num_points(&self) -> u16 {
152 unsafe { acc_config_num_points_get(self.inner) }
153 }
154
155 /// Set the step length between each data point in a sweep.
156 ///
157 /// # Arguments
158 ///
159 /// * `step_length` - The step length.
160 pub fn set_step_length(&mut self, step_length: u16) {
161 unsafe { acc_config_step_length_set(self.inner, step_length) };
162 }
163
164 /// Get the current step length between each data point in a sweep.
165 pub fn step_length(&self) -> u16 {
166 unsafe { acc_config_step_length_get(self.inner) }
167 }
168
169 /// Set the radar profile.
170 ///
171 /// # Arguments
172 ///
173 /// * `profile` - The radar profile to set.
174 pub fn set_profile(&mut self, profile: RadarProfile) {
175 unsafe { acc_config_profile_set(self.inner, profile as u32) };
176 }
177
178 /// Get the currently used radar profile
179 pub fn profile(&self) -> RadarProfile {
180 unsafe { acc_config_profile_get(self.inner) }.into()
181 }
182
183 /// Set the hardware accelerated average samples (HWAAS).
184 ///
185 /// Each data point can be sampled several times, and the sensor hardware produces an average value of those samples.
186 /// The time needed to measure a sweep is roughly proportional to the number of averaged samples.
187 /// Decreasing HWAAS can increase the update rate but may lead to lower SNR.
188 ///
189 /// HWAAS must be between 1 and 511 inclusive.
190 ///
191 /// # Arguments
192 ///
193 /// * `hwaas` - Number of hardware accelerated average samples.
194 pub fn set_hwaas(&mut self, hwaas: Hwaas) -> Result<(), ConfigError> {
195 unsafe { acc_config_hwaas_set(self.inner, hwaas.into()) };
196 Ok(())
197 }
198
199 /// Get the hardware accelerated average samples (HWAAS).
200 ///
201 /// Returns the number of hardware accelerated average samples currently set.
202 pub fn hwaas(&self) -> Hwaas {
203 unsafe { acc_config_hwaas_get(self.inner) }
204 .try_into()
205 .unwrap()
206 }
207
208 /// Set the receiver gain setting.
209 ///
210 /// Must be a value between 0 and 23 inclusive where 23 is the highest gain and 0 the lowest.
211 /// Lower gain gives higher SNR. However, too low gain may result in quantization, lowering SNR.
212 /// Too high gain may result in saturation, corrupting the data.
213 ///
214 /// # Arguments
215 ///
216 /// * `receiver_gain` - Receiver gain setting.
217 pub fn receiver_gain_set(&mut self, receiver_gain: u8) {
218 unsafe { acc_config_receiver_gain_set(self.inner, receiver_gain) };
219 }
220
221 /// Get the current receiver gain setting.
222 ///
223 /// Returns the receiver gain setting. The range is between 0 (lowest gain) and 23 (highest gain).
224 pub fn receiver_gain(&self) -> u8 {
225 unsafe { acc_config_receiver_gain_get(self.inner) }
226 }
227
228 /// Set the number of sweeps captured in each frame (measurement).
229 ///
230 /// # Arguments
231 ///
232 /// * `sweeps_per_frame` - Number of sweeps per frame.
233 pub fn set_sweeps_per_frame(&mut self, sweeps_per_frame: u16) {
234 unsafe { acc_config_sweeps_per_frame_set(self.inner, sweeps_per_frame) };
235 }
236
237 /// Get the number of sweeps captured in each frame (measurement).
238 pub fn sweeps_per_frame(&self) -> u16 {
239 unsafe { acc_config_sweeps_per_frame_get(self.inner) }
240 }
241
242 /// Set the Pulse Repetition Frequency (PRF)
243 ///
244 /// See @ref acc_config_prf_t for details.
245 ///
246 /// # Arguments
247 ///
248 /// * `prf` - The Pulse Repetition Frequency to use
249 pub fn set_prf(&mut self, prf: PulseRepetitionFrequency) {
250 unsafe { acc_config_prf_set(self.inner, prf as acc_config_prf_t) };
251 }
252
253 /// Get the Pulse Repetition Frequency
254 ///
255 /// Returns the currently set Pulse Repetition Frequency.
256 pub fn prf(&self) -> PulseRepetitionFrequency {
257 unsafe { acc_config_prf_get(self.inner) }
258 .try_into()
259 .unwrap()
260 }
261
262 /// Enable or disable phase enhancement
263 ///
264 /// If enabled, the data phase will be enhanced such that coherent distance filtering can be applied.
265 ///
266 /// # Arguments
267 ///
268 /// * `enable` - true to enable phase enhancement, false to disable
269 pub fn set_phase_enhancement(&mut self, enable: bool) {
270 unsafe { acc_config_phase_enhancement_set(self.inner, enable) };
271 }
272
273 /// Check if phase enhancement is enabled
274 ///
275 /// Returns true if phase enhancement is enabled.
276 pub fn is_phase_enhancement_enabled(&self) -> bool {
277 unsafe { acc_config_phase_enhancement_get(self.inner) }
278 }
279
280 /// Enable or disable loopback
281 ///
282 /// Loopback can't be enabled together with profile 2.
283 ///
284 /// # Arguments
285 ///
286 /// * `enable` - true to enable loopback, false otherwise
287 pub fn set_loopback(&mut self, enable: bool) {
288 unsafe { acc_config_enable_loopback_set(self.inner, enable) };
289 }
290
291 /// Get the enable loopback configuration
292 ///
293 /// Returns true if loopback is enabled.
294 pub fn is_loopback_enabled(&self) -> bool {
295 unsafe { acc_config_enable_loopback_get(self.inner) }
296 }
297
298 /// Enable or disable double buffering
299 ///
300 /// If enabled, the sensor buffer will be split in two halves reducing the
301 /// maximum number of samples.
302 ///
303 /// # Arguments
304 ///
305 /// * `enable` - true to enable double buffering, false otherwise
306 pub fn set_double_buffering(&mut self, enable: bool) {
307 unsafe { acc_config_double_buffering_set(self.inner, enable) };
308 }
309
310 /// Get the double buffering configuration
311 ///
312 /// Returns true if double buffering is enabled.
313 pub fn is_double_buffering_enabled(&self) -> bool {
314 unsafe { acc_config_double_buffering_get(self.inner) }
315 }
316
317 /// Set the frame rate
318 ///
319 /// Sets the frame rate.
320 ///
321 /// # Arguments
322 ///
323 /// * `frame_rate` - Frame rate in Hz. 0 is interpreted as unlimited
324 pub fn set_frame_rate(&mut self, frame_rate: FrameRate) {
325 match frame_rate {
326 FrameRate::Unlimited => unsafe { acc_config_frame_rate_set(self.inner, 0.0) },
327 FrameRate::Limited(rate) => unsafe { acc_config_frame_rate_set(self.inner, rate) },
328 }
329 }
330
331 /// Get the frame rate
332 ///
333 /// Returns the currently set frame rate in Hz.
334 pub fn frame_rate(&self) -> FrameRate {
335 let val = unsafe { acc_config_frame_rate_get(self.inner) };
336 if val.is_zero() {
337 FrameRate::Unlimited
338 } else {
339 FrameRate::Limited(val)
340 }
341 }
342
343 /// Enable or disable the transmitter
344 ///
345 /// # Arguments
346 ///
347 /// * `enable` - true to enable the transmitter, false to disable it
348 pub fn set_transmitter_enabled(&mut self, enable: bool) {
349 unsafe { acc_config_enable_tx_set(self.inner, enable) };
350 }
351
352 /// Get transmitter enable configuration
353 ///
354 /// Returns true if the transmitter is enabled.
355 pub fn is_transmitter_enabled(&self) -> bool {
356 unsafe { acc_config_enable_tx_get(self.inner) }
357 }
358
359 /// Set inter frame idle state
360 ///
361 /// # Arguments
362 ///
363 /// * `idle_state` - The idle state to use between frames
364 pub fn set_inter_frame_idle_state(&mut self, idle_state: RadarIdleState) {
365 unsafe { acc_config_inter_frame_idle_state_set(self.inner, idle_state as u32) };
366 }
367
368 /// Get inter frame idle state
369 ///
370 /// Returns the currently set idle state used between frames.
371 pub fn inter_frame_idle_state(&self) -> RadarIdleState {
372 let val = unsafe { acc_config_inter_frame_idle_state_get(self.inner) };
373 match val {
374 0 => RadarIdleState::DeepSleep,
375 1 => RadarIdleState::Sleep,
376 2 => RadarIdleState::Ready,
377 _ => panic!("Invalid idle state value"),
378 }
379 }
380
381 /// Set inter sweep idle state
382 ///
383 /// # Arguments
384 ///
385 /// * `idle_state` - The idle state to use between sweeps within a frame
386 pub fn set_inter_sweep_idle_state(&mut self, idle_state: RadarIdleState) {
387 unsafe { acc_config_inter_sweep_idle_state_set(self.inner, idle_state as u32) };
388 }
389
390 /// Get inter sweep idle state
391 ///
392 /// Returns the currently set idle state used between sweeps within a frame.
393 pub fn inter_sweep_idle_state(&self) -> RadarIdleState {
394 let val = unsafe { acc_config_inter_sweep_idle_state_get(self.inner) };
395 match val {
396 0 => RadarIdleState::DeepSleep,
397 1 => RadarIdleState::Sleep,
398 2 => RadarIdleState::Ready,
399 _ => panic!("Invalid idle state value"),
400 }
401 }
402
403 /// Set continuous sweep mode.
404 ///
405 /// In continuous sweep mode, the timing is identical over all sweeps, not just the sweeps in a frame.
406 /// Enabling continuous sweep mode imposes certain constraints:
407 /// - Frame rate must be set to unlimited (0.0 Hz).
408 /// - Sweep rate must be set (a value greater than 0 Hz).
409 /// - Inter-frame and inter-sweep idle states must be the same.
410 ///
411 /// # Arguments
412 ///
413 /// * `enabled` - true to enable continuous sweep mode, false to disable it.
414 fn set_continuous_sweep_mode(&mut self, enabled: bool) -> Result<(), ConfigError> {
415 if enabled {
416 if self.frame_rate().is_limited() {
417 return Err(ContinuousSweepMode);
418 }
419 if self.sweep_rate().is_zero() {
420 return Err(ContinuousSweepMode);
421 }
422 if self.inter_frame_idle_state() != self.inter_sweep_idle_state() {
423 return Err(ContinuousSweepMode);
424 }
425 }
426 unsafe { acc_config_continuous_sweep_mode_set(self.inner, enabled) };
427 Ok(())
428 }
429
430 /// Get continuous sweep mode
431 ///
432 /// Returns true if continuous sweep mode is enabled.
433 pub fn is_continuous_sweep_mode_enabled(&self) -> bool {
434 unsafe { acc_config_continuous_sweep_mode_get(self.inner) }
435 }
436
437 /// Set the sweep rate
438 ///
439 /// # Arguments
440 ///
441 /// * `sweep_rate` - Sweep rate in Hz. Must be >= 0, 0 is interpreted as max sweep rate
442 fn set_sweep_rate(&mut self, sweep_rate: f32) -> Result<(), ConfigError> {
443 if sweep_rate.is_zero() || sweep_rate.is_sign_negative() {
444 return Err(ConfigError::SweepRate);
445 }
446 unsafe { acc_config_sweep_rate_set(self.inner, sweep_rate) };
447 Ok(())
448 }
449
450 /// Get the sweep rate
451 ///
452 /// Returns the currently set sweep rate in Hz.
453 pub fn sweep_rate(&self) -> f32 {
454 unsafe { acc_config_sweep_rate_get(self.inner) }
455 }
456
457 /// Set the number of subsweeps in the radar configuration.
458 /// # Arguments
459 /// * `num_subsweep` - The number of subsweeps to set
460 pub fn set_num_subsweep(&mut self, num_subsweep: u8) -> Result<(), ConfigError> {
461 if num_subsweep == 0 {
462 return Err(ConfigError::NumSubsweep);
463 }
464 unsafe { acc_config_num_subsweeps_set(self.inner, num_subsweep) };
465 self.num_subsweep = NonZeroU8::new(num_subsweep);
466 Ok(())
467 }
468
469 /// Get the number of subsweeps in the radar configuration.
470 pub fn num_subsweep(&self) -> u8 {
471 unsafe { acc_config_num_subsweeps_get(self.inner) }
472 }
473
474 /// Get a subsweep from the radar configuration.
475 /// # Arguments
476 /// * `index` - The index of the subsweep to get
477 /// # Returns
478 /// * `Some(Subsweep)` - The subsweep at the given index
479 /// * `None` - If the index is out of bounds
480 pub fn get_subsweep(&self, index: u8) -> Option<Subsweep> {
481 if index >= self.num_subsweep() {
482 return None;
483 }
484 Some(Subsweep::new(index))
485 }
486
487 /// Get the buffer size needed for the current configuration
488 /// # Returns
489 /// * `Ok(u32)` - The buffer size needed for the current configuration
490 /// * `Err(ConfigError::BufferSize)` - If the buffer size could not be determined
491 pub fn config_buffer_size(&self) -> Result<u32, ConfigError> {
492 let mut buffer_size = 0;
493 let result: bool;
494
495 unsafe { result = acc_rss_get_buffer_size(self.inner, &mut buffer_size) };
496
497 if result {
498 Ok(buffer_size)
499 } else {
500 Err(ConfigError::BufferSize)
501 }
502 }
503}