autd3_firmware_emulator/fpga/emulator/stm/
foci.rs1use autd3_core::firmware::{Drive, Intensity, Phase, Segment};
2
3use super::super::{super::params::*, FPGAEmulator};
4
5#[bitfield_struct::bitfield(u64)]
6struct STMFocus {
7 #[bits(18)]
8 pub x: i32,
9 #[bits(18)]
10 pub y: i32,
11 #[bits(18)]
12 pub z: i32,
13 #[bits(8)]
14 pub intensity: u8,
15 #[bits(2)]
16 __: u8,
17}
18
19impl FPGAEmulator {
20 #[must_use]
21 pub fn sound_speed(&self, segment: Segment) -> u16 {
22 self.mem
23 .controller_bram
24 .read(ADDR_STM_SOUND_SPEED0 + segment as usize)
25 }
26
27 #[must_use]
28 pub fn num_foci(&self, segment: Segment) -> u8 {
29 self.mem
30 .controller_bram
31 .read(ADDR_STM_NUM_FOCI0 + segment as usize) as u8
32 }
33
34 pub(crate) fn foci_stm_drives_inplace(
35 &self,
36 segment: Segment,
37 idx: usize,
38 phase_corr_buf: &mut [Phase],
39 output_mask_buf: &mut [bool],
40 dst: &mut [Drive],
41 ) {
42 let bram = &self.mem.stm_bram[&segment];
43 let sound_speed = self.sound_speed(segment);
44 let num_foci = self.num_foci(segment) as usize;
45
46 self.phase_correction_inplace(phase_corr_buf);
47 self.output_mask_inplace(segment, output_mask_buf);
48
49 self.mem
50 .tr_pos
51 .iter()
52 .zip(phase_corr_buf.iter())
53 .zip(output_mask_buf.iter())
54 .take(self.mem.num_transducers)
55 .enumerate()
56 .for_each(|(i, ((&tr, &p), &mask))| {
57 let tr_z = ((tr >> 32) & 0xFFFF) as i16 as i32;
58 let tr_x = ((tr >> 16) & 0xFFFF) as i16 as i32;
59 let tr_y = (tr & 0xFFFF) as i16 as i32;
60 let mut intensity = 0x00;
61 let (sin, cos) = (0..num_foci).fold((0, 0), |acc, i| {
62 let f = bram.read_bram_as::<STMFocus>(
63 size_of::<STMFocus>() / size_of::<u16>() * (idx * num_foci + i),
64 );
65 let x = f.x();
66 let y = f.y();
67 let z = f.z();
68 let intensity_or_offset = f.intensity();
69 let offset = if i == 0 {
70 intensity = intensity_or_offset;
71 0x00
72 } else {
73 intensity_or_offset
74 };
75
76 let d2 =
77 (x - tr_x) * (x - tr_x) + (y - tr_y) * (y - tr_y) + (z - tr_z) * (z - tr_z);
78 let dist = d2.isqrt() as u32;
79 let q = ((dist << 14) / sound_speed as u32) as usize;
80 let q = q + offset as usize;
81 (
82 acc.0 + self.mem.sin_table[q % 256] as u16,
83 acc.1 + self.mem.sin_table[(q + 64) % 256] as u16,
84 )
85 });
86 let sin = ((sin / num_foci as u16) >> 1) as usize;
87 let cos = ((cos / num_foci as u16) >> 1) as usize;
88 let phase = self.mem.atan_table[(sin << 7) | cos];
89 dst[i] = Drive {
90 phase: Phase(phase) + p,
91 intensity: Intensity(if mask { intensity } else { 0x00 }),
92 };
93 });
94 }
95
96 #[must_use]
98 pub fn local_tr_pos(&self) -> &[u64] {
99 self.mem.tr_pos.mem.as_slice()
100 }
101 #[must_use]
104 pub fn local_tr_pos_at(&self, idx: usize) -> u64 {
105 self.mem.tr_pos[idx]
106 }
107}