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