use core::marker::PhantomData;
use crate::{
protocol::{
nec::{NecCommand, NecCommandVariant},
Nec,
},
receiver::{
time::{InfraMonotonic, PulseSpans},
DecoderFactory, DecodingError, ProtocolDecoder, State,
},
};
fn pulselens<Cmd: NecCommandVariant>() -> [u32; 8] {
[
Cmd::PULSE_DISTANCE.header_high + Cmd::PULSE_DISTANCE.header_low,
Cmd::PULSE_DISTANCE.header_high + Cmd::PULSE_DISTANCE.repeat_low,
Cmd::PULSE_DISTANCE.data_high + Cmd::PULSE_DISTANCE.data_zero_low,
Cmd::PULSE_DISTANCE.data_high + Cmd::PULSE_DISTANCE.data_one_low,
0,
0,
0,
0,
]
}
const TOL: [u32; 8] = [7, 7, 5, 5, 0, 0, 0, 0];
impl<Mono: InfraMonotonic, Cmd: NecCommandVariant> DecoderFactory<Mono> for Nec<Cmd> {
type Decoder = NecDecoder<Mono, Cmd>;
fn decoder(freq: u32) -> Self::Decoder {
NecDecoder {
state: NecState::Init,
bitbuf: 0,
cmd_type: Default::default(),
dt_save: Mono::ZERO_DURATION,
pulsespans: PulseSpans::new(freq, &pulselens::<Cmd>(), &TOL),
}
}
}
pub struct NecDecoder<Mono: InfraMonotonic, C = NecCommand> {
state: NecState,
bitbuf: u32,
cmd_type: PhantomData<C>,
dt_save: Mono::Duration,
pulsespans: PulseSpans<Mono>,
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum NecState {
Init,
Receiving(u32),
Done,
RepeatDone,
Err(DecodingError),
}
impl From<NecState> for State {
fn from(ns: NecState) -> Self {
use NecState::*;
match ns {
Init => State::Idle,
Done | RepeatDone => State::Done,
Err(e) => State::Error(e),
_ => State::Receiving,
}
}
}
impl<Mono, Cmd> ProtocolDecoder<Mono, Cmd> for NecDecoder<Mono, Cmd>
where
Mono: InfraMonotonic,
Cmd: NecCommandVariant,
{
#[rustfmt::skip]
fn event(
&mut self,
rising: bool,
dur: Mono::Duration,
) -> State {
use NecState::*;
use PulseWidth::*;
if rising {
let total_duration = dur + self.dt_save;
let pulsewidth = self.pulsespans.get(total_duration)
.unwrap_or(PulseWidth::Invalid);
let status = match (self.state, pulsewidth) {
(Init, Sync) => { self.bitbuf = 0; Receiving(0) },
(Init, Repeat) => RepeatDone,
(Init, _) => Init,
(Receiving(31), One) => { self.bitbuf |= 1 << 31; Done }
(Receiving(31), Zero) => Done,
(Receiving(bit), One) => { self.bitbuf |= 1 << bit; Receiving(bit + 1) }
(Receiving(bit), Zero) => Receiving(bit + 1),
(Receiving(_), _) => Err(DecodingError::Data),
(Done, _) => Done,
(RepeatDone, _) => RepeatDone,
(Err(err), _) => Err(err),
};
trace!(
"State(prev, new): ({:?}, {:?}) pulsewidth: {:?}",
self.state,
status,
pulsewidth
);
self.state = status;
self.dt_save = Mono::ZERO_DURATION;
} else {
self.dt_save = dur;
}
self.state.into()
}
fn command(&self) -> Option<Cmd> {
match self.state {
NecState::Done => Cmd::unpack(self.bitbuf, false),
NecState::RepeatDone => Cmd::unpack(self.bitbuf, true),
_ => None,
}
}
fn reset(&mut self) {
self.state = NecState::Init;
self.dt_save = Mono::ZERO_DURATION;
}
fn spans(&self) -> &PulseSpans<Mono> {
&self.pulsespans
}
}
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum PulseWidth {
Sync = 0,
Repeat = 1,
Zero = 2,
One = 3,
Invalid = 4,
}
impl From<usize> for PulseWidth {
fn from(v: usize) -> Self {
match v {
0 => PulseWidth::Sync,
1 => PulseWidth::Repeat,
2 => PulseWidth::Zero,
3 => PulseWidth::One,
_ => PulseWidth::Invalid,
}
}
}