use core::convert::TryInto;
#[cfg(feature = "remotes")]
use crate::receiver::{DecodingError, ProtocolDecoder, State};
use crate::{
cmd::{AddressCommand, Command},
protocol::Protocol,
receiver::{
time::{InfraMonotonic, PulseSpans},
DecoderFactory,
},
};
pub struct Sbp;
impl Protocol for Sbp {
type Cmd = SbpCommand;
}
const PULSE: [u32; 8] = [
(4500 + 4500),
(500 + 4500),
(500 + 500),
(500 + 1500),
0,
0,
0,
0,
];
const TOL: [u32; 8] = [5, 5, 10, 10, 0, 0, 0, 0];
impl<Mono: InfraMonotonic> DecoderFactory<Mono> for Sbp {
type Decoder = SbpDecoder<Mono>;
fn decoder(freq: u32) -> Self::Decoder {
SbpDecoder {
state: SbpState::Init,
address: 0,
command: 0,
since_rising: Mono::ZERO_DURATION,
spans: PulseSpans::new(freq, &PULSE, &TOL),
}
}
}
pub struct SbpDecoder<Mono: InfraMonotonic> {
state: SbpState,
address: u16,
command: u32,
since_rising: Mono::Duration,
spans: PulseSpans<Mono>,
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct SbpCommand {
pub address: u16,
pub command: u8,
pub valid: bool,
}
impl SbpCommand {
pub fn unpack(address: u16, mut command: u32) -> Self {
command >>= 4;
let valid = ((command ^ (command >> 8)) & 0xFF) == 0xFF;
Self {
address,
command: (command) as u8,
valid,
}
}
}
impl Command for SbpCommand {
fn is_repeat(&self) -> bool {
false
}
}
impl AddressCommand for SbpCommand {
fn address(&self) -> u32 {
self.address.into()
}
fn command(&self) -> u32 {
self.command.into()
}
fn create(address: u32, command: u32) -> Option<Self> {
Some(SbpCommand {
address: address.try_into().ok()?,
command: command.try_into().ok()?,
valid: true,
})
}
}
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SbpState {
Init,
Address(u16),
Divider,
Command(u16),
Done,
Err(DecodingError),
}
impl<Mono: InfraMonotonic> ProtocolDecoder<Mono, SbpCommand> for SbpDecoder<Mono> {
#[rustfmt::skip]
fn event(&mut self, rising: bool, dt: Mono::Duration) -> State {
use SbpPulse::*;
use SbpState::*;
if rising {
let dt = self.since_rising + dt;
let pulsewidth = self.spans.get::<SbpPulse>(dt).unwrap_or(SbpPulse::NotAPulseWidth);
self.state = match (self.state, pulsewidth) {
(Init, Sync) => Address(0),
(Init, _) => Init,
(Address(15), One) => { self.address |= 1 << 15; Divider }
(Address(15), Zero) => Divider,
(Address(bit), One) => { self.address |= 1 << bit; Address(bit + 1) }
(Address(bit), Zero) => Address(bit + 1),
(Address(_), _) => Err(DecodingError::Address),
(Divider, Paus) => Command(0),
(Divider, _) => Err(DecodingError::Data),
(Command(19), One) => { self.command |= 1 << 19; Done }
(Command(19), Zero) => Done,
(Command(bit), One) => { self.command |= 1 << bit; Command(bit + 1) }
(Command(bit), Zero) => Command(bit + 1),
(Command(_), _) => Err(DecodingError::Data),
(Done, _) => Done,
(Err(err), _) => Err(err),
};
} else {
self.since_rising = dt;
}
self.state.into()
}
fn command(&self) -> Option<SbpCommand> {
Some(SbpCommand::unpack(self.address, self.command))
}
fn reset(&mut self) {
self.state = SbpState::Init;
self.address = 0;
self.command = 0;
self.since_rising = Mono::ZERO_DURATION;
}
fn spans(&self) -> &PulseSpans<Mono> {
&self.spans
}
}
impl From<SbpState> for State {
fn from(state: SbpState) -> State {
use SbpState::*;
match state {
Init => State::Idle,
Done => State::Done,
Err(e) => State::Error(e),
_ => State::Receiving,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SbpPulse {
Sync = 0,
Paus = 1,
Zero = 2,
One = 3,
NotAPulseWidth = 4,
}
impl From<usize> for SbpPulse {
fn from(v: usize) -> Self {
match v {
0 => SbpPulse::Sync,
1 => SbpPulse::Paus,
2 => SbpPulse::Zero,
3 => SbpPulse::One,
_ => SbpPulse::NotAPulseWidth,
}
}
}