infrared_rs/
scanner.rs

1use std::time::Duration;
2
3use rppal::gpio::Level;
4
5use crate::{errors::Result, hardware::HardwareInput};
6
7pub struct Scanner {
8    input: HardwareInput,
9}
10
11struct Pulse {
12    value: Level,
13    length: u128,
14}
15
16impl Scanner {
17    pub fn new(input: HardwareInput) -> Self {
18        Self { input }
19    }
20
21    pub fn scan_blocking(&self) -> Result<u64> {
22        let mut command: Vec<Pulse> = Vec::with_capacity(80);
23        let mut count1 = 0u32;
24        let mut previous = Level::Low;
25        let mut value = self.input.read_value()?;
26
27        while self.input.read_value()? == Level::High {
28            spin_sleep::sleep(Duration::from_micros(100))
29        }
30
31        let mut start_time = std::time::Instant::now();
32
33        loop {
34            spin_sleep::sleep(Duration::from_nanos(50));
35
36            if value != previous {
37                let pulse_length = start_time.elapsed();
38                start_time = std::time::Instant::now();
39
40                command.push(Pulse {
41                    value: previous,
42                    length: pulse_length.as_micros(),
43                });
44            }
45
46            if value == Level::High {
47                count1 += 1;
48            }
49
50            previous = value;
51            value = self.input.read_value()?;
52
53            if count1 > 10000 {
54                break;
55            }
56        }
57
58        let mut binary = 0u64;
59        let mut bin_length = 0u8;
60
61        for item in command {
62            if item.value == Level::Low {
63                continue;
64            }
65            if item.length > 1000 {
66                binary = binary << 2 | 1;
67                bin_length += 1;
68            } else {
69                binary <<= 1;
70                bin_length += 1;
71            }
72
73            if bin_length > 34 {
74                break;
75            }
76        }
77
78        Ok(binary)
79    }
80}