autd3_rs/
firmware_version.rs1use core::fmt;
2
3use autd3_cpu_wire::params::{FUNC_EMULATOR_BIT, VERSION_NUM_MAJOR, VERSION_NUM_MINOR};
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6pub struct Version {
7 pub major: u8,
8 pub minor: u8,
9 pub patch: u8,
10}
11
12impl Version {
13 pub const UNKNOWN: Self = Self {
14 major: 0,
15 minor: 0,
16 patch: 0,
17 };
18
19 #[must_use]
20 pub const fn is_unknown(self) -> bool {
21 self.major == 0 && self.minor == 0 && self.patch == 0
22 }
23
24 #[must_use]
25 pub const fn series(self) -> (u8, u8) {
26 (self.major, self.minor)
27 }
28}
29
30impl fmt::Display for Version {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
33 }
34}
35
36#[derive(Clone, Copy, Debug, PartialEq, Eq)]
37pub struct FirmwareVersion {
38 pub cpu: Version,
39 pub fpga: Version,
40 pub(crate) function_bits: u8,
41}
42
43impl FirmwareVersion {
44 pub const SUPPORTED_SERIES: (u8, u8) = (VERSION_NUM_MAJOR, VERSION_NUM_MINOR);
45
46 #[must_use]
47 pub const fn is_emulator(&self) -> bool {
48 self.function_bits & (1 << FUNC_EMULATOR_BIT) != 0
49 }
50
51 #[must_use]
52 pub const fn is_supported(&self) -> bool {
53 !self.fpga.is_unknown() && is_supported_series(self.cpu) && is_supported_series(self.fpga)
54 }
55}
56
57const fn is_supported_series(version: Version) -> bool {
58 version.major == FirmwareVersion::SUPPORTED_SERIES.0
59 && version.minor == FirmwareVersion::SUPPORTED_SERIES.1
60}
61
62impl fmt::Display for FirmwareVersion {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 write!(f, "CPU: {}, FPGA: ", self.cpu)?;
65 if self.fpga.is_unknown() {
66 f.write_str("unknown")?;
67 } else {
68 write!(f, "{}", self.fpga)?;
69 }
70 if self.is_emulator() {
71 f.write_str(" [Emulator]")?;
72 }
73 Ok(())
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 const V: Version = Version {
82 major: 4,
83 minor: 5,
84 patch: 6,
85 };
86
87 #[test]
88 fn is_emulator() {
89 assert!(
90 FirmwareVersion {
91 cpu: V,
92 fpga: V,
93 function_bits: 1 << 7,
94 }
95 .is_emulator()
96 );
97 assert!(
98 !FirmwareVersion {
99 cpu: V,
100 fpga: V,
101 function_bits: 0x7F,
102 }
103 .is_emulator()
104 );
105 }
106
107 #[test]
108 fn display_appends_emulator_suffix() {
109 assert_eq!(
110 FirmwareVersion {
111 cpu: Version {
112 major: 1,
113 minor: 2,
114 patch: 3,
115 },
116 fpga: V,
117 function_bits: 1 << 7,
118 }
119 .to_string(),
120 "CPU: 1.2.3, FPGA: 4.5.6 [Emulator]"
121 );
122 }
123
124 #[test]
125 fn display_without_emulator_bit_has_no_suffix() {
126 assert_eq!(
127 FirmwareVersion {
128 cpu: Version {
129 major: 1,
130 minor: 2,
131 patch: 3,
132 },
133 fpga: V,
134 function_bits: 0,
135 }
136 .to_string(),
137 "CPU: 1.2.3, FPGA: 4.5.6"
138 );
139 }
140
141 #[test]
142 fn display_unknown_fpga_with_emulator_bit() {
143 assert_eq!(
144 FirmwareVersion {
145 cpu: Version {
146 major: 1,
147 minor: 2,
148 patch: 3,
149 },
150 fpga: Version::UNKNOWN,
151 function_bits: 1 << 7,
152 }
153 .to_string(),
154 "CPU: 1.2.3, FPGA: unknown [Emulator]"
155 );
156 }
157}