omnitiles/protocol/
parser.rs1use crate::protocol::messages::*;
10
11const MAX_PAYLOAD: usize = 3;
13
14enum State {
15 WaitStart,
16 WaitId,
17 WaitPayload {
18 id: u8,
19 buf: [u8; MAX_PAYLOAD],
20 received: u8,
21 expected: u8,
22 },
23 WaitChecksum {
24 id: u8,
25 buf: [u8; MAX_PAYLOAD],
26 len: u8,
27 },
28}
29
30pub struct Parser {
31 state: State,
32 checksum: u8,
33}
34
35fn payload_len(id: u8) -> Option<u8> {
36 match id {
37 MSG_M1_EXTEND | MSG_M1_RETRACT | MSG_M1_SET_POSITION | MSG_M2_EXTEND | MSG_M2_RETRACT
38 | MSG_M2_SET_POSITION => Some(1),
39 MSG_M1_BRAKE | MSG_M2_BRAKE | MSG_PING | MSG_BASE_BRAKE => Some(0),
40 MSG_BASE_VELOCITY => Some(3),
41 _ => None,
42 }
43}
44
45impl Parser {
46 pub fn new() -> Self {
47 Self {
48 state: State::WaitStart,
49 checksum: 0,
50 }
51 }
52
53 pub fn push(&mut self, byte: u8) -> Option<Command> {
55 match self.state {
56 State::WaitStart => {
57 if byte == START_BYTE {
58 self.state = State::WaitId;
59 self.checksum = 0;
60 }
61 }
62 State::WaitId => {
63 self.checksum = self.checksum.wrapping_add(byte);
64
65 match payload_len(byte) {
66 Some(0) => {
67 self.state = State::WaitChecksum {
68 id: byte,
69 buf: [0; MAX_PAYLOAD],
70 len: 0,
71 };
72 }
73 Some(n) => {
74 self.state = State::WaitPayload {
75 id: byte,
76 buf: [0; MAX_PAYLOAD],
77 received: 0,
78 expected: n,
79 };
80 }
81 None => {
82 self.state = State::WaitStart;
83 }
84 }
85 }
86 State::WaitPayload {
87 id,
88 mut buf,
89 received,
90 expected,
91 } => {
92 self.checksum = self.checksum.wrapping_add(byte);
93 buf[received as usize] = byte;
94 let received = received + 1;
95
96 if received >= expected {
97 self.state = State::WaitChecksum {
98 id,
99 buf,
100 len: received,
101 };
102 } else {
103 self.state = State::WaitPayload {
104 id,
105 buf,
106 received,
107 expected,
108 };
109 }
110 }
111 State::WaitChecksum { id, buf, len } => {
112 let valid = byte == self.checksum;
113 self.state = State::WaitStart;
114
115 if valid {
116 return match id {
117 MSG_M1_EXTEND => Some(Command::M1Extend(buf[0])),
118 MSG_M1_RETRACT => Some(Command::M1Retract(buf[0])),
119 MSG_M1_BRAKE => Some(Command::M1Brake),
120 MSG_M1_SET_POSITION => Some(Command::M1SetPosition(buf[0])),
121 MSG_M2_EXTEND => Some(Command::M2Extend(buf[0])),
122 MSG_M2_RETRACT => Some(Command::M2Retract(buf[0])),
123 MSG_M2_BRAKE => Some(Command::M2Brake),
124 MSG_M2_SET_POSITION => Some(Command::M2SetPosition(buf[0])),
125 MSG_PING => Some(Command::Ping),
126 MSG_BASE_VELOCITY if len >= 3 => Some(Command::BaseVelocity {
127 vx: buf[0] as i8,
128 vy: buf[1] as i8,
129 omega: buf[2] as i8,
130 }),
131 MSG_BASE_BRAKE => Some(Command::BaseBrake),
132 _ => None,
133 };
134 }
135 }
136 }
137 None
138 }
139}