added first sp tests
This commit is contained in:
parent
d1e55cb058
commit
4708481052
80
Cargo.lock
generated
80
Cargo.lock
generated
@ -95,6 +95,15 @@ version = "1.4.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
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]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
@ -161,14 +170,38 @@ dependencies = [
|
|||||||
"lazy_static",
|
"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]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.14.1"
|
version = "0.14.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02"
|
checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core 0.14.1",
|
||||||
"darling_macro",
|
"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]]
|
[[package]]
|
||||||
@ -185,17 +218,38 @@ dependencies = [
|
|||||||
"syn",
|
"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]]
|
[[package]]
|
||||||
name = "darling_macro"
|
name = "darling_macro"
|
||||||
version = "0.14.1"
|
version = "0.14.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5"
|
checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core 0.14.1",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"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]]
|
[[package]]
|
||||||
name = "deku"
|
name = "deku"
|
||||||
version = "0.13.1"
|
version = "0.13.1"
|
||||||
@ -203,7 +257,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "868ccf23869582b2d79279e402db457fe341da24a0c5a8927c6154a5b4733dc3"
|
checksum = "868ccf23869582b2d79279e402db457fe341da24a0c5a8927c6154a5b4733dc3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitvec",
|
"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]]
|
[[package]]
|
||||||
@ -212,7 +279,7 @@ version = "0.13.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4dfb4274ccd1c87a598e98b398b4b630aecb2e8a32fd7c88ffa190fb73870f72"
|
checksum = "4dfb4274ccd1c87a598e98b398b4b630aecb2e8a32fd7c88ffa190fb73870f72"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling 0.14.1",
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -284,7 +351,8 @@ name = "launchpad"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bus",
|
"bus",
|
||||||
"deku",
|
"ccsds_spacepacket",
|
||||||
|
"deku 0.13.1",
|
||||||
"heapless",
|
"heapless",
|
||||||
"num",
|
"num",
|
||||||
"postcard",
|
"postcard",
|
||||||
|
@ -10,6 +10,7 @@ thiserror = "1.0"
|
|||||||
bus = "2.2.3"
|
bus = "2.2.3"
|
||||||
num = "0.4"
|
num = "0.4"
|
||||||
heapless = "0.7.13"
|
heapless = "0.7.13"
|
||||||
postcard = "0.7.3"
|
postcard = { version = "0.7.3", features = ["use-std"] }
|
||||||
serde = "1.0.137"
|
serde = "1.0.137"
|
||||||
deku = "0.13"
|
deku = "0.13"
|
||||||
|
ccsds_spacepacket = "0.2.0"
|
||||||
|
@ -43,7 +43,7 @@ impl StoreAddr {
|
|||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum StoreIdError {
|
pub enum StoreIdError {
|
||||||
InvalidSubpool(u16),
|
InvalidSubpool(u16),
|
||||||
InvalidPacketIdx(u16)
|
InvalidPacketIdx(u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
@ -129,10 +129,16 @@ impl LocalPool {
|
|||||||
fn addr_check(&self, addr: &StoreAddr) -> Result<usize, StoreError> {
|
fn addr_check(&self, addr: &StoreAddr) -> Result<usize, StoreError> {
|
||||||
let pool_idx = addr.pool_idx as usize;
|
let pool_idx = addr.pool_idx as usize;
|
||||||
if pool_idx as usize >= self.pool_cfg.cfg.len() {
|
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 {
|
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 size_list = self.sizes_lists.get(pool_idx).unwrap();
|
||||||
let curr_size = size_list[addr.packet_idx as usize];
|
let curr_size = size_list[addr.packet_idx as usize];
|
||||||
@ -190,7 +196,10 @@ impl LocalPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(StoreError::InvalidStoreId(StoreIdError::InvalidSubpool(subpool),None));
|
return Err(StoreError::InvalidStoreId(
|
||||||
|
StoreIdError::InvalidSubpool(subpool),
|
||||||
|
None,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
Err(StoreError::StoreFull(subpool))
|
Err(StoreError::StoreFull(subpool))
|
||||||
}
|
}
|
||||||
@ -230,12 +239,15 @@ mod tests {
|
|||||||
let pool_cfg = PoolCfg::new(vec![(4, 4), (2, 8), (1, 16)]);
|
let pool_cfg = PoolCfg::new(vec![(4, 4), (2, 8), (1, 16)]);
|
||||||
let mut local_pool = LocalPool::new(pool_cfg);
|
let mut local_pool = LocalPool::new(pool_cfg);
|
||||||
// Try to access data which does not exist
|
// Try to access data which does not exist
|
||||||
let res = local_pool.read(&StoreAddr{
|
let res = local_pool.read(&StoreAddr {
|
||||||
packet_idx: 0,
|
packet_idx: 0,
|
||||||
pool_idx: 0
|
pool_idx: 0,
|
||||||
});
|
});
|
||||||
assert!(res.is_err());
|
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];
|
let mut test_buf: [u8; 16] = [0; 16];
|
||||||
for (i, val) in test_buf.iter_mut().enumerate() {
|
for (i, val) in test_buf.iter_mut().enumerate() {
|
||||||
*val = i as u8;
|
*val = i as u8;
|
||||||
@ -244,16 +256,19 @@ mod tests {
|
|||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let addr = res.unwrap();
|
let addr = res.unwrap();
|
||||||
// Only the second subpool has enough storage and only one bucket
|
// Only the second subpool has enough storage and only one bucket
|
||||||
assert_eq!(addr, StoreAddr {
|
assert_eq!(
|
||||||
pool_idx: 2,
|
addr,
|
||||||
packet_idx: 0
|
StoreAddr {
|
||||||
});
|
pool_idx: 2,
|
||||||
|
packet_idx: 0
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// The subpool is now full and the call should fail accordingly
|
// The subpool is now full and the call should fail accordingly
|
||||||
let res = local_pool.add(test_buf.as_slice());
|
let res = local_pool.add(test_buf.as_slice());
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
let err = res.unwrap_err();
|
let err = res.unwrap_err();
|
||||||
assert!(matches!(err, StoreError::StoreFull {..}));
|
assert!(matches!(err, StoreError::StoreFull { .. }));
|
||||||
if let StoreError::StoreFull(subpool) = err {
|
if let StoreError::StoreFull(subpool) = err {
|
||||||
assert_eq!(subpool, 2);
|
assert_eq!(subpool, 2);
|
||||||
}
|
}
|
||||||
@ -264,7 +279,7 @@ mod tests {
|
|||||||
let buf_read_back = res.unwrap();
|
let buf_read_back = res.unwrap();
|
||||||
assert_eq!(buf_read_back.len(), 16);
|
assert_eq!(buf_read_back.len(), 16);
|
||||||
for (i, &val) in buf_read_back.iter().enumerate() {
|
for (i, &val) in buf_read_back.iter().enumerate() {
|
||||||
assert_eq!(val , i as u8);
|
assert_eq!(val, i as u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete the data
|
// Delete the data
|
||||||
@ -276,7 +291,13 @@ mod tests {
|
|||||||
let res = local_pool.free_element(12);
|
let res = local_pool.free_element(12);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let (addr, buf_ref) = res.unwrap();
|
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.len(), 12);
|
||||||
assert_eq!(buf_ref, [0; 12]);
|
assert_eq!(buf_ref, [0; 12]);
|
||||||
buf_ref[0] = 5;
|
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);
|
let res = local_pool.read(&addr);
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
let err = res.unwrap_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);
|
assert_eq!(addr.raw(), 0x00020001);
|
||||||
let res = local_pool.read(&addr);
|
let res = local_pool.read(&addr);
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
let err = res.unwrap_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 data_too_large = [0; 20];
|
||||||
let res = local_pool.add(data_too_large.as_slice());
|
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);
|
let res = local_pool.free_element(LocalPool::MAX_SIZE + 1);
|
||||||
assert!(res.is_err());
|
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)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod sp;
|
pub mod sp;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
use postcard::{from_bytes, to_vec};
|
|
||||||
use heapless::Vec;
|
use heapless::Vec;
|
||||||
|
use postcard::{from_bytes, to_vec};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
|
||||||
struct RefStruct<'a> {
|
struct RefStruct<'a> {
|
||||||
@ -9,14 +9,14 @@ struct RefStruct<'a> {
|
|||||||
str_s: &'a str,
|
str_s: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let message = "hElLo";
|
let message = "hElLo";
|
||||||
let bytes = [0x01, 0x10, 0x02, 0x20];
|
let bytes = [0x01, 0x10, 0x02, 0x20];
|
||||||
let output: Vec<u8, 11> = to_vec(&RefStruct {
|
let output: Vec<u8, 11> = to_vec(&RefStruct {
|
||||||
bytes: &bytes,
|
bytes: &bytes,
|
||||||
str_s: message,
|
str_s: message,
|
||||||
}).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&[0x04, 0x01, 0x10, 0x02, 0x20, 0x05, b'h', b'E', b'l', b'L', b'o',],
|
&[0x04, 0x01, 0x10, 0x02, 0x20, 0x05, b'h', b'E', b'l', b'L', b'o',],
|
||||||
|
208
src/sp.rs
208
src/sp.rs
@ -1,16 +1,212 @@
|
|||||||
//! # Space related components including CCSDS and ECSS packet standards
|
//! # 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 {
|
pub enum PacketType {
|
||||||
Tm = 0,
|
Tm = 0,
|
||||||
Tc = 1
|
Tc = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
|
impl TryFrom<u8> for PacketType {
|
||||||
struct SpHeader {
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
|
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<u8> for SequenceFlags {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
|
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 version: u8,
|
||||||
pub ptype: PacketType,
|
pub ptype: PacketType,
|
||||||
pub apid: u16,
|
pub apid: u16,
|
||||||
pub secondary_header_flag: u8,
|
pub secondary_header_flag: bool,
|
||||||
|
pub sequence_flags: SequenceFlags,
|
||||||
pub ssc: u16,
|
pub ssc: u16,
|
||||||
}
|
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<Self> {
|
||||||
|
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> {
|
||||||
|
Self::new(apid, PacketType::Tm, ssc)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tc(apid: u16, ssc: u16) -> Option<Self> {
|
||||||
|
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<DekuSpHeader> for SpHeader {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(header: PrimaryHeader) -> Result<Self, Self::Error> {
|
||||||
|
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<SpHeader> for DekuSpHeader {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: SpHeader) -> Result<Self, Self::Error> {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user