Skip to content

Commit 7df9f03

Browse files
committed
support msp version 2
1 parent 6ae507d commit 7df9f03

File tree

3 files changed

+122
-19
lines changed

3 files changed

+122
-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

+119-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,47 @@ 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+
}
62+
63+
#[derive(Copy, Clone, PartialEq, Debug)]
64+
enum MSPVersion {
65+
V1,
66+
V2,
5567
}
5668

5769
#[derive(Debug)]
5870
/// Parser that can find packets from a raw byte stream
5971
pub struct MspParser {
6072
state: MspParserState,
73+
packet_version: MSPVersion,
6174
packet_direction: MspPacketDirection,
62-
packet_cmd: u8,
63-
packet_data_length_remaining: usize,
75+
packet_cmd: u16,
76+
packet_data_length_remaining: u16,
6477
packet_data: Vec<u8>,
65-
packet_crc: u8
78+
packet_crc: u8,
79+
packet_crc_v2: CRCu8,
6680
}
6781

6882
impl MspParser {
6983
/// Create a new parser
7084
pub fn new() -> MspParser {
71-
MspParser {
85+
Self {
7286
state: MspParserState::Header1,
87+
packet_version: MSPVersion::V1,
7388
packet_direction: MspPacketDirection::ToFlightController,
7489
packet_data_length_remaining: 0,
7590
packet_cmd: 0,
7691
packet_data: Vec::new(),
77-
packet_crc: 0
92+
packet_crc: 0,
93+
packet_crc_v2: CRCu8::crc8dvb_s2(),
7894
}
7995
}
8096

@@ -96,11 +112,16 @@ impl MspParser {
96112
},
97113

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

106127
MspParserState::Direction => {
@@ -114,20 +135,70 @@ impl MspParser {
114135
}
115136
}
116137

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

120-
MspParserState::DataLength => {
144+
MspParserState::FlagV2 => {
145+
// uint8, flag, usage to be defined (set to zero)
146+
self.state = MspParserState::CommandV2;
147+
self.packet_data = Vec::with_capacity(2);
148+
self.packet_crc_v2.digest(&[input]);
149+
},
150+
151+
MspParserState::CommandV2 => {
152+
self.packet_data.push(input);
153+
154+
if self.packet_data.len() == 2 {
155+
let mut s = [0; 2];
156+
s.copy_from_slice(&self.packet_data);
157+
self.packet_cmd = u16::from_le_bytes(s);
158+
159+
self.packet_crc_v2.digest(&self.packet_data);
160+
self.packet_data.clear();
161+
self.state = MspParserState::DataLengthV2;
162+
}
163+
},
164+
165+
MspParserState::DataLengthV2 => {
166+
self.packet_data.push(input);
167+
168+
if self.packet_data.len() == 2 {
169+
let mut s = [0; 2];
170+
s.copy_from_slice(&self.packet_data);
171+
self.packet_data_length_remaining = u16::from_le_bytes(s);
172+
self.packet_crc_v2.digest(&self.packet_data);
173+
self.packet_data = Vec::with_capacity(self.packet_data_length_remaining as usize);
174+
175+
self.state = MspParserState::DataV2;
176+
}
177+
},
178+
179+
MspParserState::DataV2 => {
180+
self.packet_data.push(input);
181+
self.packet_data_length_remaining -= 1;
182+
183+
if self.packet_data_length_remaining == 0 {
184+
self.state = MspParserState::Crc;
185+
186+
187+
self.packet_crc_v2.digest(&self.packet_data);
188+
self.packet_crc = self.packet_crc_v2.get_crc();
189+
}
190+
},
121191

122-
self.packet_data_length_remaining = input as usize;
192+
MspParserState::DataLength => {
193+
self.packet_data_length_remaining = input as u16;
123194
self.state = MspParserState::Command;
124195
self.packet_crc ^= input;
125196
self.packet_data = Vec::with_capacity(input as usize);
126197
},
127198

128199
MspParserState::Command => {
129200

130-
self.packet_cmd = input;
201+
self.packet_cmd = input as u16;
131202

132203
if self.packet_data_length_remaining == 0 {
133204
self.state = MspParserState::Crc;
@@ -153,7 +224,6 @@ impl MspParser {
153224
},
154225

155226
MspParserState::Crc => {
156-
157227
let packet_crc = self.packet_crc;
158228
if input != packet_crc {
159229
self.reset();
@@ -186,6 +256,7 @@ impl MspParser {
186256
self.packet_cmd = 0;
187257
self.packet_data.clear();
188258
self.packet_crc = 0;
259+
self.packet_crc_v2.reset();
189260
}
190261
}
191262

@@ -195,6 +266,11 @@ impl<'a> MspPacket<'a> {
195266
6 + self.data.len()
196267
}
197268

269+
/// Number of bytes that this packet requires to be packed
270+
pub fn packet_size_bytes_v2(&self) -> usize {
271+
9 + self.data.len()
272+
}
273+
198274
/// Serialize to network bytes
199275
pub fn serialize(&self, output: &mut [u8]) -> Result<(), MspPacketParseError> {
200276
let l = output.len();
@@ -207,7 +283,7 @@ impl<'a> MspPacket<'a> {
207283
output[1] = 'M' as u8;
208284
output[2] = self.direction.to_byte();
209285
output[3] = self.data.len() as u8;
210-
output[4] = self.cmd;
286+
output[4] = self.cmd as u8;
211287

212288

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

221297
Ok(())
222298
}
299+
300+
/// Serialize to network bytes
301+
pub fn serialize_v2(&self, output: &mut [u8]) -> Result<(), MspPacketParseError> {
302+
let l = output.len();
303+
304+
if l != self.packet_size_bytes_v2() {
305+
return Err(MspPacketParseError::OutputBufferSizeMismatch);
306+
}
307+
308+
output[0] = '$' as u8;
309+
output[1] = 'X' as u8;
310+
output[2] = self.direction.to_byte();
311+
output[3] = 0;
312+
output[4..6].copy_from_slice(&self.cmd.to_le_bytes());
313+
output[6..8].copy_from_slice(&(self.data.len() as u16).to_le_bytes());
314+
315+
output[8..l - 1].copy_from_slice(&self.data);
316+
317+
let mut crc = CRCu8::crc8dvb_s2();
318+
crc.digest(&output[3..l - 1]);
319+
output[l - 1] = crc.get_crc();
320+
321+
Ok(())
322+
}
223323
}
224324

225325

@@ -301,4 +401,4 @@ fn test_roundtrip() {
301401
};
302402
roundtrip(&packet);
303403
}
304-
}
404+
}

0 commit comments

Comments
 (0)