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