use byteorder::{ByteOrder, BigEndian};
#[allow(dead_code)]
pub const CCSDS_VERSION: u8 = 0;
#[allow(dead_code)]
pub const CCSDS_PRI_HEADER_SIZE_BYTES: u32 = 6;
#[allow(dead_code)]
pub const CCSDS_MIN_DATA_LENGTH_BYTES: u32 = 1;
#[allow(dead_code)]
pub const CCSDS_MIN_LENGTH: u32 = CCSDS_PRI_HEADER_SIZE_BYTES + CCSDS_MIN_DATA_LENGTH_BYTES;
#[allow(dead_code)]
pub const CCSDS_MAX_LENGTH: u32 = CCSDS_PRI_HEADER_SIZE_BYTES + CCSDS_MIN_DATA_LENGTH_BYTES + 0xFFFF;
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum PacketType {
Data,
Command,
Unknown
}
impl Default for PacketType {
fn default() -> PacketType {
PacketType::Data
}
}
impl From<u8> for PacketType {
fn from(byte: u8) -> PacketType {
match byte {
0 => PacketType::Data,
1 => PacketType::Command,
_ => PacketType::Unknown
}
}
}
impl From<PacketType> for u8 {
fn from(packet_type: PacketType) -> u8 {
match packet_type {
PacketType::Data => 0,
PacketType::Command => 1,
PacketType::Unknown => 0,
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum SecondaryHeaderFlag {
NotPresent,
Present,
Unknown
}
impl Default for SecondaryHeaderFlag {
fn default() -> SecondaryHeaderFlag {
SecondaryHeaderFlag::NotPresent
}
}
impl From<u8> for SecondaryHeaderFlag {
fn from(byte: u8) -> SecondaryHeaderFlag {
match byte {
0 => SecondaryHeaderFlag::NotPresent,
1 => SecondaryHeaderFlag::Present,
_ => SecondaryHeaderFlag::Unknown
}
}
}
impl From<SecondaryHeaderFlag> for u8 {
fn from(flag: SecondaryHeaderFlag) -> u8 {
match flag {
SecondaryHeaderFlag::NotPresent => 0,
SecondaryHeaderFlag::Present => 1,
SecondaryHeaderFlag::Unknown => 0
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum SeqFlag {
Continuation,
FirstSegment,
LastSegment,
Unsegmented,
Unknown
}
impl Default for SeqFlag {
fn default() -> SeqFlag {
SeqFlag::Unsegmented
}
}
impl From<u8> for SeqFlag {
fn from(byte: u8) -> SeqFlag {
match byte {
0 => SeqFlag::Continuation,
1 => SeqFlag::FirstSegment,
2 => SeqFlag::LastSegment,
3 => SeqFlag::Unsegmented,
_ => SeqFlag::Unknown
}
}
}
impl From<SeqFlag> for u16 {
fn from(byte: SeqFlag) -> u16 {
match byte {
SeqFlag::Continuation => 0,
SeqFlag::FirstSegment => 1,
SeqFlag::LastSegment => 2,
SeqFlag::Unsegmented => 3,
SeqFlag::Unknown => 0
}
}
}
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
pub struct ControlWord(pub [u8;2]);
impl ControlWord {
pub fn version(&self) -> u16 {
return (BigEndian::read_u16(&self.0) & 0xE000) >> 13;
}
pub fn set_version(&mut self, version: u16) {
let word = (BigEndian::read_u16(&self.0) & 0x1FFF) | (version << 13);
BigEndian::write_u16(&mut self.0, word);
}
pub fn packet_type(&self) -> PacketType {
return PacketType::from(((BigEndian::read_u16(&self.0) & 0x1000) >> 12) as u8);
}
pub fn set_packet_type(&mut self, packet_type: PacketType) {
let word = (BigEndian::read_u16(&self.0) & 0xEFFF) | ((packet_type as u16) << 12);
BigEndian::write_u16(&mut self.0, word);
}
pub fn secondary_header_flag(&self) -> SecondaryHeaderFlag {
return SecondaryHeaderFlag::from(((BigEndian::read_u16(&self.0) & 0x0800) >> 11) as u8);
}
pub fn set_secondary_header_flag(&mut self, sec_header_flag: SecondaryHeaderFlag) {
let word = (BigEndian::read_u16(&self.0) & 0xF7FF) | ((sec_header_flag as u16) << 11);
BigEndian::write_u16(&mut self.0, word);
}
pub fn apid(&self) -> u16 {
return BigEndian::read_u16(&self.0) & 0x07FF;
}
pub fn set_apid(&mut self, apid: u16) {
let word = (BigEndian::read_u16(&self.0) & 0xF800) | (apid & 0x07FF);
BigEndian::write_u16(&mut self.0, word);
}
}
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
pub struct SequenceWord(pub [u8;2]);
impl SequenceWord {
pub fn sequence_type(&self) -> SeqFlag {
SeqFlag::from((BigEndian::read_u16(&self.0) >> 14) as u8)
}
pub fn set_sequence_type(&mut self, seq_flag: SeqFlag) {
let word = (BigEndian::read_u16(&self.0) & 0x3FFF) | (u16::from(seq_flag) << 14);
BigEndian::write_u16(&mut self.0, word);
}
pub fn sequence_count(&self) -> u16 {
BigEndian::read_u16(&self.0) & 0x3FFF
}
pub fn set_sequence_count(&mut self, seq_count: u16) {
let word = (BigEndian::read_u16(&self.0) & 0xC000) | (seq_count & 0x3FFF);
BigEndian::write_u16(&mut self.0, word);
}
}
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
pub struct LengthWord(pub [u8;2]);
impl LengthWord {
pub fn length_field(&self) -> u16 {
return BigEndian::read_u16(&self.0);
}
pub fn set_length_field(&mut self, length: u16) {
BigEndian::write_u16(&mut self.0, length);
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct PrimaryHeader {
pub control: ControlWord,
pub sequence: SequenceWord,
pub length: LengthWord,
}
impl PrimaryHeader {
pub fn new(bytes: [u8;6]) -> PrimaryHeader {
let mut pri_header: PrimaryHeader = Default::default();
pri_header.control.0[0] = bytes[0];
pri_header.control.0[1] = bytes[1];
pri_header.sequence.0[0] = bytes[2];
pri_header.sequence.0[1] = bytes[3];
pri_header.length.0[0] = bytes[4];
pri_header.length.0[1] = bytes[5];
return pri_header;
}
pub fn from_slice(bytes: &[u8]) -> Option<PrimaryHeader> {
if bytes.len() >= CCSDS_PRI_HEADER_SIZE_BYTES as usize {
let mut header_bytes: [u8;6] = [0; 6];
header_bytes.copy_from_slice(&bytes[0..6]);
return Some(PrimaryHeader::new(header_bytes));
} else {
return None;
}
}
pub fn packet_length(&self) -> u32 {
return self.length.length_field() as u32 + CCSDS_PRI_HEADER_SIZE_BYTES + CCSDS_MIN_DATA_LENGTH_BYTES;
}
pub fn data_length(&self) -> u32 {
return self.length.length_field() as u32 + CCSDS_MIN_DATA_LENGTH_BYTES;
}
pub fn set_packet_length(&mut self, packet_length: u16) {
BigEndian::write_u16(&mut self.length.0, packet_length);
}
}