infrared/protocol/nec/
decoder.rs

1use core::marker::PhantomData;
2
3use crate::{
4    protocol::{
5        nec::{NecCommand, NecCommandVariant},
6        Nec,
7    },
8    receiver::{
9        time::{InfraMonotonic, PulseSpans},
10        DecoderFactory, DecodingError, ProtocolDecoder, State,
11    },
12};
13
14fn pulselens<Cmd: NecCommandVariant>() -> [u32; 8] {
15    [
16        Cmd::PULSE_DISTANCE.header_high + Cmd::PULSE_DISTANCE.header_low,
17        Cmd::PULSE_DISTANCE.header_high + Cmd::PULSE_DISTANCE.repeat_low,
18        Cmd::PULSE_DISTANCE.data_high + Cmd::PULSE_DISTANCE.data_zero_low,
19        Cmd::PULSE_DISTANCE.data_high + Cmd::PULSE_DISTANCE.data_one_low,
20        0,
21        0,
22        0,
23        0,
24    ]
25}
26
27const TOL: [u32; 8] = [7, 7, 5, 5, 0, 0, 0, 0];
28
29impl<Mono: InfraMonotonic, Cmd: NecCommandVariant> DecoderFactory<Mono> for Nec<Cmd> {
30    type Decoder = NecDecoder<Mono, Cmd>;
31
32    fn decoder(freq: u32) -> Self::Decoder {
33        NecDecoder {
34            state: NecState::Init,
35            bitbuf: 0,
36            cmd_type: Default::default(),
37            dt_save: Mono::ZERO_DURATION,
38            pulsespans: PulseSpans::new(freq, &pulselens::<Cmd>(), &TOL),
39        }
40    }
41}
42
43pub struct NecDecoder<Mono: InfraMonotonic, C = NecCommand> {
44    // State
45    state: NecState,
46    // Data buffer
47    bitbuf: u32,
48    // Nec Command type
49    cmd_type: PhantomData<C>,
50    // Saved dt
51    dt_save: Mono::Duration,
52
53    pulsespans: PulseSpans<Mono>,
54}
55
56#[derive(Debug, Copy, Clone, PartialEq)]
57#[cfg_attr(feature = "defmt", derive(defmt::Format))]
58// Internal receiver state
59pub enum NecState {
60    // Waiting for first pulse
61    Init,
62    // Receiving data
63    Receiving(u32),
64    // Command received
65    Done,
66    // Repeat command received
67    RepeatDone,
68    // In error state
69    Err(DecodingError),
70}
71
72impl From<NecState> for State {
73    fn from(ns: NecState) -> Self {
74        use NecState::*;
75        match ns {
76            Init => State::Idle,
77            Done | RepeatDone => State::Done,
78            Err(e) => State::Error(e),
79            _ => State::Receiving,
80        }
81    }
82}
83
84impl<Mono, Cmd> ProtocolDecoder<Mono, Cmd> for NecDecoder<Mono, Cmd>
85where
86    Mono: InfraMonotonic,
87    Cmd: NecCommandVariant,
88{
89    #[rustfmt::skip]
90    fn event(
91        &mut self,
92        rising: bool,
93        dur: Mono::Duration,
94    ) -> State {
95
96        use NecState::*;
97        use PulseWidth::*;
98
99        if rising {
100
101            let total_duration = dur + self.dt_save;
102
103            let pulsewidth = self.pulsespans.get(total_duration)
104                .unwrap_or(PulseWidth::Invalid);
105
106            let status = match (self.state, pulsewidth) {
107                (Init,              Sync)   => { self.bitbuf = 0; Receiving(0) },
108                (Init,              Repeat) => RepeatDone,
109                (Init,              _)      => Init,
110
111                (Receiving(31),     One)    => { self.bitbuf |= 1 << 31; Done }
112                (Receiving(31),     Zero)   => Done,
113                (Receiving(bit),    One)    => { self.bitbuf |= 1 << bit; Receiving(bit + 1) }
114                (Receiving(bit),    Zero)   => Receiving(bit + 1),
115                (Receiving(_),      _)      => Err(DecodingError::Data),
116
117                (Done,              _)      => Done,
118                (RepeatDone,        _)      => RepeatDone,
119                (Err(err),          _)      => Err(err),
120            };
121
122            trace!(
123                "State(prev, new): ({:?}, {:?}) pulsewidth: {:?}",
124                self.state,
125                status,
126                pulsewidth
127            );
128
129            self.state = status;
130
131            self.dt_save = Mono::ZERO_DURATION;
132        } else {
133            // Save
134            self.dt_save = dur;
135        }
136
137        self.state.into()
138    }
139    fn command(&self) -> Option<Cmd> {
140        match self.state {
141            NecState::Done => Cmd::unpack(self.bitbuf, false),
142            NecState::RepeatDone => Cmd::unpack(self.bitbuf, true),
143            _ => None,
144        }
145    }
146
147    fn reset(&mut self) {
148        self.state = NecState::Init;
149        self.dt_save = Mono::ZERO_DURATION;
150    }
151
152    fn spans(&self) -> &PulseSpans<Mono> {
153        &self.pulsespans
154    }
155}
156
157#[derive(Debug, Copy, Clone)]
158#[cfg_attr(feature = "defmt", derive(defmt::Format))]
159pub enum PulseWidth {
160    Sync = 0,
161    Repeat = 1,
162    Zero = 2,
163    One = 3,
164    Invalid = 4,
165}
166
167impl From<usize> for PulseWidth {
168    fn from(v: usize) -> Self {
169        match v {
170            0 => PulseWidth::Sync,
171            1 => PulseWidth::Repeat,
172            2 => PulseWidth::Zero,
173            3 => PulseWidth::One,
174            _ => PulseWidth::Invalid,
175        }
176    }
177}