Skip to content

Commit 7de0fa7

Browse files
Ilya Gutermanamfern
Ilya Guterman
authored andcommitted
support msp version 2
1 parent 6ae507d commit 7de0fa7

File tree

3 files changed

+129
-19
lines changed

3 files changed

+129
-19
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ packed_struct = "0.2"
1212
packed_struct_codegen = "0.2"
1313
serde = "1.0"
1414
serde_derive = "1.0"
15+
crc-any = "2.3.0"
1516

1617
[features]
1718
default = ["std"]

src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ extern crate alloc;
1212

1313
extern crate packed_struct;
1414

15+
extern crate crc_any;
16+
1517
#[macro_use]
1618
extern crate packed_struct_codegen;
1719

src/packet.rs

+126-19
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use prelude::v1::*;
2+
use crc_any::CRCu8;
3+
24

35
/// Packet parsing error
46
#[derive(Copy, Clone, Debug, PartialEq)]
@@ -38,7 +40,7 @@ impl MspPacketDirection {
3840
#[derive(Debug, Clone, PartialEq)]
3941
/// A decoded MSP packet, with a command code, direction and payload
4042
pub struct MspPacket<'a> {
41-
pub cmd: u8,
43+
pub cmd: u16,
4244
pub direction: MspPacketDirection,
4345
pub data: Cow<'a, [u8]>
4446
}
@@ -48,33 +50,48 @@ enum MspParserState {
4850
Header1,
4951
Header2,
5052
Direction,
53+
FlagV2,
5154
DataLength,
55+
DataLengthV2,
5256
Command,
57+
CommandV2,
5358
Data,
54-
Crc
59+
DataV2,
60+
Crc,
61+
CrcV2,
62+
}
63+
64+
#[derive(Copy, Clone, PartialEq, Debug)]
65+
enum MSPVersion {
66+
V1,
67+
V2,
5568
}
5669

5770
#[derive(Debug)]
5871
/// Parser that can find packets from a raw byte stream
5972
pub struct MspParser {
6073
state: MspParserState,
74+
packet_version: MSPVersion,
6175
packet_direction: MspPacketDirection,
62-
packet_cmd: u8,
63-
packet_data_length_remaining: usize,
76+
packet_cmd: u16,
77+
packet_data_length_remaining: u16,
6478
packet_data: Vec<u8>,
65-
packet_crc: u8
79+
packet_crc: u8,
80+
packet_crc_v2: CRCu8,
6681
}
6782

6883
impl MspParser {
6984
/// Create a new parser
7085
pub fn new() -> MspParser {
71-
MspParser {
86+
Self {
7287
state: MspParserState::Header1,
88+
packet_version: MSPVersion::V1,
7389
packet_direction: MspPacketDirection::ToFlightController,
7490
packet_data_length_remaining: 0,
7591
packet_cmd: 0,
7692
packet_data: Vec::new(),
77-
packet_crc: 0
93+
packet_crc: 0,
94+
packet_crc_v2: CRCu8::crc8dvb_s2(),
7895
}
7996
}
8097

@@ -96,11 +113,16 @@ impl MspParser {
96113
},
97114

98115
MspParserState::Header2 => {
99-
if input == ('M' as u8) {
100-
self.state = MspParserState::Direction;
101-
} else {
102-
self.reset();
103-
}
116+
self.packet_version = match input as char {
117+
'M' => MSPVersion::V1,
118+
'X' => MSPVersion::V2,
119+
_=> {
120+
self.reset();
121+
return Ok(None);
122+
},
123+
};
124+
125+
self.state = MspParserState::Direction;
104126
},
105127

106128
MspParserState::Direction => {
@@ -114,20 +136,71 @@ impl MspParser {
114136
}
115137
}
116138

117-
self.state = MspParserState::DataLength;
139+
self.state = match self.packet_version {
140+
MSPVersion::V1 => MspParserState::DataLength,
141+
MSPVersion::V2 => MspParserState::FlagV2,
142+
};
118143
},
119144

120-
MspParserState::DataLength => {
145+
MspParserState::FlagV2 => {
146+
// uint8, flag, usage to be defined (set to zero)
147+
self.state = MspParserState::CommandV2;
148+
self.packet_data = Vec::with_capacity(2);
149+
self.packet_crc_v2.digest(&[input]);
150+
},
151+
152+
MspParserState::CommandV2 => {
153+
self.packet_data.push(input);
154+
155+
if self.packet_data.len() == 2 {
156+
let mut s = [0; 2];
157+
s.copy_from_slice(&self.packet_data);
158+
self.packet_cmd = u16::from_le_bytes(s);
159+
160+
self.packet_data.clear();
161+
self.state = MspParserState::DataLengthV2;
162+
}
163+
164+
self.packet_crc_v2.digest(&[input]);
165+
},
166+
167+
MspParserState::DataLengthV2 => {
168+
self.packet_data.push(input);
121169

122-
self.packet_data_length_remaining = input as usize;
170+
if self.packet_data.len() == 2 {
171+
let mut s = [0; 2];
172+
s.copy_from_slice(&self.packet_data);
173+
self.packet_data_length_remaining = u16::from_le_bytes(s);
174+
self.packet_data = Vec::with_capacity(self.packet_data_length_remaining as usize);
175+
176+
self.state = MspParserState::DataV2;
177+
}
178+
179+
self.packet_crc_v2.digest(&[input]);
180+
},
181+
182+
MspParserState::DataV2 => {
183+
self.packet_data.push(input);
184+
self.packet_data_length_remaining -= 1;
185+
186+
187+
if self.packet_data_length_remaining == 0 {
188+
self.state = MspParserState::CrcV2;
189+
}
190+
191+
self.packet_crc_v2.digest(&[input]);
192+
},
193+
194+
MspParserState::DataLength => {
195+
self.packet_data_length_remaining = input as u16;
123196
self.state = MspParserState::Command;
124197
self.packet_crc ^= input;
125198
self.packet_data = Vec::with_capacity(input as usize);
126199
},
127200

128201
MspParserState::Command => {
129202

130-
self.packet_cmd = input;
203+
self.packet_cmd = input as u16;
131204

132205
if self.packet_data_length_remaining == 0 {
133206
self.state = MspParserState::Crc;
@@ -152,8 +225,12 @@ impl MspParser {
152225

153226
},
154227

155-
MspParserState::Crc => {
228+
MspParserState::CrcV2 => {
229+
self.packet_crc = self.packet_crc_v2.get_crc();
230+
self.state = MspParserState::Crc;
231+
},
156232

233+
MspParserState::Crc => {
157234
let packet_crc = self.packet_crc;
158235
if input != packet_crc {
159236
self.reset();
@@ -186,6 +263,7 @@ impl MspParser {
186263
self.packet_cmd = 0;
187264
self.packet_data.clear();
188265
self.packet_crc = 0;
266+
self.packet_crc_v2.reset();
189267
}
190268
}
191269

@@ -195,6 +273,11 @@ impl<'a> MspPacket<'a> {
195273
6 + self.data.len()
196274
}
197275

276+
/// Number of bytes that this packet requires to be packed
277+
pub fn packet_size_bytes_v2(&self) -> usize {
278+
9 + self.data.len()
279+
}
280+
198281
/// Serialize to network bytes
199282
pub fn serialize(&self, output: &mut [u8]) -> Result<(), MspPacketParseError> {
200283
let l = output.len();
@@ -207,7 +290,7 @@ impl<'a> MspPacket<'a> {
207290
output[1] = 'M' as u8;
208291
output[2] = self.direction.to_byte();
209292
output[3] = self.data.len() as u8;
210-
output[4] = self.cmd;
293+
output[4] = self.cmd as u8;
211294

212295

213296
output[5..l - 1].copy_from_slice(&self.data);
@@ -220,6 +303,30 @@ impl<'a> MspPacket<'a> {
220303

221304
Ok(())
222305
}
306+
307+
/// Serialize to network bytes
308+
pub fn serialize_v2(&self, output: &mut [u8]) -> Result<(), MspPacketParseError> {
309+
let l = output.len();
310+
311+
if l != self.packet_size_bytes_v2() {
312+
return Err(MspPacketParseError::OutputBufferSizeMismatch);
313+
}
314+
315+
output[0] = '$' as u8;
316+
output[1] = 'X' as u8;
317+
output[2] = self.direction.to_byte();
318+
output[3] = 0;
319+
output[4..6].copy_from_slice(&self.cmd.to_le_bytes());
320+
output[6..8].copy_from_slice(&(self.data.len() as u16).to_le_bytes());
321+
322+
output[8..l - 1].copy_from_slice(&self.data);
323+
324+
let mut crc = CRCu8::crc8dvb_s2();
325+
crc.digest(&output[3..l - 1]);
326+
output[l - 1] = CRCu8::crc8dvb_s2().get_crc();
327+
328+
Ok(())
329+
}
223330
}
224331

225332

@@ -301,4 +408,4 @@ fn test_roundtrip() {
301408
};
302409
roundtrip(&packet);
303410
}
304-
}
411+
}

0 commit comments

Comments
 (0)