1use std::io::Read;
35
36pub struct SpacePacket {
38 pub primary_header: PrimaryHeader,
39 pub payload: Vec<u8>
40}
41
42impl SpacePacket {
43 pub fn new(
44 packet_type: PacketType,
45 secondary_header: bool,
46 apid: u16,
47 sequence_flag: SequenceFlag,
48 sequence_number: u16,
49 payload: Vec<u8>
50 ) -> Self {
51 assert!(payload.len() <= u16::MAX as usize);
52 assert!(apid <= PrimaryHeader::APID_MASK);
53 assert!(sequence_number <= PrimaryHeader::SEQUENCE_NUMBER_MASK);
54
55 let primary_header = PrimaryHeader {
56 version: PrimaryHeader::VERSION,
57 packet_type,
58 secondary_header,
59 apid,
60 sequence_flag,
61 sequence_number,
62 };
63
64 Self { primary_header, payload }
65 }
66
67 pub fn encode(&self) -> Vec<u8> {
69 let mut encoded = self.primary_header.encode();
70 encoded.extend_from_slice(&u16::to_be_bytes((self.payload.len() - 1) as u16));
72 encoded.extend_from_slice(&self.payload);
73 encoded
74
75 }
76
77 pub fn decode<R: Read>(buf: &mut R) -> std::io::Result<Self> {
80 let primary_header = PrimaryHeader::decode(buf)?;
81
82 let mut tmp = [0u8; 2];
83 buf.read_exact(&mut tmp)?;
84 let payload_len = u16::from_be_bytes(tmp) + 1;
86
87 let mut payload = vec![0u8; payload_len as usize];
88 buf.read_exact(&mut payload)?;
89
90 Ok(Self { primary_header, payload })
91 }
92}
93
94
95#[derive(Debug, Clone, Copy, PartialEq, Eq)]
97pub enum PacketType {
98 Telemetry = 0,
99 Telecommand = 1,
100}
101
102impl PacketType {
103 pub fn to_bits(&self) -> u16 {
106 match self {
107 Self::Telemetry => 0b0,
108 Self::Telecommand => 0b1,
109 }
110 }
111
112 pub fn from_bits(bits: u16) -> Self {
115 match bits & 0b1 {
116 0b0 => Self::Telemetry,
117 0b1 => Self::Telecommand,
118 _ => unreachable!()
119 }
120 }
121
122 pub fn is_telecommand(&self) -> bool {
124 matches!(self, Self::Telecommand)
125 }
126
127 pub fn is_telemetry(&self) -> bool {
129 matches!(self, Self::Telemetry)
130 }
131}
132
133#[derive(Debug, Clone, Copy, PartialEq, Eq)]
134pub enum SequenceFlag {
137 Continuation = 0,
138 Start = 1,
139 End = 2,
140 Unsegmented = 3,
141}
142
143impl SequenceFlag {
144 pub fn to_bits(&self) -> u16 {
147 match self {
148 Self::Continuation => 0b00,
149 Self::Start => 0b01,
150 Self::End => 0b10,
151 Self::Unsegmented => 0b11,
152 }
153 }
154
155 pub fn from_bits(bits: u16) -> Self {
158 match bits & 0b11 {
159 0b00 => Self::Continuation,
160 0b01 => Self::Start,
161 0b10 => Self::End,
162 0b11 => Self::Unsegmented,
163 _ => unreachable!()
164 }
165 }
166
167 pub fn is_continuation(&self) -> bool {
169 matches!(self, Self::Continuation)
170 }
171
172 pub fn is_start(&self) -> bool {
174 matches!(self, Self::Start)
175 }
176
177 pub fn is_end(&self) -> bool {
179 matches!(self, Self::End)
180 }
181 pub fn is_unsegmented(&self) -> bool {
183 matches!(self, Self::Unsegmented)
184 }
185}
186
187#[derive(Debug, Clone, Copy, PartialEq, Eq)]
188pub struct PrimaryHeader {
214
215 pub version: u8,
217
218 pub packet_type: PacketType,
220
221 pub secondary_header: bool,
223
224 pub apid: u16,
226
227 pub sequence_flag: SequenceFlag,
229
230 pub sequence_number: u16,
232}
233
234impl PrimaryHeader {
235 const VERSION: u8 = 0b000;
237
238 const VERSION_SHIFT: usize = 13;
241 const PACKET_TYPE_SHIFT: usize = 12;
244 const SECONDARY_HEADER_SHIFT: usize = 11;
247 const APID_SHIFT: usize = 0;
250 const SEQUENCE_FLAG_SHIFT: usize = 14;
253
254 const PACKET_TYPE_MASK: u16 = 0x1000;
256 const SECONDARY_HEADER_MASK: u16 = 0x0800;
258 const APID_MASK: u16 = 0x03FF;
260 const SEQUENCE_FLAG_MASK: u16 = 0xC000;
262 const SEQUENCE_NUMBER_MASK: u16 = 0x3FFF;
264
265 pub fn encode(&self) -> Vec<u8> {
267 let packet_id =
268 u16::from(Self::VERSION) << Self::VERSION_SHIFT |
269 self.packet_type.to_bits() << Self::PACKET_TYPE_SHIFT |
270 u16::from(self.secondary_header) << Self::SECONDARY_HEADER_SHIFT |
271 self.apid & Self::APID_MASK << Self::APID_SHIFT;
272
273 let sequence_ctl =
274 self.sequence_flag.to_bits() << Self::SEQUENCE_FLAG_SHIFT |
275 self.sequence_number & Self::SEQUENCE_NUMBER_MASK;
276
277 let mut encoded = Vec::new();
278 encoded.extend_from_slice(&u16::to_be_bytes(packet_id));
279 encoded.extend_from_slice(&u16::to_be_bytes(sequence_ctl));
280
281 encoded
282 }
283
284 pub fn decode<R: Read>(buf: &mut R) -> std::io::Result<Self> {
287 let mut tmp = [0u8; 4];
288 buf.read_exact(&mut tmp)?;
289
290 let packet_id = u16::from_be_bytes([tmp[0], tmp[1]]);
291 let sequence_ctl = u16::from_be_bytes([tmp[2], tmp[3]]);
292
293 let (version, packet_type, secondary_header, apid) = (
294 (packet_id >> Self::VERSION_SHIFT) as u8,
295 PacketType::from_bits((packet_id & Self::PACKET_TYPE_MASK) >> Self::PACKET_TYPE_SHIFT),
296 packet_id & Self::SECONDARY_HEADER_MASK != 0,
297 packet_id & Self::APID_MASK,
298 );
299
300 let (sequence_flag, sequence_number) = (
301 SequenceFlag::from_bits((sequence_ctl & Self::SEQUENCE_FLAG_MASK) >> Self::SEQUENCE_FLAG_SHIFT),
302 sequence_ctl & Self::SEQUENCE_NUMBER_MASK
303 );
304
305 Ok(Self {version, packet_type, secondary_header, apid, sequence_flag, sequence_number})
306 }
307}
308
309
310
311#[cfg(test)]
312pub mod tests {
313 use super::*;
314 use rstest::rstest;
315
316 #[rstest]
317 fn test_spp_primary_header_codec(
318 #[values(PacketType::Telecommand, PacketType::Telemetry)]
319 packet_type: PacketType,
320 #[values(true, false)]
321 secondary_header: bool,
322 #[values(SequenceFlag::Continuation, SequenceFlag::Start, SequenceFlag::End, SequenceFlag::Unsegmented)]
323 sequence_flag: SequenceFlag,
324 ) {
325 let expected = PrimaryHeader {
326 version: PrimaryHeader::VERSION,
327 packet_type,
328 secondary_header,
329 apid: 0,
330 sequence_flag,
331 sequence_number: 0
332 };
333 let encoded = expected.encode();
334 let found = PrimaryHeader::decode(&mut encoded.as_slice()).unwrap();
335 assert_eq!(expected, found)
336 }
337
338 #[rstest]
339 #[case("Hello, World!".as_bytes().to_vec())]
340 #[case(vec![0])]
341 #[case(vec![0u8; u16::MAX as usize])]
342 fn test_test_spp_packet_codec(
343 #[values(PacketType::Telecommand, PacketType::Telemetry)]
344 packet_type: PacketType,
345 #[values(true, false)]
346 secondary_header: bool,
347 #[values(SequenceFlag::Continuation, SequenceFlag::Start, SequenceFlag::End, SequenceFlag::Unsegmented)]
348 sequence_flag: SequenceFlag,
349 #[case] payload: Vec<u8>,
350 ) {
351 let expected = SpacePacket::new(packet_type, secondary_header, 0, sequence_flag, 0, payload);
352 let encoded = expected.encode();
353 let found = SpacePacket::decode(&mut encoded.as_slice()).unwrap();
354 assert_eq!(expected.primary_header, found.primary_header);
355 assert_eq!(expected.payload, found.payload)
356 }
357}
358
359
360