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}