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