1use std::{convert::Infallible, time::Duration};
2
3use autd3_core::{
4 datagram::CombinedError, derive::SamplingConfigError, gain::GainError, link::LinkError,
5 modulation::ModulationError,
6};
7use thiserror::Error;
8
9use crate::{firmware::cpu::GainSTMMode, firmware::fpga::*};
10
11#[derive(Error, Debug, PartialEq, Clone)]
13#[non_exhaustive]
14pub enum AUTDDriverError {
15 #[error(
17 "Modulation buffer size ({0}) is out of range ([{min}, {max}])",
18 min = MOD_BUF_SIZE_MIN,
19 max = MOD_BUF_SIZE_MAX
20 )]
21 ModulationSizeOutOfRange(usize),
22
23 #[error("Silencer completion time ({0:?}) must be a multiple of the ultrasound period")]
25 InvalidSilencerCompletionTime(Duration),
26 #[error("Silencer completion time ({0:?}) is out of range")]
28 SilencerCompletionTimeOutOfRange(Duration),
29
30 #[error("{0}")]
32 SamplingConfig(#[from] SamplingConfigError),
33
34 #[error("STM sampling period ({1:?}/{0}) must be integer")]
36 STMPeriodInvalid(usize, Duration),
37
38 #[error(
40 "FociSTM size ({0}) is out of range ([{min}, {max}])",
41 min = STM_BUF_SIZE_MIN,
42 max = FOCI_STM_BUF_SIZE_MAX
43 )]
44 FociSTMPointSizeOutOfRange(usize),
45 #[error(
47 "Number of foci ({0}) is out of range ([{min}, {max}])",
48 min = 1,
49 max = FOCI_STM_FOCI_NUM_MAX
50 )]
51 FociSTMNumFociOutOfRange(usize),
52 #[error(
54 "Point coordinate ({0}, {1}, {2}) is out of range ([{x_min}, {x_max}], [{y_min}, {y_max}], [{z_min}, {z_max}])",
55 x_min = FOCI_STM_FIXED_NUM_UNIT * FOCI_STM_FIXED_NUM_LOWER_X as f32,
56 x_max = FOCI_STM_FIXED_NUM_UNIT * FOCI_STM_FIXED_NUM_UPPER_X as f32,
57 y_min = FOCI_STM_FIXED_NUM_UNIT * FOCI_STM_FIXED_NUM_LOWER_Y as f32,
58 y_max = FOCI_STM_FIXED_NUM_UNIT * FOCI_STM_FIXED_NUM_UPPER_Y as f32,
59 z_min = FOCI_STM_FIXED_NUM_UNIT * FOCI_STM_FIXED_NUM_LOWER_Z as f32,
60 z_max = FOCI_STM_FIXED_NUM_UNIT * FOCI_STM_FIXED_NUM_UPPER_Z as f32,
61 )]
62 FociSTMPointOutOfRange(f32, f32, f32),
63 #[error(
65 "GainSTM size ({0}) is out of range ([{min}, {max}])",
66 min = STM_BUF_SIZE_MIN,
67 max = GAIN_STM_BUF_SIZE_MAX
68 )]
69 GainSTMSizeOutOfRange(usize),
70 #[error("GainSTMMode ({0:?}) is not supported")]
72 GainSTMModeNotSupported(GainSTMMode),
73
74 #[error("{0}")]
76 Modulation(#[from] ModulationError),
77 #[error("{0}")]
79 Gain(#[from] GainError),
80 #[error("{0}")]
82 Link(#[from] LinkError),
83
84 #[error("Link is closed")]
86 LinkClosed,
87 #[error("Failed to confirm the response from the device")]
89 ConfirmResponseFailed,
90
91 #[error("The input data is invalid.")]
93 InvalidDateTime,
94
95 #[cfg(feature = "dynamic_freq")]
96 #[error("Ultrasound frequency ({0:?}) is not supported")]
97 InvalidFrequency(autd3_core::defined::Freq<u32>),
99
100 #[error("Not supported tag")]
104 NotSupportedTag,
105 #[doc(hidden)]
106 #[error("Invalid message ID")]
107 InvalidMessageID,
108 #[doc(hidden)]
109 #[error("Invalid info type")]
110 InvalidInfoType,
111 #[doc(hidden)]
112 #[error("Invalid GainSTM mode")]
113 InvalidGainSTMMode,
114 #[doc(hidden)]
115 #[error("Unknown firmware error: {0}")]
116 UnknownFirmwareError(u8),
117 #[error("Invalid segment transition")]
119 InvalidSegmentTransition,
120 #[error("Invalid transition mode")]
122 InvalidTransitionMode,
123 #[error("Miss transition time")]
125 MissTransitionTime,
126 #[error(
128 "Silencer cannot complete phase/intensity completion in the specified sampling period. Please lower the sampling frequency or make the completion time of Silencer longer than the sampling period."
129 )]
130 InvalidSilencerSettings,
131}
132
133impl AUTDDriverError {
134 #[doc(hidden)]
135 #[must_use]
136 pub const fn firmware_err(ack: u8) -> Self {
137 match ack {
138 0x80 => AUTDDriverError::NotSupportedTag,
139 0x81 => AUTDDriverError::InvalidMessageID,
140 0x84 => AUTDDriverError::InvalidInfoType,
141 0x85 => AUTDDriverError::InvalidGainSTMMode,
142 0x88 => AUTDDriverError::InvalidSegmentTransition,
143 0x8B => AUTDDriverError::MissTransitionTime,
144 0x8E => AUTDDriverError::InvalidSilencerSettings,
145 0x8F => AUTDDriverError::InvalidTransitionMode,
146 _ => AUTDDriverError::UnknownFirmwareError(ack),
147 }
148 }
149}
150
151impl From<Infallible> for AUTDDriverError {
153 fn from(_: Infallible) -> Self {
154 unreachable!()
155 }
156}
157
158impl<E1, E2> From<CombinedError<E1, E2>> for AUTDDriverError
159where
160 E1: std::error::Error,
161 E2: std::error::Error,
162 AUTDDriverError: From<E1> + From<E2>,
163{
164 fn from(err: CombinedError<E1, E2>) -> Self {
165 match err {
166 CombinedError::E1(e) => AUTDDriverError::from(e),
167 CombinedError::E2(e) => AUTDDriverError::from(e),
168 }
169 }
170}
171#[cfg(test)]
174mod tests {
175 use super::*;
176 use std::error::Error;
177
178 #[test]
179 fn test_unknown_firmware_err() {
180 let err = AUTDDriverError::firmware_err(0xFF);
181 assert!(err.source().is_none());
182 assert_eq!(format!("{}", err), "Unknown firmware error: 255");
183 assert_eq!(format!("{:?}", err), "UnknownFirmwareError(255)");
184 }
185}