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
use crate::{
    defined::{Freq, Hz},
    error::AUTDInternalError,
    firmware::fpga::SamplingConfig,
    utils::float::is_integer,
};

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum STMSamplingConfig {
    Freq(Freq<f32>),
    FreqNearest(Freq<f32>),
    SamplingConfig(SamplingConfig),
}

impl STMSamplingConfig {
    pub fn sampling(&self, size: usize) -> Result<SamplingConfig, AUTDInternalError> {
        match *self {
            STMSamplingConfig::Freq(f) => {
                let fs = f.hz() as f64 * size as f64;
                if !is_integer(fs) {
                    return Err(AUTDInternalError::STMFreqInvalid(size, f));
                }
                Ok(SamplingConfig::Freq(fs as u32 * Hz))
            }
            STMSamplingConfig::FreqNearest(f) => {
                Ok(SamplingConfig::FreqNearest(f.hz() * size as f32 * Hz))
            }
            Self::SamplingConfig(s) => Ok(s),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{
        defined::Hz,
        derive::{AUTDInternalError, SAMPLING_FREQ_DIV_MIN},
        firmware::fpga::{SamplingConfig, SAMPLING_FREQ_DIV_MAX},
    };

    #[rstest::rstest]
    #[test]
    #[case(Ok(SamplingConfig::Freq(4000*Hz)), 4000.*Hz, 1)]
    #[case(Ok(SamplingConfig::Freq(8000*Hz)), 4000.*Hz, 2)]
    #[case(Ok(SamplingConfig::Freq(40000*Hz)), 40000.*Hz, 1)]
    #[case(Err(AUTDInternalError::STMFreqInvalid(1, 4000.5*Hz)), 4000.5*Hz, 1)]
    fn frequency(
        #[case] expect: Result<SamplingConfig, AUTDInternalError>,
        #[case] freq: Freq<f32>,
        #[case] size: usize,
    ) {
        assert_eq!(expect, STMSamplingConfig::Freq(freq).sampling(size));
    }

    #[rstest::rstest]
    #[test]
    #[case(Ok(SamplingConfig::FreqNearest(4000.*Hz)), 4000.*Hz, 1)]
    #[case(Ok(SamplingConfig::FreqNearest(8000.*Hz)), 4000.*Hz, 2)]
    #[case(Ok(SamplingConfig::FreqNearest(4001.*Hz)), 4001.*Hz, 1)]
    #[case(Ok(SamplingConfig::FreqNearest(40000.*Hz)), 40000.*Hz, 1)]
    fn frequency_nearest(
        #[case] expect: Result<SamplingConfig, AUTDInternalError>,
        #[case] freq: Freq<f32>,
        #[case] size: usize,
    ) {
        assert_eq!(expect, STMSamplingConfig::FreqNearest(freq).sampling(size));
    }

    #[rstest::rstest]
    #[test]
    #[case(SamplingConfig::DivisionRaw(SAMPLING_FREQ_DIV_MIN), 1)]
    #[case(SamplingConfig::DivisionRaw(SAMPLING_FREQ_DIV_MIN), 2)]
    #[case(SamplingConfig::DivisionRaw(SAMPLING_FREQ_DIV_MAX), 1)]
    #[case(SamplingConfig::DivisionRaw(SAMPLING_FREQ_DIV_MAX), 2)]
    fn sampling(#[case] config: SamplingConfig, #[case] size: usize) {
        assert_eq!(
            Ok(config),
            STMSamplingConfig::SamplingConfig(config).sampling(size)
        );
    }
}