1use core::convert::TryFrom;
4
5use paste::paste;
6
7pub trait StepMode:
9 Into<u16> + TryFrom<u16, Error = InvalidStepModeError> + Copy
10{
11 type Iter: Iterator<Item = Self>;
13
14 fn iter() -> Self::Iter;
19}
20
21macro_rules! generate_step_mode_enums {
22 (
23 $(
24 $max:expr => $($variant:expr),*;
25 )*
26 ) => {
27 $(
28 generate_step_mode_enums!(@gen_enum,
29 (),
30 (),
31 (),
32 $max => $($variant,)*
33 );
34 )*
35 };
36
37 (
45 @gen_enum,
46 (),
47 (),
48 (),
49 $max:expr => $($input:expr,)*
50 ) => {
51 generate_step_mode_enums!(
52 @gen_enum,
53 (
54 #[doc = "Full steps"]
55 Full = 1,
56 ),
57 (
58 1 => Ok(Self::Full),
59 ),
60 (
61 [<StepMode $max>]::Full,
62 ),
63 $max => $($input,)*
64 );
65 };
66 (
70 @gen_enum,
71 (
72 $($variant_output:tt)*
73 ),
74 (
75 $($try_from_output:tt)*
76 ),
77 (
78 $($iter_output:tt)*
79 ),
80 $max:expr => $variant:expr, $($input:expr,)*
81 ) => {
82 generate_step_mode_enums!(
83 @gen_enum,
84 (
85 $($variant_output)*
86
87 #[doc = $variant " microsteps per full step"]
88 [<M $variant>] = $variant,
89 ),
90 (
91 $($try_from_output)*
92
93 $variant => Ok(Self::[<M $variant>]),
94 ),
95 (
96 $($iter_output)*
97
98 [<StepMode $max>]::[<M $variant>],
99 ),
100 $max => $($input,)*
101 );
102 };
103 (
107 @gen_enum,
108 (
109 $($variant_output:tt)*
110 ),
111 (
112 $($try_from_output:tt)*
113 ),
114 (
115 $($iter_output:tt)*
116 ),
117 $max:expr =>
118 ) => {
119 paste! {
120 #[doc =
121 "Defines the microstepping mode for drivers with a resolution \
122 of up to " $max " microsteps"
123 ]
124 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
125 pub enum [<StepMode $max>] {
126 $($variant_output)*
127 }
128
129 impl From<[<StepMode $max>]> for u16 {
130 fn from(step_mode: [<StepMode $max>]) -> Self {
131 step_mode as Self
132 }
133 }
134
135 impl TryFrom<u16> for [<StepMode $max>] {
136 type Error = InvalidStepModeError;
137
138 fn try_from(val: u16) -> Result<Self, Self::Error> {
139 match val {
140 $($try_from_output)*
141
142 _ => Err(InvalidStepModeError),
143 }
144 }
145 }
146
147 impl StepMode for [<StepMode $max>] {
148 type Iter = [<Iter $max>];
153
154 fn iter() -> Self::Iter {
155 [<Iter $max>] {
156 i: 0,
157 }
158 }
159 }
160
161 #[doc =
162 "An iterator over the variants of [`StepMode" $max "`]"
163 ]
164 pub struct [<Iter $max>] {
165 i: usize,
166 }
167
168 impl Iterator for [<Iter $max>] {
169 type Item = [<StepMode $max>];
170
171 fn next(&mut self) -> Option<Self::Item> {
172 let modes = [$($iter_output)*];
173
174 if self.i < modes.len() {
175 let mode = modes[self.i];
176 self.i += 1;
177 Some(mode)
178 }
179 else {
180 None
181 }
182 }
183 }
184 }
185 };
186}
187
188generate_step_mode_enums! {
189 2 => 2;
190 4 => 2, 4;
191 8 => 2, 4, 8;
192 16 => 2, 4, 8, 16;
193 32 => 2, 4, 8, 16, 32;
194 64 => 2, 4, 8, 16, 32, 64;
195 128 => 2, 4, 8, 16, 32, 64, 128;
196 256 => 2, 4, 8, 16, 32, 64, 128, 256;
197}
198
199#[derive(Clone, Copy, Debug, Eq, PartialEq)]
203pub struct InvalidStepModeError;
204
205#[cfg(test)]
206mod tests {
207 use core::convert::TryFrom;
211
212 use super::{StepMode as _, StepMode256};
213
214 #[test]
215 fn step_mode_should_convert_into_microsteps_per_step() {
216 use StepMode256::*;
217
218 assert_eq!(<StepMode256 as Into<u16>>::into(Full), 1);
219 assert_eq!(<StepMode256 as Into<u16>>::into(M2), 2);
220 assert_eq!(<StepMode256 as Into<u16>>::into(M4), 4);
221 assert_eq!(<StepMode256 as Into<u16>>::into(M8), 8);
222 assert_eq!(<StepMode256 as Into<u16>>::into(M16), 16);
223 assert_eq!(<StepMode256 as Into<u16>>::into(M32), 32);
224 assert_eq!(<StepMode256 as Into<u16>>::into(M64), 64);
225 assert_eq!(<StepMode256 as Into<u16>>::into(M128), 128);
226 assert_eq!(<StepMode256 as Into<u16>>::into(M256), 256);
227 }
228
229 #[test]
230 fn step_mode_should_convert_from_microsteps_per_step() {
231 use StepMode256::*;
232
233 assert_eq!(<StepMode256 as TryFrom<u16>>::try_from(1), Ok(Full));
234 assert_eq!(<StepMode256 as TryFrom<u16>>::try_from(2), Ok(M2));
235 assert_eq!(<StepMode256 as TryFrom<u16>>::try_from(4), Ok(M4));
236 assert_eq!(<StepMode256 as TryFrom<u16>>::try_from(8), Ok(M8));
237 assert_eq!(<StepMode256 as TryFrom<u16>>::try_from(16), Ok(M16));
238 assert_eq!(<StepMode256 as TryFrom<u16>>::try_from(32), Ok(M32));
239 assert_eq!(<StepMode256 as TryFrom<u16>>::try_from(64), Ok(M64));
240 assert_eq!(<StepMode256 as TryFrom<u16>>::try_from(128), Ok(M128));
241 assert_eq!(<StepMode256 as TryFrom<u16>>::try_from(256), Ok(M256));
242 }
243
244 #[test]
245 fn step_mode_should_provide_iterator_over_modes() {
246 use StepMode256::*;
247
248 let modes: Vec<_> = StepMode256::iter().collect();
249 assert_eq!(modes, [Full, M2, M4, M8, M16, M32, M64, M128, M256]);
250 }
251}