From d1e55cb05813ae041ea0b4ade7d8370781e38614 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 13 Jun 2022 23:22:15 +0200 Subject: [PATCH 01/16] added some deps for serde tests --- Cargo.lock | 443 +++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 4 + src/lib.rs | 1 + src/main.rs | 30 ++++ src/sp.rs | 16 ++ 5 files changed, 492 insertions(+), 2 deletions(-) create mode 100644 src/sp.rs diff --git a/Cargo.lock b/Cargo.lock index 04224db..49a4bb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,24 +2,81 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + [[package]] name = "atomic-option" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0db678acb667b525ac40a324fc5f7d3390e29239b31c7327bb8157f5b4fff593" +[[package]] +name = "atomic-polyfill" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14bf7b4f565e5e717d7a7a65b2a05c0b8c96e4db636d6f780f03b15108cdd1b" +dependencies = [ + "critical-section", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + +[[package]] +name = "bare-metal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" + +[[package]] +name = "bit_field" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + [[package]] name = "bitflags" 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" @@ -32,12 +89,24 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "cloudabi" version = "0.0.3" @@ -47,6 +116,30 @@ dependencies = [ "bitflags", ] +[[package]] +name = "cortex-m" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd20d4ac4aa86f4f75f239d59e542ef67de87cce2c282818dc6e84155d3ea126" +dependencies = [ + "bare-metal 0.2.5", + "bitfield", + "embedded-hal", + "volatile-register", +] + +[[package]] +name = "critical-section" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95da181745b56d4bd339530ec393508910c909c784e8962d15d722bacf0bcbcd" +dependencies = [ + "bare-metal 1.0.0", + "cfg-if 1.0.0", + "cortex-m", + "riscv", +] + [[package]] name = "crossbeam-channel" version = "0.4.4" @@ -64,10 +157,113 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ "autocfg", - "cfg-if", + "cfg-if 0.1.10", "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a08e755adbc0ad283725b29f4a4883deee15336f372d5f61fae59efec40f983" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version 0.4.0", + "serde", + "spin", + "stable_deref_trait", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -77,12 +273,22 @@ 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", + "heapless", "num", + "postcard", + "serde", "thiserror", ] @@ -98,12 +304,43 @@ version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +[[package]] +name = "lock_api" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "maybe-uninit" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.0.0", +] + +[[package]] +name = "nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" + [[package]] name = "num" version = "0.4.0" @@ -196,7 +433,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "cloudabi", "libc", "redox_syscall", @@ -204,6 +441,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "postcard" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a25c0b0ae06fcffe600ad392aabfa535696c8973f2253d9ac83171924c58a858" +dependencies = [ + "heapless", + "postcard-cobs", + "serde", +] + +[[package]] +name = "postcard-cobs" +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.38" @@ -222,18 +486,148 @@ 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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +[[package]] +name = "regex" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" + +[[package]] +name = "riscv" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6907ccdd7a31012b70faf2af85cd9e5ba97657cc3987c4f13f8e4d2c2a088aba" +dependencies = [ + "bare-metal 1.0.0", + "bit_field", + "riscv-target", +] + +[[package]] +name = "riscv-target" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.10", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41d061efea015927ac527063765e73601444cdc344ba855bc7bd44578b25e1c" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "smallvec" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +[[package]] +name = "spin" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +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.94" @@ -245,6 +639,12 @@ 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" @@ -265,12 +665,42 @@ 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-xid" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" +dependencies = [ + "vcell", +] + [[package]] name = "winapi" version = "0.3.9" @@ -292,3 +722,12 @@ name = "winapi-x86_64-pc-windows-gnu" 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", +] diff --git a/Cargo.toml b/Cargo.toml index b443f50..014da40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,7 @@ edition = "2021" thiserror = "1.0" bus = "2.2.3" num = "0.4" +heapless = "0.7.13" +postcard = "0.7.3" +serde = "1.0.137" +deku = "0.13" diff --git a/src/lib.rs b/src/lib.rs index 5a7ca06..737935d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,2 @@ pub mod core; +pub mod sp; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 3033f62..9313ef0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,34 @@ +use core::ops::Deref; +use serde::{Serialize, Deserialize}; +use postcard::{from_bytes, to_vec}; +use heapless::Vec; + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +struct RefStruct<'a> { + bytes: &'a [u8], + str_s: &'a str, +} + fn main() { + let message = "hElLo"; + let bytes = [0x01, 0x10, 0x02, 0x20]; + let output: Vec = to_vec(&RefStruct { + bytes: &bytes, + str_s: message, + }).unwrap(); + assert_eq!( + &[0x04, 0x01, 0x10, 0x02, 0x20, 0x05, b'h', b'E', b'l', b'L', b'o',], + output.deref() + ); + + let out: RefStruct = from_bytes(output.deref()).unwrap(); + assert_eq!( + out, + RefStruct { + bytes: &bytes, + str_s: message, + } + ); } diff --git a/src/sp.rs b/src/sp.rs new file mode 100644 index 0000000..cab55a4 --- /dev/null +++ b/src/sp.rs @@ -0,0 +1,16 @@ +//! # Space related components including CCSDS and ECSS packet standards +use serde::{Serialize, Deserialize}; + +pub enum PacketType { + Tm = 0, + Tc = 1 +} + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +struct SpHeader { + pub version: u8, + pub ptype: PacketType, + pub apid: u16, + pub secondary_header_flag: u8, + pub ssc: u16, +} \ No newline at end of file From 4708481052cfc6ef4a54739206676e3bd7b8e8ad Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 14 Jun 2022 01:25:18 +0200 Subject: [PATCH 02/16] added first sp tests --- Cargo.lock | 80 ++++++++++++++++-- Cargo.toml | 3 +- src/core/pool.rs | 74 ++++++++++++----- src/lib.rs | 2 +- src/main.rs | 8 +- src/sp.rs | 208 +++++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 338 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 49a4bb1..f69ca73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,6 +95,15 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "ccsds_spacepacket" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82251e34d2bbc33273c38d7720b65373e55e311fa0c4134b60b03601dbc92cf2" +dependencies = [ + "deku 0.12.6", +] + [[package]] name = "cfg-if" version = "0.1.10" @@ -161,14 +170,38 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core 0.13.4", + "darling_macro 0.13.4", +] + [[package]] name = "darling" version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.14.1", + "darling_macro 0.14.1", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", ] [[package]] @@ -185,17 +218,38 @@ dependencies = [ "syn", ] +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core 0.13.4", + "quote", + "syn", +] + [[package]] name = "darling_macro" version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5" dependencies = [ - "darling_core", + "darling_core 0.14.1", "quote", "syn", ] +[[package]] +name = "deku" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe18ce09f5d512cad19bbac22e395aa36cfa12cf699a3bcb3787af62dde4b13a" +dependencies = [ + "bitvec", + "deku_derive 0.12.6", +] + [[package]] name = "deku" version = "0.13.1" @@ -203,7 +257,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "868ccf23869582b2d79279e402db457fe341da24a0c5a8927c6154a5b4733dc3" dependencies = [ "bitvec", - "deku_derive", + "deku_derive 0.13.1", +] + +[[package]] +name = "deku_derive" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "691ea0b164aad4a4517f5b47130e15868af1f02fed614c45a1967cbfe2c318d7" +dependencies = [ + "darling 0.13.4", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -212,7 +279,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dfb4274ccd1c87a598e98b398b4b630aecb2e8a32fd7c88ffa190fb73870f72" dependencies = [ - "darling", + "darling 0.14.1", "proc-macro-crate", "proc-macro2", "quote", @@ -284,7 +351,8 @@ name = "launchpad" version = "0.1.0" dependencies = [ "bus", - "deku", + "ccsds_spacepacket", + "deku 0.13.1", "heapless", "num", "postcard", diff --git a/Cargo.toml b/Cargo.toml index 014da40..e7002c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ thiserror = "1.0" bus = "2.2.3" num = "0.4" heapless = "0.7.13" -postcard = "0.7.3" +postcard = { version = "0.7.3", features = ["use-std"] } serde = "1.0.137" deku = "0.13" +ccsds_spacepacket = "0.2.0" diff --git a/src/core/pool.rs b/src/core/pool.rs index 67a4ad0..ea3047a 100644 --- a/src/core/pool.rs +++ b/src/core/pool.rs @@ -43,7 +43,7 @@ impl StoreAddr { #[derive(Debug, Clone, PartialEq)] pub enum StoreIdError { InvalidSubpool(u16), - InvalidPacketIdx(u16) + InvalidPacketIdx(u16), } #[derive(Debug, Clone, PartialEq)] @@ -129,10 +129,16 @@ impl LocalPool { fn addr_check(&self, addr: &StoreAddr) -> Result { let pool_idx = addr.pool_idx as usize; if pool_idx as usize >= self.pool_cfg.cfg.len() { - return Err(StoreError::InvalidStoreId(StoreIdError::InvalidSubpool(addr.pool_idx), Some(*addr))); + return Err(StoreError::InvalidStoreId( + StoreIdError::InvalidSubpool(addr.pool_idx), + Some(*addr), + )); } if addr.packet_idx >= self.pool_cfg.cfg[addr.pool_idx as usize].0 { - return Err(StoreError::InvalidStoreId(StoreIdError::InvalidPacketIdx(addr.packet_idx), Some(*addr))); + return Err(StoreError::InvalidStoreId( + StoreIdError::InvalidPacketIdx(addr.packet_idx), + Some(*addr), + )); } let size_list = self.sizes_lists.get(pool_idx).unwrap(); let curr_size = size_list[addr.packet_idx as usize]; @@ -190,7 +196,10 @@ impl LocalPool { } } } else { - return Err(StoreError::InvalidStoreId(StoreIdError::InvalidSubpool(subpool),None)); + return Err(StoreError::InvalidStoreId( + StoreIdError::InvalidSubpool(subpool), + None, + )); } Err(StoreError::StoreFull(subpool)) } @@ -230,12 +239,15 @@ mod tests { let pool_cfg = PoolCfg::new(vec![(4, 4), (2, 8), (1, 16)]); let mut local_pool = LocalPool::new(pool_cfg); // Try to access data which does not exist - let res = local_pool.read(&StoreAddr{ + let res = local_pool.read(&StoreAddr { packet_idx: 0, - pool_idx: 0 + pool_idx: 0, }); assert!(res.is_err()); - assert!(matches!(res.unwrap_err(), StoreError::DataDoesNotExist { .. })); + assert!(matches!( + res.unwrap_err(), + StoreError::DataDoesNotExist { .. } + )); let mut test_buf: [u8; 16] = [0; 16]; for (i, val) in test_buf.iter_mut().enumerate() { *val = i as u8; @@ -244,16 +256,19 @@ mod tests { assert!(res.is_ok()); let addr = res.unwrap(); // Only the second subpool has enough storage and only one bucket - assert_eq!(addr, StoreAddr { - pool_idx: 2, - packet_idx: 0 - }); + assert_eq!( + addr, + StoreAddr { + pool_idx: 2, + packet_idx: 0 + } + ); // The subpool is now full and the call should fail accordingly let res = local_pool.add(test_buf.as_slice()); assert!(res.is_err()); let err = res.unwrap_err(); - assert!(matches!(err, StoreError::StoreFull {..})); + assert!(matches!(err, StoreError::StoreFull { .. })); if let StoreError::StoreFull(subpool) = err { assert_eq!(subpool, 2); } @@ -264,7 +279,7 @@ mod tests { let buf_read_back = res.unwrap(); assert_eq!(buf_read_back.len(), 16); for (i, &val) in buf_read_back.iter().enumerate() { - assert_eq!(val , i as u8); + assert_eq!(val, i as u8); } // Delete the data @@ -276,7 +291,13 @@ mod tests { let res = local_pool.free_element(12); assert!(res.is_ok()); let (addr, buf_ref) = res.unwrap(); - assert_eq!(addr, StoreAddr {pool_idx: 2, packet_idx:0}); + assert_eq!( + addr, + StoreAddr { + pool_idx: 2, + packet_idx: 0 + } + ); assert_eq!(buf_ref.len(), 12); assert_eq!(buf_ref, [0; 12]); buf_ref[0] = 5; @@ -300,20 +321,32 @@ mod tests { } { - let addr = StoreAddr{pool_idx: 3, packet_idx: 0}; + let addr = StoreAddr { + pool_idx: 3, + packet_idx: 0, + }; let res = local_pool.read(&addr); assert!(res.is_err()); let err = res.unwrap_err(); - assert!(matches!(err, StoreError::InvalidStoreId(StoreIdError::InvalidSubpool(3), Some(_)))); + assert!(matches!( + err, + StoreError::InvalidStoreId(StoreIdError::InvalidSubpool(3), Some(_)) + )); } { - let addr = StoreAddr{pool_idx: 2, packet_idx: 1}; + let addr = StoreAddr { + pool_idx: 2, + packet_idx: 1, + }; assert_eq!(addr.raw(), 0x00020001); let res = local_pool.read(&addr); assert!(res.is_err()); let err = res.unwrap_err(); - assert!(matches!(err, StoreError::InvalidStoreId(StoreIdError::InvalidPacketIdx(1), Some(_)))); + assert!(matches!( + err, + StoreError::InvalidStoreId(StoreIdError::InvalidPacketIdx(1), Some(_)) + )); let data_too_large = [0; 20]; let res = local_pool.add(data_too_large.as_slice()); @@ -323,7 +356,10 @@ mod tests { let res = local_pool.free_element(LocalPool::MAX_SIZE + 1); assert!(res.is_err()); - assert_eq!(res.unwrap_err(), StoreError::DataTooLarge(LocalPool::MAX_SIZE + 1)); + assert_eq!( + res.unwrap_err(), + StoreError::DataTooLarge(LocalPool::MAX_SIZE + 1) + ); } { diff --git a/src/lib.rs b/src/lib.rs index 737935d..9ebb096 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,2 @@ pub mod core; -pub mod sp; \ No newline at end of file +pub mod sp; diff --git a/src/main.rs b/src/main.rs index 9313ef0..7e28bde 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use core::ops::Deref; -use serde::{Serialize, Deserialize}; -use postcard::{from_bytes, to_vec}; use heapless::Vec; +use postcard::{from_bytes, to_vec}; +use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] struct RefStruct<'a> { @@ -9,14 +9,14 @@ struct RefStruct<'a> { str_s: &'a str, } - fn main() { let message = "hElLo"; let bytes = [0x01, 0x10, 0x02, 0x20]; let output: Vec = to_vec(&RefStruct { bytes: &bytes, str_s: message, - }).unwrap(); + }) + .unwrap(); assert_eq!( &[0x04, 0x01, 0x10, 0x02, 0x20, 0x05, b'h', b'E', b'l', b'L', b'o',], diff --git a/src/sp.rs b/src/sp.rs index cab55a4..0a7e3c5 100644 --- a/src/sp.rs +++ b/src/sp.rs @@ -1,16 +1,212 @@ //! # Space related components including CCSDS and ECSS packet standards -use serde::{Serialize, Deserialize}; +use ccsds_spacepacket::PrimaryHeader; +pub use ccsds_spacepacket::PrimaryHeader as DekuSpHeader; +use serde::{Deserialize, Serialize}; +#[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone)] pub enum PacketType { Tm = 0, - Tc = 1 + Tc = 1, } -#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] -struct SpHeader { +impl TryFrom for PacketType { + type Error = (); + + fn try_from(value: u8) -> Result { + match value { + x if x == PacketType::Tm as u8 => Ok(PacketType::Tm), + x if x == PacketType::Tc as u8 => Ok(PacketType::Tc), + _ => Err(()), + } + } +} + +#[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone)] +pub enum SequenceFlags { + ContinuationSegment = 0b00, + FirstSegment = 0b01, + LastSegment = 0b10, + Unsegmented = 0b11, +} + +impl TryFrom for SequenceFlags { + type Error = (); + + fn try_from(value: u8) -> Result { + match value { + x if x == SequenceFlags::ContinuationSegment as u8 => { + Ok(SequenceFlags::ContinuationSegment) + } + x if x == SequenceFlags::FirstSegment as u8 => Ok(SequenceFlags::FirstSegment), + x if x == SequenceFlags::LastSegment as u8 => Ok(SequenceFlags::LastSegment), + x if x == SequenceFlags::Unsegmented as u8 => Ok(SequenceFlags::Unsegmented), + _ => Err(()), + } + } +} + +/// Space Packet Primary Header according to CCSDS 133.0-B-2 +#[derive(Serialize, Deserialize, Debug, PartialEq)] +pub struct SpHeader { pub version: u8, pub ptype: PacketType, pub apid: u16, - pub secondary_header_flag: u8, + pub secondary_header_flag: bool, + pub sequence_flags: SequenceFlags, pub ssc: u16, -} \ No newline at end of file + pub packet_data_len: u16, +} + +impl Default for SpHeader { + fn default() -> Self { + SpHeader { + version: 0, + ptype: PacketType::Tm, + apid: 0, + secondary_header_flag: true, + sequence_flags: SequenceFlags::Unsegmented, + ssc: 0, + packet_data_len: 0, + } + } +} +impl SpHeader { + pub fn new(apid: u16, ptype: PacketType, ssc: u16) -> Option { + if ssc > num::pow(2, 14) || apid > num::pow(2, 11) { + return None; + } + let mut header = SpHeader::default(); + header.ptype = ptype; + header.apid = apid; + header.ssc = ssc; + Some(header) + } + + pub fn tm(apid: u16, ssc: u16) -> Option { + Self::new(apid, PacketType::Tm, ssc) + } + + pub fn tc(apid: u16, ssc: u16) -> Option { + Self::new(apid, PacketType::Tc, ssc) + } + + /// Function to retrieve the packet sequence control field + #[inline] + pub fn psc(&self) -> u16 { + ((self.sequence_flags as u16) << 14) | self.secondary_header_flag as u16 + } + + /// Retrieve Packet Identification composite field + #[inline] + pub fn packet_id(&self) -> u16 { + ((self.ptype as u16) << 13) | ((self.secondary_header_flag as u16) << 12) | self.apid + } + + #[inline] + pub fn is_tm(&self) -> bool { + self.ptype == PacketType::Tm + } + + #[inline] + pub fn is_tc(&self) -> bool { + self.ptype == PacketType::Tc + } +} + +/// The [DekuSpHeader] is very useful to deserialize a packed raw space packet header with 6 bytes. +/// This function allows converting it to the [SpHeader] which is compatible to the [serde] +/// framework +impl TryFrom for SpHeader { + type Error = (); + + fn try_from(header: PrimaryHeader) -> Result { + let seq_num = SequenceFlags::try_from(header.sequence_flags as u8)?; + let packet_type = PacketType::try_from(header.packet_type as u8)?; + let sec_header_flag = header.sec_header_flag as u8 != 0; + Ok(SpHeader { + version: header.version, + sequence_flags: seq_num, + packet_data_len: header.data_length, + ssc: header.sequence_count, + ptype: packet_type, + apid: header.app_proc_id, + secondary_header_flag: sec_header_flag, + }) + } +} + +/// It is possible to convert the [serde] compatible [SpHeader] back into a [DekuSpHeader] +/// to allow for packed binary serialization +impl TryFrom for DekuSpHeader { + type Error = (); + + fn try_from(value: SpHeader) -> Result { + use ccsds_spacepacket::types::PacketType as DekuPacketType; + use ccsds_spacepacket::types::SecondaryHeaderFlag as DekuSecHeaderFlag; + use ccsds_spacepacket::types::SeqFlag as DekuSeqFlag; + let sequence_flags = match value.sequence_flags as u8 { + x if x == SequenceFlags::Unsegmented as u8 => DekuSeqFlag::Unsegmented, + x if x == SequenceFlags::FirstSegment as u8 => DekuSeqFlag::FirstSegment, + x if x == SequenceFlags::LastSegment as u8 => DekuSeqFlag::LastSegment, + x if x == SequenceFlags::ContinuationSegment as u8 => DekuSeqFlag::Continuation, + _ => return Err(()), + }; + let packet_type = match value.ptype as u8 { + x if x == PacketType::Tm as u8 => DekuPacketType::Data, + x if x == PacketType::Tc as u8 => DekuPacketType::Command, + _ => return Err(()), + }; + let sec_header_flag = match value.secondary_header_flag as bool { + true => DekuSecHeaderFlag::Present, + false => DekuSecHeaderFlag::NotPresent, + }; + Ok(DekuSpHeader { + version: value.version, + packet_type, + sec_header_flag, + app_proc_id: value.apid, + sequence_flags, + data_length: value.packet_data_len, + sequence_count: value.ssc, + }) + } +} + +#[cfg(test)] +mod tests { + use crate::sp::{DekuSpHeader, PacketType, SequenceFlags, SpHeader}; + use deku::prelude::*; + use postcard::{from_bytes, to_stdvec}; + + #[test] + fn test_deser_internally() { + let sp_header = SpHeader::tc(0x42, 12).expect("Error creating SP header"); + assert_eq!(sp_header.version, 0b000); + assert_eq!(sp_header.secondary_header_flag, true); + assert_eq!(sp_header.ptype, PacketType::Tc); + assert_eq!(sp_header.ssc, 12); + assert_eq!(sp_header.apid, 0x42); + assert_eq!(sp_header.sequence_flags, SequenceFlags::Unsegmented); + assert_eq!(sp_header.packet_data_len, 0); + let output = to_stdvec(&sp_header).unwrap(); + println!("Output: {:?} with length {}", output, output.len()); + let sp_header: SpHeader = from_bytes(&output).unwrap(); + assert_eq!(sp_header.version, 0b000); + assert_eq!(sp_header.secondary_header_flag, true); + assert_eq!(sp_header.ptype, PacketType::Tc); + assert_eq!(sp_header.ssc, 12); + assert_eq!(sp_header.apid, 0x42); + assert_eq!(sp_header.sequence_flags, SequenceFlags::Unsegmented); + assert_eq!(sp_header.packet_data_len, 0); + } + + #[test] + fn test_deser_to_raw_packed_deku() { + let sp_header = SpHeader::tc(0x42, 12).expect("Error creating SP header"); + // TODO: Wait with these tests until KubOS merged + // https://github.com/KubOS-Preservation-Group/ccsds-spacepacket/pull/14 + let _deku_header = + DekuSpHeader::try_from(sp_header).expect("Error creating Deku Sp Header"); + // deku_header.to_bytes().unwrap(); + } +} From 5f100104a2efa78ba54530340205b795c3dce8dd Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 14 Jun 2022 11:28:50 +0200 Subject: [PATCH 03/16] add zero copy dep --- Cargo.lock | 34 ++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + 2 files changed, 35 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index f69ca73..2e5b047 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -358,6 +358,7 @@ dependencies = [ "postcard", "serde", "thiserror", + "zerocopy", ] [[package]] @@ -707,6 +708,18 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "tap" version = "1.0.1" @@ -799,3 +812,24 @@ checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188" dependencies = [ "tap", ] + +[[package]] +name = "zerocopy" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0fbc82b82efe24da867ee52e015e58178684bd9dd64c34e66bdf21da2582a9f" +dependencies = [ + "proc-macro2", + "syn", + "synstructure", +] diff --git a/Cargo.toml b/Cargo.toml index e7002c2..0924f21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,4 @@ postcard = { version = "0.7.3", features = ["use-std"] } serde = "1.0.137" deku = "0.13" ccsds_spacepacket = "0.2.0" +zerocopy = "0.6.1" From 99c827c507c1f8b510c39535ed971903126921ad Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 14 Jun 2022 14:56:18 +0200 Subject: [PATCH 04/16] new ccsds header trait and zerocopy support --- src/sp.rs | 316 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 199 insertions(+), 117 deletions(-) diff --git a/src/sp.rs b/src/sp.rs index 0a7e3c5..88c6653 100644 --- a/src/sp.rs +++ b/src/sp.rs @@ -1,5 +1,4 @@ //! # Space related components including CCSDS and ECSS packet standards -use ccsds_spacepacket::PrimaryHeader; pub use ccsds_spacepacket::PrimaryHeader as DekuSpHeader; use serde::{Deserialize, Serialize}; @@ -45,159 +44,242 @@ impl TryFrom for SequenceFlags { } } -/// Space Packet Primary Header according to CCSDS 133.0-B-2 -#[derive(Serialize, Deserialize, Debug, PartialEq)] -pub struct SpHeader { - pub version: u8, - pub ptype: PacketType, - pub apid: u16, - pub secondary_header_flag: bool, - pub sequence_flags: SequenceFlags, - pub ssc: u16, - pub packet_data_len: u16, +/// 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 version(&self) -> u8; + /// Retrieve 13 bit Packet Identification field. Can usually be retrieved with a bitwise AND + /// of the first 2 bytes with 0x1FFF + fn packet_id(&self) -> u16; + /// Retrieve Packet Sequence Count + fn psc(&self) -> u16; + /// Retrieve data length field + fn data_len(&self) -> u16; + + /// Retrieve Packet Type (TM: 0, TC: 1) + fn ptype(&self) -> PacketType { + // This call should never fail because only 0 and 1 can be passed to the try_from call + PacketType::try_from((self.packet_id() >> 13) as u8 & 0b1).unwrap() + } + + /// Retrieve the secondary header flag. Returns true if a secondary header is present + /// and false if it is not + fn sec_header_flag(&self) -> bool { + (self.packet_id() >> 12) & 0x01 != 0 + } + + /// Retrieve Application Process ID + fn apid(&self) -> u16 { + self.packet_id() & 0x7FF + } + + fn ssc(&self) -> u16 { + self.psc() & (!Self::SEQ_FLAG_MASK) + } + + fn sequence_flags(&self) -> SequenceFlags { + // This call should never fail because the mask ensures that only valid values are passed + // into the try_from function + SequenceFlags::try_from(((self.psc() & Self::SEQ_FLAG_MASK) >> 14) as u8).unwrap() + } } -impl Default for SpHeader { - fn default() -> Self { - SpHeader { - version: 0, - ptype: PacketType::Tm, - apid: 0, - secondary_header_flag: true, - sequence_flags: SequenceFlags::Unsegmented, - ssc: 0, - packet_data_len: 0, +pub mod srd { + use crate::sp::PacketType; + use crate::sp::SequenceFlags; + + /// Space Packet Primary Header according to CCSDS 133.0-B-2 + #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)] + pub struct SpHeader { + pub version: u8, + pub ptype: PacketType, + pub apid: u16, + pub sec_header_flag: bool, + pub seq_flags: SequenceFlags, + pub ssc: u16, + pub data_len: u16, + } + impl Default for SpHeader { + fn default() -> Self { + SpHeader { + version: 0, + ptype: PacketType::Tm, + apid: 0, + sec_header_flag: true, + seq_flags: SequenceFlags::Unsegmented, + ssc: 0, + data_len: 0, + } + } + } + impl SpHeader { + pub fn new(apid: u16, ptype: PacketType, ssc: u16) -> Option { + if ssc > num::pow(2, 14) || apid > num::pow(2, 11) { + return None; + } + let mut header = SpHeader::default(); + header.ptype = ptype; + header.apid = apid; + header.ssc = ssc; + Some(header) + } + + pub fn tm(apid: u16, ssc: u16) -> Option { + Self::new(apid, PacketType::Tm, ssc) + } + + pub fn tc(apid: u16, ssc: u16) -> Option { + Self::new(apid, PacketType::Tc, ssc) + } + + /// Function to retrieve the packet sequence control field + #[inline] + pub fn psc(&self) -> u16 { + ((self.seq_flags as u16) << 14) | self.sec_header_flag as u16 + } + + /// Retrieve Packet Identification composite field + #[inline] + pub fn packet_id(&self) -> u16 { + ((self.ptype as u16) << 13) | ((self.sec_header_flag as u16) << 12) | self.apid + } + + #[inline] + pub fn is_tm(&self) -> bool { + self.ptype == PacketType::Tm + } + + #[inline] + pub fn is_tc(&self) -> bool { + self.ptype == PacketType::Tc } } } -impl SpHeader { - pub fn new(apid: u16, ptype: PacketType, ssc: u16) -> Option { - if ssc > num::pow(2, 14) || apid > num::pow(2, 11) { - return None; + +pub mod zc { + use crate::sp::CcsdsPrimaryHeader; + use zerocopy::byteorder::NetworkEndian; + use zerocopy::{AsBytes, FromBytes, Unaligned, U16}; + + #[derive(FromBytes, AsBytes, Unaligned)] + #[repr(C)] + struct SpHeader { + version_packet_id: U16, + psc: U16, + data_len: U16, + } + + impl CcsdsPrimaryHeader for SpHeader { + fn version(&self) -> u8 { + ((self.version_packet_id.get() >> 13) as u8) & 0b111 } - let mut header = SpHeader::default(); - header.ptype = ptype; - header.apid = apid; - header.ssc = ssc; - Some(header) - } - pub fn tm(apid: u16, ssc: u16) -> Option { - Self::new(apid, PacketType::Tm, ssc) - } + fn packet_id(&self) -> u16 { + self.version_packet_id.get() & 0x1FFF + } - pub fn tc(apid: u16, ssc: u16) -> Option { - Self::new(apid, PacketType::Tc, ssc) - } + fn psc(&self) -> u16 { + self.psc.get() + } - /// Function to retrieve the packet sequence control field - #[inline] - pub fn psc(&self) -> u16 { - ((self.sequence_flags as u16) << 14) | self.secondary_header_flag as u16 - } - - /// Retrieve Packet Identification composite field - #[inline] - pub fn packet_id(&self) -> u16 { - ((self.ptype as u16) << 13) | ((self.secondary_header_flag as u16) << 12) | self.apid - } - - #[inline] - pub fn is_tm(&self) -> bool { - self.ptype == PacketType::Tm - } - - #[inline] - pub fn is_tc(&self) -> bool { - self.ptype == PacketType::Tc + fn data_len(&self) -> u16 { + self.data_len.get() + } } } -/// The [DekuSpHeader] is very useful to deserialize a packed raw space packet header with 6 bytes. -/// This function allows converting it to the [SpHeader] which is compatible to the [serde] -/// framework -impl TryFrom for SpHeader { - type Error = (); +pub mod deku { + use crate::sp::srd::SpHeader; + use crate::sp::{DekuSpHeader, PacketType, SequenceFlags}; + use ccsds_spacepacket::PrimaryHeader; - fn try_from(header: PrimaryHeader) -> Result { - let seq_num = SequenceFlags::try_from(header.sequence_flags as u8)?; - let packet_type = PacketType::try_from(header.packet_type as u8)?; - let sec_header_flag = header.sec_header_flag as u8 != 0; - Ok(SpHeader { - version: header.version, - sequence_flags: seq_num, - packet_data_len: header.data_length, - ssc: header.sequence_count, - ptype: packet_type, - apid: header.app_proc_id, - secondary_header_flag: sec_header_flag, - }) + /// The [DekuSpHeader] is very useful to deserialize a packed raw space packet header with 6 bytes. + /// This function allows converting it to the [SpHeader] which is compatible to the [serde] + /// framework + impl TryFrom for SpHeader { + type Error = (); + + fn try_from(header: PrimaryHeader) -> Result { + let seq_num = SequenceFlags::try_from(header.sequence_flags as u8)?; + let packet_type = PacketType::try_from(header.packet_type as u8)?; + let sec_header_flag = header.sec_header_flag as u8 != 0; + Ok(SpHeader { + version: header.version, + seq_flags: seq_num, + data_len: header.data_length, + ssc: header.sequence_count, + ptype: packet_type, + apid: header.app_proc_id, + sec_header_flag, + }) + } } -} -/// It is possible to convert the [serde] compatible [SpHeader] back into a [DekuSpHeader] -/// to allow for packed binary serialization -impl TryFrom for DekuSpHeader { - type Error = (); + /// It is possible to convert the [serde] compatible [SpHeader] back into a [DekuSpHeader] + /// to allow for packed binary serialization + impl TryFrom for DekuSpHeader { + type Error = (); - fn try_from(value: SpHeader) -> Result { - use ccsds_spacepacket::types::PacketType as DekuPacketType; - use ccsds_spacepacket::types::SecondaryHeaderFlag as DekuSecHeaderFlag; - use ccsds_spacepacket::types::SeqFlag as DekuSeqFlag; - let sequence_flags = match value.sequence_flags as u8 { - x if x == SequenceFlags::Unsegmented as u8 => DekuSeqFlag::Unsegmented, - x if x == SequenceFlags::FirstSegment as u8 => DekuSeqFlag::FirstSegment, - x if x == SequenceFlags::LastSegment as u8 => DekuSeqFlag::LastSegment, - x if x == SequenceFlags::ContinuationSegment as u8 => DekuSeqFlag::Continuation, - _ => return Err(()), - }; - let packet_type = match value.ptype as u8 { - x if x == PacketType::Tm as u8 => DekuPacketType::Data, - x if x == PacketType::Tc as u8 => DekuPacketType::Command, - _ => return Err(()), - }; - let sec_header_flag = match value.secondary_header_flag as bool { - true => DekuSecHeaderFlag::Present, - false => DekuSecHeaderFlag::NotPresent, - }; - Ok(DekuSpHeader { - version: value.version, - packet_type, - sec_header_flag, - app_proc_id: value.apid, - sequence_flags, - data_length: value.packet_data_len, - sequence_count: value.ssc, - }) + fn try_from(value: SpHeader) -> Result { + use ccsds_spacepacket::types::PacketType as DekuPacketType; + use ccsds_spacepacket::types::SecondaryHeaderFlag as DekuSecHeaderFlag; + use ccsds_spacepacket::types::SeqFlag as DekuSeqFlag; + let sequence_flags = match value.seq_flags as u8 { + x if x == SequenceFlags::Unsegmented as u8 => DekuSeqFlag::Unsegmented, + x if x == SequenceFlags::FirstSegment as u8 => DekuSeqFlag::FirstSegment, + x if x == SequenceFlags::LastSegment as u8 => DekuSeqFlag::LastSegment, + x if x == SequenceFlags::ContinuationSegment as u8 => DekuSeqFlag::Continuation, + _ => return Err(()), + }; + let packet_type = match value.ptype as u8 { + x if x == PacketType::Tm as u8 => DekuPacketType::Data, + x if x == PacketType::Tc as u8 => DekuPacketType::Command, + _ => return Err(()), + }; + let sec_header_flag = match value.sec_header_flag as bool { + true => DekuSecHeaderFlag::Present, + false => DekuSecHeaderFlag::NotPresent, + }; + Ok(DekuSpHeader { + version: value.version, + packet_type, + sec_header_flag, + app_proc_id: value.apid, + sequence_flags, + data_length: value.data_len, + sequence_count: value.ssc, + }) + } } } #[cfg(test)] mod tests { - use crate::sp::{DekuSpHeader, PacketType, SequenceFlags, SpHeader}; - use deku::prelude::*; + use crate::sp::srd::SpHeader; + use crate::sp::{DekuSpHeader, PacketType, SequenceFlags}; use postcard::{from_bytes, to_stdvec}; #[test] fn test_deser_internally() { let sp_header = SpHeader::tc(0x42, 12).expect("Error creating SP header"); assert_eq!(sp_header.version, 0b000); - assert_eq!(sp_header.secondary_header_flag, true); + assert_eq!(sp_header.sec_header_flag, true); assert_eq!(sp_header.ptype, PacketType::Tc); assert_eq!(sp_header.ssc, 12); assert_eq!(sp_header.apid, 0x42); - assert_eq!(sp_header.sequence_flags, SequenceFlags::Unsegmented); - assert_eq!(sp_header.packet_data_len, 0); + assert_eq!(sp_header.seq_flags, SequenceFlags::Unsegmented); + assert_eq!(sp_header.data_len, 0); let output = to_stdvec(&sp_header).unwrap(); println!("Output: {:?} with length {}", output, output.len()); let sp_header: SpHeader = from_bytes(&output).unwrap(); assert_eq!(sp_header.version, 0b000); - assert_eq!(sp_header.secondary_header_flag, true); + assert_eq!(sp_header.sec_header_flag, true); assert_eq!(sp_header.ptype, PacketType::Tc); assert_eq!(sp_header.ssc, 12); assert_eq!(sp_header.apid, 0x42); - assert_eq!(sp_header.sequence_flags, SequenceFlags::Unsegmented); - assert_eq!(sp_header.packet_data_len, 0); + assert_eq!(sp_header.seq_flags, SequenceFlags::Unsegmented); + assert_eq!(sp_header.data_len, 0); } #[test] From dcc29e1c5e8989f70ec801409918ed271a83ff3e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 14 Jun 2022 15:10:45 +0200 Subject: [PATCH 05/16] completed CcsdsPrimaryHeader impls --- src/sp.rs | 78 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 17 deletions(-) diff --git a/src/sp.rs b/src/sp.rs index 88c6653..f446b5e 100644 --- a/src/sp.rs +++ b/src/sp.rs @@ -57,27 +57,41 @@ pub trait CcsdsPrimaryHeader { /// Retrieve data length field fn data_len(&self) -> u16; + #[inline] /// Retrieve Packet Type (TM: 0, TC: 1) fn ptype(&self) -> PacketType { // This call should never fail because only 0 and 1 can be passed to the try_from call - PacketType::try_from((self.packet_id() >> 13) as u8 & 0b1).unwrap() + PacketType::try_from((self.packet_id() >> 12) as u8 & 0b1).unwrap() + } + #[inline] + fn is_tm(&self) -> bool { + self.ptype() == PacketType::Tm + } + + #[inline] + fn is_tc(&self) -> bool { + self.ptype() == PacketType::Tc } /// Retrieve the secondary header flag. Returns true if a secondary header is present /// and false if it is not + #[inline] fn sec_header_flag(&self) -> bool { - (self.packet_id() >> 12) & 0x01 != 0 + (self.packet_id() >> 11) & 0x01 != 0 } /// Retrieve Application Process ID + #[inline] fn apid(&self) -> u16 { self.packet_id() & 0x7FF } + #[inline] fn ssc(&self) -> u16 { self.psc() & (!Self::SEQ_FLAG_MASK) } + #[inline] fn sequence_flags(&self) -> SequenceFlags { // This call should never fail because the mask ensures that only valid values are passed // into the try_from function @@ -86,8 +100,8 @@ pub trait CcsdsPrimaryHeader { } pub mod srd { - use crate::sp::PacketType; use crate::sp::SequenceFlags; + use crate::sp::{CcsdsPrimaryHeader, PacketType}; /// Space Packet Primary Header according to CCSDS 133.0-B-2 #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)] @@ -118,11 +132,12 @@ pub mod srd { if ssc > num::pow(2, 14) || apid > num::pow(2, 11) { return None; } - let mut header = SpHeader::default(); - header.ptype = ptype; - header.apid = apid; - header.ssc = ssc; - Some(header) + Some(SpHeader { + ptype, + apid, + ssc, + ..Default::default() + }) } pub fn tm(apid: u16, ssc: u16) -> Option { @@ -132,27 +147,29 @@ pub mod srd { pub fn tc(apid: u16, ssc: u16) -> Option { Self::new(apid, PacketType::Tc, ssc) } + } - /// Function to retrieve the packet sequence control field + impl CcsdsPrimaryHeader for SpHeader { #[inline] - pub fn psc(&self) -> u16 { - ((self.seq_flags as u16) << 14) | self.sec_header_flag as u16 + fn version(&self) -> u8 { + self.version } /// Retrieve Packet Identification composite field #[inline] - pub fn packet_id(&self) -> u16 { + fn packet_id(&self) -> u16 { ((self.ptype as u16) << 13) | ((self.sec_header_flag as u16) << 12) | self.apid } + /// Function to retrieve the packet sequence control field #[inline] - pub fn is_tm(&self) -> bool { - self.ptype == PacketType::Tm + fn psc(&self) -> u16 { + ((self.seq_flags as u16) << 14) | self.sec_header_flag as u16 } #[inline] - pub fn is_tc(&self) -> bool { - self.ptype == PacketType::Tc + fn data_len(&self) -> u16 { + self.data_len } } } @@ -171,18 +188,22 @@ pub mod zc { } impl CcsdsPrimaryHeader for SpHeader { + #[inline] fn version(&self) -> u8 { ((self.version_packet_id.get() >> 13) as u8) & 0b111 } + #[inline] fn packet_id(&self) -> u16 { self.version_packet_id.get() & 0x1FFF } + #[inline] fn psc(&self) -> u16 { self.psc.get() } + #[inline] fn data_len(&self) -> u16 { self.data_len.get() } @@ -191,7 +212,7 @@ pub mod zc { pub mod deku { use crate::sp::srd::SpHeader; - use crate::sp::{DekuSpHeader, PacketType, SequenceFlags}; + use crate::sp::{CcsdsPrimaryHeader, DekuSpHeader, PacketType, SequenceFlags}; use ccsds_spacepacket::PrimaryHeader; /// The [DekuSpHeader] is very useful to deserialize a packed raw space packet header with 6 bytes. @@ -216,6 +237,29 @@ pub mod deku { } } + impl CcsdsPrimaryHeader for DekuSpHeader { + #[inline] + fn version(&self) -> u8 { + self.version + } + + #[inline] + fn packet_id(&self) -> u16 { + ((self.packet_type as u16) << 12) + | ((self.sec_header_flag as u16) << 11) + | self.app_proc_id + } + + #[inline] + fn psc(&self) -> u16 { + ((self.sequence_flags as u16) << 14) | self.sequence_count + } + + #[inline] + fn data_len(&self) -> u16 { + self.data_length + } + } /// It is possible to convert the [serde] compatible [SpHeader] back into a [DekuSpHeader] /// to allow for packed binary serialization impl TryFrom for DekuSpHeader { From 645b265742c211ea9911b17ef0556b78f3de3172 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 14 Jun 2022 17:26:29 +0200 Subject: [PATCH 06/16] added more tests for ccsds sp header impl --- Cargo.lock | 80 +----------- Cargo.toml | 2 +- src/sp.rs | 378 ++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 263 insertions(+), 197 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2e5b047..05a1a74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,15 +95,6 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" -[[package]] -name = "ccsds_spacepacket" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82251e34d2bbc33273c38d7720b65373e55e311fa0c4134b60b03601dbc92cf2" -dependencies = [ - "deku 0.12.6", -] - [[package]] name = "cfg-if" version = "0.1.10" @@ -170,38 +161,14 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", -] - [[package]] name = "darling" version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02" dependencies = [ - "darling_core 0.14.1", - "darling_macro 0.14.1", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", + "darling_core", + "darling_macro", ] [[package]] @@ -218,38 +185,17 @@ dependencies = [ "syn", ] -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core 0.13.4", - "quote", - "syn", -] - [[package]] name = "darling_macro" version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5" dependencies = [ - "darling_core 0.14.1", + "darling_core", "quote", "syn", ] -[[package]] -name = "deku" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe18ce09f5d512cad19bbac22e395aa36cfa12cf699a3bcb3787af62dde4b13a" -dependencies = [ - "bitvec", - "deku_derive 0.12.6", -] - [[package]] name = "deku" version = "0.13.1" @@ -257,20 +203,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "868ccf23869582b2d79279e402db457fe341da24a0c5a8927c6154a5b4733dc3" dependencies = [ "bitvec", - "deku_derive 0.13.1", -] - -[[package]] -name = "deku_derive" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "691ea0b164aad4a4517f5b47130e15868af1f02fed614c45a1967cbfe2c318d7" -dependencies = [ - "darling 0.13.4", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", + "deku_derive", ] [[package]] @@ -279,7 +212,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dfb4274ccd1c87a598e98b398b4b630aecb2e8a32fd7c88ffa190fb73870f72" dependencies = [ - "darling 0.14.1", + "darling", "proc-macro-crate", "proc-macro2", "quote", @@ -351,8 +284,7 @@ name = "launchpad" version = "0.1.0" dependencies = [ "bus", - "ccsds_spacepacket", - "deku 0.13.1", + "deku", "heapless", "num", "postcard", diff --git a/Cargo.toml b/Cargo.toml index 0924f21..f9a9862 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,5 +13,5 @@ heapless = "0.7.13" postcard = { version = "0.7.3", features = ["use-std"] } serde = "1.0.137" deku = "0.13" -ccsds_spacepacket = "0.2.0" +# ccsds_spacepacket = "0.2.0" zerocopy = "0.6.1" diff --git a/src/sp.rs b/src/sp.rs index f446b5e..216deab 100644 --- a/src/sp.rs +++ b/src/sp.rs @@ -1,5 +1,4 @@ //! # Space related components including CCSDS and ECSS packet standards -pub use ccsds_spacepacket::PrimaryHeader as DekuSpHeader; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone)] @@ -20,6 +19,10 @@ impl TryFrom for PacketType { } } +pub fn type_from_packet_id(packet_id: u16) -> PacketType { + PacketType::try_from((packet_id >> 12) as u8 & 0b1).unwrap() +} + #[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone)] pub enum SequenceFlags { ContinuationSegment = 0b00, @@ -44,25 +47,92 @@ impl TryFrom for SequenceFlags { } } +#[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone)] +pub struct PacketId { + pub ptype: PacketType, + pub sec_header_flag: bool, + pub apid: u16 +} + +impl PacketId { + pub fn raw(&self) -> u16 { + ((self.ptype as u16) << 12) | ((self.sec_header_flag as u16) << 11) | self.apid + } +} + +impl From for PacketId { + fn from(raw_id: u16) -> Self { + PacketId { + ptype: PacketType::try_from(((raw_id >> 12) & 0b1) as u8).unwrap(), + sec_header_flag: ((raw_id >> 11) & 0b1) != 0, + apid: raw_id & 0x7FFF + } + } +} + +#[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone)] +pub struct PacketSequenceCtrl { + pub seq_flags: SequenceFlags, + pub ssc: u16 +} + +impl PacketSequenceCtrl { + pub fn raw(&self) -> u16 { + ((self.seq_flags as u16) << 14) | self.ssc + } +} + +impl From 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 + } + } +} + +macro_rules! sph_from_other { + ($Self: path, $other: path) => { + impl From<$other> for $Self { + fn from(other: $other) -> Self { + Self::from_composite_fields(other.packet_id(), other.psc(), other.data_len(), Some(other.version())) + } + } + } +} + /// 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) -> Self; + fn version(&self) -> u8; - /// Retrieve 13 bit Packet Identification field. Can usually be retrieved with a bitwise AND - /// of the first 2 bytes with 0x1FFF - fn packet_id(&self) -> u16; - /// Retrieve Packet Sequence Count - fn psc(&self) -> u16; + fn packet_id(&self) -> PacketId; + fn psc(&self) -> PacketSequenceCtrl; + /// Retrieve data length field fn data_len(&self) -> u16; + /// Retrieve 13 bit Packet Identification field. Can usually be retrieved with a bitwise AND + /// of the first 2 bytes with 0x1FFF + #[inline] + fn packet_id_raw(&self) -> u16 { + self.packet_id().raw() + } + /// Retrieve Packet Sequence Count + #[inline] + fn psc_raw(&self) -> u16 { + self.psc().raw() + } + #[inline] /// Retrieve Packet Type (TM: 0, TC: 1) fn ptype(&self) -> PacketType { // This call should never fail because only 0 and 1 can be passed to the try_from call - PacketType::try_from((self.packet_id() >> 12) as u8 & 0b1).unwrap() + self.packet_id().ptype } + #[inline] fn is_tm(&self) -> bool { self.ptype() == PacketType::Tm @@ -77,52 +147,45 @@ pub trait CcsdsPrimaryHeader { /// and false if it is not #[inline] fn sec_header_flag(&self) -> bool { - (self.packet_id() >> 11) & 0x01 != 0 + self.packet_id().sec_header_flag } /// Retrieve Application Process ID #[inline] fn apid(&self) -> u16 { - self.packet_id() & 0x7FF + self.packet_id().apid } #[inline] fn ssc(&self) -> u16 { - self.psc() & (!Self::SEQ_FLAG_MASK) + self.psc().ssc } #[inline] fn sequence_flags(&self) -> SequenceFlags { // This call should never fail because the mask ensures that only valid values are passed // into the try_from function - SequenceFlags::try_from(((self.psc() & Self::SEQ_FLAG_MASK) >> 14) as u8).unwrap() + self.psc().seq_flags } } pub mod srd { - use crate::sp::SequenceFlags; - use crate::sp::{CcsdsPrimaryHeader, PacketType}; + use crate::sp::{self, SequenceFlags, CcsdsPrimaryHeader, PacketType, PacketId, PacketSequenceCtrl}; /// Space Packet Primary Header according to CCSDS 133.0-B-2 #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)] pub struct SpHeader { pub version: u8, - pub ptype: PacketType, - pub apid: u16, - pub sec_header_flag: bool, - pub seq_flags: SequenceFlags, - pub ssc: u16, + pub packet_id: PacketId, + pub psc: PacketSequenceCtrl, pub data_len: u16, } impl Default for SpHeader { fn default() -> Self { SpHeader { version: 0, - ptype: PacketType::Tm, - apid: 0, - sec_header_flag: true, - seq_flags: SequenceFlags::Unsegmented, - ssc: 0, + packet_id: PacketId{ ptype: PacketType::Tm, apid: 0, sec_header_flag: true}, + psc: PacketSequenceCtrl { seq_flags: SequenceFlags::Unsegmented, ssc: 0}, data_len: 0, } } @@ -132,12 +195,11 @@ pub mod srd { if ssc > num::pow(2, 14) || apid > num::pow(2, 11) { return None; } - Some(SpHeader { - ptype, - apid, - ssc, - ..Default::default() - }) + let mut header = SpHeader::default(); + header.packet_id.apid = apid; + header.packet_id.ptype = ptype; + header.psc.ssc = ssc; + Some(header) } pub fn tm(apid: u16, ssc: u16) -> Option { @@ -150,21 +212,32 @@ pub mod srd { } impl CcsdsPrimaryHeader for SpHeader { + fn from_composite_fields(packet_id: PacketId, psc: PacketSequenceCtrl, data_len: u16, version: Option) -> 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 + } + } + #[inline] fn version(&self) -> u8 { self.version } - /// Retrieve Packet Identification composite field #[inline] - fn packet_id(&self) -> u16 { - ((self.ptype as u16) << 13) | ((self.sec_header_flag as u16) << 12) | self.apid + fn packet_id(&self) -> PacketId { + self.packet_id } - /// Function to retrieve the packet sequence control field #[inline] - fn psc(&self) -> u16 { - ((self.seq_flags as u16) << 14) | self.sec_header_flag as u16 + fn psc(&self) -> PacketSequenceCtrl { + self.psc } #[inline] @@ -172,35 +245,54 @@ pub mod srd { self.data_len } } + + sph_from_other!(SpHeader, sp::zc::SpHeader); + // sph_from_other!(SpHeader, sp::deku::SpHeader); } pub mod zc { - use crate::sp::CcsdsPrimaryHeader; + use crate::sp::{self, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl}; use zerocopy::byteorder::NetworkEndian; use zerocopy::{AsBytes, FromBytes, Unaligned, U16}; #[derive(FromBytes, AsBytes, Unaligned)] #[repr(C)] - struct SpHeader { + pub struct SpHeader { version_packet_id: U16, psc: U16, data_len: U16, } + impl SpHeader { + pub fn new(packet_id: PacketId, psc: PacketSequenceCtrl, data_len: u16, version: Option) -> Self { + let mut version_packet_id = packet_id.raw(); + if let Some(version) = version { + version_packet_id = ((version as u16) << 13) | packet_id.raw() + } + SpHeader { + version_packet_id: U16::from(version_packet_id), + psc: U16::from(psc.raw()), + data_len: U16::from(data_len) + } + } + } + impl CcsdsPrimaryHeader for SpHeader { + fn from_composite_fields(packet_id: PacketId, psc: PacketSequenceCtrl, data_len: u16, version: Option) -> Self { + SpHeader::new(packet_id, psc, data_len, version) + } + #[inline] fn version(&self) -> u8 { ((self.version_packet_id.get() >> 13) as u8) & 0b111 } - #[inline] - fn packet_id(&self) -> u16 { - self.version_packet_id.get() & 0x1FFF + fn packet_id(&self) -> PacketId { + PacketId::from(self.packet_id_raw()) } - #[inline] - fn psc(&self) -> u16 { - self.psc.get() + fn psc(&self) -> PacketSequenceCtrl { + PacketSequenceCtrl::from(self.packet_id_raw()) } #[inline] @@ -208,51 +300,68 @@ pub mod zc { self.data_len.get() } } + + sph_from_other!(SpHeader, sp::srd::SpHeader); + //sph_from_other!(SpHeader, sp::deku::SpHeader); } +/* pub mod deku { - use crate::sp::srd::SpHeader; - use crate::sp::{CcsdsPrimaryHeader, DekuSpHeader, PacketType, SequenceFlags}; - use ccsds_spacepacket::PrimaryHeader; + pub use ccsds_spacepacket::PrimaryHeader as SpHeader; + use crate::sp::{self, PacketId, PacketSequenceCtrl}; + use crate::sp::{CcsdsPrimaryHeader, PacketType, SequenceFlags}; - /// The [DekuSpHeader] is very useful to deserialize a packed raw space packet header with 6 bytes. - /// This function allows converting it to the [SpHeader] which is compatible to the [serde] - /// framework - impl TryFrom for SpHeader { - type Error = (); - - fn try_from(header: PrimaryHeader) -> Result { - let seq_num = SequenceFlags::try_from(header.sequence_flags as u8)?; - let packet_type = PacketType::try_from(header.packet_type as u8)?; - let sec_header_flag = header.sec_header_flag as u8 != 0; - Ok(SpHeader { - version: header.version, - seq_flags: seq_num, - data_len: header.data_length, - ssc: header.sequence_count, - ptype: packet_type, - apid: header.app_proc_id, + impl CcsdsPrimaryHeader for SpHeader { + fn from_composite_fields(packet_id: PacketId, psc: PacketSequenceCtrl, data_len: u16, version: Option) -> Self { + let mut version_to_set = 0b000; + if let Some(version) = version { + version_to_set = version; + } + let packet_type = match packet_id.ptype { + PacketType::Tm => ccsds_spacepacket::types::PacketType::Data, + PacketType::Tc => ccsds_spacepacket::types::PacketType::Command + }; + let sec_header_flag = match packet_id.sec_header_flag { + true => ccsds_spacepacket::types::SecondaryHeaderFlag::Present, + false => ccsds_spacepacket::types::SecondaryHeaderFlag::NotPresent + }; + let sequence_flags = match psc.seq_flags { + SequenceFlags::ContinuationSegment => ccsds_spacepacket::types::SeqFlag::Continuation, + SequenceFlags::FirstSegment => ccsds_spacepacket::types::SeqFlag::FirstSegment, + SequenceFlags::LastSegment => ccsds_spacepacket::types::SeqFlag::LastSegment, + SequenceFlags::Unsegmented => ccsds_spacepacket::types::SeqFlag::Unsegmented + }; + SpHeader { + version: version_to_set, + packet_type, sec_header_flag, - }) + app_proc_id: packet_id.apid, + sequence_flags, + sequence_count: psc.ssc, + data_length: data_len + } } - } - impl CcsdsPrimaryHeader for DekuSpHeader { #[inline] fn version(&self) -> u8 { self.version } #[inline] - fn packet_id(&self) -> u16 { - ((self.packet_type as u16) << 12) - | ((self.sec_header_flag as u16) << 11) - | self.app_proc_id + fn packet_id(&self) -> PacketId { + PacketId { + ptype: PacketType::try_from(self.packet_type as u8).unwrap(), + apid: self.app_proc_id, + sec_header_flag: self.sec_header_flag as u8 != 0 + } } #[inline] - fn psc(&self) -> u16 { - ((self.sequence_flags as u16) << 14) | self.sequence_count + fn psc(&self) -> PacketSequenceCtrl { + PacketSequenceCtrl { + seq_flags: SequenceFlags::try_from(self.sequence_flags as u8).unwrap(), + ssc: self.sequence_count + } } #[inline] @@ -260,79 +369,104 @@ pub mod deku { self.data_length } } - /// It is possible to convert the [serde] compatible [SpHeader] back into a [DekuSpHeader] - /// to allow for packed binary serialization - impl TryFrom for DekuSpHeader { - type Error = (); - fn try_from(value: SpHeader) -> Result { - use ccsds_spacepacket::types::PacketType as DekuPacketType; - use ccsds_spacepacket::types::SecondaryHeaderFlag as DekuSecHeaderFlag; - use ccsds_spacepacket::types::SeqFlag as DekuSeqFlag; - let sequence_flags = match value.seq_flags as u8 { - x if x == SequenceFlags::Unsegmented as u8 => DekuSeqFlag::Unsegmented, - x if x == SequenceFlags::FirstSegment as u8 => DekuSeqFlag::FirstSegment, - x if x == SequenceFlags::LastSegment as u8 => DekuSeqFlag::LastSegment, - x if x == SequenceFlags::ContinuationSegment as u8 => DekuSeqFlag::Continuation, - _ => return Err(()), - }; - let packet_type = match value.ptype as u8 { - x if x == PacketType::Tm as u8 => DekuPacketType::Data, - x if x == PacketType::Tc as u8 => DekuPacketType::Command, - _ => return Err(()), - }; - let sec_header_flag = match value.sec_header_flag as bool { - true => DekuSecHeaderFlag::Present, - false => DekuSecHeaderFlag::NotPresent, - }; - Ok(DekuSpHeader { - version: value.version, - packet_type, - sec_header_flag, - app_proc_id: value.apid, - sequence_flags, - data_length: value.data_len, - sequence_count: value.ssc, - }) - } - } + sph_from_other!(SpHeader, sp::srd::SpHeader); + sph_from_other!(SpHeader, sp::zc::SpHeader); } +*/ #[cfg(test)] mod tests { use crate::sp::srd::SpHeader; - use crate::sp::{DekuSpHeader, PacketType, SequenceFlags}; + use crate::sp::{CcsdsPrimaryHeader, PacketType, SequenceFlags}; use postcard::{from_bytes, to_stdvec}; + use crate::sp; #[test] fn test_deser_internally() { let sp_header = SpHeader::tc(0x42, 12).expect("Error creating SP header"); - assert_eq!(sp_header.version, 0b000); - assert_eq!(sp_header.sec_header_flag, true); - assert_eq!(sp_header.ptype, PacketType::Tc); - assert_eq!(sp_header.ssc, 12); - assert_eq!(sp_header.apid, 0x42); - assert_eq!(sp_header.seq_flags, SequenceFlags::Unsegmented); - assert_eq!(sp_header.data_len, 0); + assert_eq!(sp_header.version(), 0b000); + assert_eq!(sp_header.sec_header_flag(), true); + assert_eq!(sp_header.ptype(), PacketType::Tc); + assert_eq!(sp_header.ssc(), 12); + assert_eq!(sp_header.apid(), 0x42); + assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented); + assert_eq!(sp_header.data_len(), 0); let output = to_stdvec(&sp_header).unwrap(); - println!("Output: {:?} with length {}", output, output.len()); let sp_header: SpHeader = from_bytes(&output).unwrap(); assert_eq!(sp_header.version, 0b000); - assert_eq!(sp_header.sec_header_flag, true); - assert_eq!(sp_header.ptype, PacketType::Tc); - assert_eq!(sp_header.ssc, 12); - assert_eq!(sp_header.apid, 0x42); - assert_eq!(sp_header.seq_flags, SequenceFlags::Unsegmented); + assert_eq!(sp_header.packet_id.sec_header_flag, true); + assert_eq!(sp_header.ptype(), PacketType::Tc); + assert_eq!(sp_header.ssc(), 12); + assert_eq!(sp_header.apid(), 0x42); + assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented); + assert_eq!(sp_header.packet_id_raw(), 0x1842); + assert_eq!(sp_header.psc_raw(), 0xC00C); + assert_eq!(sp_header.version(), 0b000); assert_eq!(sp_header.data_len, 0); + + let mut sp_header = SpHeader::tm(0x7, 22).expect("Error creating SP header"); + sp_header.data_len = 36; + assert_eq!(sp_header.version(), 0b000); + assert_eq!(sp_header.sec_header_flag(), true); + assert_eq!(sp_header.ptype(), PacketType::Tm); + assert_eq!(sp_header.ssc(), 22); + assert_eq!(sp_header.apid(), 0x07); + assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented); + assert_eq!(sp_header.packet_id_raw(), 0x0807); + assert_eq!(sp_header.psc_raw(), 0xC016); + assert_eq!(sp_header.data_len(), 36); + assert_eq!(sp_header.version(), 0b000); } + /* #[test] fn test_deser_to_raw_packed_deku() { let sp_header = SpHeader::tc(0x42, 12).expect("Error creating SP header"); // TODO: Wait with these tests until KubOS merged // https://github.com/KubOS-Preservation-Group/ccsds-spacepacket/pull/14 let _deku_header = - DekuSpHeader::try_from(sp_header).expect("Error creating Deku Sp Header"); + deku::SpHeader::try_from(sp_header).expect("Error creating Deku Sp Header"); // deku_header.to_bytes().unwrap(); } + */ + + #[test] + fn test_deser_zerocopy() { + use zerocopy::{AsBytes}; + + let sp_header = SpHeader::tc(0x7FF, num::pow(2, 14) - 1).expect("Error creating SP header"); + assert_eq!(sp_header.packet_id.ptype, PacketType::Tc); + let sp_header_zc = sp::zc::SpHeader::from(sp_header); + let slice = sp_header_zc.as_bytes(); + assert_eq!(slice.len(), 6); + assert_eq!(slice[0], 0x1F); + assert_eq!(slice[1], 0xFF); + assert_eq!(slice[2], 0xFF); + assert_eq!(slice[3], 0xFF); + assert_eq!(slice[4], 0x00); + assert_eq!(slice[5], 0x00); + + let mut slice = [0; 6]; + sp_header_zc.write_to(slice.as_mut_slice()); + assert_eq!(slice.len(), 6); + assert_eq!(slice[0], 0x1F); + assert_eq!(slice[1], 0xFF); + assert_eq!(slice[2], 0xFF); + assert_eq!(slice[3], 0xFF); + assert_eq!(slice[4], 0x00); + assert_eq!(slice[5], 0x00); + + let mut test_vec = vec![0 as u8; 6]; + let slice = test_vec.as_mut_slice(); + sp_header_zc.write_to(slice); + let slice = test_vec.as_slice(); + assert_eq!(slice.len(), 6); + assert_eq!(slice[0], 0x1F); + assert_eq!(slice[1], 0xFF); + assert_eq!(slice[2], 0xFF); + assert_eq!(slice[3], 0xFF); + assert_eq!(slice[4], 0x00); + assert_eq!(slice[5], 0x00); + } } From 7f369e1d5a31a438e3ade2ceffe25dc7f3c04f65 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 14 Jun 2022 17:26:51 +0200 Subject: [PATCH 07/16] cargo fmt --- src/sp.rs | 70 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/src/sp.rs b/src/sp.rs index 216deab..ccfaf77 100644 --- a/src/sp.rs +++ b/src/sp.rs @@ -20,7 +20,7 @@ impl TryFrom for PacketType { } pub fn type_from_packet_id(packet_id: u16) -> PacketType { - PacketType::try_from((packet_id >> 12) as u8 & 0b1).unwrap() + PacketType::try_from((packet_id >> 12) as u8 & 0b1).unwrap() } #[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone)] @@ -51,7 +51,7 @@ impl TryFrom for SequenceFlags { pub struct PacketId { pub ptype: PacketType, pub sec_header_flag: bool, - pub apid: u16 + pub apid: u16, } impl PacketId { @@ -65,7 +65,7 @@ impl From 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 & 0x7FFF, } } } @@ -73,7 +73,7 @@ impl From for PacketId { #[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone)] pub struct PacketSequenceCtrl { pub seq_flags: SequenceFlags, - pub ssc: u16 + pub ssc: u16, } impl PacketSequenceCtrl { @@ -86,7 +86,7 @@ impl From 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 & 0x3FFF, } } } @@ -95,17 +95,27 @@ macro_rules! sph_from_other { ($Self: path, $other: path) => { impl From<$other> for $Self { fn from(other: $other) -> Self { - Self::from_composite_fields(other.packet_id(), other.psc(), other.data_len(), Some(other.version())) + Self::from_composite_fields( + other.packet_id(), + other.psc(), + other.data_len(), + Some(other.version()), + ) } } - } + }; } /// 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) -> Self; + fn from_composite_fields( + packet_id: PacketId, + psc: PacketSequenceCtrl, + data_len: u16, + version: Option, + ) -> Self; fn version(&self) -> u8; fn packet_id(&self) -> PacketId; @@ -170,7 +180,9 @@ pub trait CcsdsPrimaryHeader { } pub mod srd { - use crate::sp::{self, SequenceFlags, CcsdsPrimaryHeader, PacketType, PacketId, PacketSequenceCtrl}; + use crate::sp::{ + self, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl, PacketType, SequenceFlags, + }; /// Space Packet Primary Header according to CCSDS 133.0-B-2 #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)] @@ -184,8 +196,15 @@ pub mod srd { fn default() -> Self { SpHeader { version: 0, - packet_id: PacketId{ ptype: PacketType::Tm, apid: 0, sec_header_flag: true}, - psc: PacketSequenceCtrl { seq_flags: SequenceFlags::Unsegmented, ssc: 0}, + packet_id: PacketId { + ptype: PacketType::Tm, + apid: 0, + sec_header_flag: true, + }, + psc: PacketSequenceCtrl { + seq_flags: SequenceFlags::Unsegmented, + ssc: 0, + }, data_len: 0, } } @@ -212,7 +231,12 @@ pub mod srd { } impl CcsdsPrimaryHeader for SpHeader { - fn from_composite_fields(packet_id: PacketId, psc: PacketSequenceCtrl, data_len: u16, version: Option) -> Self { + fn from_composite_fields( + packet_id: PacketId, + psc: PacketSequenceCtrl, + data_len: u16, + version: Option, + ) -> Self { let mut version_to_set = 0b000; if let Some(version) = version { version_to_set = version; @@ -221,7 +245,7 @@ pub mod srd { version: version_to_set, packet_id, psc, - data_len + data_len, } } @@ -264,7 +288,12 @@ pub mod zc { } impl SpHeader { - pub fn new(packet_id: PacketId, psc: PacketSequenceCtrl, data_len: u16, version: Option) -> Self { + pub fn new( + packet_id: PacketId, + psc: PacketSequenceCtrl, + data_len: u16, + version: Option, + ) -> Self { let mut version_packet_id = packet_id.raw(); if let Some(version) = version { version_packet_id = ((version as u16) << 13) | packet_id.raw() @@ -272,13 +301,18 @@ pub mod zc { SpHeader { version_packet_id: U16::from(version_packet_id), psc: U16::from(psc.raw()), - data_len: U16::from(data_len) + data_len: U16::from(data_len), } } } impl CcsdsPrimaryHeader for SpHeader { - fn from_composite_fields(packet_id: PacketId, psc: PacketSequenceCtrl, data_len: u16, version: Option) -> Self { + fn from_composite_fields( + packet_id: PacketId, + psc: PacketSequenceCtrl, + data_len: u16, + version: Option, + ) -> Self { SpHeader::new(packet_id, psc, data_len, version) } @@ -377,10 +411,10 @@ pub mod deku { #[cfg(test)] mod tests { + use crate::sp; use crate::sp::srd::SpHeader; use crate::sp::{CcsdsPrimaryHeader, PacketType, SequenceFlags}; use postcard::{from_bytes, to_stdvec}; - use crate::sp; #[test] fn test_deser_internally() { @@ -433,7 +467,7 @@ mod tests { #[test] fn test_deser_zerocopy() { - use zerocopy::{AsBytes}; + use zerocopy::AsBytes; let sp_header = SpHeader::tc(0x7FF, num::pow(2, 14) - 1).expect("Error creating SP header"); assert_eq!(sp_header.packet_id.ptype, PacketType::Tc); From 933d946f6820bacd31d50fd8f3872d604ed32cea Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 14 Jun 2022 17:39:13 +0200 Subject: [PATCH 08/16] improved module structure, new archive file --- .idea/runConfigurations/Test.xml | 1 + src/archive.rs | 82 ++++++++++++++++++++++++ src/{core.rs => core/mod.rs} | 0 src/{sp.rs => sp/mod.rs} | 106 ++++++------------------------- 4 files changed, 104 insertions(+), 85 deletions(-) create mode 100644 src/archive.rs rename src/{core.rs => core/mod.rs} (100%) rename src/{sp.rs => sp/mod.rs} (79%) diff --git a/.idea/runConfigurations/Test.xml b/.idea/runConfigurations/Test.xml index 15edb2f..9f2b663 100644 --- a/.idea/runConfigurations/Test.xml +++ b/.idea/runConfigurations/Test.xml @@ -7,6 +7,7 @@