add PUS A support #132
15
CHANGELOG.md
15
CHANGELOG.md
@@ -8,6 +8,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- `PusVersion::VersionNotSupported` contains raw version number instead of `PusVersion` enum now
|
||||||
|
to make it more flexible.
|
||||||
|
- `pus_version` API now returns a `Result<PusVersion, u8>` instead of a `PusVersion` to allow
|
||||||
|
modelling invalid version numbers properly.
|
||||||
|
|
||||||
|
## Removed
|
||||||
|
|
||||||
|
- `PusVersion::Invalid`, which will be modelled with `Result<PusVersion, u8>` now.
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- Added PUS A legacy support for telecommands inside the `ecss.tc_pus_a` module
|
||||||
|
|
||||||
# [v0.15.0] 2025-07-18
|
# [v0.15.0] 2025-07-18
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ pub(crate) fn generic_len_check_deserialization(
|
|||||||
|
|
||||||
impl<'data> Lv<'data> {
|
impl<'data> Lv<'data> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(data: &[u8]) -> Result<Lv, TlvLvDataTooLargeError> {
|
pub fn new(data: &[u8]) -> Result<Lv<'_>, TlvLvDataTooLargeError> {
|
||||||
if data.len() > u8::MAX as usize {
|
if data.len() > u8::MAX as usize {
|
||||||
return Err(TlvLvDataTooLargeError(data.len()));
|
return Err(TlvLvDataTooLargeError(data.len()));
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ impl<'data> Lv<'data> {
|
|||||||
/// Helper function to build a string LV. This is especially useful for the file or directory
|
/// Helper function to build a string LV. This is especially useful for the file or directory
|
||||||
/// path LVs
|
/// path LVs
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_from_str(str_slice: &str) -> Result<Lv, TlvLvDataTooLargeError> {
|
pub fn new_from_str(str_slice: &str) -> Result<Lv<'_>, TlvLvDataTooLargeError> {
|
||||||
Self::new(str_slice.as_bytes())
|
Self::new(str_slice.as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ impl<'seg_meta, 'file_data> FileDataPdu<'seg_meta, 'file_data> {
|
|||||||
.calc_pdu_datafield_len(self.file_data.len() as u64)
|
.calc_pdu_datafield_len(self.file_data.len() as u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn segment_metadata(&self) -> Option<&SegmentMetadata> {
|
pub fn segment_metadata(&self) -> Option<&SegmentMetadata<'_>> {
|
||||||
self.common.segment_metadata.as_ref()
|
self.common.segment_metadata.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,8 +419,8 @@ pub fn calculate_max_file_seg_len_for_max_packet_len_and_pdu_header(
|
|||||||
segment_metadata: Option<&SegmentMetadata>,
|
segment_metadata: Option<&SegmentMetadata>,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let mut subtract = pdu_header.header_len();
|
let mut subtract = pdu_header.header_len();
|
||||||
if segment_metadata.is_some() {
|
if let Some(segment_metadata) = segment_metadata {
|
||||||
subtract += 1 + segment_metadata.as_ref().unwrap().metadata().unwrap().len();
|
subtract += 1 + segment_metadata.metadata().unwrap().len();
|
||||||
}
|
}
|
||||||
if pdu_header.common_pdu_conf().file_flag == LargeFileFlag::Large {
|
if pdu_header.common_pdu_conf().file_flag == LargeFileFlag::Large {
|
||||||
subtract += 8;
|
subtract += 8;
|
||||||
|
|||||||
@@ -338,11 +338,11 @@ impl<'raw> MetadataPduReader<'raw> {
|
|||||||
&self.metadata_params
|
&self.metadata_params
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn src_file_name(&self) -> Lv {
|
pub fn src_file_name(&self) -> Lv<'_> {
|
||||||
self.src_file_name
|
self.src_file_name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dest_file_name(&self) -> Lv {
|
pub fn dest_file_name(&self) -> Lv<'_> {
|
||||||
self.dest_file_name
|
self.dest_file_name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ impl<'seg_reqs> NakPduCreator<'seg_reqs> {
|
|||||||
self.end_of_scope
|
self.end_of_scope
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn segment_requests(&self) -> Option<&SegmentRequests> {
|
pub fn segment_requests(&self) -> Option<&SegmentRequests<'_>> {
|
||||||
self.segment_requests.as_ref()
|
self.segment_requests.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -153,14 +153,17 @@ pub struct Tlv<'data> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'data> Tlv<'data> {
|
impl<'data> Tlv<'data> {
|
||||||
pub fn new(tlv_type: TlvType, data: &[u8]) -> Result<Tlv, TlvLvDataTooLargeError> {
|
pub fn new(tlv_type: TlvType, data: &[u8]) -> Result<Tlv<'_>, TlvLvDataTooLargeError> {
|
||||||
Ok(Tlv {
|
Ok(Tlv {
|
||||||
tlv_type_field: TlvTypeField::Standard(tlv_type),
|
tlv_type_field: TlvTypeField::Standard(tlv_type),
|
||||||
lv: Lv::new(data)?,
|
lv: Lv::new(data)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_custom_type(tlv_type: u8, data: &[u8]) -> Result<Tlv, TlvLvDataTooLargeError> {
|
pub fn new_with_custom_type(
|
||||||
|
tlv_type: u8,
|
||||||
|
data: &[u8],
|
||||||
|
) -> Result<Tlv<'_>, TlvLvDataTooLargeError> {
|
||||||
Ok(Tlv {
|
Ok(Tlv {
|
||||||
tlv_type_field: TlvTypeField::Custom(tlv_type),
|
tlv_type_field: TlvTypeField::Custom(tlv_type),
|
||||||
lv: Lv::new(data)?,
|
lv: Lv::new(data)?,
|
||||||
@@ -370,7 +373,7 @@ impl EntityIdTlv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to a generic [Tlv], which also erases the programmatic type information.
|
/// Convert to a generic [Tlv], which also erases the programmatic type information.
|
||||||
pub fn to_tlv(self, buf: &mut [u8]) -> Result<Tlv, ByteConversionError> {
|
pub fn to_tlv(self, buf: &mut [u8]) -> Result<Tlv<'_>, ByteConversionError> {
|
||||||
Self::len_check(buf)?;
|
Self::len_check(buf)?;
|
||||||
self.entity_id
|
self.entity_id
|
||||||
.write_to_be_bytes(&mut buf[2..2 + self.entity_id.size()])?;
|
.write_to_be_bytes(&mut buf[2..2 + self.entity_id.size()])?;
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ pub mod event;
|
|||||||
pub mod hk;
|
pub mod hk;
|
||||||
pub mod scheduling;
|
pub mod scheduling;
|
||||||
pub mod tc;
|
pub mod tc;
|
||||||
|
pub mod tc_pus_a;
|
||||||
pub mod tm;
|
pub mod tm;
|
||||||
|
pub mod tm_pus_a;
|
||||||
pub mod verification;
|
pub mod verification;
|
||||||
|
|
||||||
pub type CrcType = u16;
|
pub type CrcType = u16;
|
||||||
@@ -80,18 +82,17 @@ pub enum PusVersion {
|
|||||||
EsaPus = 0,
|
EsaPus = 0,
|
||||||
PusA = 1,
|
PusA = 1,
|
||||||
PusC = 2,
|
PusC = 2,
|
||||||
Invalid = 0b1111,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<u8> for PusVersion {
|
impl TryFrom<u8> for PusVersion {
|
||||||
type Error = ();
|
type Error = u8;
|
||||||
|
|
||||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
match value {
|
match value {
|
||||||
x if x == PusVersion::EsaPus as u8 => Ok(PusVersion::EsaPus),
|
x if x == PusVersion::EsaPus as u8 => Ok(PusVersion::EsaPus),
|
||||||
x if x == PusVersion::PusA as u8 => Ok(PusVersion::PusA),
|
x if x == PusVersion::PusA as u8 => Ok(PusVersion::PusA),
|
||||||
x if x == PusVersion::PusC as u8 => Ok(PusVersion::PusC),
|
x if x == PusVersion::PusC as u8 => Ok(PusVersion::PusC),
|
||||||
_ => Err(()),
|
_ => Err(value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,7 +155,7 @@ pub enum PfcReal {
|
|||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum PusError {
|
pub enum PusError {
|
||||||
#[error("PUS version {0:?} not supported")]
|
#[error("PUS version {0:?} not supported")]
|
||||||
VersionNotSupported(PusVersion),
|
VersionNotSupported(u8),
|
||||||
#[error("checksum verification for crc16 {0:#06x} failed")]
|
#[error("checksum verification for crc16 {0:#06x} failed")]
|
||||||
ChecksumFailure(u16),
|
ChecksumFailure(u16),
|
||||||
/// CRC16 needs to be calculated first
|
/// CRC16 needs to be calculated first
|
||||||
@@ -167,9 +168,7 @@ pub enum PusError {
|
|||||||
/// Generic trait to describe common attributes for both PUS Telecommands (TC) and PUS Telemetry
|
/// Generic trait to describe common attributes for both PUS Telecommands (TC) and PUS Telemetry
|
||||||
/// (TM) packets. All PUS packets are also a special type of [CcsdsPacket]s.
|
/// (TM) packets. All PUS packets are also a special type of [CcsdsPacket]s.
|
||||||
pub trait PusPacket: CcsdsPacket {
|
pub trait PusPacket: CcsdsPacket {
|
||||||
const PUS_VERSION: PusVersion = PusVersion::PusC;
|
fn pus_version(&self) -> Result<PusVersion, u8>;
|
||||||
|
|
||||||
fn pus_version(&self) -> PusVersion;
|
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
fn subservice(&self) -> u8;
|
fn subservice(&self) -> u8;
|
||||||
fn user_data(&self) -> &[u8];
|
fn user_data(&self) -> &[u8];
|
||||||
@@ -369,6 +368,7 @@ generic_ecss_enum_typedefs_and_from_impls! {
|
|||||||
/// byte representation. This is especially useful for generic abstractions which depend only
|
/// byte representation. This is especially useful for generic abstractions which depend only
|
||||||
/// on the serialization of those packets.
|
/// on the serialization of those packets.
|
||||||
pub trait WritablePusPacket {
|
pub trait WritablePusPacket {
|
||||||
|
/// The length here also includes the CRC length.
|
||||||
fn len_written(&self) -> usize;
|
fn len_written(&self) -> usize;
|
||||||
|
|
||||||
/// Writes the packet to the given slice without writing the CRC.
|
/// Writes the packet to the given slice without writing the CRC.
|
||||||
@@ -536,9 +536,9 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pus_error_display() {
|
fn test_pus_error_display() {
|
||||||
let unsupport_version = PusError::VersionNotSupported(super::PusVersion::EsaPus);
|
let unsupport_version = PusError::VersionNotSupported(super::PusVersion::EsaPus as u8);
|
||||||
let write_str = unsupport_version.to_string();
|
let write_str = unsupport_version.to_string();
|
||||||
assert_eq!(write_str, "PUS version EsaPus not supported")
|
assert_eq!(write_str, "PUS version 0 not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -572,8 +572,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_pus_error_eq_impl() {
|
fn test_pus_error_eq_impl() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
PusError::VersionNotSupported(PusVersion::EsaPus),
|
PusError::VersionNotSupported(PusVersion::EsaPus as u8),
|
||||||
PusError::VersionNotSupported(PusVersion::EsaPus)
|
PusError::VersionNotSupported(PusVersion::EsaPus as u8)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ pub const ACK_ALL: u8 = AckOpts::Acceptance as u8
|
|||||||
| AckOpts::Completion as u8;
|
| AckOpts::Completion as u8;
|
||||||
|
|
||||||
pub trait GenericPusTcSecondaryHeader {
|
pub trait GenericPusTcSecondaryHeader {
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> Result<PusVersion, u8>;
|
||||||
fn ack_flags(&self) -> u8;
|
fn ack_flags(&self) -> u8;
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
fn subservice(&self) -> u8;
|
fn subservice(&self) -> u8;
|
||||||
@@ -104,7 +104,7 @@ pub mod zc {
|
|||||||
type Error = PusError;
|
type Error = PusError;
|
||||||
fn try_from(value: crate::ecss::tc::PusTcSecondaryHeader) -> Result<Self, Self::Error> {
|
fn try_from(value: crate::ecss::tc::PusTcSecondaryHeader) -> Result<Self, Self::Error> {
|
||||||
if value.version != PusVersion::PusC {
|
if value.version != PusVersion::PusC {
|
||||||
return Err(PusError::VersionNotSupported(value.version));
|
return Err(PusError::VersionNotSupported(value.version as u8));
|
||||||
}
|
}
|
||||||
Ok(PusTcSecondaryHeader {
|
Ok(PusTcSecondaryHeader {
|
||||||
version_ack: ((value.version as u8) << 4) | value.ack,
|
version_ack: ((value.version as u8) << 4) | value.ack,
|
||||||
@@ -117,8 +117,8 @@ pub mod zc {
|
|||||||
|
|
||||||
impl GenericPusTcSecondaryHeader for PusTcSecondaryHeader {
|
impl GenericPusTcSecondaryHeader for PusTcSecondaryHeader {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion {
|
fn pus_version(&self) -> Result<PusVersion, u8> {
|
||||||
PusVersion::try_from((self.version_ack >> 4) & 0b1111).unwrap_or(PusVersion::Invalid)
|
PusVersion::try_from((self.version_ack >> 4) & 0b1111)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -156,8 +156,8 @@ pub struct PusTcSecondaryHeader {
|
|||||||
|
|
||||||
impl GenericPusTcSecondaryHeader for PusTcSecondaryHeader {
|
impl GenericPusTcSecondaryHeader for PusTcSecondaryHeader {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion {
|
fn pus_version(&self) -> Result<PusVersion, u8> {
|
||||||
self.version
|
Ok(self.version)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -444,7 +444,7 @@ impl CcsdsPacket for PusTcCreator<'_> {
|
|||||||
impl PusPacket for PusTcCreator<'_> {
|
impl PusPacket for PusTcCreator<'_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> Result<PusVersion, u8>;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -465,7 +465,7 @@ impl PusPacket for PusTcCreator<'_> {
|
|||||||
impl GenericPusTcSecondaryHeader for PusTcCreator<'_> {
|
impl GenericPusTcSecondaryHeader for PusTcCreator<'_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> Result<PusVersion, u8>;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -730,7 +730,7 @@ impl CcsdsPacket for PusTcReader<'_> {
|
|||||||
impl PusPacket for PusTcReader<'_> {
|
impl PusPacket for PusTcReader<'_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> Result<PusVersion, u8>;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -751,7 +751,7 @@ impl PusPacket for PusTcReader<'_> {
|
|||||||
impl GenericPusTcSecondaryHeader for PusTcReader<'_> {
|
impl GenericPusTcSecondaryHeader for PusTcReader<'_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> Result<PusVersion, u8>;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -1157,14 +1157,14 @@ mod tests {
|
|||||||
assert_eq!(PusPacket::subservice(tc), 1);
|
assert_eq!(PusPacket::subservice(tc), 1);
|
||||||
assert_eq!(GenericPusTcSecondaryHeader::subservice(tc), 1);
|
assert_eq!(GenericPusTcSecondaryHeader::subservice(tc), 1);
|
||||||
assert!(tc.sec_header_flag());
|
assert!(tc.sec_header_flag());
|
||||||
assert_eq!(PusPacket::pus_version(tc), PusC);
|
assert_eq!(PusPacket::pus_version(tc).unwrap(), PusC);
|
||||||
assert_eq!(tc.seq_count(), 0x34);
|
assert_eq!(tc.seq_count(), 0x34);
|
||||||
assert_eq!(tc.source_id(), 0);
|
assert_eq!(tc.source_id(), 0);
|
||||||
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!(PusPacket::pus_version(tc), PusVersion::PusC);
|
assert_eq!(PusPacket::pus_version(tc).unwrap(), PusVersion::PusC);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
GenericPusTcSecondaryHeader::pus_version(tc),
|
GenericPusTcSecondaryHeader::pus_version(tc).unwrap(),
|
||||||
PusVersion::PusC
|
PusVersion::PusC
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
1353
src/ecss/tc_pus_a.rs
Normal file
1353
src/ecss/tc_pus_a.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -75,7 +75,7 @@ pub const PUS_TM_MIN_LEN_WITHOUT_SOURCE_DATA: usize =
|
|||||||
CCSDS_HEADER_LEN + PUS_TM_MIN_SEC_HEADER_LEN + size_of::<CrcType>();
|
CCSDS_HEADER_LEN + PUS_TM_MIN_SEC_HEADER_LEN + size_of::<CrcType>();
|
||||||
|
|
||||||
pub trait GenericPusTmSecondaryHeader {
|
pub trait GenericPusTmSecondaryHeader {
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> Result<PusVersion, u8>;
|
||||||
fn sc_time_ref_status(&self) -> u8;
|
fn sc_time_ref_status(&self) -> u8;
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
fn subservice(&self) -> u8;
|
fn subservice(&self) -> u8;
|
||||||
@@ -107,7 +107,7 @@ pub mod zc {
|
|||||||
type Error = PusError;
|
type Error = PusError;
|
||||||
fn try_from(header: crate::ecss::tm::PusTmSecondaryHeader) -> Result<Self, Self::Error> {
|
fn try_from(header: crate::ecss::tm::PusTmSecondaryHeader) -> Result<Self, Self::Error> {
|
||||||
if header.pus_version != PusVersion::PusC {
|
if header.pus_version != PusVersion::PusC {
|
||||||
return Err(PusError::VersionNotSupported(header.pus_version));
|
return Err(PusError::VersionNotSupported(header.pus_version as u8));
|
||||||
}
|
}
|
||||||
Ok(PusTmSecHeaderWithoutTimestamp {
|
Ok(PusTmSecHeaderWithoutTimestamp {
|
||||||
pus_version_and_sc_time_ref_status: ((header.pus_version as u8) << 4)
|
pus_version_and_sc_time_ref_status: ((header.pus_version as u8) << 4)
|
||||||
@@ -122,9 +122,8 @@ pub mod zc {
|
|||||||
|
|
||||||
impl GenericPusTmSecondaryHeader for PusTmSecHeaderWithoutTimestamp {
|
impl GenericPusTmSecondaryHeader for PusTmSecHeaderWithoutTimestamp {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion {
|
fn pus_version(&self) -> Result<PusVersion, u8> {
|
||||||
PusVersion::try_from((self.pus_version_and_sc_time_ref_status >> 4) & 0b1111)
|
PusVersion::try_from((self.pus_version_and_sc_time_ref_status >> 4) & 0b1111)
|
||||||
.unwrap_or(PusVersion::Invalid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -201,8 +200,8 @@ impl<'stamp> PusTmSecondaryHeader<'stamp> {
|
|||||||
|
|
||||||
impl GenericPusTmSecondaryHeader for PusTmSecondaryHeader<'_> {
|
impl GenericPusTmSecondaryHeader for PusTmSecondaryHeader<'_> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion {
|
fn pus_version(&self) -> Result<PusVersion, u8> {
|
||||||
self.pus_version
|
Ok(self.pus_version)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -232,12 +231,16 @@ impl GenericPusTmSecondaryHeader for PusTmSecondaryHeader<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'slice> TryFrom<zc::PusTmSecHeader<'slice>> for PusTmSecondaryHeader<'slice> {
|
impl<'slice> TryFrom<zc::PusTmSecHeader<'slice>> for PusTmSecondaryHeader<'slice> {
|
||||||
type Error = ();
|
type Error = PusError;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_from(sec_header: zc::PusTmSecHeader<'slice>) -> Result<Self, Self::Error> {
|
fn try_from(sec_header: zc::PusTmSecHeader<'slice>) -> Result<Self, Self::Error> {
|
||||||
|
let version = sec_header.zc_header.pus_version();
|
||||||
|
if let Err(e) = version {
|
||||||
|
return Err(PusError::VersionNotSupported(e));
|
||||||
|
}
|
||||||
Ok(PusTmSecondaryHeader {
|
Ok(PusTmSecondaryHeader {
|
||||||
pus_version: sec_header.zc_header.pus_version(),
|
pus_version: version.unwrap(),
|
||||||
sc_time_ref_status: sec_header.zc_header.sc_time_ref_status(),
|
sc_time_ref_status: sec_header.zc_header.sc_time_ref_status(),
|
||||||
service: sec_header.zc_header.service(),
|
service: sec_header.zc_header.service(),
|
||||||
subservice: sec_header.zc_header.subservice(),
|
subservice: sec_header.zc_header.subservice(),
|
||||||
@@ -488,9 +491,12 @@ impl CcsdsPacket for PusTmCreator<'_, '_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PusPacket for PusTmCreator<'_, '_> {
|
impl PusPacket for PusTmCreator<'_, '_> {
|
||||||
delegate!(to self.sec_header {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> Result<PusVersion, u8> {
|
||||||
|
Ok(self.sec_header.pus_version)
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate!(to self.sec_header {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -511,7 +517,7 @@ impl PusPacket for PusTmCreator<'_, '_> {
|
|||||||
impl GenericPusTmSecondaryHeader for PusTmCreator<'_, '_> {
|
impl GenericPusTmSecondaryHeader for PusTmCreator<'_, '_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> Result<PusVersion, u8>;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -797,7 +803,7 @@ impl CcsdsPacket for PusTmReader<'_> {
|
|||||||
impl PusPacket for PusTmReader<'_> {
|
impl PusPacket for PusTmReader<'_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> Result<PusVersion, u8>;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -818,7 +824,7 @@ impl PusPacket for PusTmReader<'_> {
|
|||||||
impl GenericPusTmSecondaryHeader for PusTmReader<'_> {
|
impl GenericPusTmSecondaryHeader for PusTmReader<'_> {
|
||||||
delegate!(to self.sec_header {
|
delegate!(to self.sec_header {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> Result<PusVersion, u8>;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn service(&self) -> u8;
|
fn service(&self) -> u8;
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -977,7 +983,7 @@ impl CcsdsPacket for PusTmZeroCopyWriter<'_> {
|
|||||||
|
|
||||||
impl PusPacket for PusTmZeroCopyWriter<'_> {
|
impl PusPacket for PusTmZeroCopyWriter<'_> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion {
|
fn pus_version(&self) -> Result<PusVersion, u8> {
|
||||||
self.sec_header_without_timestamp().pus_version()
|
self.sec_header_without_timestamp().pus_version()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1011,7 +1017,7 @@ impl GenericPusTmSecondaryHeader for PusTmZeroCopyWriter<'_> {
|
|||||||
delegate! {
|
delegate! {
|
||||||
to self.sec_header_without_timestamp() {
|
to self.sec_header_without_timestamp() {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pus_version(&self) -> PusVersion;
|
fn pus_version(&self) -> Result<PusVersion, u8>;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sc_time_ref_status(&self) -> u8;
|
fn sc_time_ref_status(&self) -> u8;
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -1047,12 +1053,12 @@ mod tests {
|
|||||||
|
|
||||||
const DUMMY_DATA: &[u8] = &[0, 1, 2];
|
const DUMMY_DATA: &[u8] = &[0, 1, 2];
|
||||||
|
|
||||||
fn base_ping_reply_full_ctor(timestamp: &[u8]) -> PusTmCreator {
|
fn base_ping_reply_full_ctor<'a, 'b>(timestamp: &'a [u8]) -> PusTmCreator<'a, 'b> {
|
||||||
let sph = SpHeader::new_for_unseg_tm_checked(0x123, 0x234, 0).unwrap();
|
let sph = SpHeader::new_for_unseg_tm_checked(0x123, 0x234, 0).unwrap();
|
||||||
let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp);
|
let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp);
|
||||||
PusTmCreator::new_no_source_data(sph, tm_header, true)
|
PusTmCreator::new_no_source_data(sph, tm_header, true)
|
||||||
}
|
}
|
||||||
fn ping_reply_with_data(timestamp: &[u8]) -> PusTmCreator {
|
fn ping_reply_with_data<'a, 'b>(timestamp: &'a [u8]) -> PusTmCreator<'a, 'b> {
|
||||||
let sph = SpHeader::new_for_unseg_tm_checked(0x123, 0x234, 0).unwrap();
|
let sph = SpHeader::new_for_unseg_tm_checked(0x123, 0x234, 0).unwrap();
|
||||||
let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp);
|
let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp);
|
||||||
PusTmCreator::new(sph, tm_header, DUMMY_DATA, true)
|
PusTmCreator::new(sph, tm_header, DUMMY_DATA, true)
|
||||||
@@ -1442,12 +1448,12 @@ mod tests {
|
|||||||
if has_user_data {
|
if has_user_data {
|
||||||
assert!(!tm.user_data().is_empty());
|
assert!(!tm.user_data().is_empty());
|
||||||
}
|
}
|
||||||
assert_eq!(PusPacket::pus_version(tm), PusC);
|
assert_eq!(PusPacket::pus_version(tm).unwrap(), PusC);
|
||||||
assert_eq!(tm.apid(), 0x123);
|
assert_eq!(tm.apid(), 0x123);
|
||||||
assert_eq!(tm.seq_count(), 0x234);
|
assert_eq!(tm.seq_count(), 0x234);
|
||||||
assert_eq!(PusPacket::pus_version(tm), PusVersion::PusC);
|
assert_eq!(PusPacket::pus_version(tm).unwrap(), PusVersion::PusC);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
GenericPusTmSecondaryHeader::pus_version(tm),
|
GenericPusTmSecondaryHeader::pus_version(tm).unwrap(),
|
||||||
PusVersion::PusC
|
PusVersion::PusC
|
||||||
);
|
);
|
||||||
assert_eq!(tm.data_len(), exp_full_len as u16 - 7);
|
assert_eq!(tm.data_len(), exp_full_len as u16 - 7);
|
||||||
|
|||||||
1952
src/ecss/tm_pus_a.rs
Normal file
1952
src/ecss/tm_pus_a.rs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user