stabilizer_stream/de/
data.rs

1use thiserror::Error;
2
3#[derive(Error, Debug, Clone)]
4pub enum FormatError {}
5
6pub trait Payload {
7    fn new(batches: usize, data: &[u8]) -> Result<Self, FormatError>
8    where
9        Self: Sized;
10    fn traces(&self) -> &[Vec<f32>];
11    fn traces_mut(&mut self) -> &mut [Vec<f32>];
12    fn labels(&self) -> &[&str];
13}
14
15pub struct AdcDac {
16    traces: [Vec<f32>; 4],
17}
18
19impl Payload for AdcDac {
20    /// Extract AdcDacData from a binary data block in the stream.
21    ///
22    /// # Args
23    /// * `batch_size` - The size of each batch in samples.
24    /// * `data` - The binary data composing the stream frame.
25    fn new(batches: usize, data: &[u8]) -> Result<Self, FormatError> {
26        const CHANNELS: usize = 4;
27        const BATCH_SIZE: usize = 8;
28
29        // The DAC output range in bipolar mode (including the external output op-amp) is +/- 4.096
30        // V with 16-bit resolution. The anti-aliasing filter has an additional gain of 2.5.
31        const DAC_VOLT_PER_LSB: f32 = 4.096 * 2.5 / (1u16 << 15) as f32;
32        // The ADC has a differential input with a range of +/- 4.096 V and 16-bit resolution.
33        // The gain into the two inputs is 1/5.
34        const ADC_VOLT_PER_LSB: f32 = 5.0 / 2.0 * 4.096 / (1u16 << 15) as f32;
35        assert_eq!(DAC_VOLT_PER_LSB, ADC_VOLT_PER_LSB);
36
37        let v = Vec::with_capacity(data.len() * BATCH_SIZE);
38        let mut traces = [v.clone(), v.clone(), v.clone(), v];
39        let data: &[[[[u8; 2]; BATCH_SIZE]; CHANNELS]] = bytemuck::cast_slice(data);
40        assert_eq!(data.len(), batches);
41        for b in data.iter() {
42            traces[0].extend(
43                b[0].into_iter()
44                    .map(|x| i16::from_le_bytes(x) as f32 * ADC_VOLT_PER_LSB),
45            );
46            traces[1].extend(
47                b[1].into_iter()
48                    .map(|x| i16::from_le_bytes(x) as f32 * ADC_VOLT_PER_LSB),
49            );
50            traces[2].extend(
51                b[2].into_iter().map(|x| {
52                    i16::from_le_bytes(x).wrapping_add(i16::MIN) as f32 * DAC_VOLT_PER_LSB
53                }),
54            );
55            traces[3].extend(
56                b[3].into_iter().map(|x| {
57                    i16::from_le_bytes(x).wrapping_add(i16::MIN) as f32 * DAC_VOLT_PER_LSB
58                }),
59            );
60        }
61        Ok(Self { traces })
62    }
63
64    fn traces(&self) -> &[Vec<f32>] {
65        &self.traces
66    }
67
68    fn traces_mut(&mut self) -> &mut [Vec<f32>] {
69        &mut self.traces
70    }
71    fn labels(&self) -> &[&str] {
72        &["ADC0", "ADC1", "DAC0", "DAC1"]
73    }
74}
75
76pub struct Fls {
77    traces: [Vec<f32>; 4],
78}
79
80impl Payload for Fls {
81    fn new(batches: usize, data: &[u8]) -> Result<Self, FormatError> {
82        let data: &[[[i32; 6]; 2]] = bytemuck::cast_slice(data);
83        // demod_re, demod_im, wraps, ftw, pow_amp, pll
84        assert_eq!(batches, data.len());
85        let traces: [Vec<f32>; 4] = [
86            data.iter()
87                .map(|b| {
88                    ((b[0][0] as f32).powi(2) + (b[0][1] as f32).powi(2)).sqrt() / (i32::MAX as f32)
89                })
90                .collect(),
91            data.iter()
92                .map(|b| (b[0][1] as f32).atan2(b[0][0] as f32))
93                .collect(),
94            data.iter()
95                .map(|b| b[1][0] as f32 / i32::MAX as f32)
96                .collect(),
97            data.iter()
98                .map(|b| b[1][1] as f32 / i32::MAX as f32)
99                .collect(),
100        ];
101        Ok(Self { traces })
102    }
103
104    fn labels(&self) -> &[&str] {
105        &["AR", "AP", "BI", "BQ"]
106    }
107
108    fn traces(&self) -> &[Vec<f32>] {
109        &self.traces
110    }
111    fn traces_mut(&mut self) -> &mut [Vec<f32>] {
112        &mut self.traces
113    }
114}