autd3_driver/datagram/
silencer.rs

1use std::{convert::Infallible, num::NonZeroU16};
2
3use autd3_core::{
4    common::{SILENCER_STEPS_INTENSITY_DEFAULT, SILENCER_STEPS_PHASE_DEFAULT, ULTRASOUND_PERIOD},
5    datagram::{Datagram, DeviceMask},
6    environment::Environment,
7    geometry::Geometry,
8};
9
10pub trait SilencerConfig: Clone + Copy {}
11
12/// To configure the silencer by the completion time.
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub struct FixedCompletionTime {
15    /// The completion time of the intensity change. The value must be multiple of the ultrasound period.
16    ///
17    /// The larger this value, the more the noise is suppressed.
18    pub intensity: std::time::Duration,
19    /// The completion time of the phase change. The value must be multiple of the ultrasound period.
20    ///
21    /// The larger this value, the more the noise is suppressed.
22    pub phase: std::time::Duration,
23    /// Whether the strict mode is enabled. The default is `true`.
24    ///
25    /// If the strict mode is enabled, an error is returned if the phase/intensity change of [`Modulation`], [`FociSTM`] or [`GainSTM`] cannot be completed within the time specified by the silencer.
26    ///
27    /// [`Modulation`]: autd3_core::modulation::Modulation
28    /// [`FociSTM`]: crate::datagram::FociSTM
29    /// [`GainSTM`]: crate::datagram::GainSTM
30    pub strict: bool,
31}
32impl SilencerConfig for FixedCompletionTime {}
33
34impl Default for FixedCompletionTime {
35    fn default() -> Self {
36        FixedCompletionTime {
37            intensity: SILENCER_STEPS_INTENSITY_DEFAULT as u32 * ULTRASOUND_PERIOD,
38            phase: SILENCER_STEPS_PHASE_DEFAULT as u32 * ULTRASOUND_PERIOD,
39            strict: true,
40        }
41    }
42}
43
44/// To configure the silencer by the completion steps.
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46#[repr(C)]
47pub struct FixedCompletionSteps {
48    /// The completion steps of the intensity change.
49    ///
50    /// The larger this value, the more the noise is suppressed.
51    pub intensity: NonZeroU16,
52    /// The completion time of the phase change.
53    ///
54    /// The larger this value, the more the noise is suppressed.
55    pub phase: NonZeroU16,
56    /// Whether the strict mode is enabled. The default is `true`.
57    ///
58    /// If the strict mode is enabled, an error is returned if the phase/intensity change of [`Modulation`], [`FociSTM`] or [`GainSTM`] cannot be completed within the time specified by the silencer.
59    ///
60    /// [`Modulation`]: autd3_core::modulation::Modulation
61    /// [`FociSTM`]: crate::datagram::FociSTM
62    /// [`GainSTM`]: crate::datagram::GainSTM
63    pub strict: bool,
64}
65impl SilencerConfig for FixedCompletionSteps {}
66
67impl Default for FixedCompletionSteps {
68    fn default() -> Self {
69        FixedCompletionSteps {
70            intensity: NonZeroU16::new(SILENCER_STEPS_INTENSITY_DEFAULT).unwrap(),
71            phase: NonZeroU16::new(SILENCER_STEPS_PHASE_DEFAULT).unwrap(),
72            strict: true,
73        }
74    }
75}
76
77/// To configure the silencer by the update rate.
78#[derive(Debug, Clone, Copy, PartialEq, Eq)]
79#[repr(C)]
80pub struct FixedUpdateRate {
81    /// The update rate of the intensity change.
82    ///
83    /// The smaller this value, the more the noise is suppressed.
84    pub intensity: NonZeroU16,
85    /// The update rate of the phase change.
86    ///
87    /// The smaller this value, the more the noise is suppressed.
88    pub phase: NonZeroU16,
89}
90impl SilencerConfig for FixedUpdateRate {}
91
92/// [`Datagram`] to configure the silencer.
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94pub struct Silencer<T> {
95    /// Configuration of the silencer.
96    pub config: T,
97}
98
99impl<T: SilencerConfig> Silencer<T> {
100    /// Creates a new [`Silencer`].
101    #[must_use]
102    pub const fn new(config: T) -> Self {
103        Self { config }
104    }
105}
106
107impl Silencer<FixedCompletionSteps> {
108    /// Creates a [`Silencer`] to disable the silencer.
109    #[must_use]
110    pub const fn disable() -> Silencer<FixedCompletionSteps> {
111        Silencer {
112            config: FixedCompletionSteps {
113                intensity: NonZeroU16::MIN,
114                phase: NonZeroU16::MIN,
115                strict: true,
116            },
117        }
118    }
119}
120
121impl Default for Silencer<FixedCompletionSteps> {
122    fn default() -> Self {
123        Silencer {
124            config: Default::default(),
125        }
126    }
127}
128
129impl<T: SilencerConfig> Datagram<'_> for Silencer<T> {
130    type G = T;
131    type Error = Infallible;
132
133    fn operation_generator(
134        self,
135        _: &Geometry,
136        _: &Environment,
137        _: &DeviceMask,
138    ) -> Result<Self::G, Self::Error> {
139        Ok(self.config)
140    }
141}
142
143#[cfg(test)]
144mod tests {
145    use super::*;
146
147    #[test]
148    fn disable() {
149        let s = Silencer::disable();
150        assert_eq!(1, s.config.intensity.get());
151        assert_eq!(1, s.config.phase.get());
152        assert!(s.config.strict);
153    }
154
155    #[test]
156    fn fixed_completion_steps_default() {
157        let s: Silencer<FixedCompletionSteps> = Silencer::default();
158        assert_eq!(10, s.config.intensity.get());
159        assert_eq!(40, s.config.phase.get());
160        assert!(s.config.strict);
161    }
162
163    #[test]
164    fn fixed_completion_time_default() {
165        let s: Silencer<FixedCompletionTime> = Silencer::new(Default::default());
166        assert_eq!(std::time::Duration::from_micros(250), s.config.intensity);
167        assert_eq!(std::time::Duration::from_micros(1000), s.config.phase);
168        assert!(s.config.strict);
169    }
170}