1pub struct IbusParser {
10 buffer: [u8; 32],
11 index: usize,
12 state: IbusState,
13}
14
15enum IbusState {
16 Sync,
17 Data,
18}
19
20impl IbusParser {
21 pub fn new() -> Self {
22 Self {
23 buffer: [0; 32],
24 index: 0,
25 state: IbusState::Sync,
26 }
27 }
28
29 pub fn parse_byte(&mut self, byte: u8) -> Option<IbusMessage> {
30 match self.state {
31 IbusState::Sync => {
32 if byte == 0x20 {
33 self.buffer[0] = byte;
34 self.index = 1;
35 self.state = IbusState::Data;
36 }
37 }
38 IbusState::Data => {
39 self.buffer[self.index] = byte;
40 self.index += 1;
41
42 if self.index == 32 {
43 let mut checksum: u16 = 0xffff;
44 for byte in &self.buffer[0..30] {
45 checksum -= *byte as u16;
46 }
47
48 if checksum == ((self.buffer[31] as u16) << 8) | (self.buffer[30] as u16) {
49 let message = IbusMessage::from_buffer(&self.buffer);
50 self.state = IbusState::Sync;
51 return Some(message);
52 } else {
53 self.state = IbusState::Sync;
54 }
55 }
56 }
57 }
58
59 None
60 }
61}
62
63#[derive(Debug)]
64pub struct IbusMessage {
65 pub channels: [u16; 14],
66}
67
68impl IbusMessage {
69 pub fn from_buffer(buffer: &[u8]) -> Self {
70 let mut channels = [0; 14];
71 for ch in 0..14 {
72 channels[ch] =
73 ((buffer[2 * (ch + 1) + 1] as u16) << 8) | buffer[2 * (ch + 1) + 0] as u16;
74 }
75 Self { channels }
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn parse_message() {
85 let stream: [u8; 32] = [
86 0x20, 0x40, 0xDB, 0x5, 0xDC, 0x5, 0x54, 0x5, 0xDC, 0x5, 0xE8, 0x3, 0xD0, 0x7, 0xD2,
87 0x5, 0xE8, 0x3, 0xDC, 0x5, 0xDC, 0x5, 0xDC, 0x5, 0xDC, 0x5, 0xDC, 0x5, 0xDC, 0x5, 0xDA,
88 0xF3,
89 ];
90 let ref_msg: [u16; 14] = [
91 1499, 1500, 1364, 1500, 1000, 2000, 1490, 1000, 1500, 1500, 1500, 1500, 1500, 1500,
92 ];
93
94 let mut ibus = IbusParser::new();
95 for byte in stream {
96 if let Some(message) = ibus.parse_byte(byte) {
97 let channels = message.channels;
98 for i in 0..14 {
99 assert_eq!(channels[i], ref_msg[i]);
100 }
101 }
102 }
103 }
104}