autd3_firmware_emulator/fpga/emulator/stm/
mod.rs

1use 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}