1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use crate::{
protocol::{rc5::Rc5Command, Rc5},
receiver::{
time::{InfraMonotonic, PulseSpans},
DecoderFactory, DecodingError, ProtocolDecoder, State,
},
};
const RC5_BASE_TIME: u32 = 889;
const PULSE: [u32; 8] = [RC5_BASE_TIME, 2 * RC5_BASE_TIME, 0, 0, 0, 0, 0, 0];
const TOL: [u32; 8] = [12, 10, 0, 0, 0, 0, 0, 0];
impl<Mono: InfraMonotonic> DecoderFactory<Mono> for Rc5 {
type Decoder = Rc5Decoder<Mono>;
fn decoder(freq: u32) -> Self::Decoder {
Rc5Decoder {
state: Rc5State::Idle,
bitbuf: 0,
clock: 0,
spans: PulseSpans::new(freq, &PULSE, &TOL),
}
}
}
impl<Mono: InfraMonotonic> ProtocolDecoder<Mono, Rc5Command> for Rc5Decoder<Mono> {
fn event(&mut self, rising: bool, delta_t: Mono::Duration) -> State {
use Rc5State::*;
let clock_ticks = self.spans.get::<usize>(delta_t);
if let Some(ticks) = clock_ticks {
self.clock += ticks + 1;
} else {
self.reset();
}
let is_odd = self.clock & 1 == 0;
self.state = match (self.state, rising, clock_ticks) {
(Idle, false, _) => Idle,
(Idle, true, _) => {
self.clock = 0;
self.bitbuf |= 1 << 13;
Data(12)
}
(Data(0), true, Some(_)) if is_odd => {
self.bitbuf |= 1;
Done
}
(Data(0), false, Some(_)) if is_odd => Done,
(Data(bit), true, Some(_)) if is_odd => {
self.bitbuf |= 1 << bit;
Data(bit - 1)
}
(Data(bit), false, Some(_)) if is_odd => Data(bit - 1),
(Data(bit), _, Some(_)) => Data(bit),
(Data(_), _, None) => Err(DecodingError::Data),
(Done, _, _) => Done,
(Err(err), _, _) => Err(err),
};
self.state.into()
}
fn command(&self) -> Option<Rc5Command> {
Some(Rc5Command::unpack(self.bitbuf))
}
fn reset(&mut self) {
self.state = Rc5State::Idle;
self.bitbuf = 0;
self.clock = 0;
}
fn spans(&self) -> &PulseSpans<Mono> {
&self.spans
}
}
pub struct Rc5Decoder<Mono: InfraMonotonic> {
pub(crate) state: Rc5State,
bitbuf: u16,
pub(crate) clock: usize,
spans: PulseSpans<Mono>,
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Rc5State {
Idle,
Data(u8),
Done,
Err(DecodingError),
}
impl Default for Rc5State {
fn default() -> Self {
Rc5State::Idle
}
}
impl From<Rc5State> for State {
fn from(rs: Rc5State) -> Self {
match rs {
Rc5State::Idle => State::Idle,
Rc5State::Data(_) => State::Receiving,
Rc5State::Done => State::Done,
Rc5State::Err(e) => State::Error(e),
}
}
}