autd3_driver/datagram/modulation/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
mod boxed;

pub use boxed::{BoxedModulation, IntoBoxedModulation};

use std::sync::Arc;

use super::silencer::HasSamplingConfig;
use crate::{
    error::AUTDDriverError,
    firmware::{
        fpga::{LoopBehavior, SamplingConfig, Segment, TransitionMode},
        operation::{ModulationOp, NullOp, OperationGenerator},
    },
    geometry::Device,
};

/// A trait to get the modulation property. (This trait is automatically implemented by the [`Modulation`] derive macro.)
///
/// [`Modulation`]: autd3_derive::Modulation
pub trait ModulationProperty {
    /// Get the sampling configuration.
    fn sampling_config(&self) -> SamplingConfig;
    /// Get the loop behavior.
    fn loop_behavior(&self) -> LoopBehavior;
}

/// Trait for applying amplitude modulation.
///
/// See also [`Modulation`] derive macro.
///
/// [`Modulation`]: autd3_derive::Modulation
pub trait Modulation: ModulationProperty + std::fmt::Debug {
    /// Calculate the modulation data.
    fn calc(self) -> Result<Vec<u8>, AUTDDriverError>;
}

impl<M: Modulation> HasSamplingConfig for M {
    fn intensity(&self) -> Option<SamplingConfig> {
        Some(self.sampling_config())
    }
    fn phase(&self) -> Option<SamplingConfig> {
        None
    }
}

#[doc(hidden)]
pub struct ModulationOperationGenerator {
    pub g: Arc<Vec<u8>>,
    pub config: SamplingConfig,
    pub loop_behavior: LoopBehavior,
    pub segment: Segment,
    pub transition_mode: Option<TransitionMode>,
}

impl OperationGenerator for ModulationOperationGenerator {
    type O1 = ModulationOp;
    type O2 = NullOp;

    fn generate(&mut self, _: &Device) -> (Self::O1, Self::O2) {
        let d = self.g.clone();
        (
            Self::O1::new(
                d,
                self.config,
                self.loop_behavior,
                self.segment,
                self.transition_mode,
            ),
            Self::O2::new(),
        )
    }
}

#[cfg(test)]
pub mod tests {
    use autd3_derive::Modulation;

    use super::*;
    use crate::{datagram::DatagramS, geometry::Geometry};

    #[derive(Modulation, Clone, PartialEq, Debug)]
    pub struct TestModulation {
        pub config: SamplingConfig,
        pub loop_behavior: LoopBehavior,
    }

    impl Modulation for TestModulation {
        fn calc(self) -> Result<Vec<u8>, AUTDDriverError> {
            Ok(vec![0; 2])
        }
    }

    #[test]
    fn test() {
        let m = TestModulation {
            config: SamplingConfig::FREQ_4K,
            loop_behavior: LoopBehavior::infinite(),
        };

        assert_eq!(SamplingConfig::FREQ_4K, m.sampling_config());
        assert_eq!(LoopBehavior::infinite(), m.loop_behavior());
        assert_eq!(Ok(vec![0; 2]), m.calc());
    }
}