1use embedded_hal::blocking::delay::DelayMs;
2use embedded_hal::digital::v2::PinState::{High, Low};
3use embedded_hal::digital::v2::{InputPin, OutputPin};
4
5#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
7pub struct Normal;
8
9#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
11pub struct Wakeup;
12
13#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
15pub struct Monitor;
16
17#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
19pub struct Program;
20
21pub trait Mode {
22 fn id(&self) -> u8;
23
24 fn set_pins<Aux, M0, M1, D>(aux: &mut Aux, m0: &mut M0, m1: &mut M1, delay: &mut D)
25 where
26 Aux: InputPin,
27 M0: OutputPin,
28 M1: OutputPin,
29 D: DelayMs<u32>;
30}
31
32macro_rules! impl_mode {
33 ($($type: ty)*, $id: literal, $m0_state: path, $m1_state: path) => {
34 $(
35 impl Mode for $type {
36 fn id(&self) -> u8 {
37 $id
38 }
39
40 fn set_pins<Aux, M0, M1, D>(aux: &mut Aux, m0: &mut M0, m1: &mut M1, delay: &mut D)
41 where
42 Aux: InputPin,
43 M0: OutputPin,
44 M1: OutputPin,
45 D: DelayMs<u32> {
46 delay.delay_ms(40);
48 let _m0 = m0.set_state($m0_state);
50 let _m1 = m1.set_state($m1_state);
51 delay.delay_ms(40);
52
53 loop {
54 match aux.is_low() {
56 Ok(true) => continue,
57 Ok(false) => break,
58 Err(_e) => panic!("failed to wait for aux pin"),
60 }
61 }
62 }
63 }
64 )*
65 };
66}
67
68impl_mode!(Normal, 0, Low, Low);
69impl_mode!(Wakeup, 1, High, Low);
70impl_mode!(Monitor, 2, Low, High);
71impl_mode!(Program, 3, High, High);
72
73#[cfg(test)]
74mod test {
75 use super::*;
76 use embedded_hal_mock::delay::MockNoop;
77 use embedded_hal_mock::pin::Mock as Pin;
78 use embedded_hal_mock::pin::{
79 State::{High, Low},
80 Transaction,
81 };
82
83 #[test]
84 fn id() {
85 let mode = Normal;
86 assert_eq!(mode.id(), 0);
87
88 let mode = Wakeup;
89 assert_eq!(mode.id(), 1);
90
91 let mode = Monitor;
92 assert_eq!(mode.id(), 2);
93
94 let mode = Program;
95 assert_eq!(mode.id(), 3);
96 }
97
98 #[test]
99 fn pins_normal() {
100 let mut m0 = Pin::new(&vec![Transaction::set(Low)]);
101 let mut m1 = Pin::new(&vec![Transaction::set(Low)]);
102 let mut aux = Pin::new(&vec![
103 Transaction::get(Low),
104 Transaction::get(Low),
105 Transaction::get(High),
106 ]);
107 Normal::set_pins(&mut aux, &mut m0, &mut m1, &mut MockNoop);
108 m0.done();
109 m1.done();
110 aux.done();
111 }
112
113 #[test]
114 fn pins_wakeup() {
115 let mut m0 = Pin::new(&vec![Transaction::set(High)]);
116 let mut m1 = Pin::new(&vec![Transaction::set(Low)]);
117 let mut aux = Pin::new(&vec![
118 Transaction::get(Low),
119 Transaction::get(Low),
120 Transaction::get(High),
121 ]);
122 Wakeup::set_pins(&mut aux, &mut m0, &mut m1, &mut MockNoop);
123 m0.done();
124 m1.done();
125 aux.done();
126 }
127
128 #[test]
129 fn pins_powerdown() {
130 let mut m0 = Pin::new(&vec![Transaction::set(Low)]);
131 let mut m1 = Pin::new(&vec![Transaction::set(High)]);
132 let mut aux = Pin::new(&vec![
133 Transaction::get(Low),
134 Transaction::get(Low),
135 Transaction::get(High),
136 ]);
137 Monitor::set_pins(&mut aux, &mut m0, &mut m1, &mut MockNoop);
138 m0.done();
139 m1.done();
140 aux.done();
141 }
142
143 #[test]
144 fn pins_program() {
145 let mut m0 = Pin::new(&vec![Transaction::set(High)]);
146 let mut m1 = Pin::new(&vec![Transaction::set(High)]);
147 let mut aux = Pin::new(&vec![
148 Transaction::get(Low),
149 Transaction::get(Low),
150 Transaction::get(High),
151 ]);
152 Program::set_pins(&mut aux, &mut m0, &mut m1, &mut MockNoop);
153 m0.done();
154 m1.done();
155 aux.done();
156 }
157}