cfdp_simplified/ccsds/
mod.rs1use ::tracing::warn;
2use anyhow::Result;
3use bit_struct::*;
4
5pub mod constants {
6 use bit_struct::u3;
7
8 pub const CCSDS_HEADER_LENGTH: usize = 6;
9 pub const CCSDS_SECONDARY_HEADER_LENGTH: usize = 6;
10 pub const CCSDS_VERSION: u3 = u3!(0);
11 pub const OUTGOING_CCSDS_APID_ENV_VAR: &str = "CCSDS_APID_TX";
12}
13pub use constants::*;
14
15enums! {
16 pub PacketType {Telemetry, Telecommand}
17 pub SecondaryHeaderFlag {NoSecondaryHeader, SecondaryHeader}
18}
19
20pub fn encode_space_packet(data: &[u8], apid: u11, secondary_hdr_flag: u8) -> Result<Vec<u8>> {
21 let has_secondary_header = secondary_hdr_flag == 1;
22 let secondary_header_flag = if has_secondary_header {
23 SecondaryHeaderFlag::SecondaryHeader
24 } else {
25 SecondaryHeaderFlag::NoSecondaryHeader
26 };
27
28 let packet_data_length = if has_secondary_header {
29 (data.len() + CCSDS_SECONDARY_HEADER_LENGTH - 1) as u16
30 } else {
31 data.len() as u16
32 };
33 let header = CcsdsHeader::new(
34 CCSDS_VERSION,
35 PacketType::Telemetry,
36 secondary_header_flag,
37 apid,
38 u2!(3),
39 u14!(1),
40 packet_data_length,
41 );
42
43 let packet_size = if has_secondary_header {
44 CCSDS_HEADER_LENGTH + CCSDS_SECONDARY_HEADER_LENGTH + data.len()
45 } else {
46 CCSDS_HEADER_LENGTH + data.len()
47 };
48
49 let mut packet = Vec::with_capacity(packet_size);
50 packet.extend(&u48::to_be_bytes(header.raw()));
51 if has_secondary_header {
52 let secondary_header = CcsdsSecondaryHeader::new(0, 0, 0);
53 packet.extend(&u48::to_be_bytes(secondary_header.raw()));
54 }
55 packet.extend(data);
56
57 Ok(packet)
58}
59
60pub fn decode_ccsds_header(data: &[u8]) -> Result<(CcsdsHeader, CcsdsSecondaryHeader)> {
61 if data.len() < CCSDS_HEADER_LENGTH + CCSDS_SECONDARY_HEADER_LENGTH {
62 warn!("Insufficient data length for CCSDS headers");
63 return Err(anyhow::anyhow!(
64 "Insufficient data length for CCSDS headers"
65 ));
66 }
67
68 let header = u48::from_be_bytes(data[0..6].try_into().unwrap_or_else(|_| {
69 warn!("Failed to convert header bytes");
70 [0; 6]
71 }));
72
73 let secondary_header = u48::from_be_bytes(data[6..12].try_into().unwrap_or_else(|_| {
74 warn!("Failed to convert secondary header bytes");
75 [0; 6]
76 }));
77
78 Ok((
79 CcsdsHeader::exact_from(header),
80 CcsdsSecondaryHeader::exact_from(secondary_header),
81 ))
82}
83
84bit_struct! {
85 struct CcsdsHeader(u48) {
86 ccsds_version: u3,
88
89 packet_type: PacketType,
91
92 secondary_header_flag: SecondaryHeaderFlag,
94
95 application_process_id: u11,
97
98 sequence_flags: u2,
100
101 packet_sequence_count: u14,
103
104 packet_data_length: u16,
106 }
107
108 struct CcsdsSecondaryHeader(u48) {
109 time_stamp_seconds: u32,
110
111 time_stamp_subseconds: u8,
112
113 reserved: u8,
114 }
115}