pico_common/
config.rs

1use super::{PicoCoupling, PicoRange};
2use num_derive::*;
3use std::convert::From;
4
5/// Pico time units
6#[derive(Debug, Clone, Copy, FromPrimitive, ToPrimitive, PartialEq)]
7pub enum TimeUnits {
8    FS = 0,
9    PS = 1,
10    NS = 2,
11    US = 3,
12    MS = 4,
13    S = 5,
14}
15
16impl From<TimeUnits> for u32 {
17    fn from(value: TimeUnits) -> Self {
18        num_traits::ToPrimitive::to_u32(&value).expect("Non-valid time unit")
19    }
20}
21
22impl From<TimeUnits> for i16 {
23    fn from(value: TimeUnits) -> Self {
24        num_traits::ToPrimitive::to_i16(&value).expect("Non-valid time unit")
25    }
26}
27
28impl From<i32> for TimeUnits {
29    fn from(value: i32) -> Self {
30        num_traits::FromPrimitive::from_i32(value).expect("Non-valid time unit")
31    }
32}
33
34impl TimeUnits {
35    pub fn get_multiplier(self) -> f64 {
36        match self {
37            TimeUnits::S => 1.0,
38            TimeUnits::MS => 1e-3,
39            TimeUnits::US => 1e-6,
40            TimeUnits::NS => 1e-9,
41            TimeUnits::PS => 1e-12,
42            TimeUnits::FS => 1e-15,
43        }
44    }
45}
46
47/// Sample configuration
48#[derive(Debug, Clone, Copy)]
49pub struct SampleConfig {
50    pub interval: u32,
51    pub units: TimeUnits,
52}
53
54impl SampleConfig {
55    pub fn new(interval: u32, units: TimeUnits) -> SampleConfig {
56        SampleConfig { interval, units }
57    }
58
59    pub fn from_samples_per_second(samples_per_second: u32) -> SampleConfig {
60        let interval: f64 = (1f64 / (samples_per_second as f64)) * 1_000_000_000_f64;
61
62        SampleConfig {
63            interval: interval as u32,
64            units: TimeUnits::NS,
65        }
66    }
67
68    pub fn get_interval(self) -> f64 {
69        self.units.get_multiplier() * (self.interval as f64)
70    }
71
72    pub fn samples_per_second(self) -> u32 {
73        (1f64 / self.get_interval()) as u32
74    }
75
76    pub fn with_interval(self, interval: u32) -> SampleConfig {
77        SampleConfig { interval, ..self }
78    }
79}
80
81impl Default for SampleConfig {
82    fn default() -> Self {
83        SampleConfig::new(1, TimeUnits::MS)
84    }
85}
86
87#[cfg(test)]
88#[allow(clippy::float_cmp)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn from_samples_per_second() {
94        let sc = SampleConfig::from_samples_per_second(1);
95        assert_eq!(sc.interval, 1_000_000_000);
96        assert_eq!(sc.units, TimeUnits::NS);
97        assert_eq!(sc.samples_per_second(), 1);
98
99        let sc = SampleConfig::from_samples_per_second(1000);
100        assert_eq!(sc.interval, 1_000_000);
101        assert_eq!(sc.units, TimeUnits::NS);
102        assert_eq!(sc.samples_per_second(), 1000);
103
104        let sc = SampleConfig::from_samples_per_second(15657);
105        assert_eq!(sc.interval, 63_869);
106        assert_eq!(sc.units, TimeUnits::NS);
107        assert_eq!(sc.samples_per_second(), 15657);
108    }
109
110    #[test]
111    fn get_interval() {
112        let sc = SampleConfig::from_samples_per_second(1000);
113        assert_eq!(sc.get_interval(), 0.001);
114
115        let sc = SampleConfig::from_samples_per_second(1234);
116        assert_eq!(sc.get_interval(), 0.000_810_372_000_000_000_1);
117    }
118}
119
120/// Channel configuration
121#[derive(Debug, Clone, Copy)]
122#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
123pub struct ChannelConfig {
124    pub coupling: PicoCoupling,
125    pub range: PicoRange,
126    pub offset: f64,
127}
128
129impl ChannelConfig {
130    pub fn new() -> ChannelConfig {
131        ChannelConfig {
132            coupling: PicoCoupling::DC,
133            range: PicoRange::X1_PROBE_20V,
134            offset: 0.0,
135        }
136    }
137}
138
139impl Default for ChannelConfig {
140    fn default() -> Self {
141        ChannelConfig::new()
142    }
143}