Skip to main content

cfdp_simplified/ccsds/
mod.rs

1use ::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 number
87        ccsds_version: u3,
88
89        /// Packet Type (0 for telemetry, 1 for telecommand)
90        packet_type: PacketType,
91
92        /// Secondary Header Flag (0 for no secondary header, 1 for secondary header)
93        secondary_header_flag: SecondaryHeaderFlag,
94
95        /// Application Process ID (APID)
96        application_process_id: u11,
97
98        /// Sequence flags (3 for none)
99        sequence_flags: u2,
100
101        /// Packet Sequence Count (incremented for each packet)
102        packet_sequence_count: u14,
103
104        /// Packet Data Length (in bytes)
105        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}