autd3_driver/datagram/
silencer.rs

1use std::{convert::Infallible, num::NonZeroU16};
2
3use crate::{
4    firmware::{
5        fpga::{SILENCER_STEPS_INTENSITY_DEFAULT, SILENCER_STEPS_PHASE_DEFAULT},
6        operation::{
7            NullOp, OperationGenerator, SilencerFixedCompletionStepsOp, SilencerFixedUpdateRateOp,
8        },
9    },
10    geometry::{Device, Geometry},
11};
12
13use super::Datagram;
14
15pub trait SilencerConfig: std::fmt::Debug + Clone + Copy {}
16impl SilencerConfig for () {}
17
18/// To configure the silencer by the completion time.
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub struct FixedCompletionTime {
21    /// The completion time of the intensity change. The value must be multiple of the ultrasound period.
22    ///
23    /// The larger this value, the more the noise is suppressed.
24    pub intensity: std::time::Duration,
25    /// The completion time of the phase change. The value must be multiple of the ultrasound period.
26    ///
27    /// The larger this value, the more the noise is suppressed.
28    pub phase: std::time::Duration,
29    /// Whether the strict mode is enabled. The default is `true`.
30    ///
31    /// 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.
32    ///
33    /// [`Modulation`]: autd3_core::modulation::Modulation
34    /// [`FociSTM`]: crate::datagram::FociSTM
35    /// [`GainSTM`]: crate::datagram::GainSTM
36    pub strict_mode: bool,
37}
38impl SilencerConfig for FixedCompletionTime {}
39
40impl Default for FixedCompletionTime {
41    fn default() -> Self {
42        FixedCompletionTime {
43            intensity: SILENCER_STEPS_INTENSITY_DEFAULT as u32
44                * autd3_core::defined::ULTRASOUND_PERIOD,
45            phase: SILENCER_STEPS_PHASE_DEFAULT as u32 * autd3_core::defined::ULTRASOUND_PERIOD,
46            strict_mode: true,
47        }
48    }
49}
50
51/// To configure the silencer by the completion steps.
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
53#[repr(C)]
54pub struct FixedCompletionSteps {
55    /// The completion steps of the intensity change.
56    ///
57    /// The larger this value, the more the noise is suppressed.
58    pub intensity: NonZeroU16,
59    /// The completion time of the phase change.
60    ///
61    /// The larger this value, the more the noise is suppressed.
62    pub phase: NonZeroU16,
63    /// Whether the strict mode is enabled. The default is `true`.
64    ///
65    /// 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.
66    ///
67    /// [`Modulation`]: autd3_core::modulation::Modulation
68    /// [`FociSTM`]: crate::datagram::FociSTM
69    /// [`GainSTM`]: crate::datagram::GainSTM
70    pub strict_mode: bool,
71}
72impl SilencerConfig for FixedCompletionSteps {}
73
74impl Default for FixedCompletionSteps {
75    fn default() -> Self {
76        FixedCompletionSteps {
77            intensity: NonZeroU16::new(SILENCER_STEPS_INTENSITY_DEFAULT).unwrap(),
78            phase: NonZeroU16::new(SILENCER_STEPS_PHASE_DEFAULT).unwrap(),
79            strict_mode: true,
80        }
81    }
82}
83
84/// To configure the silencer by the update rate.
85#[derive(Debug, Clone, Copy, PartialEq, Eq)]
86#[repr(C)]
87pub struct FixedUpdateRate {
88    /// The update rate of the intensity change.
89    ///
90    /// The smaller this value, the more the noise is suppressed.
91    pub intensity: NonZeroU16,
92    /// The update rate of the phase change.
93    ///
94    /// The smaller this value, the more the noise is suppressed.
95    pub phase: NonZeroU16,
96}
97impl SilencerConfig for FixedUpdateRate {}
98
99/// [`Datagram`] to configure the silencer.
100#[derive(Debug, Clone, Copy, PartialEq, Eq)]
101pub struct Silencer<T: SilencerConfig> {
102    /// Configuration of the silencer.
103    pub config: T,
104}
105
106impl<T: SilencerConfig> Silencer<T> {
107    /// Creates a new [`Silencer`].
108    #[must_use]
109    pub const fn new(config: T) -> Self {
110        Self { config }
111    }
112}
113
114impl Silencer<()> {
115    /// Creates a [`Silencer`] to disable the silencer.
116    #[must_use]
117    pub const fn disable() -> Silencer<FixedCompletionSteps> {
118        Silencer {
119            config: FixedCompletionSteps {
120                intensity: NonZeroU16::MIN,
121                phase: NonZeroU16::MIN,
122                strict_mode: true,
123            },
124        }
125    }
126}
127
128impl Default for Silencer<FixedCompletionSteps> {
129    fn default() -> Self {
130        Silencer {
131            config: Default::default(),
132        }
133    }
134}
135
136pub struct SilencerOpGenerator<T: SilencerConfig> {
137    config: T,
138}
139
140impl OperationGenerator for SilencerOpGenerator<FixedUpdateRate> {
141    type O1 = SilencerFixedUpdateRateOp;
142    type O2 = NullOp;
143
144    fn generate(&mut self, _: &Device) -> (Self::O1, Self::O2) {
145        (
146            Self::O1::new(self.config.intensity, self.config.phase),
147            Self::O2 {},
148        )
149    }
150}
151
152impl OperationGenerator for SilencerOpGenerator<FixedCompletionTime> {
153    type O1 = crate::firmware::operation::SilencerFixedCompletionTimeOp;
154    type O2 = NullOp;
155
156    fn generate(&mut self, _: &Device) -> (Self::O1, Self::O2) {
157        (
158            Self::O1::new(
159                self.config.intensity,
160                self.config.phase,
161                self.config.strict_mode,
162            ),
163            Self::O2 {},
164        )
165    }
166}
167
168impl OperationGenerator for SilencerOpGenerator<FixedCompletionSteps> {
169    type O1 = SilencerFixedCompletionStepsOp;
170    type O2 = NullOp;
171
172    fn generate(&mut self, _: &Device) -> (Self::O1, Self::O2) {
173        (
174            Self::O1::new(
175                self.config.intensity,
176                self.config.phase,
177                self.config.strict_mode,
178            ),
179            Self::O2 {},
180        )
181    }
182}
183
184impl<T: SilencerConfig> Datagram for Silencer<T>
185where
186    SilencerOpGenerator<T>: OperationGenerator,
187{
188    type G = SilencerOpGenerator<T>;
189    type Error = Infallible;
190
191    fn operation_generator(self, _: &Geometry, _: bool) -> Result<Self::G, Self::Error> {
192        Ok(Self::G {
193            config: self.config,
194        })
195    }
196}
197
198#[cfg(test)]
199mod tests {
200    use super::*;
201
202    #[test]
203    fn disable() {
204        let s = Silencer::disable();
205        assert_eq!(1, s.config.intensity.get());
206        assert_eq!(1, s.config.phase.get());
207        assert!(s.config.strict_mode);
208    }
209
210    #[test]
211    fn fixed_completion_steps_default() {
212        let s: Silencer<FixedCompletionSteps> = Silencer::default();
213        assert_eq!(10, s.config.intensity.get());
214        assert_eq!(40, s.config.phase.get());
215        assert!(s.config.strict_mode);
216    }
217
218    #[test]
219    fn fixed_completion_time_default() {
220        let s: Silencer<FixedCompletionTime> = Silencer::new(Default::default());
221        assert_eq!(std::time::Duration::from_micros(250), s.config.intensity);
222        assert_eq!(std::time::Duration::from_micros(1000), s.config.phase);
223        assert!(s.config.strict_mode);
224    }
225}