Skip to content

FociStm

FociStm provides an STM feature that switches single- and multi-focus sound fields by a hardware timer. Unlike PatternStm, it can only handle focal points, but the amount of data to transfer is small and the latency is low.

FociStm::new(config, &points, option);
Parameter Type Description
config SamplingConfig Sampling configuration per sample
points &[ControlPoints] Sequence of focal point samples (at least 2 samples)
option FociStmOption Options such as sound speed, loop, and transition

config is the sampling configuration per sample. To derive it from “the frequency of one full cycle over all samples”, multiply that frequency by the number of samples (e.g. 200 samples at 1 Hz is 200 Hz).

A single sample is represented by ControlPoints. The length of points is the number of focal points emitted simultaneously (1 to 8), and it must be the same for every sample (otherwise sending fails with an error).

  • ControlPoint { point, phase_offset } — focal point coordinate [mm] and phase offset.
  • ControlPoints { points: Vec<ControlPoint>, intensity } — a sequence of focal points and an amplitude.
FociStmOption {
bank,
sound_speed,
loop_behavior,
transition_mode,
..Default::default()
}
Field Type Default Description
bank PatternBank PatternBank::B0 Bank to write to / play back
sound_speed Velocity 340 m/s Sound speed used for focus computation
loop_behavior LoopBehavior LoopBehavior::Infinite Loop count
transition_mode TransitionMode TransitionMode::Immediate Transition timing on bank switching

For the behavior of loop_behavior and transition_mode, see playback control.

FociStm is equivalent to the three commands WriteFociBuffer + ConfigFociStm + ActivatePatternBank. The following is equivalent to FociStm::new(config, &points, option).

let max_len = WriteFociBuffer::max_len(num_foci);
for (i, chunk) in points.chunks(max_len).enumerate() {
WriteFociBuffer {
bank: option.bank,
start_index: i * max_len,
points: chunk,
};
}
ConfigFociStm {
bank: option.bank,
config,
size: points.len(),
num_foci,
sound_speed: option.sound_speed,
loop_behavior: option.loop_behavior,
};
ActivatePatternBank {
bank: option.bank,
transition_mode: option.transition_mode,
};
use std::f32::consts::PI;
use autd3_rs::commands::{Clear, FociStm, FociStmOption, Synchronize};
use autd3_rs::geometry::{Autd3, Geometry, offset};
use autd3_rs::units::{Hz, m, mm, s};
use autd3_rs::value::{ControlPoints, LoopBehavior, PatternBank, SamplingConfig, TransitionMode};
use autd3_rs::Client;
use autd3_rs::udp::TransportOption;
let geometry = Geometry::new(vec![Autd3::default()]);
let option = TransportOption::default();
let mut client = Client::open(&geometry, &option).await?;
client.send(Clear).await?;
client.send(Synchronize).await?;
let center = geometry.center() + offset(0.0 * mm, 0.0 * mm, 150.0 * mm);
let points: Vec<ControlPoints> = (0..200)
.map(|i| {
let theta = 2.0 * PI * i as f32 / 200.0;
ControlPoints::from(center + offset(30.0 * mm * theta.cos(), 30.0 * mm * theta.sin(), 0.0 * mm))
})
.collect();
client.send(FociStm::new(
SamplingConfig::from_freq(1.0 * Hz * points.len() as f32)?,
&points,
FociStmOption {
bank: PatternBank::B0,
sound_speed: 340.0 * m / s,
loop_behavior: LoopBehavior::Infinite,
transition_mode: TransitionMode::Immediate,
..Default::default()
},
)).await?;