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