ir_remote/ir_signal/
decode.rs1use std::time::Duration;
2
3use bitvec::bitarr;
4use bitvec::prelude::*;
5
6use crate::are_all_equal::AreAllEqual;
7use crate::is_around::IsAround;
8
9use super::{
10 Event, IrPacket, IrSignal, RemoteType, Repeat, FIRST_LOW_DURATION, HIGH_DURATION,
11 LOW_0_DURATION, LOW_1_DURATION,
12};
13
14#[derive(Debug)]
15pub enum DecodeError {
16 FirstHighMissing,
17 LengthBad,
18 FirstHighBad,
19 FirstLowBad,
20 HighNotHigh,
21 HighBad(Duration),
22 LowNotLow,
23 LowBad(Duration),
24 IdBad,
25 LastByteBad,
26 SpaceNotLow,
27 MultipleDifferentPackets(Vec<IrPacket>),
28}
29
30impl IrSignal {
31 pub fn decode<'a, T: Iterator<Item = &'a Event>>(mut events: T) -> Result<Self, DecodeError> {
32 let acceptable_error: f64 = 0.2;
33
34 let decode_packet = |events: &mut T| {
35 let signal_type = {
37 let first_high = events.next().ok_or(DecodeError::FirstHighMissing)?;
38 if !first_high.is_on {
39 return Err(DecodeError::FirstHighBad);
40 }
41
42 RemoteType::decode_first_high(first_high.duration).ok_or(DecodeError::FirstHighBad)
43 }?;
44 {
45 let first_low = events.next().ok_or(DecodeError::LengthBad)?;
46 if first_low.is_on {
47 return Err(DecodeError::FirstLowBad);
48 }
49 if !first_low.duration.is_around(
50 Duration::from_secs_f64(FIRST_LOW_DURATION),
51 acceptable_error,
52 ) {
53 return Err(DecodeError::FirstLowBad);
54 }
55 }
56
57 let consume_high = |events: &mut T| -> Result<(), DecodeError> {
58 let high = events.next().ok_or(DecodeError::LengthBad)?;
59 if !high.is_on {
60 return Err(DecodeError::HighNotHigh);
61 }
62 if !high
63 .duration
64 .is_around(Duration::from_secs_f64(HIGH_DURATION), acceptable_error)
65 {
66 return Err(DecodeError::HighBad(high.duration));
67 }
68 Ok(())
69 };
70 let mut bits = bitarr!(u32, Msb0; 0; 32);
72 for i in 0..bits.len() {
73 consume_high(events)?;
74 {
75 let low = events.next().ok_or(DecodeError::LengthBad)?;
76 if low.is_on {
77 return Err(DecodeError::LowNotLow);
78 }
79 let bit = match low.duration {
80 duration
81 if duration.is_around(
82 Duration::from_secs_f64(LOW_0_DURATION),
83 acceptable_error,
84 ) =>
85 {
86 Some(false)
87 }
88 duration
89 if duration.is_around(
90 Duration::from_secs_f64(LOW_1_DURATION),
91 acceptable_error,
92 ) =>
93 {
94 Some(true)
95 }
96 _ => None,
97 };
98 bits.set(i, bit.ok_or(DecodeError::LowBad(low.duration))?);
99 }
100 }
101 consume_high(events)?;
103
104 if bits[24..32] != !bits[16..24].to_owned() {
106 return Err(DecodeError::LastByteBad);
107 }
108
109 Ok(IrPacket {
110 remote_type: signal_type,
111 receiver_id: bits[..16].load(),
112 button: bits[16..24].load(),
113 })
114 };
115 let mut packets = vec![decode_packet(&mut events)?];
116 let mut spaces = vec![];
117 loop {
118 match events.next() {
119 Some(event) => {
120 if event.is_on {
121 println!("{:#?}", event);
122 break Err(DecodeError::SpaceNotLow);
123 }
124 spaces.push(event.duration);
125 packets.push(decode_packet(&mut events)?);
126 }
127 None => {
128 if !packets.are_all_equal() {
129 break Err(DecodeError::MultipleDifferentPackets(packets));
130 }
131 break Ok(Self {
134 packet: packets[0],
135 repeat: match spaces.len() {
136 0 => None,
137 1.. => Some(Repeat {
138 times: packets.len(),
139 duration_between: spaces[0],
141 }),
142 },
143 });
144 }
145 };
146 }
147 }
148}