1#![no_std]
2#![forbid(unsafe_code)]
3
4const SBUS_PACKET_SIZE: usize = 25;
5const SBUS_NUM_CHANNELS: usize = 16;
6const SBUS_HEADER: u8 = 0x0F;
7const SBUS_FLAG_BYTE_MASK: u8 = 0xF0;
8const SBUS_FOOTER: u8 = 0x00;
9const CHAN_MASK: u16 = 0x07FF;
10
11#[derive(Debug, PartialEq, Eq)]
12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13pub enum SbusParserError {
14 InvalidFooter(u8),
15 InvalidFlags(u8),
16}
17
18#[inline]
19fn is_sbus_footer(byte: u8) -> bool {
20 match byte {
21 0x00 => true, 0x04 => true, 0x14 => true, 0x24 => true, 0x34 => true, _ => false,
27 }
28}
29
30#[inline]
31fn is_flag_set_at_position(flag_byte: u8, shift_by: u8) -> bool {
32 (flag_byte >> shift_by) & 1 == 1
33}
34
35#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone)]
36#[cfg_attr(feature = "defmt", derive(defmt::Format))]
37pub struct RawSbusPacket {
38 bytes: [u8; SBUS_PACKET_SIZE],
39}
40
41impl RawSbusPacket {
42 pub fn new(bytes: &[u8; SBUS_PACKET_SIZE]) -> Self {
43 Self { bytes: *bytes }
44 }
45
46 pub fn as_bytes(&self) -> &[u8] {
47 &self.bytes
48 }
49}
50
51#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone)]
52#[cfg_attr(feature = "defmt", derive(defmt::Format))]
53pub struct SbusPacket {
54 pub channels: [u16; SBUS_NUM_CHANNELS],
55 pub channel_17: bool,
56 pub channel_18: bool,
57 pub failsafe: bool,
58 pub frame_lost: bool,
59}
60
61impl SbusPacket {
62 pub fn parse(raw_packet: &RawSbusPacket) -> Self {
63 let buf = raw_packet.as_bytes();
64 let mut ch: [u16; SBUS_NUM_CHANNELS] = [CHAN_MASK; SBUS_NUM_CHANNELS];
66
67 ch[0] &= (buf[1] as u16) | ((buf[2] as u16) << 8);
68 ch[1] &= ((buf[2] as u16) >> 3) | ((buf[3] as u16) << 5);
69 ch[2] &= ((buf[3] as u16) >> 6) | ((buf[4] as u16) << 2) | ((buf[5] as u16) << 10);
70 ch[3] &= ((buf[5] as u16) >> 1) | ((buf[6] as u16) << 7);
71 ch[4] &= ((buf[6] as u16) >> 4) | ((buf[7] as u16) << 4);
72 ch[5] &= ((buf[7] as u16) >> 7) | ((buf[8] as u16) << 1) | ((buf[9] as u16) << 9);
73 ch[6] &= ((buf[9] as u16) >> 2) | ((buf[10] as u16) << 6);
74 ch[7] &= ((buf[10] as u16) >> 5) | ((buf[11] as u16) << 3);
75
76 ch[8] &= (buf[12] as u16) | ((buf[13] as u16) << 8);
77 ch[9] &= ((buf[13] as u16) >> 3) | ((buf[14] as u16) << 5);
78 ch[10] &= ((buf[14] as u16) >> 6) | ((buf[15] as u16) << 2) | ((buf[16] as u16) << 10);
79 ch[11] &= ((buf[16] as u16) >> 1) | ((buf[17] as u16) << 7);
80 ch[12] &= ((buf[17] as u16) >> 4) | ((buf[18] as u16) << 4);
81 ch[13] &= ((buf[18] as u16) >> 7) | ((buf[19] as u16) << 1) | ((buf[20] as u16) << 9);
82 ch[14] &= ((buf[20] as u16) >> 2) | ((buf[21] as u16) << 6);
83 ch[15] &= ((buf[21] as u16) >> 5) | ((buf[22] as u16) << 3);
84
85 let flag_byte = buf[23];
86
87 SbusPacket {
88 channels: ch,
89 channel_17: is_flag_set_at_position(flag_byte, 0),
90 channel_18: is_flag_set_at_position(flag_byte, 1),
91 frame_lost: is_flag_set_at_position(flag_byte, 2),
92 failsafe: is_flag_set_at_position(flag_byte, 3),
93 }
94 }
95}
96
97#[derive(Debug, Default, Ord, PartialOrd, Eq, PartialEq, Copy, Clone)]
98pub enum State {
99 #[default]
100 AwaitingHead,
101 Reading(usize),
102}
103
104#[derive(Debug, Default)]
105pub struct SbusParser {
106 buffer: [u8; SBUS_PACKET_SIZE],
107 state: State,
108}
109
110pub struct PacketIterator<'a, 'b> {
111 parser: &'a mut SbusParser,
112 remaining_data: &'b [u8],
113}
114
115impl Iterator for PacketIterator<'_, '_> {
116 type Item = Result<SbusPacket, SbusParserError>;
117
118 fn next(&mut self) -> Option<Self::Item> {
119 loop {
120 if self.remaining_data.is_empty() {
121 break;
122 }
123
124 let byte = self.remaining_data[0];
125 self.remaining_data = &self.remaining_data[1..];
126
127 if let Some(result) = self.parser.push_byte(byte) {
128 return Some(result);
129 }
130 }
131 None
132 }
133}
134
135pub struct RawPacketIterator<'a, 'b> {
136 parser: &'a mut SbusParser,
137 remaining_data: &'b [u8],
138}
139
140impl Iterator for RawPacketIterator<'_, '_> {
141 type Item = Result<RawSbusPacket, SbusParserError>;
142
143 fn next(&mut self) -> Option<Self::Item> {
144 loop {
145 if self.remaining_data.is_empty() {
146 break;
147 }
148
149 let byte = self.remaining_data[0];
150 self.remaining_data = &self.remaining_data[1..];
151
152 if let Some(result) = self.parser.push_byte_raw(byte) {
153 return Some(result);
154 }
155 }
156 None
157 }
158}
159
160impl SbusParser {
161 pub fn new() -> Self {
162 Self {
163 buffer: [0; SBUS_PACKET_SIZE],
164 state: State::AwaitingHead,
165 }
166 }
167 pub fn push_byte_raw(&mut self, byte: u8) -> Option<Result<RawSbusPacket, SbusParserError>> {
168 match self.state {
169 State::AwaitingHead => {
170 if byte == SBUS_HEADER {
171 self.buffer[0] = byte;
172 self.state = State::Reading(1);
173 }
174 }
175 State::Reading(n) if n == SBUS_PACKET_SIZE - 1 => {
176 self.buffer[n] = byte;
177 self.state = State::AwaitingHead;
178 return Some(self.try_parse());
179 }
180 State::Reading(n) => {
181 self.buffer[n] = byte;
182 self.state = State::Reading(n + 1)
183 }
184 }
185 None
186 }
187 pub fn push_byte(&mut self, byte: u8) -> Option<Result<SbusPacket, SbusParserError>> {
188 self.push_byte_raw(byte)
189 .map(|res| res.map(|raw_packet| SbusPacket::parse(&raw_packet)))
190 }
191
192 pub fn reset(&mut self) {
193 self.state = State::AwaitingHead;
194 }
195
196 fn try_parse(&self) -> Result<RawSbusPacket, SbusParserError> {
197 if self.state != State::Reading(SBUS_PACKET_SIZE) {
198 self.validate_frame()?;
199 }
200 Ok(RawSbusPacket::new(&self.buffer))
201 }
202
203 pub fn validate_frame(&self) -> Result<(), SbusParserError> {
204 let footer = self.buffer[SBUS_PACKET_SIZE - 1];
205 let flags = self.buffer[SBUS_PACKET_SIZE - 2];
206
207 if !is_sbus_footer(footer) {
208 Err(SbusParserError::InvalidFooter(footer))
209 } else if flags & SBUS_FLAG_BYTE_MASK != 0 {
210 Err(SbusParserError::InvalidFlags(flags))
211 } else {
212 Ok(())
213 }
214 }
215 pub fn iter_packets<'a, 'b>(&'a mut self, data: &'b [u8]) -> PacketIterator<'a, 'b> {
216 PacketIterator {
217 parser: self,
218 remaining_data: data,
219 }
220 }
221 pub fn iter_packets_raw<'a, 'b>(&'a mut self, data: &'b [u8]) -> RawPacketIterator<'a, 'b> {
222 RawPacketIterator {
223 parser: self,
224 remaining_data: data,
225 }
226 }
227}
228
229#[inline(always)]
230pub fn encode_packet(buf: &mut [u8; SBUS_PACKET_SIZE], packet: &SbusPacket) {
231 let ch = &packet.channels;
232
233 buf[0] = SBUS_HEADER;
235
236 buf[1] = ch[0] as u8;
239 buf[2] = (buf[2] & !0x07) | ((ch[0] >> 8) & 0x07) as u8;
240 buf[2] = (buf[2] & !0xF8) | ((ch[1] & 0x1F) << 3) as u8;
242
243 buf[3] = ((ch[1] >> 5) & 0x3F) as u8 | ((ch[2] & 0x03) << 6) as u8;
245
246 buf[4] = ((ch[2] >> 2) & 0xFF) as u8;
248 buf[5] = ((ch[2] >> 10) & 0x01) as u8 | ((ch[3] & 0x7F) << 1) as u8;
250
251 buf[6] = ((ch[3] >> 7) & 0x0F) as u8 | ((ch[4] & 0x0F) << 4) as u8;
253
254 buf[7] = ((ch[4] >> 4) & 0x7F) as u8 | ((ch[5] & 0x01) << 7) as u8;
256
257 buf[8] = ((ch[5] >> 1) & 0xFF) as u8;
259 buf[9] = ((ch[5] >> 9) & 0x03) as u8 | ((ch[6] & 0x3F) << 2) as u8;
261
262 buf[10] = ((ch[6] >> 6) & 0x1F) as u8 | ((ch[7] & 0x07) << 5) as u8;
264
265 buf[11] = ((ch[7] >> 3) & 0xFF) as u8;
267
268 buf[12] = ch[8] as u8;
270 buf[13] = ((ch[8] >> 8) & 0x07) as u8 | ((ch[9] & 0x1F) << 3) as u8;
271
272 buf[14] = ((ch[9] >> 5) & 0x3F) as u8 | ((ch[10] & 0x03) << 6) as u8;
273 buf[15] = ((ch[10] >> 2) & 0xFF) as u8;
274 buf[16] = ((ch[10] >> 10) & 0x01) as u8 | ((ch[11] & 0x7F) << 1) as u8;
275
276 buf[17] = ((ch[11] >> 7) & 0x0F) as u8 | ((ch[12] & 0x0F) << 4) as u8;
277 buf[18] = ((ch[12] >> 4) & 0x7F) as u8 | ((ch[13] & 0x01) << 7) as u8;
278
279 buf[19] = ((ch[13] >> 1) & 0xFF) as u8;
280 buf[20] = ((ch[13] >> 9) & 0x03) as u8 | ((ch[14] & 0x3F) << 2) as u8;
281
282 buf[21] = ((ch[14] >> 6) & 0x1F) as u8 | ((ch[15] & 0x07) << 5) as u8;
283 buf[22] = ((ch[15] >> 3) & 0xFF) as u8;
284 buf[23] = 0x00;
286 buf[23] = buf[23]
287 | (packet.channel_17 as u8)
288 | ((packet.channel_18 as u8) << 1)
289 | ((packet.frame_lost as u8) << 2)
290 | ((packet.failsafe as u8) << 3);
291
292 buf[24] = SBUS_FOOTER;
293}
294
295#[cfg(test)]
296mod tests {
297 use super::*;
298 extern crate std;
299 const RAW_BYTES: [u8; SBUS_PACKET_SIZE] = [
300 0x0F, 0xE0, 0x03, 0x1F, 0x58, 0xC0, 0x07, 0x16, 0xB0, 0x80, 0x05, 0x2C, 0x60, 0x01, 0x0B,
301 0xF8, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
302 ];
303
304 #[test]
305 fn test_basic_packing_unpacking() {
306 let mut p = SbusParser::new();
307 assert!(p.state == State::AwaitingHead);
308
309 for b in &RAW_BYTES[0..RAW_BYTES.len() - 1] {
310 assert!(p.push_byte(*b).is_none());
311 }
312 let packet = p.push_byte(RAW_BYTES[24]).unwrap().unwrap();
313 let expected = SbusPacket {
314 channels: [
315 992, 992, 352, 992, 352, 352, 352, 352, 352, 352, 992, 992, 0, 0, 0, 0,
316 ],
317 channel_17: true,
318 channel_18: true,
319 failsafe: false,
320 frame_lost: false,
321 };
322 assert!(packet == expected);
323
324 let mut buffer: [u8; SBUS_PACKET_SIZE] = [255; SBUS_PACKET_SIZE];
326 encode_packet(&mut buffer, &packet);
327 assert!(buffer == RAW_BYTES);
328 }
329
330 #[test]
331 fn test_low_value() {
332 const EXPECTED: [u8; SBUS_PACKET_SIZE] = [
333 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 ];
336
337 let packet = SbusPacket {
338 channels: [0; 16],
339 channel_17: false,
340 channel_18: false,
341 failsafe: false,
342 frame_lost: false,
343 };
344 let mut buffer: [u8; SBUS_PACKET_SIZE] = [255; SBUS_PACKET_SIZE];
346 encode_packet(&mut buffer, &packet);
347 assert!(buffer == EXPECTED);
348 }
349
350 #[test]
351 fn test_high_value() {
352 const EXPECTED: [u8; SBUS_PACKET_SIZE] = [
353 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
354 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00,
355 ];
356
357 let packet = SbusPacket {
358 channels: [2047; 16],
359 channel_17: true,
360 channel_18: true,
361 failsafe: true,
362 frame_lost: true,
363 };
364
365 let mut buffer: [u8; SBUS_PACKET_SIZE] = [0; SBUS_PACKET_SIZE];
366 encode_packet(&mut buffer, &packet);
367 assert!(buffer == EXPECTED);
368 }
369 #[test]
370 fn test_malformed_footer() {
371 let mut p = SbusParser::new();
372 const BAD_FOOTER: [u8; SBUS_PACKET_SIZE] = [
373 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
374 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF,
375 ];
376
377 assert!(p.state == State::AwaitingHead);
378 for b in &BAD_FOOTER[0..BAD_FOOTER.len() - 1] {
379 assert!(p.push_byte(*b).is_none());
380 }
381 let err = p.push_byte(BAD_FOOTER[24]).unwrap();
382 assert!(err == Err(SbusParserError::InvalidFooter(0xff)));
383 }
384
385 #[test]
386 fn test_malformed_flags() {
387 let mut p = SbusParser::new();
388 const BAD_FLAGS: [u8; SBUS_PACKET_SIZE] = [
389 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
390 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
391 ];
392
393 assert!(p.state == State::AwaitingHead);
394 for b in &BAD_FLAGS[0..BAD_FLAGS.len() - 1] {
395 assert!(p.push_byte(*b).is_none());
396 }
397 let err = p.push_byte(BAD_FLAGS[24]).unwrap();
398 assert!(err == Err(SbusParserError::InvalidFlags(0xff)));
399 }
400
401 #[test]
402 fn test_basic_raw_packet() {
403 let mut p = SbusParser::new();
404 for b in &RAW_BYTES[0..RAW_BYTES.len() - 1] {
405 assert!(p.push_byte(*b).is_none());
406 }
407 let raw_packet = p.push_byte_raw(RAW_BYTES[24]).unwrap().unwrap();
408 let packet = SbusPacket::parse(&raw_packet);
409
410 let expected = SbusPacket {
411 channels: [
412 992, 992, 352, 992, 352, 352, 352, 352, 352, 352, 992, 992, 0, 0, 0, 0,
413 ],
414 channel_17: true,
415 channel_18: true,
416 failsafe: false,
417 frame_lost: false,
418 };
419 assert!(packet == expected);
420 }
421
422 #[test]
423 fn test_basic_iterator() {
424 let data = [
425 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
426 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x0F, 0xE0, 0x03,
427 0x1F, 0x58, 0xC0, 0x07, 0x16, 0xB0, 0x80, 0x05, 0x2C, 0x60, 0x01, 0x0B, 0xF8, 0xC0,
428 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
429 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
430 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
433 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
434 ];
435 let mut parser = SbusParser::new();
436 let expected = SbusPacket {
437 channels: [
438 992, 992, 352, 992, 352, 352, 352, 352, 352, 352, 992, 992, 0, 0, 0, 0,
439 ],
440 channel_17: true,
441 channel_18: true,
442 failsafe: false,
443 frame_lost: false,
444 };
445
446 let results: std::vec::Vec<Result<SbusPacket, SbusParserError>> =
447 parser.iter_packets(&data).collect();
448 assert!(results.len() == 5);
449 assert!(results[0].is_err());
450 assert!(results[1] == Ok(expected));
451 assert!(results[4].is_err());
452
453 let raw_results: std::vec::Vec<Result<RawSbusPacket, SbusParserError>> =
454 parser.iter_packets_raw(&data).collect();
455 assert!(raw_results.len() == 5);
456 assert!(raw_results[0].is_err());
457
458 assert!(SbusPacket::parse(&raw_results[1].as_ref().unwrap()) == expected);
459 assert!(raw_results[4].is_err());
460 }
461}