1use autd3_core::{environment::Environment, link::Link, sleep::Sleep};
2
3use crate::{
4 error::AUTDDriverError,
5 firmware::driver::{Driver, FixedSchedule, Sender, TimerStrategy, Version},
6};
7
8use getset::CopyGetters;
9
10#[derive(CopyGetters)]
12pub struct Auto {
13 #[getset(get_copy = "pub")]
14 pub(crate) version: Version,
16}
17
18impl<'a, L: Link, S: Sleep, T: TimerStrategy<S>> Sender<'a, L, S, T>
19 for super::transmission::Sender<'a, L, S, T>
20{
21 fn initialize_devices(self) -> Result<(), crate::error::AUTDDriverError> {
22 match self.inner {
23 super::transmission::Inner::V10(inner) => inner.initialize_devices(),
24 super::transmission::Inner::V11(inner) => inner.inner.initialize_devices(),
25 super::transmission::Inner::V12(inner) => inner.initialize_devices(),
26 super::transmission::Inner::V12_1(inner) => inner.inner.initialize_devices(),
27 }
28 }
29
30 fn firmware_version(
31 self,
32 ) -> Result<Vec<crate::firmware::version::FirmwareVersion>, crate::error::AUTDDriverError> {
33 match self.inner {
34 super::transmission::Inner::V10(inner) => inner.firmware_version(),
35 super::transmission::Inner::V11(inner) => inner.inner.firmware_version(),
36 super::transmission::Inner::V12(inner) => inner.firmware_version(),
37 super::transmission::Inner::V12_1(inner) => inner.inner.firmware_version(),
38 }
39 }
40
41 fn close(self) -> Result<(), crate::error::AUTDDriverError> {
42 match self.inner {
43 super::transmission::Inner::V10(inner) => inner.close(),
44 super::transmission::Inner::V11(inner) => inner.inner.close(),
45 super::transmission::Inner::V12(inner) => inner.close(),
46 super::transmission::Inner::V12_1(inner) => inner.inner.close(),
47 }
48 }
49}
50
51impl Driver for Auto {
52 type Sender<'a, L, S, T>
53 = super::transmission::Sender<'a, L, S, T>
54 where
55 L: Link + 'a,
56 S: Sleep,
57 T: TimerStrategy<S>;
58 type FPGAState = super::super::v12_1::fpga::FPGAState;
59
60 fn new() -> Self {
61 Self {
62 version: Version::V12_1,
63 }
64 }
65
66 fn detect_version<'a, L>(
67 &mut self,
68 msg_id: &'a mut autd3_core::link::MsgId,
69 link: &'a mut L,
70 geometry: &'a autd3_core::derive::Geometry,
71 sent_flags: &'a mut [bool],
72 rx: &'a mut [autd3_core::link::RxMessage],
73 env: &'a Environment,
74 ) -> Result<(), AUTDDriverError>
75 where
76 L: autd3_core::link::Link + 'a,
77 {
78 let mut sender = self.sender(
79 msg_id,
80 link,
81 geometry,
82 sent_flags,
83 rx,
84 env,
85 crate::firmware::driver::SenderOption {
86 timeout: Some(std::time::Duration::from_secs(1)),
87 ..Default::default()
88 },
89 FixedSchedule::default(),
90 );
91 let _ = sender.send(crate::datagram::ReadsFPGAState::new(|_| false));
92
93 let version_list = sender.firmware_version()?;
94 self.version = check_firmware_version(&version_list)?;
95
96 Ok(())
97 }
98
99 fn sender<'a, L, S, T>(
100 &self,
101 msg_id: &'a mut autd3_core::link::MsgId,
102 link: &'a mut L,
103 geometry: &'a autd3_core::derive::Geometry,
104 sent_flags: &'a mut [bool],
105 rx: &'a mut [autd3_core::link::RxMessage],
106 env: &'a Environment,
107 option: crate::firmware::driver::SenderOption,
108 timer_strategy: T,
109 ) -> Self::Sender<'a, L, S, T>
110 where
111 L: Link + 'a,
112 S: Sleep,
113 T: TimerStrategy<S>,
114 {
115 Self::Sender {
116 inner: match self.version {
117 Version::V10 => {
118 super::transmission::Inner::V10(crate::firmware::v10::transmission::Sender {
119 msg_id,
120 link,
121 geometry,
122 sent_flags,
123 rx,
124 env,
125 option,
126 timer_strategy,
127 _phantom: std::marker::PhantomData,
128 })
129 }
130 Version::V11 => {
131 super::transmission::Inner::V11(crate::firmware::v11::transmission::Sender {
132 inner: crate::firmware::v10::transmission::Sender {
133 msg_id,
134 link,
135 geometry,
136 sent_flags,
137 rx,
138 env,
139 option,
140 timer_strategy,
141 _phantom: std::marker::PhantomData,
142 },
143 })
144 }
145 Version::V12 => {
146 super::transmission::Inner::V12(crate::firmware::v12::transmission::Sender {
147 msg_id,
148 link,
149 geometry,
150 sent_flags,
151 rx,
152 env,
153 option,
154 timer_strategy,
155 _phantom: std::marker::PhantomData,
156 })
157 }
158 Version::V12_1 => super::transmission::Inner::V12_1(
159 crate::firmware::v12_1::transmission::Sender {
160 inner: crate::firmware::v12::transmission::Sender {
161 msg_id,
162 link,
163 geometry,
164 sent_flags,
165 rx,
166 env,
167 option,
168 timer_strategy,
169 _phantom: std::marker::PhantomData,
170 },
171 },
172 ),
173 },
174 version: self.version,
175 limits: self.firmware_limits(),
176 }
177 }
178
179 fn firmware_limits(&self) -> autd3_core::derive::FirmwareLimits {
180 match self.version {
181 Version::V10 => super::super::v10::V10.firmware_limits(),
182 Version::V11 => super::super::v11::V11.firmware_limits(),
183 Version::V12 => super::super::v12::V12.firmware_limits(),
184 Version::V12_1 => super::super::v12_1::V12_1.firmware_limits(),
185 }
186 }
187}
188
189fn check_firmware_version(
190 version_list: &[crate::firmware::version::FirmwareVersion],
191) -> Result<Version, AUTDDriverError> {
192 if version_list.is_empty() {
193 return Err(AUTDDriverError::FirmwareVersionMismatch);
194 }
195
196 let version = version_list[0];
197 if version_list
198 .iter()
199 .skip(1)
200 .any(|v| v.cpu.major != version.cpu.major || v.fpga.major != version.fpga.major)
201 {
202 return Err(AUTDDriverError::FirmwareVersionMismatch);
203 }
204
205 match version.cpu.major.0 {
206 0xA2..=0xA2 => Ok(Version::V10),
207 0xA3..=0xA3 => Ok(Version::V11),
208 0xA4..=0xA4 => Ok(Version::V12),
209 0xA5..=0xA5 => Ok(Version::V12_1),
210 _ => Err(AUTDDriverError::UnsupportedFirmware),
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use super::*;
217
218 use crate::firmware::version::{CPUVersion, FPGAVersion, FirmwareVersion, Major, Minor};
219
220 #[rstest::rstest]
221 #[case::v10(
222 Ok(Version::V10),
223 vec![FirmwareVersion {
224 idx: 0,
225 cpu: CPUVersion {
226 major: Major(0xA2),
227 minor: Minor(0x00),
228 },
229 fpga: FPGAVersion {
230 major: Major(0xA2),
231 minor: Minor(0x00),
232 function_bits: 0,
233 },
234 }]
235 )]
236 #[case::v11(
237 Ok(Version::V11),
238 vec![FirmwareVersion {
239 idx: 0,
240 cpu: CPUVersion {
241 major: Major(0xA3),
242 minor: Minor(0x00),
243 },
244 fpga: FPGAVersion {
245 major: Major(0xA3),
246 minor: Minor(0x00),
247 function_bits: 0,
248 },
249 }]
250 )]
251 #[case::v12(
252 Ok(Version::V12),
253 vec![FirmwareVersion {
254 idx: 0,
255 cpu: CPUVersion {
256 major: Major(0xA4),
257 minor: Minor(0x00),
258 },
259 fpga: FPGAVersion {
260 major: Major(0xA4),
261 minor: Minor(0x00),
262 function_bits: 0,
263 },
264 }]
265 )]
266 #[case::v12(
267 Ok(Version::V12_1),
268 vec![FirmwareVersion {
269 idx: 0,
270 cpu: CPUVersion {
271 major: Major(0xA5),
272 minor: Minor(0x00),
273 },
274 fpga: FPGAVersion {
275 major: Major(0xA5),
276 minor: Minor(0x00),
277 function_bits: 0,
278 },
279 }]
280 )]
281 #[case::empty(
282 Err(AUTDDriverError::FirmwareVersionMismatch),
283 vec![]
284 )]
285 #[case::mismatch(
286 Err(AUTDDriverError::FirmwareVersionMismatch),
287 vec![
288 FirmwareVersion {
289 idx: 0,
290 cpu: CPUVersion {
291 major: Major(0xA2),
292 minor: Minor(0x00),
293 },
294 fpga: FPGAVersion {
295 major: Major(0xA2),
296 minor: Minor(0x00),
297 function_bits: 0,
298 },
299 },
300 FirmwareVersion {
301 idx: 1,
302 cpu: CPUVersion {
303 major: Major(0xA3),
304 minor: Minor(0x00),
305 },
306 fpga: FPGAVersion {
307 major: Major(0xA3),
308 minor: Minor(0x00),
309 function_bits: 0,
310 },
311 }
312 ]
313 )]
314 #[case::unsupported(
315 Err(AUTDDriverError::UnsupportedFirmware),
316 vec![FirmwareVersion {
317 idx: 0,
318 cpu: CPUVersion {
319 major: Major(0xFF),
320 minor: Minor(0x00),
321 },
322 fpga: FPGAVersion {
323 major: Major(0xFF),
324 minor: Minor(0x00),
325 function_bits: 0,
326 },
327 }]
328 )]
329 #[test]
330 fn check_firmware_version(
331 #[case] expect: Result<Version, AUTDDriverError>,
332 #[case] version_list: Vec<crate::firmware::version::FirmwareVersion>,
333 ) {
334 assert_eq!(expect, super::check_firmware_version(&version_list));
335 }
336}