use crate::{error::SbusError, packet::SbusPacket, parser::SBUS_FRAME_LENGTH, Parser};
use embedded_io::Read;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Blocking {}
impl super::Mode for Blocking {}
impl super::Sealed for Blocking {}
impl<R: Read> Parser<R, Blocking> {
pub fn new(reader: R) -> Self {
Self {
reader,
_mode: Default::default(),
}
}
pub fn read_frame(&mut self) -> Result<SbusPacket, SbusError> {
let mut buffer = [0u8; SBUS_FRAME_LENGTH];
self.reader
.read_exact(&mut buffer)
.map_err(|_| SbusError::ReadError)?;
SbusPacket::from_array(&buffer)
}
}
pub type SbusParser<R> = Parser<R, Blocking>;
#[cfg(test)]
mod tests {
use crate::{SbusError, SbusParser, CHANNEL_MAX};
use embedded_io_adapters::std::FromStd;
use std::io::Cursor;
const TEST_PACKET: [u8; 25] = [
0x0F, (1024 & 0x07FF) as u8,
(((1024 & 0x07FF) >> 8) | ((1024 & 0x07FF) << 3)) as u8,
(((1024 & 0x07FF) >> 5) | ((1024 & 0x07FF) << 6)) as u8,
((1024 & 0x07FF) >> 2) as u8,
(((1024 & 0x07FF) >> 10) | ((1024 & 0x07FF) << 1)) as u8,
(((1024 & 0x07FF) >> 7) | ((1024 & 0x07FF) << 4)) as u8,
((1024 & 0x07FF) >> 4) as u8,
((1024 & 0x07FF) << 2) as u8,
(((1024 & 0x07FF) >> 8) | ((1024 & 0x07FF) << 5)) as u8,
((1024 & 0x07FF) >> 1) as u8,
(((1024 & 0x07FF) >> 9) | ((1024 & 0x07FF) << 6)) as u8,
((1024 & 0x07FF) >> 3) as u8,
(((1024 & 0x07FF) >> 10) | ((1024 & 0x07FF) << 1)) as u8,
(((1024 & 0x07FF) >> 7) | ((1024 & 0x07FF) << 4)) as u8,
((1024 & 0x07FF) >> 4) as u8,
((1024 & 0x07FF) << 2) as u8,
(((1024 & 0x07FF) >> 8) | ((1024 & 0x07FF) << 5)) as u8,
((1024 & 0x07FF) >> 1) as u8,
(((1024 & 0x07FF) >> 9) | ((1024 & 0x07FF) << 6)) as u8,
((1024 & 0x07FF) >> 3) as u8,
(((1024 & 0x07FF) >> 10) | ((1024 & 0x07FF) << 1)) as u8,
(((1024 & 0x07FF) >> 7) | ((1024 & 0x07FF) << 4)) as u8,
0x00, 0x00, ];
#[test]
fn test_valid_sbus_frame() {
let data = [
0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
let cursor = Cursor::new(data);
let mut parser = SbusParser::new(FromStd::new(cursor));
let packet = parser.read_frame().expect("Should be a valid frame");
assert_eq!(packet.channels[0], 0);
assert_eq!(packet.channels[15], 0);
assert!(!packet.flags.d1);
assert!(!packet.flags.d2);
assert!(!packet.flags.frame_lost);
assert!(!packet.flags.failsafe);
}
#[test]
fn test_invalid_header() {
let mut data = TEST_PACKET;
data[0] = 0x00;
let cursor = Cursor::new(data);
let mut parser = SbusParser::new(FromStd::new(cursor));
let result = parser.read_frame();
assert!(matches!(result, Err(SbusError::InvalidHeader(0x00))));
}
#[test]
fn test_invalid_footer() {
let mut data = TEST_PACKET;
data[24] = 0xFF;
let cursor = Cursor::new(data);
let mut parser = SbusParser::new(FromStd::new(cursor));
let result = parser.read_frame();
assert!(matches!(result, Err(SbusError::InvalidFooter(0xFF))));
}
#[test]
fn test_flag_bytes() {
let mut data = TEST_PACKET;
data[23] = 0b00001111;
let cursor = Cursor::new(data);
let mut parser = SbusParser::new(FromStd::new(cursor));
let result = parser.read_frame();
assert!(result.is_ok());
let packet = result.unwrap();
assert!(packet.flags.d1);
assert!(packet.flags.d2);
assert!(packet.flags.frame_lost);
assert!(packet.flags.failsafe);
}
#[test]
fn test_partial_frame() {
let data = &TEST_PACKET[..20];
let cursor = Cursor::new(data);
let mut parser = SbusParser::new(FromStd::new(cursor));
let result = parser.read_frame();
assert!(matches!(result, Err(SbusError::ReadError)));
}
#[test]
fn test_channel_decoding() {
let mut data = [0u8; 25];
data[0] = 0x0F; data[1] = 0;
data[2] = 0;
data[2] |= (CHANNEL_MAX << 3) as u8; data[3] = ((CHANNEL_MAX >> 5) & 0xFF) as u8; data[4] = ((CHANNEL_MAX >> 5) & 0x07) as u8; data[24] = 0x00;
let cursor = Cursor::new(data);
let mut parser = SbusParser::new(FromStd::new(cursor));
let result = parser.read_frame();
assert!(result.is_ok());
let packet = result.unwrap();
assert_eq!(packet.channels[0], 0); assert_eq!(packet.channels[1], CHANNEL_MAX); }
}