alloc support behind feature gate
This commit is contained in:
parent
b7f3ec424c
commit
deee70f40d
@ -30,6 +30,6 @@ version = "0.7.3"
|
|||||||
features = ["use-std"]
|
features = ["use-std"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
std = ["postcard/use-std"]
|
|
||||||
default = ["heapless", "alloc"]
|
default = ["heapless", "alloc"]
|
||||||
|
std = ["postcard/use-std"]
|
||||||
alloc = ["serde/alloc"]
|
alloc = ["serde/alloc"]
|
||||||
|
243
src/lib.rs
243
src/lib.rs
@ -5,6 +5,7 @@ extern crate alloc;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
extern crate std;
|
extern crate std;
|
||||||
|
|
||||||
|
use delegate::delegate;
|
||||||
use crate::ecss::CCSDS_HEADER_LEN;
|
use crate::ecss::CCSDS_HEADER_LEN;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -259,102 +260,122 @@ pub trait CcsdsPrimaryHeader {
|
|||||||
) -> Self;
|
) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod ser {
|
/// Space Packet Primary Header according to CCSDS 133.0-B-2
|
||||||
use crate::{
|
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Copy, Clone)]
|
||||||
CcsdsPacket, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl, PacketType, SequenceFlags,
|
pub struct SpHeader {
|
||||||
};
|
pub version: u8,
|
||||||
|
pub packet_id: PacketId,
|
||||||
/// Space Packet Primary Header according to CCSDS 133.0-B-2
|
pub psc: PacketSequenceCtrl,
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Copy, Clone)]
|
pub data_len: u16,
|
||||||
pub struct SpHeader {
|
|
||||||
pub version: u8,
|
|
||||||
pub packet_id: PacketId,
|
|
||||||
pub psc: PacketSequenceCtrl,
|
|
||||||
pub data_len: u16,
|
|
||||||
}
|
|
||||||
impl Default for SpHeader {
|
|
||||||
fn default() -> Self {
|
|
||||||
SpHeader {
|
|
||||||
version: 0,
|
|
||||||
packet_id: PacketId {
|
|
||||||
ptype: PacketType::Tm,
|
|
||||||
apid: 0,
|
|
||||||
sec_header_flag: true,
|
|
||||||
},
|
|
||||||
psc: PacketSequenceCtrl {
|
|
||||||
seq_flags: SequenceFlags::Unsegmented,
|
|
||||||
seq_count: 0,
|
|
||||||
},
|
|
||||||
data_len: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl SpHeader {
|
|
||||||
pub fn new(apid: u16, ptype: PacketType, ssc: u16, data_len: u16) -> Option<Self> {
|
|
||||||
if ssc > num::pow(2, 14) - 1 || apid > num::pow(2, 11) - 1 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let mut header = SpHeader::default();
|
|
||||||
header.packet_id.apid = apid;
|
|
||||||
header.packet_id.ptype = ptype;
|
|
||||||
header.psc.seq_count = ssc;
|
|
||||||
header.data_len = data_len;
|
|
||||||
Some(header)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tm(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> {
|
|
||||||
Self::new(apid, PacketType::Tm, seq_count, data_len)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tc(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> {
|
|
||||||
Self::new(apid, PacketType::Tc, seq_count, data_len)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CcsdsPacket for SpHeader {
|
|
||||||
#[inline]
|
|
||||||
fn ccsds_version(&self) -> u8 {
|
|
||||||
self.version
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn packet_id(&self) -> PacketId {
|
|
||||||
self.packet_id
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn psc(&self) -> PacketSequenceCtrl {
|
|
||||||
self.psc
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn data_len(&self) -> u16 {
|
|
||||||
self.data_len
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CcsdsPrimaryHeader for SpHeader {
|
|
||||||
fn from_composite_fields(
|
|
||||||
packet_id: PacketId,
|
|
||||||
psc: PacketSequenceCtrl,
|
|
||||||
data_len: u16,
|
|
||||||
version: Option<u8>,
|
|
||||||
) -> Self {
|
|
||||||
let mut version_to_set = 0b000;
|
|
||||||
if let Some(version) = version {
|
|
||||||
version_to_set = version;
|
|
||||||
}
|
|
||||||
SpHeader {
|
|
||||||
version: version_to_set,
|
|
||||||
packet_id,
|
|
||||||
psc,
|
|
||||||
data_len,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sph_from_other!(SpHeader, crate::zc::SpHeader);
|
|
||||||
}
|
}
|
||||||
|
impl Default for SpHeader {
|
||||||
|
fn default() -> Self {
|
||||||
|
SpHeader {
|
||||||
|
version: 0,
|
||||||
|
packet_id: PacketId {
|
||||||
|
ptype: PacketType::Tm,
|
||||||
|
apid: 0,
|
||||||
|
sec_header_flag: false,
|
||||||
|
},
|
||||||
|
psc: PacketSequenceCtrl {
|
||||||
|
seq_flags: SequenceFlags::Unsegmented,
|
||||||
|
seq_count: 0,
|
||||||
|
},
|
||||||
|
data_len: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl SpHeader {
|
||||||
|
pub fn new(ptype: PacketType, sec_header: bool, apid: u16, ssc: u16, data_len: u16) -> Option<Self> {
|
||||||
|
if ssc > num::pow(2, 14) - 1 || apid > num::pow(2, 11) - 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut header = SpHeader::default();
|
||||||
|
header.packet_id.sec_header_flag = sec_header;
|
||||||
|
header.packet_id.apid = apid;
|
||||||
|
header.packet_id.ptype = ptype;
|
||||||
|
header.psc.seq_count = ssc;
|
||||||
|
header.data_len = data_len;
|
||||||
|
Some(header)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tm(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> {
|
||||||
|
Self::new(PacketType::Tm, false, apid, seq_count, data_len)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tc(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> {
|
||||||
|
Self::new(PacketType::Tc, false, apid, seq_count, data_len)
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection RsTraitImplementation
|
||||||
|
delegate!(to self.packet_id {
|
||||||
|
pub fn set_apid(&mut self, apid: u16) -> bool;
|
||||||
|
});
|
||||||
|
|
||||||
|
delegate!(to self.psc {
|
||||||
|
pub fn set_seq_count(&mut self, seq_count: u16) -> bool;
|
||||||
|
});
|
||||||
|
|
||||||
|
pub fn set_seq_flags(&mut self, seq_flags: SequenceFlags) {
|
||||||
|
self.psc.seq_flags = seq_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_sec_header_flag(&mut self) {
|
||||||
|
self.packet_id.sec_header_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_sec_header_flag(&mut self) {
|
||||||
|
self.packet_id.sec_header_flag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_packet_type(&mut self, packet_type: PacketType) {
|
||||||
|
self.packet_id.ptype = packet_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CcsdsPacket for SpHeader {
|
||||||
|
#[inline]
|
||||||
|
fn ccsds_version(&self) -> u8 {
|
||||||
|
self.version
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn packet_id(&self) -> PacketId {
|
||||||
|
self.packet_id
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn psc(&self) -> PacketSequenceCtrl {
|
||||||
|
self.psc
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn data_len(&self) -> u16 {
|
||||||
|
self.data_len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CcsdsPrimaryHeader for SpHeader {
|
||||||
|
fn from_composite_fields(
|
||||||
|
packet_id: PacketId,
|
||||||
|
psc: PacketSequenceCtrl,
|
||||||
|
data_len: u16,
|
||||||
|
version: Option<u8>,
|
||||||
|
) -> Self {
|
||||||
|
let mut version_to_set = 0b000;
|
||||||
|
if let Some(version) = version {
|
||||||
|
version_to_set = version;
|
||||||
|
}
|
||||||
|
SpHeader {
|
||||||
|
version: version_to_set,
|
||||||
|
packet_id,
|
||||||
|
psc,
|
||||||
|
data_len,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sph_from_other!(SpHeader, crate::zc::SpHeader);
|
||||||
|
|
||||||
pub mod zc {
|
pub mod zc {
|
||||||
use crate::{CcsdsPacket, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl, VERSION_MASK};
|
use crate::{CcsdsPacket, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl, VERSION_MASK};
|
||||||
@ -434,12 +455,12 @@ pub mod zc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sph_from_other!(SpHeader, crate::ser::SpHeader);
|
sph_from_other!(SpHeader, crate::SpHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::ser::SpHeader;
|
use crate::SpHeader;
|
||||||
use crate::{
|
use crate::{
|
||||||
packet_type_in_raw_packet_id, zc, CcsdsPacket, CcsdsPrimaryHeader, PacketId,
|
packet_type_in_raw_packet_id, zc, CcsdsPacket, CcsdsPrimaryHeader, PacketId,
|
||||||
PacketSequenceCtrl, PacketType, SequenceFlags,
|
PacketSequenceCtrl, PacketType, SequenceFlags,
|
||||||
@ -532,7 +553,7 @@ mod tests {
|
|||||||
let sp_header = SpHeader::tc(0x42, 12, 0).expect("Error creating SP header");
|
let sp_header = SpHeader::tc(0x42, 12, 0).expect("Error creating SP header");
|
||||||
assert_eq!(sp_header.ccsds_version(), 0b000);
|
assert_eq!(sp_header.ccsds_version(), 0b000);
|
||||||
assert!(sp_header.is_tc());
|
assert!(sp_header.is_tc());
|
||||||
assert!(sp_header.sec_header_flag());
|
assert!(!sp_header.sec_header_flag());
|
||||||
assert_eq!(sp_header.ptype(), PacketType::Tc);
|
assert_eq!(sp_header.ptype(), PacketType::Tc);
|
||||||
assert_eq!(sp_header.seq_count(), 12);
|
assert_eq!(sp_header.seq_count(), 12);
|
||||||
assert_eq!(sp_header.apid(), 0x42);
|
assert_eq!(sp_header.apid(), 0x42);
|
||||||
@ -541,12 +562,12 @@ mod tests {
|
|||||||
let output = to_stdvec(&sp_header).unwrap();
|
let output = to_stdvec(&sp_header).unwrap();
|
||||||
let sp_header: SpHeader = from_bytes(&output).unwrap();
|
let sp_header: SpHeader = from_bytes(&output).unwrap();
|
||||||
assert_eq!(sp_header.version, 0b000);
|
assert_eq!(sp_header.version, 0b000);
|
||||||
assert!(sp_header.packet_id.sec_header_flag);
|
assert!(!sp_header.packet_id.sec_header_flag);
|
||||||
assert_eq!(sp_header.ptype(), PacketType::Tc);
|
assert_eq!(sp_header.ptype(), PacketType::Tc);
|
||||||
assert_eq!(sp_header.seq_count(), 12);
|
assert_eq!(sp_header.seq_count(), 12);
|
||||||
assert_eq!(sp_header.apid(), 0x42);
|
assert_eq!(sp_header.apid(), 0x42);
|
||||||
assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented);
|
assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented);
|
||||||
assert_eq!(sp_header.packet_id_raw(), 0x1842);
|
assert_eq!(sp_header.packet_id_raw(), 0x1042);
|
||||||
assert_eq!(sp_header.psc_raw(), 0xC00C);
|
assert_eq!(sp_header.psc_raw(), 0xC00C);
|
||||||
assert_eq!(sp_header.ccsds_version(), 0b000);
|
assert_eq!(sp_header.ccsds_version(), 0b000);
|
||||||
assert_eq!(sp_header.data_len, 0);
|
assert_eq!(sp_header.data_len, 0);
|
||||||
@ -554,12 +575,12 @@ mod tests {
|
|||||||
let sp_header = SpHeader::tm(0x7, 22, 36).expect("Error creating SP header");
|
let sp_header = SpHeader::tm(0x7, 22, 36).expect("Error creating SP header");
|
||||||
assert_eq!(sp_header.ccsds_version(), 0b000);
|
assert_eq!(sp_header.ccsds_version(), 0b000);
|
||||||
assert!(sp_header.is_tm());
|
assert!(sp_header.is_tm());
|
||||||
assert!(sp_header.sec_header_flag());
|
assert!(!sp_header.sec_header_flag());
|
||||||
assert_eq!(sp_header.ptype(), PacketType::Tm);
|
assert_eq!(sp_header.ptype(), PacketType::Tm);
|
||||||
assert_eq!(sp_header.seq_count(), 22);
|
assert_eq!(sp_header.seq_count(), 22);
|
||||||
assert_eq!(sp_header.apid(), 0x07);
|
assert_eq!(sp_header.apid(), 0x07);
|
||||||
assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented);
|
assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented);
|
||||||
assert_eq!(sp_header.packet_id_raw(), 0x0807);
|
assert_eq!(sp_header.packet_id_raw(), 0x0007);
|
||||||
assert_eq!(sp_header.psc_raw(), 0xC016);
|
assert_eq!(sp_header.psc_raw(), 0xC016);
|
||||||
assert_eq!(sp_header.data_len(), 36);
|
assert_eq!(sp_header.data_len(), 36);
|
||||||
assert_eq!(sp_header.ccsds_version(), 0b000);
|
assert_eq!(sp_header.ccsds_version(), 0b000);
|
||||||
@ -581,6 +602,24 @@ mod tests {
|
|||||||
assert_eq!(from_comp_fields.data_len(), 0);
|
assert_eq!(from_comp_fields.data_len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sp_header_setters() {
|
||||||
|
let mut sp_header = SpHeader::tc(0x42, 12, 0).expect("Error creating SP header");
|
||||||
|
assert_eq!(sp_header.apid(), 0x42);
|
||||||
|
sp_header.set_apid(0x12);
|
||||||
|
assert_eq!(sp_header.apid(), 0x12);
|
||||||
|
|
||||||
|
sp_header.set_sec_header_flag();
|
||||||
|
assert!(sp_header.sec_header_flag());
|
||||||
|
sp_header.clear_sec_header_flag();
|
||||||
|
assert!(!sp_header.sec_header_flag());
|
||||||
|
sp_header.set_seq_count(0x45);
|
||||||
|
assert_eq!(sp_header.seq_count(), 0x45);
|
||||||
|
assert_eq!(sp_header.ptype(), PacketType::Tc);
|
||||||
|
sp_header.set_packet_type(PacketType::Tm);
|
||||||
|
assert_eq!(sp_header.ptype(), PacketType::Tm);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_zc_sph() {
|
fn test_zc_sph() {
|
||||||
use zerocopy::AsBytes;
|
use zerocopy::AsBytes;
|
||||||
|
19
src/tc.rs
19
src/tc.rs
@ -1,14 +1,16 @@
|
|||||||
use crate::ecss::{
|
use crate::ecss::{
|
||||||
crc_from_raw_data, crc_procedure, CrcType, PusError, PusPacket, PusVersion, CRC_CCITT_FALSE,
|
crc_from_raw_data, crc_procedure, CrcType, PusError, PusPacket, PusVersion, CRC_CCITT_FALSE,
|
||||||
};
|
};
|
||||||
use crate::ser::SpHeader;
|
use crate::SpHeader;
|
||||||
use crate::{CcsdsPacket, PacketError, PacketType, SequenceFlags, SizeMissmatch, CCSDS_HEADER_LEN};
|
use crate::{CcsdsPacket, PacketError, PacketType, SequenceFlags, SizeMissmatch, CCSDS_HEADER_LEN};
|
||||||
use alloc::vec::Vec;
|
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
use delegate::delegate;
|
use delegate::delegate;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use zerocopy::AsBytes;
|
use zerocopy::AsBytes;
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
/// PUS C secondary header length is fixed
|
/// PUS C secondary header length is fixed
|
||||||
pub const PUC_TC_SECONDARY_HEADER_LEN: usize = size_of::<zc::PusTcSecondaryHeader>();
|
pub const PUC_TC_SECONDARY_HEADER_LEN: usize = size_of::<zc::PusTcSecondaryHeader>();
|
||||||
pub const PUS_TC_MIN_LEN_WITHOUT_APP_DATA: usize =
|
pub const PUS_TC_MIN_LEN_WITHOUT_APP_DATA: usize =
|
||||||
@ -201,7 +203,8 @@ impl<'slice> PusTc<'slice> {
|
|||||||
app_data: Option<&'slice [u8]>,
|
app_data: Option<&'slice [u8]>,
|
||||||
set_ccsds_len: bool,
|
set_ccsds_len: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
sp_header.packet_id.ptype = PacketType::Tc;
|
sp_header.set_packet_type(PacketType::Tc);
|
||||||
|
sp_header.set_sec_header_flag();
|
||||||
let mut pus_tc = PusTc {
|
let mut pus_tc = PusTc {
|
||||||
sp_header: *sp_header,
|
sp_header: *sp_header,
|
||||||
raw_data: None,
|
raw_data: None,
|
||||||
@ -335,6 +338,7 @@ impl<'slice> PusTc<'slice> {
|
|||||||
Ok(curr_idx)
|
Ok(curr_idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
pub fn append_to_vec(&self, vec: &mut Vec<u8>) -> Result<usize, PusError> {
|
pub fn append_to_vec(&self, vec: &mut Vec<u8>) -> Result<usize, PusError> {
|
||||||
let sph_zc = crate::zc::SpHeader::from(self.sp_header);
|
let sph_zc = crate::zc::SpHeader::from(self.sp_header);
|
||||||
let mut appended_len = PUS_TC_MIN_LEN_WITHOUT_APP_DATA;
|
let mut appended_len = PUS_TC_MIN_LEN_WITHOUT_APP_DATA;
|
||||||
@ -366,7 +370,7 @@ impl<'slice> PusTc<'slice> {
|
|||||||
/// Create a PusTc instance from a raw slice. On success, it returns a tuple containing
|
/// Create a PusTc instance from a raw slice. On success, it returns a tuple containing
|
||||||
/// the instance and the found byte length of the packet
|
/// the instance and the found byte length of the packet
|
||||||
pub fn new_from_raw_slice(
|
pub fn new_from_raw_slice(
|
||||||
slice: &'slice (impl AsRef<[u8]> + ?Sized),
|
slice: &'slice [u8],
|
||||||
) -> Result<(Self, usize), PusError> {
|
) -> Result<(Self, usize), PusError> {
|
||||||
let slice_ref = slice.as_ref();
|
let slice_ref = slice.as_ref();
|
||||||
let raw_data_len = slice_ref.len();
|
let raw_data_len = slice_ref.len();
|
||||||
@ -465,7 +469,7 @@ impl PusTcSecondaryHeaderT for PusTc<'_> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use crate::ecss::PusVersion::PusC;
|
use crate::ecss::PusVersion::PusC;
|
||||||
use crate::ecss::{PusError, PusPacket};
|
use crate::ecss::{PusError, PusPacket};
|
||||||
use crate::ser::SpHeader;
|
use crate::SpHeader;
|
||||||
use crate::tc::ACK_ALL;
|
use crate::tc::ACK_ALL;
|
||||||
use crate::tc::{PusTc, PusTcSecondaryHeader, PusTcSecondaryHeaderT};
|
use crate::tc::{PusTc, PusTcSecondaryHeader, PusTcSecondaryHeaderT};
|
||||||
use crate::{CcsdsPacket, SequenceFlags};
|
use crate::{CcsdsPacket, SequenceFlags};
|
||||||
@ -628,6 +632,7 @@ mod tests {
|
|||||||
fn verify_test_tc(tc: &PusTc, has_user_data: bool, exp_full_len: usize) {
|
fn verify_test_tc(tc: &PusTc, has_user_data: bool, exp_full_len: usize) {
|
||||||
assert_eq!(PusPacket::service(tc), 17);
|
assert_eq!(PusPacket::service(tc), 17);
|
||||||
assert_eq!(PusPacket::subservice(tc), 1);
|
assert_eq!(PusPacket::subservice(tc), 1);
|
||||||
|
assert!(tc.sec_header_flag());
|
||||||
assert_eq!(PusPacket::pus_version(tc), PusC);
|
assert_eq!(PusPacket::pus_version(tc), PusC);
|
||||||
if !has_user_data {
|
if !has_user_data {
|
||||||
assert_eq!(tc.user_data(), None);
|
assert_eq!(tc.user_data(), None);
|
||||||
@ -637,9 +642,11 @@ mod tests {
|
|||||||
assert_eq!(tc.apid(), 0x02);
|
assert_eq!(tc.apid(), 0x02);
|
||||||
assert_eq!(tc.ack_flags(), ACK_ALL);
|
assert_eq!(tc.ack_flags(), ACK_ALL);
|
||||||
assert_eq!(tc.len_packed(), exp_full_len);
|
assert_eq!(tc.len_packed(), exp_full_len);
|
||||||
|
let mut comp_header = SpHeader::tc(0x02, 0x34, exp_full_len as u16 - 7).unwrap();
|
||||||
|
comp_header.set_sec_header_flag();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tc.sp_header,
|
tc.sp_header,
|
||||||
SpHeader::tc(0x02, 0x34, exp_full_len as u16 - 7).unwrap()
|
comp_header
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,6 +308,7 @@ mod tests {
|
|||||||
generic_dt_property_equality_check(dt.minute(), compare_stamp.minute(), 0, 59);
|
generic_dt_property_equality_check(dt.minute(), compare_stamp.minute(), 0, 59);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
fn generic_dt_property_equality_check(first: u32, second: u32, start: u32, end: u32) {
|
fn generic_dt_property_equality_check(first: u32, second: u32, start: u32, end: u32) {
|
||||||
if second < first {
|
if second < first {
|
||||||
assert_eq!(second, start);
|
assert_eq!(second, start);
|
||||||
|
40
src/tm.rs
40
src/tm.rs
@ -1,10 +1,12 @@
|
|||||||
use crate::ecss::{crc_procedure, CrcType, PusError, PusVersion, CRC_CCITT_FALSE};
|
use crate::ecss::{crc_procedure, CrcType, PusError, PusVersion, CRC_CCITT_FALSE};
|
||||||
use crate::ser::SpHeader;
|
use crate::{PacketError, PacketType, SizeMissmatch, SpHeader, CCSDS_HEADER_LEN};
|
||||||
use crate::{PacketError, PacketType, SizeMissmatch, CCSDS_HEADER_LEN};
|
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use zerocopy::AsBytes;
|
use zerocopy::AsBytes;
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
/// Length without timestamp
|
/// Length without timestamp
|
||||||
pub const PUC_TM_MIN_SEC_HEADER_LEN: usize = 7;
|
pub const PUC_TM_MIN_SEC_HEADER_LEN: usize = 7;
|
||||||
pub const PUS_TM_MIN_LEN_WITHOUT_SOURCE_DATA: usize =
|
pub const PUS_TM_MIN_LEN_WITHOUT_SOURCE_DATA: usize =
|
||||||
@ -132,7 +134,8 @@ impl<'slice> PusTm<'slice> {
|
|||||||
source_data: Option<&'slice [u8]>,
|
source_data: Option<&'slice [u8]>,
|
||||||
set_ccsds_len: bool,
|
set_ccsds_len: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
sp_header.packet_id.ptype = PacketType::Tm;
|
sp_header.set_packet_type(PacketType::Tm);
|
||||||
|
sp_header.set_sec_header_flag();
|
||||||
let mut pus_tm = PusTm {
|
let mut pus_tm = PusTm {
|
||||||
sp_header: *sp_header,
|
sp_header: *sp_header,
|
||||||
raw_data: None,
|
raw_data: None,
|
||||||
@ -225,6 +228,37 @@ impl<'slice> PusTm<'slice> {
|
|||||||
curr_idx += 2;
|
curr_idx += 2;
|
||||||
Ok(curr_idx)
|
Ok(curr_idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
pub fn append_to_vec(&self, vec: &mut Vec<u8>) -> Result<usize, PusError> {
|
||||||
|
let sph_zc = crate::zc::SpHeader::from(self.sp_header);
|
||||||
|
let mut appended_len = PUS_TM_MIN_LEN_WITHOUT_SOURCE_DATA + self.sec_header.time_stamp.len();
|
||||||
|
if let Some(src_data) = self.source_data {
|
||||||
|
appended_len += src_data.len();
|
||||||
|
};
|
||||||
|
let start_idx = vec.len();
|
||||||
|
let mut curr_idx = vec.len();
|
||||||
|
vec.extend_from_slice(sph_zc.as_bytes());
|
||||||
|
curr_idx += sph_zc.as_bytes().len();
|
||||||
|
// The PUS version is hardcoded to PUS C
|
||||||
|
let sec_header = zc::PusTmSecHeaderWithoutTimestamp::try_from(self.sec_header).unwrap();
|
||||||
|
vec.extend_from_slice(sec_header.as_bytes());
|
||||||
|
curr_idx += sec_header.as_bytes().len();
|
||||||
|
vec.extend_from_slice(self.sec_header.time_stamp);
|
||||||
|
curr_idx += self.sec_header.time_stamp.len();
|
||||||
|
if let Some(src_data) = self.source_data {
|
||||||
|
vec.extend_from_slice(src_data);
|
||||||
|
curr_idx += src_data.len();
|
||||||
|
}
|
||||||
|
let crc16 = crc_procedure(
|
||||||
|
self.calc_crc_on_serialization,
|
||||||
|
&self.crc16,
|
||||||
|
curr_idx,
|
||||||
|
&vec[start_idx..curr_idx],
|
||||||
|
)?;
|
||||||
|
vec.extend_from_slice(crc16.to_be_bytes().as_slice());
|
||||||
|
Ok(appended_len)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
Loading…
Reference in New Issue
Block a user