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