sbus_rs/parser/
blocking.rs

1use crate::{error::SbusError, packet::SbusPacket, parser::SBUS_FRAME_LENGTH, Parser};
2use embedded_io::Read;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6pub struct Blocking {}
7impl super::Mode for Blocking {}
8impl super::Sealed for Blocking {}
9
10impl<R: Read> Parser<R, Blocking> {
11    pub fn new(reader: R) -> Self {
12        Self {
13            reader,
14            _mode: Default::default(),
15        }
16    }
17
18    /// Reads the next complete SBUS frame
19    ///
20    /// # Returns
21    ///
22    /// * `Ok(SbusPacket)` if a valid frame was read
23    /// * `Err(SbusError)` if an error occurred or the frame was invalid
24    pub fn read_frame(&mut self) -> Result<SbusPacket, SbusError> {
25        let mut buffer = [0u8; SBUS_FRAME_LENGTH];
26        self.reader
27            .read_exact(&mut buffer)
28            .map_err(|_| SbusError::ReadError)?;
29
30        SbusPacket::from_array(&buffer)
31    }
32}
33
34pub type SbusParser<R> = Parser<R, Blocking>;
35
36#[cfg(test)]
37mod tests {
38    use crate::{SbusError, SbusParser, CHANNEL_MAX};
39    use embedded_io_adapters::std::FromStd;
40    use std::io::Cursor;
41
42    const TEST_PACKET: [u8; 25] = [
43        0x0F, // HEAD_BYTE
44        (1024 & 0x07FF) as u8,
45        (((1024 & 0x07FF) >> 8) | ((1024 & 0x07FF) << 3)) as u8,
46        (((1024 & 0x07FF) >> 5) | ((1024 & 0x07FF) << 6)) as u8,
47        ((1024 & 0x07FF) >> 2) as u8,
48        (((1024 & 0x07FF) >> 10) | ((1024 & 0x07FF) << 1)) as u8,
49        (((1024 & 0x07FF) >> 7) | ((1024 & 0x07FF) << 4)) as u8,
50        ((1024 & 0x07FF) >> 4) as u8,
51        ((1024 & 0x07FF) << 2) as u8,
52        (((1024 & 0x07FF) >> 8) | ((1024 & 0x07FF) << 5)) as u8,
53        ((1024 & 0x07FF) >> 1) as u8,
54        (((1024 & 0x07FF) >> 9) | ((1024 & 0x07FF) << 6)) as u8,
55        ((1024 & 0x07FF) >> 3) as u8,
56        (((1024 & 0x07FF) >> 10) | ((1024 & 0x07FF) << 1)) as u8,
57        (((1024 & 0x07FF) >> 7) | ((1024 & 0x07FF) << 4)) as u8,
58        ((1024 & 0x07FF) >> 4) as u8,
59        ((1024 & 0x07FF) << 2) as u8,
60        (((1024 & 0x07FF) >> 8) | ((1024 & 0x07FF) << 5)) as u8,
61        ((1024 & 0x07FF) >> 1) as u8,
62        (((1024 & 0x07FF) >> 9) | ((1024 & 0x07FF) << 6)) as u8,
63        ((1024 & 0x07FF) >> 3) as u8,
64        (((1024 & 0x07FF) >> 10) | ((1024 & 0x07FF) << 1)) as u8,
65        (((1024 & 0x07FF) >> 7) | ((1024 & 0x07FF) << 4)) as u8,
66        0x00, // FLAGS_BYTE, no flags set
67        0x00, // FOOT_BYTE
68    ];
69
70    #[test]
71    fn test_valid_sbus_frame() {
72        // Simulate a valid SBUS frame
73        let data = [
74            0x0F, // Header
75            0x00, 0x00, // Channel 1 (bits 0-10)
76            0x00, 0x00, // Channel 2 (bits 0-10)
77            // Remaining channels omitted for brevity, but should be similar
78            // Ensure to simulate all 16 channels and the flags byte
79            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Flags
81            0x00, // Footer
82        ];
83        let cursor = Cursor::new(data);
84        let mut parser = SbusParser::new(FromStd::new(cursor));
85
86        let packet = parser.read_frame().expect("Should be a valid frame");
87
88        assert_eq!(packet.channels[0], 0);
89        assert_eq!(packet.channels[15], 0);
90        assert!(!packet.flags.d1);
91        assert!(!packet.flags.d2);
92        assert!(!packet.flags.frame_lost);
93        assert!(!packet.flags.failsafe);
94    }
95
96    #[test]
97    fn test_invalid_header() {
98        // Simulate a frame with an invalid header
99        let mut data = TEST_PACKET;
100        data[0] = 0x00; // Invalid header
101
102        let cursor = Cursor::new(data);
103        let mut parser = SbusParser::new(FromStd::new(cursor));
104
105        let result = parser.read_frame();
106        assert!(matches!(result, Err(SbusError::InvalidHeader(0x00))));
107    }
108
109    #[test]
110    fn test_invalid_footer() {
111        let mut data = TEST_PACKET;
112        data[24] = 0xFF; // Invalid footer
113
114        let cursor = Cursor::new(data);
115        let mut parser = SbusParser::new(FromStd::new(cursor));
116
117        let result = parser.read_frame();
118        assert!(matches!(result, Err(SbusError::InvalidFooter(0xFF))));
119    }
120
121    #[test]
122    fn test_flag_bytes() {
123        let mut data = TEST_PACKET;
124        data[23] = 0b00001111; // All flags set
125
126        let cursor = Cursor::new(data);
127        let mut parser = SbusParser::new(FromStd::new(cursor));
128
129        let result = parser.read_frame();
130        assert!(result.is_ok());
131        let packet = result.unwrap();
132        assert!(packet.flags.d1);
133        assert!(packet.flags.d2);
134        assert!(packet.flags.frame_lost);
135        assert!(packet.flags.failsafe);
136    }
137
138    #[test]
139    fn test_partial_frame() {
140        let data = &TEST_PACKET[..20]; // Cut off the last few bytes
141
142        let cursor = Cursor::new(data);
143        let mut parser = SbusParser::new(FromStd::new(cursor));
144
145        let result = parser.read_frame();
146        assert!(matches!(result, Err(SbusError::ReadError)));
147    }
148
149    #[test]
150    fn test_channel_decoding() {
151        let mut data = [0u8; 25];
152        data[0] = 0x0F; // Header
153                        // Channel 1 set to 0
154        data[1] = 0;
155        data[2] = 0;
156        // Channel 2 set to 2047, needs to correctly span bytes 2, 3, and 4
157        data[2] |= (CHANNEL_MAX << 3) as u8; // Start from bit 3 of byte 2
158        data[3] = ((CHANNEL_MAX >> 5) & 0xFF) as u8; // Next full byte
159        data[4] = ((CHANNEL_MAX >> 5) & 0x07) as u8; // Last few bits that fit into byte 4
160        data[24] = 0x00; // Footer
161
162        let cursor = Cursor::new(data);
163        let mut parser = SbusParser::new(FromStd::new(cursor));
164
165        let result = parser.read_frame();
166        assert!(result.is_ok());
167        let packet = result.unwrap();
168        assert_eq!(packet.channels[0], 0); // Channel 1 should be 0
169        assert_eq!(packet.channels[1], CHANNEL_MAX); // Channel 2 should be 2047
170    }
171}