autd3_firmware_emulator/fpga/emulator/stm/
mod.rs1use std::num::NonZeroU16;
2
3use autd3_driver::{
4 ethercat::DcSysTime,
5 firmware::fpga::{Drive, GPIOIn, LoopBehavior, Segment, TransitionMode},
6};
7
8use super::{super::params::*, FPGAEmulator, memory::Memory};
9
10mod foci;
11mod gain;
12
13impl FPGAEmulator {
14 #[must_use]
15 pub fn is_stm_gain_mode(&self, segment: Segment) -> bool {
16 match segment {
17 Segment::S0 => self.mem.controller_bram.borrow()[ADDR_STM_MODE0] == STM_MODE_GAIN,
18 Segment::S1 => self.mem.controller_bram.borrow()[ADDR_STM_MODE1] == STM_MODE_GAIN,
19 }
20 }
21
22 #[must_use]
23 pub fn stm_freq_division(&self, segment: Segment) -> u16 {
24 Memory::read_bram_as::<u16>(
25 &self.mem.controller_bram.borrow(),
26 match segment {
27 Segment::S0 => ADDR_STM_FREQ_DIV0,
28 Segment::S1 => ADDR_STM_FREQ_DIV1,
29 },
30 )
31 }
32
33 #[must_use]
34 pub fn stm_cycle(&self, segment: Segment) -> usize {
35 self.mem.controller_bram.borrow()[match segment {
36 Segment::S0 => ADDR_STM_CYCLE0,
37 Segment::S1 => ADDR_STM_CYCLE1,
38 }] as usize
39 + 1
40 }
41
42 #[must_use]
43 pub fn stm_loop_behavior(&self, segment: Segment) -> LoopBehavior {
44 match Memory::read_bram_as::<u16>(
45 &self.mem.controller_bram.borrow(),
46 match segment {
47 Segment::S0 => ADDR_STM_REP0,
48 Segment::S1 => ADDR_STM_REP1,
49 },
50 ) {
51 0xFFFF => LoopBehavior::Infinite,
52 v => LoopBehavior::Finite(NonZeroU16::new(v + 1).unwrap()),
53 }
54 }
55
56 #[must_use]
57 pub fn stm_transition_mode(&self) -> TransitionMode {
58 match self.mem.controller_bram.borrow()[ADDR_STM_TRANSITION_MODE] as u8 {
59 TRANSITION_MODE_SYNC_IDX => TransitionMode::SyncIdx,
60 TRANSITION_MODE_SYS_TIME => TransitionMode::SysTime(
61 DcSysTime::ZERO
62 + std::time::Duration::from_nanos(Memory::read_bram_as::<u64>(
63 &self.mem.controller_bram.borrow(),
64 ADDR_STM_TRANSITION_VALUE_0,
65 )),
66 ),
67 TRANSITION_MODE_GPIO => TransitionMode::GPIO(
68 match Memory::read_bram_as::<u64>(
69 &self.mem.controller_bram.borrow(),
70 ADDR_STM_TRANSITION_VALUE_0,
71 ) {
72 0 => GPIOIn::I0,
73 1 => GPIOIn::I1,
74 2 => GPIOIn::I2,
75 3 => GPIOIn::I3,
76 _ => unreachable!(),
77 },
78 ),
79 TRANSITION_MODE_EXT => TransitionMode::Ext,
80 TRANSITION_MODE_IMMEDIATE => TransitionMode::Immediate,
81 _ => unreachable!(),
82 }
83 }
84
85 #[must_use]
86 pub fn req_stm_segment(&self) -> Segment {
87 match self.mem.controller_bram.borrow()[ADDR_STM_REQ_RD_SEGMENT] {
88 0 => Segment::S0,
89 1 => Segment::S1,
90 _ => unreachable!(),
91 }
92 }
93
94 #[must_use]
95 pub fn drives(&self) -> Vec<Drive> {
96 self.drives_at(self.current_stm_segment(), self.current_stm_idx())
97 }
98
99 #[must_use]
100 pub fn drives_at(&self, segment: Segment, idx: usize) -> Vec<Drive> {
101 let mut dst = vec![Drive::NULL; self.mem.num_transducers];
102 self.drives_at_inplace(segment, idx, &mut dst);
103 dst
104 }
105
106 pub fn drives_at_inplace(&self, segment: Segment, idx: usize, dst: &mut [Drive]) {
107 if self.is_stm_gain_mode(segment) {
108 self.gain_stm_drives_inplace(segment, idx, dst)
109 } else {
110 self.foci_stm_drives_inplace(segment, idx, dst)
111 }
112 }
113}