autd3_driver/firmware/transmission/
sender.rs1use std::time::{Duration, Instant};
2
3use super::SenderOption;
4use crate::{
5 error::AUTDDriverError,
6 firmware::{
7 cpu::{check_firmware_err, check_if_msg_is_processed},
8 operation::{Operation, OperationGenerator, OperationHandler},
9 version::FirmwareVersion,
10 },
11};
12
13use autd3_core::{
14 datagram::{Datagram, DeviceMask},
15 environment::Environment,
16 geometry::Geometry,
17 link::{Link, MsgId, RxMessage, TxMessage},
18 sleep::Sleeper,
19};
20
21pub struct Sender<'a, L: Link, S: Sleeper> {
23 pub(crate) msg_id: &'a mut MsgId,
24 pub(crate) link: &'a mut L,
25 pub(crate) geometry: &'a Geometry,
26 pub(crate) sent_flags: &'a mut [bool],
27 pub(crate) rx: &'a mut [RxMessage],
28 pub(crate) env: &'a Environment,
29 pub(crate) option: SenderOption,
30 pub(crate) sleeper: S,
31}
32
33impl<'a, L: Link, S: Sleeper> Sender<'a, L, S> {
34 #[doc(hidden)]
35 #[allow(clippy::too_many_arguments)]
36 pub fn new(
37 msg_id: &'a mut autd3_core::link::MsgId,
38 link: &'a mut L,
39 geometry: &'a autd3_core::geometry::Geometry,
40 sent_flags: &'a mut [bool],
41 rx: &'a mut [autd3_core::link::RxMessage],
42 env: &'a Environment,
43 option: SenderOption,
44 sleeper: S,
45 ) -> Self {
46 Self {
47 msg_id,
48 link,
49 geometry,
50 sent_flags,
51 rx,
52 env,
53 option,
54 sleeper,
55 }
56 }
57
58 pub fn send<D: Datagram<'a>>(&mut self, s: D) -> Result<(), AUTDDriverError>
60 where
61 AUTDDriverError: From<D::Error>,
62 D::G: OperationGenerator<'a>,
63 AUTDDriverError: From<<<D::G as OperationGenerator<'a>>::O1 as Operation<'a>>::Error>
64 + From<<<D::G as OperationGenerator<'a>>::O2 as Operation<'a>>::Error>,
65 {
66 let timeout = self.option.timeout.unwrap_or(s.option().timeout);
67 let parallel_threshold = s.option().parallel_threshold;
68
69 let mut g = s.operation_generator(self.geometry, self.env, &DeviceMask::AllEnabled)?;
70 let mut operations = self
71 .geometry
72 .iter()
73 .map(|dev| g.generate(dev))
74 .collect::<Vec<_>>();
75
76 self.send_impl(timeout, parallel_threshold, &mut operations)
77 }
78
79 #[doc(hidden)]
80 pub fn initialize_devices(mut self) -> Result<(), AUTDDriverError> {
81 const V12_1: u8 = 0xA5;
82
83 let r = self._initialize_devices();
84 if r.is_err()
85 && let Ok(list) = self.firmware_version()
86 && list.into_iter().all(|f| f.cpu.major.0 < V12_1)
87 {
88 return Err(AUTDDriverError::UnsupportedFirmware);
89 }
90 r
91 }
92
93 fn _initialize_devices(&mut self) -> Result<(), AUTDDriverError> {
94 use crate::datagram::{Clear, Nop, Synchronize};
95
96 self.send(Nop)?;
99
100 self.send((Clear::new(), Synchronize::new()))
101 }
102
103 #[doc(hidden)]
104 pub fn firmware_version(mut self) -> Result<Vec<FirmwareVersion>, AUTDDriverError> {
105 use crate::{
106 datagram::FirmwareVersionType::*,
107 firmware::version::{CPUVersion, FPGAVersion, Major, Minor},
108 };
109
110 let cpu_major = self.fetch_firminfo(CPUMajor)?;
111 let cpu_minor = self.fetch_firminfo(CPUMinor)?;
112 let fpga_major = self.fetch_firminfo(FPGAMajor)?;
113 let fpga_minor = self.fetch_firminfo(FPGAMinor)?;
114 let fpga_functions = self.fetch_firminfo(FPGAFunctions)?;
115 self.fetch_firminfo(Clear)?;
116
117 Ok(self
118 .geometry
119 .iter()
120 .map(|dev| FirmwareVersion {
121 idx: dev.idx(),
122 cpu: CPUVersion {
123 major: Major(cpu_major[dev.idx()]),
124 minor: Minor(cpu_minor[dev.idx()]),
125 },
126 fpga: FPGAVersion {
127 major: Major(fpga_major[dev.idx()]),
128 minor: Minor(fpga_minor[dev.idx()]),
129 function_bits: fpga_functions[dev.idx()],
130 },
131 })
132 .collect())
133 }
134
135 #[doc(hidden)]
136 pub fn close(mut self) -> Result<(), AUTDDriverError> {
137 use crate::datagram::{
138 Clear, FixedCompletionSteps, Silencer,
139 implements::{Null, Static},
140 };
141
142 [
143 self.send(Silencer {
144 config: FixedCompletionSteps {
145 strict: false,
146 ..Default::default()
147 },
148 }),
149 self.send((Static::default(), Null)),
150 self.send(Clear {}),
151 Ok(self.link.close()?),
152 ]
153 .into_iter()
154 .try_fold((), |_, x| x)
155 }
156}
157
158impl<'a, L: Link, S: Sleeper> Sender<'a, L, S> {
159 pub(crate) fn send_impl<O1, O2>(
160 &mut self,
161 timeout: Duration,
162 parallel_threshold: usize,
163 operations: &mut [Option<(O1, O2)>],
164 ) -> Result<(), AUTDDriverError>
165 where
166 O1: Operation<'a>,
167 O2: Operation<'a>,
168 AUTDDriverError: From<O1::Error> + From<O2::Error>,
169 {
170 operations
171 .iter()
172 .zip(self.sent_flags.iter_mut())
173 .for_each(|(op, flag)| {
174 *flag = op.is_some();
175 });
176
177 let num_enabled = self.sent_flags.iter().filter(|x| **x).count();
178 let parallel = self
179 .option
180 .parallel
181 .is_parallel(num_enabled, parallel_threshold);
182
183 self.link.ensure_is_open()?;
184 self.link.update(self.geometry)?;
185
186 let mut send_timing = Instant::now();
187 loop {
188 let mut tx = self.link.alloc_tx_buffer()?;
189
190 self.msg_id.increment();
191 OperationHandler::pack(*self.msg_id, operations, self.geometry, &mut tx, parallel)?;
192
193 self.send_receive(tx, timeout)?;
194
195 if OperationHandler::is_done(operations) {
196 return Ok(());
197 }
198
199 if let Some(interval) = self.option.send_interval {
200 let next = send_timing + interval;
201 self.sleeper
202 .sleep(next.saturating_duration_since(Instant::now()));
203 send_timing = next;
204 }
205 }
206 }
207
208 fn send_receive(
209 &mut self,
210 tx: Vec<TxMessage>,
211 timeout: Duration,
212 ) -> Result<(), AUTDDriverError> {
213 self.link.ensure_is_open()?;
214 self.link.send(tx)?;
215 self.wait_msg_processed(timeout)
216 }
217
218 fn wait_msg_processed(&mut self, timeout: Duration) -> Result<(), AUTDDriverError> {
219 let start = Instant::now();
220 let mut receive_timing = Instant::now();
221 loop {
222 self.link.ensure_is_open()?;
223 self.link.receive(self.rx)?;
224
225 if check_if_msg_is_processed(*self.msg_id, self.rx)
226 .zip(self.sent_flags.iter())
227 .filter_map(|(r, sent)| sent.then_some(r))
228 .all(std::convert::identity)
229 {
230 break;
231 }
232
233 if start.elapsed() > timeout {
234 return Err(AUTDDriverError::ConfirmResponseFailed);
235 }
236
237 if let Some(interval) = self.option.receive_interval {
238 let next = receive_timing + interval;
239 self.sleeper
240 .sleep(next.saturating_duration_since(Instant::now()));
241 receive_timing = next;
242 }
243 }
244
245 self.rx
246 .iter()
247 .try_fold((), |_, r| check_firmware_err(r.ack()))
248 }
249
250 pub(crate) fn fetch_firminfo(
251 &mut self,
252 ty: crate::datagram::FirmwareVersionType,
253 ) -> Result<Vec<u8>, AUTDDriverError> {
254 self.send(ty).map_err(|_| {
255 AUTDDriverError::ReadFirmwareVersionFailed(
256 check_if_msg_is_processed(*self.msg_id, self.rx).collect(),
257 )
258 })?;
259 Ok(self.rx.iter().map(|rx| rx.data()).collect())
260 }
261}