Skip to content

Commit b6b357e

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

File tree

3 files changed

+127
-19
lines changed

3 files changed

+127
-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"
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

+124-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,
75+
packet_cmd: u16,
6376
packet_data_length_remaining: usize,
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,29 +112,84 @@ 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 => {
107128
match input {
108-
60 => self.packet_direction = MspPacketDirection::ToFlightController,
109-
62 => self.packet_direction = MspPacketDirection::FromFlightController,
110-
33 => self.packet_direction = MspPacketDirection::Unsupported,
129+
60 => self.packet_direction = MspPacketDirection::ToFlightController, // '>'
130+
62 => self.packet_direction = MspPacketDirection::FromFlightController, // '<'
131+
33 => self.packet_direction = MspPacketDirection::Unsupported, // '!' error
111132
_ => {
112133
self.reset();
113134
return Ok(None);
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; 8];
170+
s[5..7].copy_from_slice(&self.packet_data);
171+
self.packet_data_length_remaining = usize::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+
if (self.packet_data_length_remaining == 0) {
176+
self.state = MspParserState::Crc;
177+
} else {
178+
self.state = MspParserState::DataV2;
179+
}
180+
}
181+
},
182+
183+
MspParserState::DataV2 => {
184+
self.packet_data.push(input);
185+
self.packet_data_length_remaining -= 1;
186+
187+
if self.packet_data_length_remaining == 0 {
188+
self.state = MspParserState::Crc;
189+
}
190+
},
121191

192+
MspParserState::DataLength => {
122193
self.packet_data_length_remaining = input as usize;
123194
self.state = MspParserState::Command;
124195
self.packet_crc ^= input;
@@ -127,7 +198,7 @@ impl MspParser {
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,6 +224,10 @@ impl MspParser {
153224
},
154225

155226
MspParserState::Crc => {
227+
if self.packet_version == MSPVersion::V2 {
228+
self.packet_crc_v2.digest(&self.packet_data);
229+
self.packet_crc = self.packet_crc_v2.get_crc();
230+
}
156231

157232
let packet_crc = self.packet_crc;
158233
if input != packet_crc {
@@ -186,6 +261,7 @@ impl MspParser {
186261
self.packet_cmd = 0;
187262
self.packet_data.clear();
188263
self.packet_crc = 0;
264+
self.packet_crc_v2.reset();
189265
}
190266
}
191267

@@ -195,6 +271,11 @@ impl<'a> MspPacket<'a> {
195271
6 + self.data.len()
196272
}
197273

274+
/// Number of bytes that this packet requires to be packed
275+
pub fn packet_size_bytes_v2(&self) -> usize {
276+
9 + self.data.len()
277+
}
278+
198279
/// Serialize to network bytes
199280
pub fn serialize(&self, output: &mut [u8]) -> Result<(), MspPacketParseError> {
200281
let l = output.len();
@@ -207,7 +288,7 @@ impl<'a> MspPacket<'a> {
207288
output[1] = 'M' as u8;
208289
output[2] = self.direction.to_byte();
209290
output[3] = self.data.len() as u8;
210-
output[4] = self.cmd;
291+
output[4] = self.cmd as u8;
211292

212293

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

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

225330

@@ -301,4 +406,4 @@ fn test_roundtrip() {
301406
};
302407
roundtrip(&packet);
303408
}
304-
}
409+
}

0 commit comments

Comments
 (0)