autd3_firmware_emulator/fpga/emulator/
modulation.rs

1use std::num::NonZeroU16;
2
3use autd3_core::datagram::{GPIOIn, LoopBehavior, Segment, TransitionMode};
4use autd3_driver::ethercat::DcSysTime;
5
6use super::{super::params::*, FPGAEmulator};
7
8impl FPGAEmulator {
9    #[must_use]
10    pub fn modulation_freq_divide(&self, segment: Segment) -> u16 {
11        self.mem
12            .controller_bram
13            .read(ADDR_MOD_FREQ_DIV0 + segment as usize)
14    }
15
16    #[must_use]
17    pub fn modulation_cycle(&self, segment: Segment) -> usize {
18        self.mem
19            .controller_bram
20            .read(ADDR_MOD_CYCLE0 + segment as usize) as usize
21            + 1
22    }
23
24    #[must_use]
25    pub fn modulation_loop_behavior(&self, segment: Segment) -> LoopBehavior {
26        match &self
27            .mem
28            .controller_bram
29            .read(ADDR_MOD_REP0 + segment as usize)
30        {
31            0xFFFF => LoopBehavior::Infinite,
32            v => LoopBehavior::Finite(NonZeroU16::new(v + 1).unwrap()),
33        }
34    }
35
36    #[must_use]
37    pub fn modulation(&self) -> u8 {
38        self.modulation_at(self.current_mod_segment(), self.current_mod_idx())
39    }
40
41    #[must_use]
42    pub fn modulation_at(&self, segment: Segment, idx: usize) -> u8 {
43        let m = &self.mem.modulation_bram[&segment].read(idx >> 1);
44        let m = if idx % 2 == 0 { m & 0xFF } else { m >> 8 };
45        m as u8
46    }
47
48    #[must_use]
49    pub fn modulation_buffer(&self, segment: Segment) -> Vec<u8> {
50        let mut dst = vec![0; self.modulation_cycle(segment)];
51        self.modulation_buffer_inplace(segment, &mut dst);
52        dst
53    }
54
55    pub fn modulation_buffer_inplace(&self, segment: Segment, dst: &mut [u8]) {
56        (0..self.modulation_cycle(segment)).for_each(|i| dst[i] = self.modulation_at(segment, i));
57    }
58
59    #[must_use]
60    pub fn modulation_transition_mode(&self) -> TransitionMode {
61        match self.mem.controller_bram.read(ADDR_MOD_TRANSITION_MODE) as u8 {
62            TRANSITION_MODE_SYNC_IDX => TransitionMode::SyncIdx,
63            TRANSITION_MODE_SYS_TIME => TransitionMode::SysTime(
64                DcSysTime::ZERO
65                    + std::time::Duration::from_nanos(
66                        self.mem
67                            .controller_bram
68                            .read_bram_as::<u64>(ADDR_MOD_TRANSITION_VALUE_0),
69                    ),
70            ),
71            TRANSITION_MODE_GPIO => TransitionMode::GPIO(
72                match self
73                    .mem
74                    .controller_bram
75                    .read_bram_as::<u64>(ADDR_MOD_TRANSITION_VALUE_0)
76                {
77                    0 => GPIOIn::I0,
78                    1 => GPIOIn::I1,
79                    2 => GPIOIn::I2,
80                    3 => GPIOIn::I3,
81                    _ => unreachable!(),
82                },
83            ),
84            TRANSITION_MODE_EXT => TransitionMode::Ext,
85            TRANSITION_MODE_IMMEDIATE => TransitionMode::Immediate,
86            _ => unreachable!(),
87        }
88    }
89
90    #[must_use]
91    pub fn req_modulation_segment(&self) -> Segment {
92        match self.mem.controller_bram.read(ADDR_MOD_REQ_RD_SEGMENT) {
93            0 => Segment::S0,
94            1 => Segment::S1,
95            _ => unreachable!(),
96        }
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn modulation() {
106        let fpga = FPGAEmulator::new(249);
107        fpga.mem.modulation_bram[&Segment::S0].write(0, 0x1234);
108        fpga.mem.modulation_bram[&Segment::S0].write(1, 0x5678);
109        fpga.mem.controller_bram.write(ADDR_MOD_CYCLE0, 3 - 1);
110        assert_eq!(3, fpga.modulation_cycle(Segment::S0));
111        assert_eq!(0x34, fpga.modulation());
112        assert_eq!(0x34, fpga.modulation_at(Segment::S0, 0));
113        assert_eq!(0x12, fpga.modulation_at(Segment::S0, 1));
114        assert_eq!(0x78, fpga.modulation_at(Segment::S0, 2));
115        assert_eq!(vec![0x34, 0x12, 0x78], fpga.modulation_buffer(Segment::S0));
116    }
117}