autd3_firmware_emulator/fpga/emulator/
pwe.rs

1use autd3_driver::firmware::fpga::EmitIntensity;
2
3use super::FPGAEmulator;
4
5impl FPGAEmulator {
6    #[must_use]
7    pub fn pulse_width_encoder_table_at(&self, idx: usize) -> u8 {
8        let v = self.mem.duty_table_bram.borrow()[idx >> 1];
9        let v = if idx % 2 == 0 { v & 0xFF } else { v >> 8 };
10        v as u8
11    }
12
13    #[must_use]
14    pub fn pulse_width_encoder_table(&self) -> Vec<u8> {
15        let mut dst = vec![0; 256];
16        self.pulse_width_encoder_table_inplace(&mut dst);
17        dst
18    }
19
20    pub fn pulse_width_encoder_table_inplace(&self, dst: &mut [u8]) {
21        self.mem
22            .duty_table_bram
23            .borrow()
24            .iter()
25            .flat_map(|&d| [(d & 0xFF) as u8, (d >> 8) as u8])
26            .enumerate()
27            .for_each(|(i, v)| dst[i] = v);
28    }
29
30    #[must_use]
31    pub fn to_pulse_width(&self, a: EmitIntensity, b: u8) -> u8 {
32        let key = (a.0 as usize * b as usize) / 255;
33        self.pulse_width_encoder_table_at(key)
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40
41    static ASIN_TABLE: &[u8; 256] = include_bytes!("asin.dat");
42
43    fn to_pulse_width_actual(a: u8, b: u8) -> u8 {
44        let idx = (a as usize * b as usize) / 255;
45        ASIN_TABLE[idx]
46    }
47
48    #[test]
49    fn test_to_pulse_width() {
50        let fpga = FPGAEmulator::new(249);
51        itertools::iproduct!(0x00..=0xFF, 0x00..=0xFF).for_each(|(a, b)| {
52            assert_eq!(
53                to_pulse_width_actual(a, b),
54                fpga.to_pulse_width(EmitIntensity(a), b)
55            );
56        });
57    }
58}