autd3_firmware_emulator/fpga/emulator/
modulation.rs1use 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}