add CRC16 dependency, continued PUS TC impl

This commit is contained in:
Robin Müller 2022-06-15 00:58:58 +02:00
parent f07a1bbb62
commit 007cf06141
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
7 changed files with 258 additions and 198 deletions

151
Cargo.lock generated
View File

@ -65,18 +65,6 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitvec"
version = "0.22.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "bus"
version = "2.2.3"
@ -128,6 +116,21 @@ dependencies = [
"volatile-register",
]
[[package]]
name = "crc"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3"
dependencies = [
"crc-catalog",
]
[[package]]
name = "crc-catalog"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff"
[[package]]
name = "critical-section"
version = "0.2.7"
@ -161,64 +164,6 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "darling"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "649c91bc01e8b1eac09fb91e8dbc7d517684ca6be8ebc75bb9cafc894f9fdb6f"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "deku"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "868ccf23869582b2d79279e402db457fe341da24a0c5a8927c6154a5b4733dc3"
dependencies = [
"bitvec",
"deku_derive",
]
[[package]]
name = "deku_derive"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dfb4274ccd1c87a598e98b398b4b630aecb2e8a32fd7c88ffa190fb73870f72"
dependencies = [
"darling",
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "embedded-hal"
version = "0.2.7"
@ -229,18 +174,6 @@ dependencies = [
"void",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "funty"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e"
[[package]]
name = "hash32"
version = "0.2.1"
@ -273,18 +206,12 @@ dependencies = [
"libc",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "launchpad"
version = "0.1.0"
dependencies = [
"bus",
"deku",
"crc",
"heapless",
"num",
"postcard",
@ -459,16 +386,6 @@ version = "0.1.5-pre"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c68cb38ed13fd7bc9dd5db8f165b7c8d9c1a315104083a2b10f11354c2af97f"
[[package]]
name = "proc-macro-crate"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
dependencies = [
"thiserror",
"toml",
]
[[package]]
name = "proc-macro2"
version = "1.0.39"
@ -487,12 +404,6 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "radium"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb"
[[package]]
name = "redox_syscall"
version = "0.1.57"
@ -623,12 +534,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.96"
@ -652,12 +557,6 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "thiserror"
version = "1.0.31"
@ -678,15 +577,6 @@ dependencies = [
"syn",
]
[[package]]
name = "toml"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
dependencies = [
"serde",
]
[[package]]
name = "unicode-ident"
version = "1.0.1"
@ -742,15 +632,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "wyz"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188"
dependencies = [
"tap",
]
[[package]]
name = "zerocopy"
version = "0.6.1"

View File

@ -12,6 +12,5 @@ num = "0.4"
heapless = "0.7.13"
postcard = { version = "0.7.3", features = ["use-std"] }
serde = "1.0.137"
deku = "0.13"
# ccsds_spacepacket = "0.2.0"
zerocopy = "0.6.1"
crc = "3.0.0"

View File

@ -1,7 +1,7 @@
use postcard::{from_bytes, to_stdvec, to_vec};
use postcard::to_stdvec;
use serde::{Deserialize, Serialize};
use zerocopy::byteorder::{U16, I32};
use zerocopy::{FromBytes, AsBytes, Unaligned, NetworkEndian};
use zerocopy::byteorder::{I32, U16};
use zerocopy::{AsBytes, FromBytes, NetworkEndian, Unaligned};
#[derive(AsBytes, FromBytes, Unaligned, Debug, Eq, PartialEq)]
#[repr(C, packed)]
@ -9,7 +9,7 @@ struct ZeroCopyTest {
some_bool: u8,
some_u16: U16<NetworkEndian>,
some_i32: I32<NetworkEndian>,
some_float: [u8; 4]
some_float: [u8; 4],
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
@ -17,7 +17,7 @@ struct PostcardTest {
some_bool: u8,
some_u16: u16,
some_i32: i32,
some_float: f32
some_float: f32,
}
fn main() {
@ -25,7 +25,7 @@ fn main() {
some_bool: true as u8,
some_u16: 0x42,
some_i32: -200,
some_float: 7.7_f32
some_float: 7.7_f32,
};
let out = to_stdvec(&pc_test).unwrap();
@ -35,7 +35,7 @@ fn main() {
some_bool: true as u8,
some_u16: U16::from(0x42),
some_i32: I32::from(-200),
some_float: 7.7_f32.to_ne_bytes()
some_float: 7.7_f32.to_ne_bytes(),
};
let mut slice = [0; 11];
sample_hk.write_to(slice.as_mut_slice());

13
src/sp/ecss.rs Normal file
View File

@ -0,0 +1,13 @@
use crate::sp::CcsdsPacket;
pub trait PusPacket: CcsdsPacket {
fn service(&self) -> u8;
fn subservice(&self) -> u8;
fn source_id(&self) -> u16;
fn ack_flags(&self) -> u8;
fn user_data(&self) -> Option<&[u8]>;
fn crc16(&self) -> u16;
/// Verify that the packet is valid. PUS packets have a CRC16 checksum to do this
fn verify(&mut self) -> bool;
}

View File

@ -1,5 +1,6 @@
//! # Space related components including CCSDS and ECSS packet standards
use serde::{Deserialize, Serialize};
pub mod ecss;
pub mod tc;
pub mod tm;
@ -90,7 +91,7 @@ impl From<u16> for PacketId {
PacketId {
ptype: PacketType::try_from(((raw_id >> 12) & 0b1) as u8).unwrap(),
sec_header_flag: ((raw_id >> 11) & 0b1) != 0,
apid: raw_id & 0x7FFF,
apid: raw_id & 0x7FF,
}
}
}
@ -128,7 +129,7 @@ impl From<u16> for PacketSequenceCtrl {
fn from(raw_id: u16) -> Self {
PacketSequenceCtrl {
seq_flags: SequenceFlags::try_from(((raw_id >> 14) & 0b11) as u8).unwrap(),
ssc: raw_id & 0x3FFF,
ssc: raw_id & SSC_MASK,
}
}
}
@ -148,17 +149,11 @@ macro_rules! sph_from_other {
};
}
const SSC_MASK: u16 = 0x3FFF;
const VERSION_MASK: u16 = 0xE000;
/// Generic trait to access fields of a CCSDS space packet header according to CCSDS 133.0-B-2
pub trait CcsdsPrimaryHeader {
const SEQ_FLAG_MASK: u16 = 0xC000;
fn from_composite_fields(
packet_id: PacketId,
psc: PacketSequenceCtrl,
data_len: u16,
version: Option<u8>,
) -> Self;
pub trait CcsdsPacket {
fn version(&self) -> u8;
fn packet_id(&self) -> PacketId;
fn psc(&self) -> PacketSequenceCtrl;
@ -221,13 +216,23 @@ pub trait CcsdsPrimaryHeader {
}
}
pub trait CcsdsPrimaryHeader {
fn from_composite_fields(
packet_id: PacketId,
psc: PacketSequenceCtrl,
data_len: u16,
version: Option<u8>,
) -> Self;
}
pub mod srd {
use crate::sp::{
self, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl, PacketType, SequenceFlags,
self, CcsdsPacket, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl, PacketType,
SequenceFlags,
};
/// Space Packet Primary Header according to CCSDS 133.0-B-2
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Copy, Clone)]
pub struct SpHeader {
pub version: u8,
pub packet_id: PacketId,
@ -272,25 +277,7 @@ pub mod srd {
}
}
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,
}
}
impl CcsdsPacket for SpHeader {
#[inline]
fn version(&self) -> u8 {
self.version
@ -312,15 +299,37 @@ pub mod srd {
}
}
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, sp::zc::SpHeader);
}
pub mod zc {
use crate::sp::{self, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl};
use crate::sp::{
self, CcsdsPacket, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl, VERSION_MASK,
};
use zerocopy::byteorder::NetworkEndian;
use zerocopy::{AsBytes, FromBytes, Unaligned, U16};
#[derive(FromBytes, AsBytes, Unaligned)]
#[derive(FromBytes, AsBytes, Unaligned, Debug)]
#[repr(C)]
pub struct SpHeader {
version_packet_id: U16<NetworkEndian>,
@ -345,6 +354,37 @@ pub mod zc {
data_len: U16::from(data_len),
}
}
pub fn from_slice(slice: impl AsRef<[u8]>) -> Option<Self> {
SpHeader::read_from(slice.as_ref())
}
}
impl CcsdsPacket for SpHeader {
#[inline]
fn version(&self) -> u8 {
((self.version_packet_id.get() >> 13) as u8) & 0b111
}
fn packet_id_raw(&self) -> u16 {
self.version_packet_id.get() & (!VERSION_MASK)
}
fn packet_id(&self) -> PacketId {
PacketId::from(self.packet_id_raw())
}
fn psc_raw(&self) -> u16 {
self.psc.get()
}
fn psc(&self) -> PacketSequenceCtrl {
PacketSequenceCtrl::from(self.psc_raw())
}
#[inline]
fn data_len(&self) -> u16 {
self.data_len.get()
}
}
impl CcsdsPrimaryHeader for SpHeader {
@ -356,24 +396,6 @@ pub mod zc {
) -> Self {
SpHeader::new(packet_id, psc, data_len, version)
}
#[inline]
fn version(&self) -> u8 {
((self.version_packet_id.get() >> 13) as u8) & 0b111
}
fn packet_id(&self) -> PacketId {
PacketId::from(self.packet_id_raw())
}
fn psc(&self) -> PacketSequenceCtrl {
PacketSequenceCtrl::from(self.packet_id_raw())
}
#[inline]
fn data_len(&self) -> u16 {
self.data_len.get()
}
}
sph_from_other!(SpHeader, sp::srd::SpHeader);
@ -383,7 +405,7 @@ pub mod zc {
mod tests {
use crate::sp;
use crate::sp::srd::SpHeader;
use crate::sp::{CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl, PacketType, SequenceFlags};
use crate::sp::{zc, CcsdsPacket, PacketId, PacketSequenceCtrl, PacketType, SequenceFlags};
use postcard::{from_bytes, to_stdvec};
#[test]
@ -492,5 +514,15 @@ mod tests {
assert_eq!(slice[3], 0xFF);
assert_eq!(slice[4], 0x00);
assert_eq!(slice[5], 0x00);
let sp_header = zc::SpHeader::from_slice(slice);
assert!(sp_header.is_some());
let sp_header = sp_header.unwrap();
println!("Header: {:?}", sp_header);
assert_eq!(sp_header.version(), 0b000);
assert_eq!(sp_header.packet_id_raw(), 0x1FFF);
assert_eq!(sp_header.apid(), 0x7FF);
assert_eq!(sp_header.ptype(), PacketType::Tc);
assert_eq!(sp_header.data_len(), 0);
}
}

View File

@ -0,0 +1,134 @@
use crc::{Crc, CRC_16_IBM_3740};
use serde::{Deserialize, Serialize};
/// All PUS versions. Only PUS C is supported by this library
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize)]
pub enum PusVersion {
EsaPus = 0,
PusA = 1,
PusC = 2,
}
pub const CRC_CCITT_FALSE: Crc<u16> = Crc::<u16>::new(&CRC_16_IBM_3740);
pub mod srd {
use crate::sp::ecss::PusPacket;
use crate::sp::srd::SpHeader;
use crate::sp::tc::{PusVersion, CRC_CCITT_FALSE};
use crate::sp::{CcsdsPacket, PacketId, PacketSequenceCtrl};
use serde::{Deserialize, Serialize};
#[derive(PartialEq, Copy, Clone, Serialize, Deserialize)]
pub struct PusTcDataFieldHeader {
pub service: u8,
pub subservice: u8,
pub source_id: u16,
pub ack: u8,
pub version: PusVersion,
}
impl PusTcDataFieldHeader {
pub fn new(service: u8, subservice: u8, ack: u8) -> Self {
PusTcDataFieldHeader {
service,
subservice,
ack,
source_id: 0,
version: PusVersion::PusC,
}
}
}
pub struct PusTc<'slice> {
pub sph: SpHeader,
pub data_field_header: PusTcDataFieldHeader,
raw_data: Option<&'slice [u8]>,
app_data: Option<&'slice [u8]>,
crc16: u16,
}
impl<'slice> PusTc<'slice> {
pub fn new(
sph: &SpHeader,
service: u8,
subservice: u8,
app_data: Option<&'slice [u8]>,
) -> Self {
PusTc {
sph: sph.clone(),
raw_data: None,
app_data,
data_field_header: PusTcDataFieldHeader::new(service, subservice, 0b1111),
crc16: 0,
}
}
}
impl CcsdsPacket for PusTc<'_> {
fn version(&self) -> u8 {
self.sph.version
}
fn packet_id(&self) -> PacketId {
self.sph.packet_id
}
fn psc(&self) -> PacketSequenceCtrl {
self.sph.psc
}
fn data_len(&self) -> u16 {
self.sph.data_len
}
}
impl PusPacket for PusTc<'_> {
fn service(&self) -> u8 {
self.data_field_header.service
}
fn subservice(&self) -> u8 {
self.data_field_header.subservice
}
fn source_id(&self) -> u16 {
self.data_field_header.source_id
}
fn ack_flags(&self) -> u8 {
self.data_field_header.ack
}
fn user_data(&self) -> Option<&[u8]> {
self.app_data
}
fn crc16(&self) -> u16 {
self.crc16
}
fn verify(&mut self) -> bool {
let mut digest = CRC_CCITT_FALSE.digest();
if self.raw_data.is_none() {
return false;
}
digest.update(self.raw_data.unwrap().as_ref());
if digest.finalize() == 0 {
return true;
}
false
}
}
}
pub mod zc {
use zerocopy::{AsBytes, FromBytes, NetworkEndian, Unaligned, U16};
#[derive(FromBytes, AsBytes, Unaligned)]
#[repr(C)]
pub struct PusTcDataFieldHeader {
version_ack: u8,
service: u8,
subservice: u8,
source_id: U16<NetworkEndian>,
}
}

View File

@ -0,0 +1 @@