extern crate alloc; use std::{ sync::mpsc, time::{Duration, Instant}, }; pub use models::ComponentId; use models::ccsds::{CcsdsTcPacketOwned, CcsdsTmPacketOwned}; use satrs::spacepackets::{CcsdsPacketIdAndPsc, time::cds::CdsTime}; pub mod config; /// Simple type modelling packet stored in the heap. This structure is intended to /// be used when sending a packet via a message queue, so it also contains the sender ID. #[derive(Debug, PartialEq, Eq, Clone)] pub struct PacketAsVec { pub sender_id: ComponentId, pub packet: Vec, } impl PacketAsVec { pub fn new(sender_id: ComponentId, packet: Vec) -> Self { Self { sender_id, packet } } } pub struct TimestampHelper { stamper: CdsTime, time_stamp: [u8; 7], } impl TimestampHelper { pub fn stamp(&self) -> &[u8] { &self.time_stamp } pub fn update_from_now(&mut self) { self.stamper .update_from_now() .expect("Updating timestamp failed"); self.stamper .write_to_bytes(&mut self.time_stamp) .expect("Writing timestamp failed"); } } impl Default for TimestampHelper { fn default() -> Self { Self { stamper: CdsTime::now_with_u16_days().expect("creating time stamper failed"), time_stamp: Default::default(), } } } /// Helper structure for periodic HK generation of a single set. #[derive(Debug)] pub struct HkHelperSingleSet { pub enabled: bool, pub frequency: Duration, pub last_generated: Option, } impl HkHelperSingleSet { #[inline] pub const fn new(enabled: bool, init_frequency: Duration) -> Self { Self { enabled, frequency: init_frequency, last_generated: None, } } #[inline] pub const fn enabled(&self) -> bool { self.enabled } /// Check whether a new HK packet needs to be generated. pub fn needs_generation(&mut self) -> bool { if !self.enabled { return false; } if self.last_generated.is_none() { self.last_generated = Some(Instant::now()); return true; } let last_generated = self.last_generated.unwrap(); if Instant::now() - last_generated >= self.frequency { self.last_generated = Some(Instant::now()); return true; } false } } pub struct TmtcQueues { pub tc_rx: mpsc::Receiver, pub tm_tx: mpsc::SyncSender, } #[derive(Debug)] pub struct ModeHelper { pub current: Mode, pub target: Option, pub tc_commander: Option, pub transition_start: Option, pub timeout: Duration, pub transition_state: TransitionState, } impl ModeHelper { pub fn new(init_mode: Mode, timeout: Duration) -> Self { Self { current: init_mode, target: Default::default(), tc_commander: Default::default(), transition_start: None, timeout, transition_state: Default::default(), } } pub fn start(&mut self, target: Mode) { self.target = Some(target); self.transition_start = Some(Instant::now()); self.transition_state = TransitionState::default(); } #[inline] pub fn transition_active(&self) -> bool { self.target.is_some() } pub fn timed_out(&self) -> bool { if self.target.is_none() { return false; } if let Some(transition_start) = self.transition_start { return Instant::now() - transition_start >= self.timeout; } false } pub fn finish(&mut self, success: bool) -> Option { self.target?; if success { self.current = self.target.take().unwrap(); } else { self.target = None; } self.transition_state = Default::default(); self.transition_start = None; self.tc_commander.take() } }