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