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
117
118
119
120
121
use core::ops::Range;
use crate::{
protocols::rc5::Rc5Command,
recv::{Error, ReceiverSM, State},
};
#[derive(Default)]
pub struct Rc5 {
pub(crate) state: Rc5State,
bitbuf: u16,
pub(crate) rc5cntr: u32,
}
impl Rc5 {
pub fn interval_to_units(&self, interval: u32) -> Option<u32> {
for i in 1..=2 {
if rc5_multiplier(i).contains(&interval) {
return Some(i);
}
}
None
}
}
#[derive(Clone, Copy, Debug)]
pub enum Rc5State {
Idle,
Data(u8),
Done,
Err(Error),
}
impl Default for Rc5State {
fn default() -> Self {
Rc5State::Idle
}
}
impl From<Rc5State> for State {
fn from(rs: Rc5State) -> Self {
use Rc5State::*;
match rs {
Idle => State::Idle,
Data(_) => State::Receiving,
Done => State::Done,
Err(e) => State::Error(e),
}
}
}
impl ReceiverSM for Rc5 {
type Cmd = Rc5Command;
type InternalState = Rc5State;
fn create() -> Self {
Rc5::default()
}
#[rustfmt::skip]
fn event(&mut self, rising: bool, dt: u32) -> Self::InternalState {
use Rc5State::*;
let rc5units = self.interval_to_units(dt);
if let Some(units) = rc5units {
self.rc5cntr += units;
} else {
self.reset();
}
let is_odd = self.rc5cntr & 1 == 0;
self.state = match (self.state, rising, rc5units) {
(Idle, false, _) => Idle,
(Idle, true, _) => {
self.rc5cntr = 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(Error::Data),
(Done, _, _) => Done,
(Err(err), _, _) => Err(err),
};
self.state
}
fn command(&self) -> Option<Self::Cmd> {
Some(Rc5Command::from_bits(self.bitbuf))
}
fn reset(&mut self) {
self.state = Rc5State::Idle;
self.bitbuf = 0;
self.rc5cntr = 0;
}
}
const fn rc5_multiplier(multiplier: u32) -> Range<u32> {
let base = 889 * multiplier;
range(base, 10)
}
const fn range(len: u32, percent: u32) -> Range<u32> {
let tol = (len * percent) / 100;
Range {
start: len - tol - 2,
end: len + tol + 2,
}
}