ebyte_e32/
mode.rs

1use embedded_hal::blocking::delay::DelayMs;
2use embedded_hal::digital::v2::PinState::{High, Low};
3use embedded_hal::digital::v2::{InputPin, OutputPin};
4
5/// Send and receive.
6#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
7pub struct Normal;
8
9/// Send preamble to wake receiver.
10#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
11pub struct Wakeup;
12
13/// Powerdown.
14#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
15pub struct Monitor;
16
17/// Programming.
18#[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                        // TODO check if delay times can be reduced.
47                            delay.delay_ms(40);
48                            // TODO handle errors here.
49                            let _m0 = m0.set_state($m0_state);
50                            let _m1 = m1.set_state($m1_state);
51                            delay.delay_ms(40);
52
53                            loop {
54                                // TODO timeouts?
55                                match aux.is_low() {
56                                    Ok(true) => continue,
57                                    Ok(false) => break,
58                                    // TODO error handling.
59                                    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}