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