start baseline CUC Impl
This commit is contained in:
parent
48e5b22c27
commit
c60ebc2a6e
@ -224,6 +224,14 @@ pub trait ToBeBytes {
|
|||||||
fn to_be_bytes(&self) -> Self::ByteArray;
|
fn to_be_bytes(&self) -> Self::ByteArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToBeBytes for () {
|
||||||
|
type ByteArray = [u8; 0];
|
||||||
|
|
||||||
|
fn to_be_bytes(&self) -> Self::ByteArray {
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToBeBytes for u8 {
|
impl ToBeBytes for u8 {
|
||||||
type ByteArray = [u8; 1];
|
type ByteArray = [u8; 1];
|
||||||
|
|
||||||
|
119
src/time.rs
119
src/time.rs
@ -814,6 +814,125 @@ pub mod cds {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod cuc {
|
||||||
|
use core::fmt::Debug;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct WidthCounterPair(u8, u32);
|
||||||
|
|
||||||
|
/// This provider uses the CCSDS epoch. Furthermore the preamble field only has one byte,
|
||||||
|
/// which allows a time code representation through the year 2094.
|
||||||
|
///
|
||||||
|
/// More specifically, only having a preamble field of one byte limits the width of the counter
|
||||||
|
/// type (generally seconds) to 4 bytes and the width of the fractions type to 3 bytes.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct TimeProviderCcsdsEpoch {
|
||||||
|
pfield: u8,
|
||||||
|
counter: WidthCounterPair,
|
||||||
|
fractions: Option<WidthCounterPair>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn pfield_len(pfield: u8) -> usize {
|
||||||
|
if ((pfield >> 7) & 0b1) == 1 {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TimeProviderCcsdsEpoch {
|
||||||
|
fn build_p_field(counter_width: u8, fractions_width: Option<u8>) -> u8 {
|
||||||
|
let mut pfield = (CcsdsTimeCodes::CucCcsdsEpoch as u8) << 4;
|
||||||
|
if counter_width < 1 || counter_width > 4 {
|
||||||
|
panic!("invalid counter width {} for cuc timestamp", counter_width);
|
||||||
|
}
|
||||||
|
pfield |= counter_width << 3;
|
||||||
|
if let Some(fractions_width) = fractions_width {
|
||||||
|
if fractions_width < 1 || fractions_width > 3 {
|
||||||
|
panic!("invalid fractions width {} for cuc timestamp", fractions_width);
|
||||||
|
}
|
||||||
|
pfield |= fractions_width;
|
||||||
|
}
|
||||||
|
pfield
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn len_packed(&self) -> usize {
|
||||||
|
// TODO: Implement
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TimeProviderCcsdsEpoch {
|
||||||
|
pub fn new_default(counter: u32) -> Self {
|
||||||
|
Self::new(WidthCounterPair(4, counter), None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(counter: WidthCounterPair, fractions: Option<WidthCounterPair>) -> Self {
|
||||||
|
let fractions_width = match fractions {
|
||||||
|
None => 0,
|
||||||
|
Some(fractions) => fractions.0
|
||||||
|
};
|
||||||
|
Self {
|
||||||
|
pfield: Self::build_p_field(counter.0.into(), fractions_width.into()),
|
||||||
|
counter,
|
||||||
|
fractions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TimeReader for TimeProviderCcsdsEpoch {
|
||||||
|
fn from_bytes(_buf: &[u8]) -> Result<Self, TimestampError> where Self: Sized {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TimeWriter for TimeProviderCcsdsEpoch {
|
||||||
|
fn write_to_bytes(&self, bytes: &mut [u8]) -> Result<usize, TimestampError> {
|
||||||
|
// Cross check the sizes of the counters against byte widths in the ctor
|
||||||
|
if bytes.len() < self.len_packed() {
|
||||||
|
return Err(TimestampError::ByteConversionError(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
|
||||||
|
found: bytes.len(),
|
||||||
|
expected: self.len_packed()
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
bytes[0] = self.pfield;
|
||||||
|
let mut current_idx: usize = 1;
|
||||||
|
match self.counter.0 {
|
||||||
|
1 => {
|
||||||
|
bytes[1] = self.counter.1 as u8;
|
||||||
|
},
|
||||||
|
2 => {
|
||||||
|
bytes[1..3].copy_from_slice(&(self.counter.1 as u16).to_be_bytes());
|
||||||
|
},
|
||||||
|
3 => {
|
||||||
|
bytes[1..4].copy_from_slice(&self.counter.1.to_be_bytes()[1..4]);
|
||||||
|
},
|
||||||
|
4 => {
|
||||||
|
bytes[1..5].copy_from_slice(&self.counter.1.to_be_bytes());
|
||||||
|
},
|
||||||
|
// Should never happen
|
||||||
|
_ => panic!("invalid counter width value")
|
||||||
|
}
|
||||||
|
current_idx += self.counter.0 as usize;
|
||||||
|
if let Some(fractions) = self.fractions {
|
||||||
|
match fractions.0 {
|
||||||
|
1 => bytes[current_idx] = fractions.1 as u8,
|
||||||
|
2 => bytes[current_idx..current_idx + 2].copy_from_slice(&(fractions.1 as u16).to_be_bytes()),
|
||||||
|
3 => bytes[current_idx..current_idx + 3].copy_from_slice(&fractions.1.to_be_bytes()[1..4]),
|
||||||
|
// Should also never happen
|
||||||
|
_ => panic!("invalid fractions value")
|
||||||
|
}
|
||||||
|
current_idx += fractions.0 as usize;
|
||||||
|
}
|
||||||
|
Ok(current_idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
/// Module to generate the ASCII timecodes specified in
|
/// Module to generate the ASCII timecodes specified in
|
||||||
/// [CCSDS 301.0-B-4](https://public.ccsds.org/Pubs/301x0b4e1.pdf) section 3.5 .
|
/// [CCSDS 301.0-B-4](https://public.ccsds.org/Pubs/301x0b4e1.pdf) section 3.5 .
|
||||||
/// See [chrono::DateTime::format] for a usage example of the generated
|
/// See [chrono::DateTime::format] for a usage example of the generated
|
||||||
|
Loading…
Reference in New Issue
Block a user