autd3_firmware_emulator/fpga/emulator/
modulation.rs

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