1use autd3_core::{
2 datagram::{Inspectable, InspectionResult},
3 derive::{Datagram, DeviceFilter},
4 link::{Ack, Link, MsgId, RxMessage},
5 sleep::Sleep,
6};
7pub use autd3_driver::firmware::driver::{
8 Driver, FPGAState, FixedDelay, FixedSchedule, ParallelMode, SenderOption, TimerStrategy,
9};
10use autd3_driver::{
11 error::AUTDDriverError,
12 firmware::{self, auto::Auto, driver::Sender, version::FirmwareVersion},
13 geometry::{Device, Geometry},
14};
15
16use derive_more::{Deref, DerefMut};
17use getset::{Getters, MutGetters};
18
19#[derive(Deref, DerefMut, Getters, MutGetters)]
23pub struct Controller<L: Link, V: Driver> {
24 #[getset(get = "pub", get_mut = "pub")]
26 link: L,
27 #[doc(hidden)]
28 #[getset(get = "pub")]
29 driver: V,
30 #[getset(get = "pub", get_mut = "pub")]
32 #[deref]
33 #[deref_mut]
34 geometry: Geometry,
35 msg_id: MsgId,
36 sent_flags: smallvec::SmallVec<[bool; 32]>,
37 rx_buf: Vec<RxMessage>,
38 pub default_sender_option: SenderOption,
40}
41
42impl<L: Link> Controller<L, Auto> {
43 pub fn open<D: Into<Device>, F: IntoIterator<Item = D>>(
45 devices: F,
46 link: L,
47 ) -> Result<Self, AUTDDriverError> {
48 Self::open_with_option(devices, link, Default::default(), FixedSchedule::default())
49 }
50}
51
52impl<L: Link, V: Driver> Controller<L, V> {
53 pub fn open_with<D: Into<Device>, F: IntoIterator<Item = D>>(
55 devices: F,
56 link: L,
57 ) -> Result<Self, AUTDDriverError> {
58 Self::open_with_option(devices, link, Default::default(), FixedSchedule::default())
59 }
60
61 pub fn open_with_option<
65 D: Into<Device>,
66 F: IntoIterator<Item = D>,
67 S: Sleep,
68 T: TimerStrategy<S>,
69 >(
70 devices: F,
71 mut link: L,
72 option: SenderOption,
73 timer_strategy: T,
74 ) -> Result<Self, AUTDDriverError> {
75 let geometry = Geometry::new(devices.into_iter().map(|d| d.into()).collect());
76
77 link.open(&geometry)?;
78
79 let mut msg_id = MsgId::new(0);
80 let mut sent_flags = smallvec::smallvec![false; geometry.len()];
81 let mut rx_buf = vec![RxMessage::new(0, Ack::new()); geometry.len()];
82
83 let mut driver = V::new();
84 driver.detect_version(
85 &mut msg_id,
86 &mut link,
87 &geometry,
88 &mut sent_flags,
89 &mut rx_buf,
90 )?;
91
92 let mut cnt = Controller {
93 link,
94 driver,
95 msg_id,
96 sent_flags,
97 rx_buf,
98 geometry,
99 default_sender_option: option,
100 };
101
102 cnt.sender(option, timer_strategy).initialize_devices()?;
103
104 Ok(cnt)
105 }
106
107 pub fn sender<S: Sleep, T: TimerStrategy<S>>(
109 &mut self,
110 option: SenderOption,
111 timer_strategy: T,
112 ) -> V::Sender<'_, L, S, T> {
113 self.driver.sender(
114 &mut self.msg_id,
115 &mut self.link,
116 &self.geometry,
117 &mut self.sent_flags,
118 &mut self.rx_buf,
119 option,
120 timer_strategy,
121 )
122 }
123
124 pub fn inspect<I: Inspectable>(&self, s: I) -> Result<InspectionResult<I::Result>, I::Error> {
126 s.inspect(
127 &self.geometry,
128 &DeviceFilter::all_enabled(),
129 &self.driver.firmware_limits(),
130 )
131 }
132
133 pub fn close(mut self) -> Result<(), AUTDDriverError> {
135 self.close_impl(self.default_sender_option, FixedSchedule::default())
136 }
137
138 pub fn firmware_version(&mut self) -> Result<Vec<FirmwareVersion>, AUTDDriverError> {
140 self.sender(self.default_sender_option, FixedSchedule::default())
141 .firmware_version()
142 }
143
144 pub fn fpga_state(&mut self) -> Result<Vec<Option<V::FPGAState>>, AUTDDriverError> {
165 self.link.ensure_is_open()?;
166 self.link.receive(&mut self.rx_buf)?;
167 Ok(self.rx_buf.iter().map(V::FPGAState::from_rx).collect())
168 }
169}
170
171impl<L: Link, V: Driver> Controller<L, V> {
172 fn close_impl<S: Sleep, T: TimerStrategy<S>>(
173 &mut self,
174 option: SenderOption,
175 timer_strategy: T,
176 ) -> Result<(), AUTDDriverError> {
177 if !self.link.is_open() {
178 return Ok(());
179 }
180
181 self.sender(option, timer_strategy).close()
182 }
183}
184
185impl<'a, L: Link, V: Driver> IntoIterator for &'a Controller<L, V> {
186 type Item = &'a Device;
187 type IntoIter = std::slice::Iter<'a, Device>;
188
189 fn into_iter(self) -> Self::IntoIter {
190 self.geometry.iter()
191 }
192}
193
194impl<'a, L: Link, V: Driver> IntoIterator for &'a mut Controller<L, V> {
195 type Item = &'a mut Device;
196 type IntoIter = std::slice::IterMut<'a, Device>;
197
198 fn into_iter(self) -> Self::IntoIter {
199 self.geometry.iter_mut()
200 }
201}
202
203impl<L: Link + 'static, V: Driver> Controller<L, V> {
204 pub fn into_boxed_link(self) -> Controller<Box<dyn Link>, V> {
206 let cnt = std::mem::ManuallyDrop::new(self);
207 let msg_id = unsafe { std::ptr::read(&cnt.msg_id) };
208 let driver = unsafe { std::ptr::read(&cnt.driver) };
209 let link = unsafe { std::ptr::read(&cnt.link) };
210 let geometry = unsafe { std::ptr::read(&cnt.geometry) };
211 let sent_flags = unsafe { std::ptr::read(&cnt.sent_flags) };
212 let rx_buf = unsafe { std::ptr::read(&cnt.rx_buf) };
213 let default_sender_option = unsafe { std::ptr::read(&cnt.default_sender_option) };
214 Controller {
215 msg_id,
216 driver,
217 link: Box::new(link) as _,
218 geometry,
219 sent_flags,
220 rx_buf,
221 default_sender_option,
222 }
223 }
224
225 pub unsafe fn from_boxed_link(cnt: Controller<Box<dyn Link>, V>) -> Controller<L, V> {
231 let cnt = std::mem::ManuallyDrop::new(cnt);
232 let msg_id = unsafe { std::ptr::read(&cnt.msg_id) };
233 let driver = unsafe { std::ptr::read(&cnt.driver) };
234 let link = unsafe { std::ptr::read(&cnt.link) };
235 let geometry = unsafe { std::ptr::read(&cnt.geometry) };
236 let sent_flags = unsafe { std::ptr::read(&cnt.sent_flags) };
237 let rx_buf = unsafe { std::ptr::read(&cnt.rx_buf) };
238 let default_sender_option = unsafe { std::ptr::read(&cnt.default_sender_option) };
239 Controller {
240 msg_id,
241 driver,
242 link: unsafe { *Box::from_raw(Box::into_raw(link) as *mut L) },
243 geometry,
244 sent_flags,
245 rx_buf,
246 default_sender_option,
247 }
248 }
249}
250
251impl<L: Link, V: Driver> Drop for Controller<L, V> {
252 fn drop(&mut self) {
253 if !self.link.is_open() {
254 return;
255 }
256 let _ = self.close_impl(self.default_sender_option, FixedSchedule::default());
257 }
258}
259
260impl<L: Link> Controller<L, firmware::v12::V12> {
264 pub fn send<D: Datagram>(&mut self, s: D) -> Result<(), AUTDDriverError>
268 where
269 AUTDDriverError: From<D::Error>,
270 D::G: autd3_driver::firmware::v12::operation::OperationGenerator,
271 AUTDDriverError: From<<<D::G as autd3_driver::firmware::v12::operation::OperationGenerator>::O1 as autd3_driver::firmware::driver::Operation>::Error>
272 + From<<<D::G as autd3_driver::firmware::v12::operation::OperationGenerator>::O2 as autd3_driver::firmware::driver::Operation>::Error>,
273 {
274 self.sender(self.default_sender_option, FixedSchedule::default())
275 .send(s)
276 }
277}
278
279impl<L: Link> Controller<L, firmware::v11::V11> {
280 pub fn send<D: Datagram>(&mut self, s: D) -> Result<(), AUTDDriverError>
284 where
285 AUTDDriverError: From<D::Error>,
286 D::G: autd3_driver::firmware::v11::operation::OperationGenerator,
287 AUTDDriverError: From<<<D::G as autd3_driver::firmware::v11::operation::OperationGenerator>::O1 as autd3_driver::firmware::driver::Operation>::Error>
288 + From<<<D::G as autd3_driver::firmware::v11::operation::OperationGenerator>::O2 as autd3_driver::firmware::driver::Operation>::Error>,
289 {
290 self.sender(self.default_sender_option, FixedSchedule::default())
291 .send(s)
292 }
293}
294
295impl<L: Link> Controller<L, firmware::v10::V10> {
296 pub fn send<D: Datagram>(&mut self, s: D) -> Result<(), AUTDDriverError>
300 where
301 AUTDDriverError: From<D::Error>,
302 D::G: autd3_driver::firmware::v10::operation::OperationGenerator,
303 AUTDDriverError: From<<<D::G as autd3_driver::firmware::v10::operation::OperationGenerator>::O1 as autd3_driver::firmware::driver::Operation>::Error>
304 + From<<<D::G as autd3_driver::firmware::v10::operation::OperationGenerator>::O2 as autd3_driver::firmware::driver::Operation>::Error>,
305 {
306 self.sender(self.default_sender_option, FixedSchedule::default())
307 .send(s)
308 }
309}
310
311impl<L: Link> Controller<L, firmware::auto::Auto> {
312 pub fn send<D: Datagram>(&mut self, s: D) -> Result<(), AUTDDriverError>
316 where
317 AUTDDriverError: From<D::Error>,
318 D::G: autd3_driver::firmware::auto::operation::OperationGenerator,
319 AUTDDriverError: From<<<D::G as autd3_driver::firmware::auto::operation::OperationGenerator>::O1 as autd3_driver::firmware::driver::Operation>::Error>
320 + From<<<D::G as autd3_driver::firmware::auto::operation::OperationGenerator>::O2 as autd3_driver::firmware::driver::Operation>::Error>,
321 {
322 self.sender(self.default_sender_option, FixedSchedule::default())
323 .send(s)
324 }
325}
326
327#[cfg(test)]
328pub(crate) mod tests {
329 use autd3_driver::firmware::driver::BoxedDatagram;
330
331 use crate::{
332 core::{
333 common::mm,
334 derive::*,
335 gain::{Gain, GainCalculator, GainCalculatorGenerator},
336 link::LinkError,
337 },
338 driver::{
339 autd3_device::AUTD3,
340 common::Hz,
341 datagram::{GainSTM, ReadsFPGAState},
342 firmware,
343 firmware::latest::Latest,
344 },
345 gain::Uniform,
346 link::{Audit, AuditOption, audit::version},
347 modulation::{Sine, Static},
348 };
349
350 use super::*;
351
352 pub fn create_controller(
353 dev_num: usize,
354 ) -> anyhow::Result<Controller<Audit<version::Latest>, Latest>> {
355 Ok(Controller::open_with(
356 (0..dev_num).map(|_| AUTD3::default()),
357 Audit::latest(AuditOption::default()),
358 )?)
359 }
360
361 #[test]
362 fn open_failed() {
363 assert_eq!(
364 Some(AUTDDriverError::Link(LinkError::new("broken"))),
365 Controller::<_, Latest>::open_with(
366 [AUTD3::default()],
367 Audit::latest(AuditOption {
368 broken: true,
369 ..Default::default()
370 }),
371 )
372 .err()
373 );
374 }
375
376 #[test]
377 fn send() -> anyhow::Result<()> {
378 let mut autd = create_controller(1)?;
379 autd.send((
380 Sine {
381 freq: 150. * Hz,
382 option: Default::default(),
383 },
384 GainSTM {
385 gains: vec![
386 Uniform {
387 intensity: Intensity(0x80),
388 phase: Phase::ZERO,
389 },
390 Uniform {
391 intensity: Intensity(0x81),
392 phase: Phase::ZERO,
393 },
394 ],
395 config: 1. * Hz,
396 option: Default::default(),
397 },
398 ))?;
399
400 autd.iter().try_for_each(|dev| {
401 assert_eq!(
402 *Sine {
403 freq: 150. * Hz,
404 option: Default::default(),
405 }
406 .calc(&Latest.firmware_limits())?,
407 autd.link[dev.idx()].fpga().modulation_buffer(Segment::S0)
408 );
409 let f = Uniform {
410 intensity: Intensity(0x80),
411 phase: Phase::ZERO,
412 }
413 .init(&autd.geometry, &TransducerFilter::all_enabled())?
414 .generate(dev);
415 assert_eq!(
416 dev.iter().map(|tr| f.calc(tr)).collect::<Vec<_>>(),
417 autd.link[dev.idx()].fpga().drives_at(Segment::S0, 0)
418 );
419 let f = Uniform {
420 intensity: Intensity(0x81),
421 phase: Phase::ZERO,
422 }
423 .init(&autd.geometry, &TransducerFilter::all_enabled())?
424 .generate(dev);
425 assert_eq!(
426 dev.iter().map(|tr| f.calc(tr)).collect::<Vec<_>>(),
427 autd.link[dev.idx()].fpga().drives_at(Segment::S0, 1)
428 );
429 anyhow::Ok(())
430 })?;
431
432 autd.close()?;
433
434 Ok(())
435 }
436
437 #[test]
438 fn inspect() -> anyhow::Result<()> {
439 let autd = create_controller(2)?;
440
441 let r = autd.inspect(autd3_driver::datagram::Group::new(
442 |dev| (dev.idx() == 0).then_some(()),
443 HashMap::from([((), Static::default())]),
444 ))?;
445 assert_eq!(autd.geometry.len(), r.len());
446 assert_eq!(
447 Some(ModulationInspectionResult {
448 name: "Static".to_string(),
449 data: vec![0xFF, 0xFF],
450 config: Static::default().sampling_config(),
451 loop_behavior: LoopBehavior::Infinite,
452 segment: Segment::S0,
453 transition_mode: None
454 }),
455 r[0]
456 );
457 assert_eq!(None, r[1]);
458
459 autd.close()?;
460
461 Ok(())
462 }
463
464 #[test]
465 fn firmware_version() -> anyhow::Result<()> {
466 use autd3_driver::firmware::version::{CPUVersion, FPGAVersion};
467
468 let mut autd = create_controller(1)?;
469 assert_eq!(
470 vec![FirmwareVersion {
471 idx: 0,
472 cpu: CPUVersion {
473 major: FirmwareVersion::LATEST_VERSION_NUM_MAJOR,
474 minor: FirmwareVersion::LATEST_VERSION_NUM_MINOR
475 },
476 fpga: FPGAVersion {
477 major: FirmwareVersion::LATEST_VERSION_NUM_MAJOR,
478 minor: FirmwareVersion::LATEST_VERSION_NUM_MINOR,
479 function_bits: FPGAVersion::ENABLED_EMULATOR_BIT
480 }
481 }],
482 autd.firmware_version()?
483 );
484 Ok(())
485 }
486
487 #[test]
488 fn firmware_version_err() -> anyhow::Result<()> {
489 let mut autd = create_controller(2)?;
490 autd.link_mut().break_down();
491 assert_eq!(
492 Err(AUTDDriverError::ReadFirmwareVersionFailed(vec![
493 false, false
494 ])),
495 autd.firmware_version()
496 );
497 Ok(())
498 }
499
500 #[test]
501 fn close() -> anyhow::Result<()> {
502 {
503 let mut autd = create_controller(1)?;
504 autd.close_impl(SenderOption::default(), FixedSchedule::default())?;
505 autd.close()?;
506 }
507
508 {
509 let mut autd = create_controller(1)?;
510 autd.link_mut().break_down();
511 assert_eq!(
512 Err(AUTDDriverError::Link(LinkError::new("broken"))),
513 autd.close()
514 );
515 }
516
517 Ok(())
518 }
519
520 #[test]
521 fn fpga_state() -> anyhow::Result<()> {
522 let mut autd = Controller::<_, Latest>::open_with(
523 [AUTD3::default(), AUTD3::default()],
524 Audit::latest(AuditOption::default()),
525 )?;
526
527 autd.send(ReadsFPGAState::new(|_| true))?;
528 {
529 autd.link_mut()[0].fpga_mut().assert_thermal_sensor();
530
531 let states = autd.fpga_state()?;
532 assert_eq!(2, states.len());
533 assert!(
534 states[0]
535 .ok_or(anyhow::anyhow!("state shouldn't be None here"))?
536 .is_thermal_assert()
537 );
538 assert!(
539 !states[1]
540 .ok_or(anyhow::anyhow!("state shouldn't be None here"))?
541 .is_thermal_assert()
542 );
543 }
544
545 {
546 autd.link_mut()[0].fpga_mut().deassert_thermal_sensor();
547 autd.link_mut()[1].fpga_mut().assert_thermal_sensor();
548
549 let states = autd.fpga_state()?;
550 assert_eq!(2, states.len());
551 assert!(
552 !states[0]
553 .ok_or(anyhow::anyhow!("state shouldn't be None here"))?
554 .is_thermal_assert()
555 );
556 assert!(
557 states[1]
558 .ok_or(anyhow::anyhow!("state shouldn't be None here"))?
559 .is_thermal_assert()
560 );
561 }
562
563 autd.send(ReadsFPGAState::new(|dev| dev.idx() == 1))?;
564 {
565 let states = autd.fpga_state()?;
566 assert_eq!(2, states.len());
567 assert!(states[0].is_none());
568 assert!(
569 states[1]
570 .ok_or(anyhow::anyhow!("state shouldn't be None here"))?
571 .is_thermal_assert()
572 );
573 }
574
575 Ok(())
576 }
577
578 #[test]
579 fn into_iter() -> anyhow::Result<()> {
580 let mut autd = create_controller(1)?;
581
582 for dev in &mut autd {
583 dev.sound_speed = 300e3 * mm;
584 }
585
586 for dev in &autd {
587 assert_eq!(300e3 * mm, dev.sound_speed);
588 }
589
590 Ok(())
591 }
592
593 #[test]
594 fn with_boxed_link() -> anyhow::Result<()> {
595 let link: Box<dyn Link> = Box::new(Audit::latest(AuditOption::default()));
596 let mut autd = Controller::<_, Latest>::open_with([AUTD3::default()], link)?;
597
598 autd.send(Sine {
599 freq: 150. * Hz,
600 option: Default::default(),
601 })?;
602
603 autd.close()?;
604
605 Ok(())
606 }
607
608 #[test]
609 fn into_boxed_link_unsafe() -> anyhow::Result<()> {
610 let autd = Controller::<_, Latest>::open_with_option(
611 [AUTD3::default()],
612 Audit::latest(AuditOption::default()),
613 SenderOption::default(),
614 FixedSchedule::default(),
615 )?;
616
617 let mut autd = autd.into_boxed_link();
618
619 autd.send((
620 Sine {
621 freq: 150. * Hz,
622 option: Default::default(),
623 },
624 GainSTM {
625 gains: vec![
626 Uniform {
627 intensity: Intensity(0x80),
628 phase: Phase::ZERO,
629 },
630 Uniform {
631 intensity: Intensity(0x81),
632 phase: Phase::ZERO,
633 },
634 ],
635 config: 1. * Hz,
636 option: Default::default(),
637 },
638 ))?;
639
640 let autd = unsafe { Controller::<Audit<version::Latest>, _>::from_boxed_link(autd) };
641
642 autd.iter().try_for_each(|dev| {
643 assert_eq!(
644 *Sine {
645 freq: 150. * Hz,
646 option: Default::default(),
647 }
648 .calc(&Latest.firmware_limits())?,
649 autd.link[dev.idx()].fpga().modulation_buffer(Segment::S0)
650 );
651 let f = Uniform {
652 intensity: Intensity(0x80),
653 phase: Phase::ZERO,
654 }
655 .init(&autd.geometry, &TransducerFilter::all_enabled())?
656 .generate(dev);
657 assert_eq!(
658 dev.iter().map(|tr| f.calc(tr)).collect::<Vec<_>>(),
659 autd.link[dev.idx()].fpga().drives_at(Segment::S0, 0)
660 );
661 let f = Uniform {
662 intensity: Intensity(0x81),
663 phase: Phase::ZERO,
664 }
665 .init(&autd.geometry, &TransducerFilter::all_enabled())?
666 .generate(dev);
667 assert_eq!(
668 dev.iter().map(|tr| f.calc(tr)).collect::<Vec<_>>(),
669 autd.link[dev.idx()].fpga().drives_at(Segment::S0, 1)
670 );
671 anyhow::Ok(())
672 })?;
673
674 autd.close()?;
675
676 Ok(())
677 }
678
679 #[test]
680 fn into_boxed_link_close() -> anyhow::Result<()> {
681 let autd = create_controller(1)?;
682 let autd = autd.into_boxed_link();
683
684 autd.close()?;
685
686 Ok(())
687 }
688
689 #[test]
690 fn send_boxed() -> anyhow::Result<()> {
691 use crate::gain::Null;
692
693 {
694 let mut autd = Controller::<_, firmware::v12::V12>::open_with(
695 [AUTD3::default()],
696 Audit::<version::V12>::new(AuditOption::default()),
697 )?;
698
699 autd.send(BoxedDatagram::new(Null))?;
700
701 autd.close()?;
702 }
703
704 {
705 let mut autd = Controller::<_, firmware::v11::V11>::open_with(
706 [AUTD3::default()],
707 Audit::<version::V11>::new(AuditOption::default()),
708 )?;
709
710 autd.send(BoxedDatagram::new(Null))?;
711
712 autd.close()?;
713 }
714
715 {
716 let mut autd = Controller::<_, firmware::v10::V10>::open_with(
717 [AUTD3::default()],
718 Audit::<version::V10>::new(AuditOption::default()),
719 )?;
720
721 autd.send(BoxedDatagram::new(Null))?;
722
723 autd.close()?;
724 }
725
726 {
727 let mut autd = Controller::<_, firmware::auto::Auto>::open_with(
728 [AUTD3::default()],
729 Audit::<version::Latest>::new(AuditOption::default()),
730 )?;
731
732 autd.send(BoxedDatagram::new(Null))?;
733
734 autd.close()?;
735 }
736
737 Ok(())
738 }
739}