Skip to content

Commit 7606767

Browse files
committed
the PCDU handler is already required
1 parent 37b32a9 commit 7606767

File tree

7 files changed

+338
-105
lines changed

7 files changed

+338
-105
lines changed

satrs-example/src/acs/mgm.rs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use satrs::spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
66
use satrs::spacepackets::SpHeader;
77
use satrs_example::{DeviceMode, TimestampHelper};
88
use satrs_minisim::acs::lis3mdl::{
9-
MgmLis3MdlReply, FIELD_LSB_PER_GAUSS_4_SENS, GAUSS_TO_MICROTESLA_FACTOR,
9+
MgmLis3MdlReply, MgmLis3RawValues, FIELD_LSB_PER_GAUSS_4_SENS, GAUSS_TO_MICROTESLA_FACTOR,
1010
};
1111
use satrs_minisim::acs::MgmRequestLis3Mdl;
1212
use satrs_minisim::{SerializableSimMsgPayload, SimReply, SimRequest};
@@ -47,18 +47,16 @@ pub trait SpiInterface {
4747

4848
#[derive(Default)]
4949
pub struct SpiDummyInterface {
50-
pub dummy_val_0: i16,
51-
pub dummy_val_1: i16,
52-
pub dummy_val_2: i16,
50+
pub dummy_values: MgmLis3RawValues,
5351
}
5452

5553
impl SpiInterface for SpiDummyInterface {
5654
type Error = ();
5755

5856
fn transfer(&mut self, _tx: &[u8], rx: &mut [u8]) -> Result<(), Self::Error> {
59-
rx[X_LOWBYTE_IDX..X_LOWBYTE_IDX + 2].copy_from_slice(&self.dummy_val_0.to_le_bytes());
60-
rx[Y_LOWBYTE_IDX..Y_LOWBYTE_IDX + 2].copy_from_slice(&self.dummy_val_1.to_be_bytes());
61-
rx[Z_LOWBYTE_IDX..Z_LOWBYTE_IDX + 2].copy_from_slice(&self.dummy_val_2.to_be_bytes());
57+
rx[X_LOWBYTE_IDX..X_LOWBYTE_IDX + 2].copy_from_slice(&self.dummy_values.x.to_le_bytes());
58+
rx[Y_LOWBYTE_IDX..Y_LOWBYTE_IDX + 2].copy_from_slice(&self.dummy_values.y.to_be_bytes());
59+
rx[Z_LOWBYTE_IDX..Z_LOWBYTE_IDX + 2].copy_from_slice(&self.dummy_values.z.to_be_bytes());
6260
Ok(())
6361
}
6462
}
@@ -74,18 +72,27 @@ impl SpiInterface for SpiSimInterface {
7472
// Right now, we only support requesting sensor data and not configuration of the sensor.
7573
fn transfer(&mut self, _tx: &[u8], rx: &mut [u8]) -> Result<(), Self::Error> {
7674
let mgm_sensor_request = MgmRequestLis3Mdl::RequestSensorData;
77-
self.sim_request_tx
75+
if let Err(e) = self
76+
.sim_request_tx
7877
.send(SimRequest::new_with_epoch_time(mgm_sensor_request))
79-
.expect("failed to send request");
80-
let sim_reply = self
81-
.sim_reply_rx
82-
.recv_timeout(Duration::from_millis(100))
83-
.expect("reply timeout");
84-
let sim_reply_lis3 =
85-
MgmLis3MdlReply::from_sim_message(&sim_reply).expect("failed to parse LIS3 reply");
86-
rx[X_LOWBYTE_IDX..X_LOWBYTE_IDX + 2].copy_from_slice(&sim_reply_lis3.raw.x.to_le_bytes());
87-
rx[Y_LOWBYTE_IDX..Y_LOWBYTE_IDX + 2].copy_from_slice(&sim_reply_lis3.raw.y.to_le_bytes());
88-
rx[Z_LOWBYTE_IDX..Z_LOWBYTE_IDX + 2].copy_from_slice(&sim_reply_lis3.raw.z.to_le_bytes());
78+
{
79+
log::error!("failed to send MGM LIS3 request: {}", e);
80+
}
81+
match self.sim_reply_rx.recv_timeout(Duration::from_millis(50)) {
82+
Ok(sim_reply) => {
83+
let sim_reply_lis3 = MgmLis3MdlReply::from_sim_message(&sim_reply)
84+
.expect("failed to parse LIS3 reply");
85+
rx[X_LOWBYTE_IDX..X_LOWBYTE_IDX + 2]
86+
.copy_from_slice(&sim_reply_lis3.raw.x.to_le_bytes());
87+
rx[Y_LOWBYTE_IDX..Y_LOWBYTE_IDX + 2]
88+
.copy_from_slice(&sim_reply_lis3.raw.y.to_le_bytes());
89+
rx[Z_LOWBYTE_IDX..Z_LOWBYTE_IDX + 2]
90+
.copy_from_slice(&sim_reply_lis3.raw.z.to_le_bytes());
91+
}
92+
Err(e) => {
93+
log::warn!("MGM LIS3 SIM reply timeout: {}", e);
94+
}
95+
}
8996
Ok(())
9097
}
9198
}

satrs-example/src/eps/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod pcdu;

satrs-example/src/eps/pcdu.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use std::{
2+
collections::HashMap,
3+
sync::{mpsc, Arc, Mutex},
4+
};
5+
6+
use derive_new::new;
7+
use satrs::{
8+
mode::ModeAndSubmode,
9+
power::SwitchState,
10+
pus::EcssTmSender,
11+
request::{GenericMessage, UniqueApidTargetId},
12+
};
13+
use satrs_example::TimestampHelper;
14+
15+
use crate::{acs::mgm::MpscModeLeafInterface, pus::hk::HkReply, requests::CompositeRequest};
16+
17+
pub trait SerialInterface {}
18+
19+
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
20+
#[repr(u32)]
21+
pub enum SwitchId {
22+
Mgm0 = 0,
23+
Mgt = 1,
24+
}
25+
26+
pub type SwitchMap = HashMap<SwitchId, SwitchState>;
27+
28+
/// Example PCDU device handler.
29+
#[derive(new)]
30+
#[allow(clippy::too_many_arguments)]
31+
pub struct PcduHandler<ComInterface: SerialInterface, TmSender: EcssTmSender> {
32+
id: UniqueApidTargetId,
33+
dev_str: &'static str,
34+
mode_interface: MpscModeLeafInterface,
35+
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
36+
hk_reply_tx: mpsc::Sender<GenericMessage<HkReply>>,
37+
tm_sender: TmSender,
38+
pub com_interface: ComInterface,
39+
shared_switch_map: Arc<Mutex<SwitchMap>>,
40+
#[new(value = "ModeAndSubmode::new(satrs_example::DeviceMode::Off as u32, 0)")]
41+
mode_and_submode: ModeAndSubmode,
42+
#[new(default)]
43+
stamp_helper: TimestampHelper,
44+
}

satrs-example/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod acs;
2+
mod eps;
23
mod events;
34
mod hk;
45
mod interface;

satrs-minisim/src/acs.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use satrs_minisim::{
1515

1616
use crate::time::current_millis;
1717

18-
// Earth magnetic field varies between -30 uT and 30 uT
18+
// Earth magnetic field varies between roughly -30 uT and 30 uT
1919
const AMPLITUDE_MGM_UT: f32 = 30.0;
2020
// Lets start with a simple frequency here.
2121
const FREQUENCY_MGM: f32 = 1.0;
@@ -26,14 +26,9 @@ const PHASE_Z: f32 = 0.2;
2626

2727
/// Simple model for a magnetometer where the measure magnetic fields are modeled with sine waves.
2828
///
29-
/// Please note that that a more realistic MGM model wouold include the following components
30-
/// which are not included here to simplify the model:
31-
///
32-
/// 1. It would probably generate signed [i16] values which need to be converted to SI units
33-
/// because it is a digital sensor
34-
/// 2. It would sample the magnetic field at a high fixed rate. This might not be possible for
35-
/// a general purpose OS, but self self-sampling at a relatively high rate (20-40 ms) might
36-
/// stil lbe possible.
29+
/// An ideal sensor would sample the magnetic field at a high fixed rate. This might not be
30+
/// possible for a general purpose OS, but self self-sampling at a relatively high rate (20-40 ms)
31+
/// might still be possible and is probably sufficient for many OBSW needs.
3732
pub struct MagnetometerModel<ReplyProvider: MgmReplyProvider> {
3833
pub switch_state: SwitchStateBinary,
3934
pub periodicity: Duration,

satrs-minisim/src/lib.rs

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ pub mod acs {
236236
y: -30.0,
237237
z: 30.0,
238238
};
239+
pub const ALL_ONES_SENSOR_VAL: i16 = 0xffff_u16 as i16;
239240

240241
pub mod lis3mdl {
241242
use super::*;
@@ -264,27 +265,39 @@ pub mod acs {
264265

265266
impl MgmLis3MdlReply {
266267
pub fn new(common: MgmReplyCommon) -> Self {
267-
let mut raw_reply: [u8; 7] = [0; 7];
268-
let raw_x: i16 = (common.sensor_values.x
269-
/ (GAUSS_TO_MICROTESLA_FACTOR as f32 * FIELD_LSB_PER_GAUSS_4_SENS))
270-
.round() as i16;
271-
let raw_y: i16 = (common.sensor_values.y
272-
/ (GAUSS_TO_MICROTESLA_FACTOR as f32 * FIELD_LSB_PER_GAUSS_4_SENS))
273-
.round() as i16;
274-
let raw_z: i16 = (common.sensor_values.z
275-
/ (GAUSS_TO_MICROTESLA_FACTOR as f32 * FIELD_LSB_PER_GAUSS_4_SENS))
276-
.round() as i16;
277-
// The first byte is a dummy byte.
278-
raw_reply[1..3].copy_from_slice(&raw_x.to_be_bytes());
279-
raw_reply[3..5].copy_from_slice(&raw_y.to_be_bytes());
280-
raw_reply[5..7].copy_from_slice(&raw_z.to_be_bytes());
281-
Self {
282-
common,
283-
raw: MgmLis3RawValues {
284-
x: raw_x,
285-
y: raw_y,
286-
z: raw_z,
268+
match common.switch_state {
269+
SwitchStateBinary::Off => Self {
270+
common,
271+
raw: MgmLis3RawValues {
272+
x: ALL_ONES_SENSOR_VAL,
273+
y: ALL_ONES_SENSOR_VAL,
274+
z: ALL_ONES_SENSOR_VAL,
275+
},
287276
},
277+
SwitchStateBinary::On => {
278+
let mut raw_reply: [u8; 7] = [0; 7];
279+
let raw_x: i16 = (common.sensor_values.x
280+
/ (GAUSS_TO_MICROTESLA_FACTOR as f32 * FIELD_LSB_PER_GAUSS_4_SENS))
281+
.round() as i16;
282+
let raw_y: i16 = (common.sensor_values.y
283+
/ (GAUSS_TO_MICROTESLA_FACTOR as f32 * FIELD_LSB_PER_GAUSS_4_SENS))
284+
.round() as i16;
285+
let raw_z: i16 = (common.sensor_values.z
286+
/ (GAUSS_TO_MICROTESLA_FACTOR as f32 * FIELD_LSB_PER_GAUSS_4_SENS))
287+
.round() as i16;
288+
// The first byte is a dummy byte.
289+
raw_reply[1..3].copy_from_slice(&raw_x.to_be_bytes());
290+
raw_reply[3..5].copy_from_slice(&raw_y.to_be_bytes());
291+
raw_reply[5..7].copy_from_slice(&raw_z.to_be_bytes());
292+
Self {
293+
common,
294+
raw: MgmLis3RawValues {
295+
x: raw_x,
296+
y: raw_y,
297+
z: raw_z,
298+
},
299+
}
300+
}
288301
}
289302
}
290303
}

0 commit comments

Comments
 (0)