firmly/
codec.rs

1#[derive(Debug, Clone)]
2pub enum Command {
3    SetPinMode(SetPinMode),
4    DigitalWrite(DigitalWrite),
5    DigitalWritePin(DigitalWritePin),
6}
7
8pub fn encode(cmd: &Command, buf: &mut [u8]) -> Option<usize> {
9    match cmd {
10        Command::SetPinMode(SetPinMode { pin, mode }) => {
11            if buf.len() >= 3 {
12                buf[0] = 0xf4;
13                buf[1] = *pin & 0x7f;
14                buf[2] = mode.encoded();
15                Some(3)
16            } else {
17                None
18            }
19        }
20        Command::DigitalWrite(DigitalWrite { port, values }) => {
21            if buf.len() >= 3 {
22                buf[0] = 0x90 | (*port & 0x7f);
23                buf[1] = *values & 0x7f;
24                buf[2] = *values >> 7;
25                Some(3)
26            } else {
27                None
28            }
29        }
30        Command::DigitalWritePin(DigitalWritePin { pin, value }) => {
31            if buf.len() >= 3 {
32                buf[0] = 0xf5;
33                buf[1] = *pin & 0x7f;
34                buf[2] = if *value { 0x01 } else { 0x00 };
35                Some(3)
36            } else {
37                None
38            }
39        }
40    }
41}
42
43#[derive(Debug, Clone, Copy)]
44pub struct SetPinMode {
45    pub pin: u8,
46    pub mode: PinMode,
47}
48
49#[derive(Debug, Clone, Copy)]
50pub enum PinMode {
51    Input,
52    Output,
53    AnalogInput,
54    Pwm,
55    Servo,
56    Shift,
57    I2c,
58    OneWire,
59    Stepper,
60    Encoder,
61    Serial,
62    InputPullup,
63}
64
65impl PinMode {
66    fn encoded(&self) -> u8 {
67        match self {
68            PinMode::Input => 0,
69            PinMode::Output => 1,
70            PinMode::AnalogInput => 2,
71            PinMode::Pwm => 3,
72            PinMode::Servo => 4,
73            PinMode::Shift => 5,
74            PinMode::I2c => 6,
75            PinMode::OneWire => 7,
76            PinMode::Stepper => 8,
77            PinMode::Encoder => 9,
78            PinMode::Serial => 0xa,
79            PinMode::InputPullup => 0xb,
80        }
81    }
82}
83
84#[derive(Debug, Clone, Copy)]
85pub struct DigitalWrite {
86    pub port: u8,
87    pub values: u8,
88}
89
90#[derive(Debug, Clone, Copy)]
91pub struct DigitalWritePin {
92    pub pin: u8,
93    pub value: bool,
94}
95
96#[cfg(test)]
97mod test {
98    use super::*;
99
100    #[test]
101    fn test_set_pin_mode() {
102        let mut buf = [0u8; 4];
103        let bytes_encoded = encode(
104            &Command::SetPinMode(SetPinMode {
105                pin: 13,
106                mode: PinMode::Output,
107            }),
108            &mut buf[..],
109        )
110        .unwrap();
111
112        assert_eq!(3, bytes_encoded);
113        assert_eq!(&[0xf4, 0xd, 0x01], &buf[..bytes_encoded]);
114    }
115
116    #[test]
117    fn test_write_digital_out() {
118        let mut buf = [0u8; 4];
119        let bytes_encoded = encode(
120            &Command::DigitalWrite(DigitalWrite {
121                port: 1,
122                values: 0xaa,
123            }),
124            &mut buf[..],
125        )
126        .unwrap();
127
128        assert_eq!(3, bytes_encoded);
129        assert_eq!(&[0x91, 0x2a, 0x01], &buf[..bytes_encoded]);
130    }
131
132    #[test]
133    fn test_write_digital_pin() {
134        let mut buf = [0u8; 4];
135        let bytes_encoded = encode(
136            &Command::DigitalWritePin(DigitalWritePin {
137                pin: 13,
138                value: true,
139            }),
140            &mut buf,
141        )
142        .unwrap();
143
144        assert_eq!(3, bytes_encoded);
145        assert_eq!(&[0xf5, 0x0d, 0x01], &buf[..bytes_encoded]);
146    }
147}