more simplifications
This commit is contained in:
@@ -3,8 +3,8 @@ use arbitrary_int::u11;
|
||||
use clap::Parser as _;
|
||||
use satrs_example::config::{OBSW_SERVER_ADDR, SERVER_PORT};
|
||||
use satrs_minisim::{
|
||||
SimCtrlReply, SimCtrlRequest, SimReply, SimRequest, SimRequestWithTime, acs,
|
||||
acs::MgmRequestLis3Mdl, acs::SpiFault, acs::mgm::MgmId, udp::SIM_CTRL_PORT,
|
||||
SimCtrlReply, SimCtrlRequest, SimReply, SimRequest, SimRequestWithTime, acs::mgm,
|
||||
udp::SIM_CTRL_PORT,
|
||||
};
|
||||
use spacepackets::{CcsdsPacketIdAndPsc, SpacePacketHeader};
|
||||
use std::{
|
||||
@@ -97,12 +97,12 @@ enum FaultMode {
|
||||
AllOnes,
|
||||
}
|
||||
|
||||
impl From<FaultMode> for acs::SpiFaultMode {
|
||||
impl From<FaultMode> for mgm::SpiFaultMode {
|
||||
fn from(mode: FaultMode) -> Self {
|
||||
match mode {
|
||||
FaultMode::None => acs::SpiFaultMode::None,
|
||||
FaultMode::AllZeros => acs::SpiFaultMode::AllZeros,
|
||||
FaultMode::AllOnes => acs::SpiFaultMode::AllOnes,
|
||||
FaultMode::None => mgm::SpiFaultMode::None,
|
||||
FaultMode::AllZeros => mgm::SpiFaultMode::AllZeros,
|
||||
FaultMode::AllOnes => mgm::SpiFaultMode::AllOnes,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -204,7 +204,7 @@ fn handle_mgm_command(
|
||||
if let Some(mode) = args.fault {
|
||||
inject_mgm_failure(
|
||||
target_id,
|
||||
SpiFault {
|
||||
mgm::SpiFault {
|
||||
mode: mode.into(),
|
||||
cleared_by_power_cycle: args.fault_kind == FaultKind::Transient,
|
||||
},
|
||||
@@ -499,7 +499,7 @@ fn main() -> anyhow::Result<()> {
|
||||
/// Confirms the simulator is actually reachable first (same ping/pong check the OBSW's own
|
||||
/// internal sim client does, see `SimClientUdp::attempt_connection`), since a fire-and-forget
|
||||
/// UDP send would otherwise silently do nothing if minisim is not running.
|
||||
fn inject_mgm_failure(target_id: types::ComponentId, fault: SpiFault) -> anyhow::Result<()> {
|
||||
fn inject_mgm_failure(target_id: types::ComponentId, fault: mgm::SpiFault) -> anyhow::Result<()> {
|
||||
let sim_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), SIM_CTRL_PORT);
|
||||
let sim_socket = UdpSocket::bind("127.0.0.1:0")?;
|
||||
sim_socket.set_read_timeout(Some(Duration::from_millis(200)))?;
|
||||
@@ -526,13 +526,13 @@ fn inject_mgm_failure(target_id: types::ComponentId, fault: SpiFault) -> anyhow:
|
||||
}
|
||||
|
||||
let id = match target_id {
|
||||
types::ComponentId::AcsMgm0 => MgmId::Mgm0,
|
||||
types::ComponentId::AcsMgm1 => MgmId::Mgm1,
|
||||
types::ComponentId::AcsMgm0 => mgm::Id::Mgm0,
|
||||
types::ComponentId::AcsMgm1 => mgm::Id::Mgm1,
|
||||
_ => bail!("SPI fault injection is not supported for {target_id:?}"),
|
||||
};
|
||||
let request = SimRequestWithTime::new_with_epoch_time(SimRequest::Mgm {
|
||||
id,
|
||||
request: MgmRequestLis3Mdl::SetSpiFault(fault),
|
||||
request: mgm::Request::SetSpiFault(fault),
|
||||
});
|
||||
sim_socket.send_to(&serde_json::to_vec(&request)?, sim_addr)?;
|
||||
log::info!("injected SPI fault {fault:?} into minisim {target_id:?}");
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
use std::{f32::consts::PI, sync::mpsc, time::Duration};
|
||||
|
||||
use nexosim::model::{Context, Model};
|
||||
use satrs_minisim::{
|
||||
acs::{
|
||||
mgm::{MgmId, MgmReply},
|
||||
MgmSensorValuesMicroTesla, SpiFault,
|
||||
},
|
||||
SimReply,
|
||||
};
|
||||
use satrs_minisim::{acs::mgm, SimReply};
|
||||
use types::pcdu::SwitchStateBinary;
|
||||
|
||||
use crate::time::current_millis;
|
||||
@@ -25,24 +19,28 @@ const PHASE_Z: f32 = 0.2;
|
||||
/// An ideal sensor would sample the magnetic field at a high fixed rate. This might not be
|
||||
/// possible for a general purpose OS, but self self-sampling at a relatively high rate (20-40 ms)
|
||||
/// might still be possible and is probably sufficient for many OBSW needs.
|
||||
pub struct MagnetometerModel {
|
||||
pub id: MgmId,
|
||||
pub struct MgmModel {
|
||||
pub id: mgm::Id,
|
||||
pub switch_state: SwitchStateBinary,
|
||||
#[allow(dead_code)]
|
||||
pub periodicity: Duration,
|
||||
pub external_mag_field: Option<MgmSensorValuesMicroTesla>,
|
||||
pub spi_fault: SpiFault,
|
||||
pub external_mag_field: Option<mgm::SensorValuesMicroTesla>,
|
||||
pub spi_fault: mgm::SpiFault,
|
||||
pub reply_sender: mpsc::Sender<SimReply>,
|
||||
}
|
||||
|
||||
impl MagnetometerModel {
|
||||
pub fn new(mgm_id: MgmId, periodicity: Duration, reply_sender: mpsc::Sender<SimReply>) -> Self {
|
||||
impl MgmModel {
|
||||
pub fn new(
|
||||
mgm_id: mgm::Id,
|
||||
periodicity: Duration,
|
||||
reply_sender: mpsc::Sender<SimReply>,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: mgm_id,
|
||||
switch_state: SwitchStateBinary::Off,
|
||||
periodicity,
|
||||
external_mag_field: None,
|
||||
spi_fault: SpiFault::default(),
|
||||
spi_fault: mgm::SpiFault::default(),
|
||||
reply_sender,
|
||||
}
|
||||
}
|
||||
@@ -50,19 +48,19 @@ impl MagnetometerModel {
|
||||
pub async fn switch_device(&mut self, switch_state: SwitchStateBinary) {
|
||||
self.switch_state = switch_state;
|
||||
if switch_state == SwitchStateBinary::Off && self.spi_fault.cleared_by_power_cycle {
|
||||
self.spi_fault = SpiFault::default();
|
||||
self.spi_fault = mgm::SpiFault::default();
|
||||
}
|
||||
}
|
||||
|
||||
/// Force (or clear) a stuck-bus SPI fault, for FDIR testing purposes.
|
||||
pub async fn set_spi_fault(&mut self, fault: SpiFault) {
|
||||
pub async fn set_spi_fault(&mut self, fault: mgm::SpiFault) {
|
||||
self.spi_fault = fault;
|
||||
}
|
||||
|
||||
pub async fn send_sensor_values(&mut self, _: (), scheduler: &mut Context<Self>) {
|
||||
let reply = SimReply::Mgm {
|
||||
id: self.id,
|
||||
reply: MgmReply::new(
|
||||
reply: mgm::Reply::new(
|
||||
self.switch_state,
|
||||
self.calculate_current_mgm_tuple(current_millis(scheduler.time())),
|
||||
self.spi_fault.mode,
|
||||
@@ -75,23 +73,23 @@ impl MagnetometerModel {
|
||||
|
||||
// Devices like magnetorquers generate a strong magnetic field which overrides the default
|
||||
// model for the measured magnetic field.
|
||||
pub async fn apply_external_magnetic_field(&mut self, field: MgmSensorValuesMicroTesla) {
|
||||
pub async fn apply_external_magnetic_field(&mut self, field: mgm::SensorValuesMicroTesla) {
|
||||
self.external_mag_field = Some(field);
|
||||
}
|
||||
|
||||
fn calculate_current_mgm_tuple(&self, time_ms: u64) -> MgmSensorValuesMicroTesla {
|
||||
fn calculate_current_mgm_tuple(&self, time_ms: u64) -> mgm::SensorValuesMicroTesla {
|
||||
if SwitchStateBinary::On == self.switch_state {
|
||||
if let Some(ext_field) = self.external_mag_field {
|
||||
return ext_field;
|
||||
}
|
||||
let base_sin_val = 2.0 * PI * FREQUENCY_MGM * (time_ms as f32 / 1000.0);
|
||||
return MgmSensorValuesMicroTesla {
|
||||
return mgm::SensorValuesMicroTesla {
|
||||
x: AMPLITUDE_MGM_UT * (base_sin_val + PHASE_X).sin(),
|
||||
y: AMPLITUDE_MGM_UT * (base_sin_val + PHASE_Y).sin(),
|
||||
z: AMPLITUDE_MGM_UT * (base_sin_val + PHASE_Z).sin(),
|
||||
};
|
||||
}
|
||||
MgmSensorValuesMicroTesla {
|
||||
mgm::SensorValuesMicroTesla {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
@@ -99,19 +97,13 @@ impl MagnetometerModel {
|
||||
}
|
||||
}
|
||||
|
||||
impl Model for MagnetometerModel {}
|
||||
impl Model for MgmModel {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
use satrs_minisim::{
|
||||
acs::{
|
||||
mgm::{self, MgmId, MgmReply},
|
||||
MgmRequestLis3Mdl, SpiFault, SpiFaultMode,
|
||||
},
|
||||
SimComponent, SimReply, SimRequest, SimRequestWithTime,
|
||||
};
|
||||
use satrs_minisim::{acs::mgm, SimComponent, SimReply, SimRequest, SimRequestWithTime};
|
||||
use types::pcdu::{SwitchId, SwitchStateBinary};
|
||||
|
||||
use crate::{
|
||||
@@ -119,11 +111,11 @@ mod tests {
|
||||
test_helpers::SimTestbench,
|
||||
};
|
||||
|
||||
fn mgm_request(id: MgmId, request: MgmRequestLis3Mdl) -> SimRequestWithTime {
|
||||
fn mgm_request(id: mgm::Id, request: mgm::Request) -> SimRequestWithTime {
|
||||
SimRequestWithTime::new_with_epoch_time(SimRequest::Mgm { id, request })
|
||||
}
|
||||
|
||||
fn unwrap_mgm_reply(sim_reply: SimReply) -> (MgmId, MgmReply) {
|
||||
fn unwrap_mgm_reply(sim_reply: SimReply) -> (mgm::Id, mgm::Reply) {
|
||||
match sim_reply {
|
||||
SimReply::Mgm { id, reply } => (id, reply),
|
||||
_ => panic!("unexpected reply {sim_reply:?}"),
|
||||
@@ -133,7 +125,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_basic_mgm_request() {
|
||||
let mut sim_testbench = SimTestbench::new();
|
||||
let request = mgm_request(MgmId::Mgm0, MgmRequestLis3Mdl::RequestSensorData);
|
||||
let request = mgm_request(mgm::Id::Mgm0, mgm::Request::RequestSensorData);
|
||||
sim_testbench
|
||||
.send_request(request)
|
||||
.expect("sending MGM request failed");
|
||||
@@ -144,7 +136,7 @@ mod tests {
|
||||
let sim_reply = sim_reply.unwrap();
|
||||
assert_eq!(sim_reply.component(), SimComponent::Mgm0Lis3Mdl);
|
||||
let (id, reply) = unwrap_mgm_reply(sim_reply);
|
||||
assert_eq!(id, MgmId::Mgm0);
|
||||
assert_eq!(id, mgm::Id::Mgm0);
|
||||
assert_eq!(reply.switch_state, SwitchStateBinary::Off);
|
||||
assert_eq!(reply.sensor_values.x, 0.0);
|
||||
assert_eq!(reply.sensor_values.y, 0.0);
|
||||
@@ -153,9 +145,9 @@ mod tests {
|
||||
|
||||
fn inject_spi_fault(sim_testbench: &mut SimTestbench, cleared_by_power_cycle: bool) {
|
||||
let fault_request = mgm_request(
|
||||
MgmId::Mgm0,
|
||||
MgmRequestLis3Mdl::SetSpiFault(SpiFault {
|
||||
mode: SpiFaultMode::AllOnes,
|
||||
mgm::Id::Mgm0,
|
||||
mgm::Request::SetSpiFault(mgm::SpiFault {
|
||||
mode: mgm::SpiFaultMode::AllOnes,
|
||||
cleared_by_power_cycle,
|
||||
}),
|
||||
);
|
||||
@@ -166,8 +158,8 @@ mod tests {
|
||||
sim_testbench.step().unwrap();
|
||||
}
|
||||
|
||||
fn request_mgm_reply(sim_testbench: &mut SimTestbench) -> MgmReply {
|
||||
let data_request = mgm_request(MgmId::Mgm0, MgmRequestLis3Mdl::RequestSensorData);
|
||||
fn request_mgm_reply(sim_testbench: &mut SimTestbench) -> mgm::Reply {
|
||||
let data_request = mgm_request(mgm::Id::Mgm0, mgm::Request::RequestSensorData);
|
||||
sim_testbench
|
||||
.send_request(data_request)
|
||||
.expect("sending MGM request failed");
|
||||
@@ -179,7 +171,7 @@ mod tests {
|
||||
unwrap_mgm_reply(sim_reply).1
|
||||
}
|
||||
|
||||
fn is_stuck_bus_reply(reply: &MgmReply) -> bool {
|
||||
fn is_stuck_bus_reply(reply: &mgm::Reply) -> bool {
|
||||
reply.raw.x == -1 && reply.raw.y == -1 && reply.raw.z == -1
|
||||
}
|
||||
|
||||
@@ -226,7 +218,7 @@ mod tests {
|
||||
let mut sim_testbench = SimTestbench::new();
|
||||
switch_device_on(&mut sim_testbench, SwitchId::Mgm0);
|
||||
|
||||
let mut request = mgm_request(MgmId::Mgm0, MgmRequestLis3Mdl::RequestSensorData);
|
||||
let mut request = mgm_request(mgm::Id::Mgm0, mgm::Request::RequestSensorData);
|
||||
sim_testbench
|
||||
.send_request(request)
|
||||
.expect("sending MGM request failed");
|
||||
@@ -239,7 +231,7 @@ mod tests {
|
||||
let first_reply = unwrap_mgm_reply(sim_reply).1;
|
||||
sim_testbench.step_until(Duration::from_millis(50)).unwrap();
|
||||
|
||||
request = mgm_request(MgmId::Mgm0, MgmRequestLis3Mdl::RequestSensorData);
|
||||
request = mgm_request(mgm::Id::Mgm0, mgm::Request::RequestSensorData);
|
||||
sim_testbench
|
||||
.send_request(request)
|
||||
.expect("sending MGM request failed");
|
||||
@@ -276,8 +268,8 @@ mod tests {
|
||||
switch_device_on(&mut sim_testbench, SwitchId::Mgm1);
|
||||
|
||||
for request in [
|
||||
mgm_request(MgmId::Mgm0, MgmRequestLis3Mdl::RequestSensorData),
|
||||
mgm_request(MgmId::Mgm1, MgmRequestLis3Mdl::RequestSensorData),
|
||||
mgm_request(mgm::Id::Mgm0, mgm::Request::RequestSensorData),
|
||||
mgm_request(mgm::Id::Mgm1, mgm::Request::RequestSensorData),
|
||||
] {
|
||||
sim_testbench
|
||||
.send_request(request)
|
||||
@@ -291,7 +283,7 @@ mod tests {
|
||||
.expect("no MGM0 reply received");
|
||||
assert_eq!(sim_reply.component(), SimComponent::Mgm0Lis3Mdl);
|
||||
let (id, reply) = unwrap_mgm_reply(sim_reply);
|
||||
assert_eq!(id, MgmId::Mgm0);
|
||||
assert_eq!(id, mgm::Id::Mgm0);
|
||||
assert_eq!(reply.switch_state, SwitchStateBinary::Off);
|
||||
|
||||
let sim_reply = sim_testbench
|
||||
@@ -299,7 +291,7 @@ mod tests {
|
||||
.expect("no MGM1 reply received");
|
||||
assert_eq!(sim_reply.component(), SimComponent::Mgm1Lis3Mdl);
|
||||
let (id, reply) = unwrap_mgm_reply(sim_reply);
|
||||
assert_eq!(id, MgmId::Mgm1);
|
||||
assert_eq!(id, mgm::Id::Mgm1);
|
||||
assert_eq!(reply.switch_state, SwitchStateBinary::On);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use nexosim::{
|
||||
ports::Output,
|
||||
};
|
||||
use satrs_minisim::{
|
||||
acs::{MgmSensorValuesMicroTesla, MgtDipole, MgtHkSet, MgtReply, MGT_GEN_MAGNETIC_FIELD},
|
||||
acs::{mgm, mgt},
|
||||
SimReply,
|
||||
};
|
||||
use std::{sync::mpsc, time::Duration};
|
||||
@@ -12,8 +12,8 @@ use types::pcdu::SwitchStateBinary;
|
||||
pub struct MagnetorquerModel {
|
||||
switch_state: SwitchStateBinary,
|
||||
torquing: bool,
|
||||
torque_dipole: MgtDipole,
|
||||
pub gen_magnetic_field: Output<MgmSensorValuesMicroTesla>,
|
||||
torque_dipole: mgt::Dipole,
|
||||
pub gen_magnetic_field: Output<mgm::SensorValuesMicroTesla>,
|
||||
reply_sender: mpsc::Sender<SimReply>,
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ impl MagnetorquerModel {
|
||||
Self {
|
||||
switch_state: SwitchStateBinary::Off,
|
||||
torquing: false,
|
||||
torque_dipole: MgtDipole::default(),
|
||||
torque_dipole: mgt::Dipole::default(),
|
||||
gen_magnetic_field: Output::new(),
|
||||
reply_sender,
|
||||
}
|
||||
@@ -30,7 +30,7 @@ impl MagnetorquerModel {
|
||||
|
||||
pub async fn apply_torque(
|
||||
&mut self,
|
||||
duration_and_dipole: (Duration, MgtDipole),
|
||||
duration_and_dipole: (Duration, mgt::Dipole),
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.torque_dipole = duration_and_dipole.1;
|
||||
@@ -45,7 +45,7 @@ impl MagnetorquerModel {
|
||||
}
|
||||
|
||||
pub async fn clear_torque(&mut self, _: ()) {
|
||||
self.torque_dipole = MgtDipole::default();
|
||||
self.torque_dipole = mgt::Dipole::default();
|
||||
self.torquing = false;
|
||||
self.generate_magnetic_field(()).await;
|
||||
}
|
||||
@@ -65,17 +65,17 @@ impl MagnetorquerModel {
|
||||
|
||||
pub fn send_housekeeping_data(&mut self) {
|
||||
self.reply_sender
|
||||
.send(SimReply::from(MgtReply::Hk(MgtHkSet {
|
||||
.send(SimReply::from(mgt::Reply::Hk(mgt::HkSet {
|
||||
dipole: self.torque_dipole,
|
||||
torquing: self.torquing,
|
||||
})))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn calc_magnetic_field(&self, _: MgtDipole) -> MgmSensorValuesMicroTesla {
|
||||
fn calc_magnetic_field(&self, _: mgt::Dipole) -> mgm::SensorValuesMicroTesla {
|
||||
// Simplified model: Just returns some fixed magnetic field for now.
|
||||
// Later, we could make this more fancy by incorporating the commanded dipole.
|
||||
MGT_GEN_MAGNETIC_FIELD
|
||||
mgm::MGT_GEN_MAGNETIC_FIELD
|
||||
}
|
||||
|
||||
/// A torquing magnetorquer generates a magnetic field. This function can be used to apply
|
||||
@@ -96,10 +96,7 @@ impl Model for MagnetorquerModel {}
|
||||
mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
use satrs_minisim::{
|
||||
acs::{MgtDipole, MgtHkSet, MgtReply, MgtRequest},
|
||||
SimReply, SimRequestWithTime,
|
||||
};
|
||||
use satrs_minisim::{acs::mgt, SimReply, SimRequestWithTime};
|
||||
use types::pcdu::SwitchId;
|
||||
|
||||
use crate::{eps::tests::switch_device_on, test_helpers::SimTestbench};
|
||||
@@ -107,7 +104,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_basic_mgt_request_is_off() {
|
||||
let mut sim_testbench = SimTestbench::new();
|
||||
let request = SimRequestWithTime::new_with_epoch_time(MgtRequest::RequestHk);
|
||||
let request = SimRequestWithTime::new_with_epoch_time(mgt::Request::RequestHk);
|
||||
sim_testbench
|
||||
.send_request(request)
|
||||
.expect("sending MGM request failed");
|
||||
@@ -121,7 +118,7 @@ mod tests {
|
||||
fn test_basic_mgt_request_is_on() {
|
||||
let mut sim_testbench = SimTestbench::new();
|
||||
switch_device_on(&mut sim_testbench, SwitchId::Mgt);
|
||||
let request = SimRequestWithTime::new_with_epoch_time(MgtRequest::RequestHk);
|
||||
let request = SimRequestWithTime::new_with_epoch_time(mgt::Request::RequestHk);
|
||||
|
||||
sim_testbench
|
||||
.send_request(request)
|
||||
@@ -135,16 +132,16 @@ mod tests {
|
||||
panic!("unexpected reply");
|
||||
};
|
||||
match mgt_reply {
|
||||
MgtReply::Hk(hk) => {
|
||||
assert_eq!(hk.dipole, MgtDipole::default());
|
||||
mgt::Reply::Hk(hk) => {
|
||||
assert_eq!(hk.dipole, mgt::Dipole::default());
|
||||
assert!(!hk.torquing);
|
||||
}
|
||||
_ => panic!("unexpected reply"),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_mgt_hk(sim_testbench: &mut SimTestbench, expected_hk_set: MgtHkSet) {
|
||||
let request = SimRequestWithTime::new_with_epoch_time(MgtRequest::RequestHk);
|
||||
fn check_mgt_hk(sim_testbench: &mut SimTestbench, expected_hk_set: mgt::HkSet) {
|
||||
let request = SimRequestWithTime::new_with_epoch_time(mgt::Request::RequestHk);
|
||||
sim_testbench
|
||||
.send_request(request)
|
||||
.expect("sending MGM request failed");
|
||||
@@ -157,7 +154,7 @@ mod tests {
|
||||
panic!("unexpected reply");
|
||||
};
|
||||
match mgt_reply {
|
||||
MgtReply::Hk(hk) => {
|
||||
mgt::Reply::Hk(hk) => {
|
||||
assert_eq!(hk, expected_hk_set);
|
||||
}
|
||||
_ => panic!("unexpected reply"),
|
||||
@@ -168,12 +165,12 @@ mod tests {
|
||||
fn test_basic_mgt_request_is_on_and_torquing() {
|
||||
let mut sim_testbench = SimTestbench::new();
|
||||
switch_device_on(&mut sim_testbench, SwitchId::Mgt);
|
||||
let commanded_dipole = MgtDipole {
|
||||
let commanded_dipole = mgt::Dipole {
|
||||
x: -200,
|
||||
y: 200,
|
||||
z: 1000,
|
||||
};
|
||||
let request = SimRequestWithTime::new_with_epoch_time(MgtRequest::ApplyTorque {
|
||||
let request = SimRequestWithTime::new_with_epoch_time(mgt::Request::ApplyTorque {
|
||||
duration: Duration::from_millis(100),
|
||||
dipole: commanded_dipole,
|
||||
});
|
||||
@@ -185,7 +182,7 @@ mod tests {
|
||||
|
||||
check_mgt_hk(
|
||||
&mut sim_testbench,
|
||||
MgtHkSet {
|
||||
mgt::HkSet {
|
||||
dipole: commanded_dipole,
|
||||
torquing: true,
|
||||
},
|
||||
@@ -195,8 +192,8 @@ mod tests {
|
||||
.unwrap();
|
||||
check_mgt_hk(
|
||||
&mut sim_testbench,
|
||||
MgtHkSet {
|
||||
dipole: MgtDipole::default(),
|
||||
mgt::HkSet {
|
||||
dipole: mgt::Dipole::default(),
|
||||
torquing: false,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -5,13 +5,13 @@ use nexosim::{
|
||||
time::{Clock, MonotonicTime, SystemClock},
|
||||
};
|
||||
use satrs_minisim::{
|
||||
acs::{mgm::MgmId, MgmRequestLis3Mdl, MgtRequest},
|
||||
acs::{mgm, mgt},
|
||||
eps::PcduRequest,
|
||||
SimCtrlReply, SimCtrlRequest, SimReply, SimRequest, SimRequestWithTime,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
acs::{mgm::MagnetometerModel, mgt::MagnetorquerModel},
|
||||
acs::{mgm::MgmModel, mgt::MagnetorquerModel},
|
||||
eps::PcduModel,
|
||||
};
|
||||
|
||||
@@ -23,8 +23,8 @@ const PCDU_REQ_WIRETAPPING: bool = false;
|
||||
const MGT_REQ_WIRETAPPING: bool = false;
|
||||
|
||||
pub struct ModelAddrWrapper {
|
||||
mgm_0_addr: Address<MagnetometerModel>,
|
||||
mgm_1_addr: Address<MagnetometerModel>,
|
||||
mgm_0_addr: Address<MgmModel>,
|
||||
mgm_1_addr: Address<MgmModel>,
|
||||
pcdu_addr: Address<PcduModel>,
|
||||
mgt_addr: Address<MagnetorquerModel>,
|
||||
}
|
||||
@@ -42,8 +42,8 @@ pub struct SimController {
|
||||
|
||||
impl ModelAddrWrapper {
|
||||
pub fn new(
|
||||
mgm_0_addr: Address<MagnetometerModel>,
|
||||
mgm_1_addr: Address<MagnetometerModel>,
|
||||
mgm_0_addr: Address<MgmModel>,
|
||||
mgm_1_addr: Address<MgmModel>,
|
||||
pcdu_addr: Address<PcduModel>,
|
||||
mgt_addr: Address<MagnetorquerModel>,
|
||||
) -> Self {
|
||||
@@ -127,24 +127,24 @@ impl SimController {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_mgm_request(&mut self, mgm_id: MgmId, mgm_request: MgmRequestLis3Mdl) {
|
||||
fn handle_mgm_request(&mut self, mgm_id: mgm::Id, mgm_request: mgm::Request) {
|
||||
let addr = match mgm_id {
|
||||
MgmId::Mgm0 => &self.addr_wrapper.mgm_0_addr,
|
||||
MgmId::Mgm1 => &self.addr_wrapper.mgm_1_addr,
|
||||
mgm::Id::Mgm0 => &self.addr_wrapper.mgm_0_addr,
|
||||
mgm::Id::Mgm1 => &self.addr_wrapper.mgm_1_addr,
|
||||
};
|
||||
if MGM_REQ_WIRETAPPING {
|
||||
log::info!("received {mgm_id:?} request: {mgm_request:?}");
|
||||
}
|
||||
match mgm_request {
|
||||
MgmRequestLis3Mdl::RequestSensorData => {
|
||||
mgm::Request::RequestSensorData => {
|
||||
self.simulation
|
||||
.process_event(MagnetometerModel::send_sensor_values, (), addr)
|
||||
.process_event(MgmModel::send_sensor_values, (), addr)
|
||||
.expect("event execution error for mgm");
|
||||
}
|
||||
MgmRequestLis3Mdl::SetSpiFault(fault_mode) => {
|
||||
mgm::Request::SetSpiFault(fault_mode) => {
|
||||
log::info!("{mgm_id:?}: setting SPI fault mode to {fault_mode:?}");
|
||||
self.simulation
|
||||
.process_event(MagnetometerModel::set_spi_fault, fault_mode, addr)
|
||||
.process_event(MgmModel::set_spi_fault, fault_mode, addr)
|
||||
.expect("event execution error for mgm");
|
||||
}
|
||||
}
|
||||
@@ -176,12 +176,12 @@ impl SimController {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_mgt_request(&mut self, mgt_request: MgtRequest) {
|
||||
fn handle_mgt_request(&mut self, mgt_request: mgt::Request) {
|
||||
if MGT_REQ_WIRETAPPING {
|
||||
log::info!("received MGT request: {mgt_request:?}");
|
||||
}
|
||||
match mgt_request {
|
||||
MgtRequest::ApplyTorque { duration, dipole } => self
|
||||
mgt::Request::ApplyTorque { duration, dipole } => self
|
||||
.simulation
|
||||
.process_event(
|
||||
MagnetorquerModel::apply_torque,
|
||||
@@ -189,7 +189,7 @@ impl SimController {
|
||||
&self.addr_wrapper.mgt_addr,
|
||||
)
|
||||
.unwrap(),
|
||||
MgtRequest::RequestHk => self
|
||||
mgt::Request::RequestHk => self
|
||||
.simulation
|
||||
.process_event(
|
||||
MagnetorquerModel::request_housekeeping_data,
|
||||
|
||||
@@ -2,10 +2,7 @@ use nexosim::time::MonotonicTime;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
acs::{
|
||||
mgm::{MgmId, MgmReply},
|
||||
MgmRequestLis3Mdl, MgtReply, MgtRequest,
|
||||
},
|
||||
acs::{mgm, mgt},
|
||||
eps::{PcduReply, PcduRequest},
|
||||
};
|
||||
|
||||
@@ -22,11 +19,8 @@ pub enum SimComponent {
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum SimRequest {
|
||||
SimCtrl(SimCtrlRequest),
|
||||
Mgm {
|
||||
id: MgmId,
|
||||
request: MgmRequestLis3Mdl,
|
||||
},
|
||||
Mgt(MgtRequest),
|
||||
Mgm { id: mgm::Id, request: mgm::Request },
|
||||
Mgt(mgt::Request),
|
||||
Pcdu(PcduRequest),
|
||||
}
|
||||
|
||||
@@ -36,8 +30,8 @@ impl From<SimCtrlRequest> for SimRequest {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MgtRequest> for SimRequest {
|
||||
fn from(request: MgtRequest) -> Self {
|
||||
impl From<mgt::Request> for SimRequest {
|
||||
fn from(request: mgt::Request) -> Self {
|
||||
Self::Mgt(request)
|
||||
}
|
||||
}
|
||||
@@ -70,8 +64,8 @@ impl SimRequestWithTime {
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum SimReply {
|
||||
SimCtrl(SimCtrlReply),
|
||||
Mgm { id: MgmId, reply: MgmReply },
|
||||
Mgt(MgtReply),
|
||||
Mgm { id: mgm::Id, reply: mgm::Reply },
|
||||
Mgt(mgt::Reply),
|
||||
Pcdu(PcduReply),
|
||||
}
|
||||
|
||||
@@ -92,8 +86,8 @@ impl From<SimCtrlReply> for SimReply {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MgtReply> for SimReply {
|
||||
fn from(reply: MgtReply) -> Self {
|
||||
impl From<mgt::Reply> for SimReply {
|
||||
fn from(reply: mgt::Reply) -> Self {
|
||||
Self::Mgt(reply)
|
||||
}
|
||||
}
|
||||
@@ -142,62 +136,50 @@ pub mod eps {
|
||||
}
|
||||
|
||||
pub mod acs {
|
||||
use std::time::Duration;
|
||||
|
||||
use types::pcdu::SwitchStateBinary;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Fault mode injected on the simulated SPI bus, independent of the switch state.
|
||||
///
|
||||
/// Models the classic symptom of a stuck SPI bus: an undriven MISO line commonly reads
|
||||
/// back as all-1s, a shorted/grounded one as all-0s.
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum SpiFaultMode {
|
||||
#[default]
|
||||
None,
|
||||
AllZeros,
|
||||
AllOnes,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct SpiFault {
|
||||
pub mode: SpiFaultMode,
|
||||
/// The fault is cleared when the device is switched off, so a power cycle recovers
|
||||
/// from it.
|
||||
pub cleared_by_power_cycle: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum MgmRequestLis3Mdl {
|
||||
RequestSensorData,
|
||||
/// Force the raw register reply into a stuck-bus pattern, regardless of switch state.
|
||||
/// Used to test FDIR handling of SPI bus faults.
|
||||
SetSpiFault(SpiFault),
|
||||
}
|
||||
|
||||
// Normally, small magnetometers generate their output as a signed 16 bit raw format or something
|
||||
// similar which needs to be converted to a signed float value with physical units. We will
|
||||
// simplify this now and generate the signed float values directly. The unit is micro tesla.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct MgmSensorValuesMicroTesla {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
}
|
||||
|
||||
pub const MGT_GEN_MAGNETIC_FIELD: MgmSensorValuesMicroTesla = MgmSensorValuesMicroTesla {
|
||||
x: 30.0,
|
||||
y: -30.0,
|
||||
z: 30.0,
|
||||
};
|
||||
pub const ALL_ONES_SENSOR_VAL: i16 = 0xffff_u16 as i16;
|
||||
pub const ALL_ZEROS_SENSOR_VAL: i16 = 0;
|
||||
|
||||
/// MGM module strongly based on the LIS3MDL device.
|
||||
pub mod mgm {
|
||||
use serde::{Deserialize, Serialize};
|
||||
use types::pcdu::SwitchStateBinary;
|
||||
|
||||
use super::*;
|
||||
use crate::SimComponent;
|
||||
|
||||
/// Fault mode injected on the simulated SPI bus, independent of the switch state.
|
||||
///
|
||||
/// Models the classic symptom of a stuck SPI bus: an undriven MISO line commonly reads
|
||||
/// back as all-1s, a shorted/grounded one as all-0s.
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum SpiFaultMode {
|
||||
#[default]
|
||||
None,
|
||||
AllZeros,
|
||||
AllOnes,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct SpiFault {
|
||||
pub mode: SpiFaultMode,
|
||||
/// The fault is cleared when the device is switched off, so a power cycle recovers
|
||||
/// from it.
|
||||
pub cleared_by_power_cycle: bool,
|
||||
}
|
||||
|
||||
// Normally, small magnetometers generate their output as a signed 16 bit raw format or something
|
||||
// similar which needs to be converted to a signed float value with physical units. We will
|
||||
// simplify this now and generate the signed float values directly. The unit is micro tesla.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct SensorValuesMicroTesla {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
}
|
||||
|
||||
pub const MGT_GEN_MAGNETIC_FIELD: SensorValuesMicroTesla = SensorValuesMicroTesla {
|
||||
x: 30.0,
|
||||
y: -30.0,
|
||||
z: 30.0,
|
||||
};
|
||||
pub const ALL_ONES_SENSOR_VAL: i16 = 0xffff_u16 as i16;
|
||||
pub const ALL_ZEROS_SENSOR_VAL: i16 = 0;
|
||||
|
||||
// Field data register scaling
|
||||
pub const GAUSS_TO_MICROTESLA_FACTOR: u32 = 100;
|
||||
@@ -212,35 +194,42 @@ pub mod acs {
|
||||
pub y: i16,
|
||||
pub z: i16,
|
||||
}
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Request {
|
||||
RequestSensorData,
|
||||
/// Force the raw register reply into a stuck-bus pattern, regardless of switch state.
|
||||
/// Used to test FDIR handling of SPI bus faults.
|
||||
SetSpiFault(SpiFault),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct MgmReply {
|
||||
pub struct Reply {
|
||||
pub switch_state: SwitchStateBinary,
|
||||
pub sensor_values: MgmSensorValuesMicroTesla,
|
||||
pub sensor_values: SensorValuesMicroTesla,
|
||||
// Raw sensor values which are transmitted by the LIS3 device in little-endian
|
||||
// order.
|
||||
pub raw: RawValues,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum MgmId {
|
||||
pub enum Id {
|
||||
Mgm0,
|
||||
Mgm1,
|
||||
}
|
||||
|
||||
impl MgmId {
|
||||
impl Id {
|
||||
pub const fn sim_component(&self) -> SimComponent {
|
||||
match self {
|
||||
MgmId::Mgm0 => SimComponent::Mgm0Lis3Mdl,
|
||||
MgmId::Mgm1 => SimComponent::Mgm1Lis3Mdl,
|
||||
Id::Mgm0 => SimComponent::Mgm0Lis3Mdl,
|
||||
Id::Mgm1 => SimComponent::Mgm1Lis3Mdl,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MgmReply {
|
||||
impl Reply {
|
||||
pub fn new(
|
||||
switch_state: SwitchStateBinary,
|
||||
sensor_values: MgmSensorValuesMicroTesla,
|
||||
sensor_values: SensorValuesMicroTesla,
|
||||
fault_mode: SpiFaultMode,
|
||||
) -> Self {
|
||||
match fault_mode {
|
||||
@@ -308,39 +297,42 @@ pub mod acs {
|
||||
}
|
||||
}
|
||||
|
||||
// Simple model using i16 values.
|
||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct MgtDipole {
|
||||
pub x: i16,
|
||||
pub y: i16,
|
||||
pub z: i16,
|
||||
}
|
||||
pub mod mgt {
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum MgtRequestType {
|
||||
ApplyTorque,
|
||||
}
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum MgtRequest {
|
||||
ApplyTorque {
|
||||
duration: Duration,
|
||||
dipole: MgtDipole,
|
||||
},
|
||||
RequestHk,
|
||||
}
|
||||
// Simple model using i16 values.
|
||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Dipole {
|
||||
pub x: i16,
|
||||
pub y: i16,
|
||||
pub z: i16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct MgtHkSet {
|
||||
pub dipole: MgtDipole,
|
||||
pub torquing: bool,
|
||||
}
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum RequestType {
|
||||
ApplyTorque,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum MgtReply {
|
||||
Ack(MgtRequestType),
|
||||
Nak(MgtRequestType),
|
||||
Hk(MgtHkSet),
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Request {
|
||||
ApplyTorque { duration: Duration, dipole: Dipole },
|
||||
RequestHk,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct HkSet {
|
||||
pub dipole: Dipole,
|
||||
pub torquing: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Reply {
|
||||
Ack(RequestType),
|
||||
Nak(RequestType),
|
||||
Hk(HkSet),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use acs::{mgm::MagnetometerModel, mgt::MagnetorquerModel};
|
||||
use acs::{mgm::MgmModel, mgt::MagnetorquerModel};
|
||||
use controller::{ModelAddrWrapper, SimController};
|
||||
use eps::PcduModel;
|
||||
use nexosim::simulation::{Mailbox, SimInit};
|
||||
use nexosim::time::{MonotonicTime, SystemClock};
|
||||
use satrs_minisim::acs::mgm::MgmId;
|
||||
use satrs_minisim::acs::mgm;
|
||||
use satrs_minisim::udp::SIM_CTRL_PORT;
|
||||
use satrs_minisim::{SimReply, SimRequestWithTime};
|
||||
use std::sync::mpsc;
|
||||
@@ -32,10 +32,16 @@ fn create_sim_controller(
|
||||
request_receiver: mpsc::Receiver<SimRequestWithTime>,
|
||||
) -> SimController {
|
||||
// Instantiate models and their mailboxes.
|
||||
let mgm_0_model =
|
||||
MagnetometerModel::new(MgmId::Mgm0, Duration::from_millis(50), reply_sender.clone());
|
||||
let mgm_1_model =
|
||||
MagnetometerModel::new(MgmId::Mgm1, Duration::from_millis(50), reply_sender.clone());
|
||||
let mgm_0_model = MgmModel::new(
|
||||
mgm::Id::Mgm0,
|
||||
Duration::from_millis(50),
|
||||
reply_sender.clone(),
|
||||
);
|
||||
let mgm_1_model = MgmModel::new(
|
||||
mgm::Id::Mgm1,
|
||||
Duration::from_millis(50),
|
||||
reply_sender.clone(),
|
||||
);
|
||||
|
||||
let mgm_0_mailbox = Mailbox::new();
|
||||
let mgm_0_addr = mgm_0_mailbox.address();
|
||||
@@ -49,10 +55,10 @@ fn create_sim_controller(
|
||||
let mut pcdu_model = PcduModel::new(reply_sender.clone());
|
||||
pcdu_model
|
||||
.mgm_0_switch
|
||||
.connect(MagnetometerModel::switch_device, &mgm_0_addr);
|
||||
.connect(MgmModel::switch_device, &mgm_0_addr);
|
||||
pcdu_model
|
||||
.mgm_1_switch
|
||||
.connect(MagnetometerModel::switch_device, &mgm_1_addr);
|
||||
.connect(MgmModel::switch_device, &mgm_1_addr);
|
||||
|
||||
let mut mgt_model = MagnetorquerModel::new(reply_sender.clone());
|
||||
// Input connections.
|
||||
@@ -60,14 +66,12 @@ fn create_sim_controller(
|
||||
.mgt_switch
|
||||
.connect(MagnetorquerModel::switch_device, &mgt_addr);
|
||||
// Output connections.
|
||||
mgt_model.gen_magnetic_field.connect(
|
||||
MagnetometerModel::apply_external_magnetic_field,
|
||||
&mgm_0_addr,
|
||||
);
|
||||
mgt_model.gen_magnetic_field.connect(
|
||||
MagnetometerModel::apply_external_magnetic_field,
|
||||
&mgm_1_addr,
|
||||
);
|
||||
mgt_model
|
||||
.gen_magnetic_field
|
||||
.connect(MgmModel::apply_external_magnetic_field, &mgm_0_addr);
|
||||
mgt_model
|
||||
.gen_magnetic_field
|
||||
.connect(MgmModel::apply_external_magnetic_field, &mgm_1_addr);
|
||||
|
||||
// Instantiate the simulator
|
||||
let sys_clock = SystemClock::from_system_time(start_time, SystemTime::now());
|
||||
|
||||
@@ -2,8 +2,8 @@ use satrs::fdir::{FaultCounterStd, FaultResponse, RecoveryEvent, RecoveryFdir};
|
||||
use satrs::health::HealthTableMapSync;
|
||||
use satrs::spacepackets::CcsdsPacketIdAndPsc;
|
||||
use satrs_example::{HkHelperSingleSet, TimestampHelper, TmtcQueues};
|
||||
use satrs_minisim::acs::MgmRequestLis3Mdl;
|
||||
use satrs_minisim::acs::mgm::{FIELD_LSB_PER_GAUSS_4_SENS, GAUSS_TO_MICROTESLA_FACTOR, RawValues};
|
||||
use satrs_minisim::acs::mgm as sim_mgm;
|
||||
use satrs_minisim::acs::mgm::{FIELD_LSB_PER_GAUSS_4_SENS, GAUSS_TO_MICROTESLA_FACTOR};
|
||||
use satrs_minisim::{SimReply, SimRequest, SimRequestWithTime};
|
||||
use std::sync::mpsc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
@@ -74,7 +74,7 @@ impl MgmId {
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SpiDummyInterface {
|
||||
pub dummy_values: RawValues,
|
||||
pub dummy_values: sim_mgm::RawValues,
|
||||
}
|
||||
|
||||
impl SpiDummyInterface {
|
||||
@@ -88,7 +88,7 @@ impl SpiDummyInterface {
|
||||
#[derive(Default)]
|
||||
pub struct TestSpiInterface {
|
||||
pub call_count: u32,
|
||||
pub next_mgm_data: RawValues,
|
||||
pub next_mgm_data: sim_mgm::RawValues,
|
||||
}
|
||||
|
||||
impl TestSpiInterface {
|
||||
@@ -110,12 +110,12 @@ impl SpiSimInterface {
|
||||
// Right now, we only support requesting sensor data and not configuration of the sensor.
|
||||
fn transfer(&mut self, _tx: &[u8], rx: &mut [u8]) {
|
||||
let sim_id = match self.id {
|
||||
MgmId::_0 => satrs_minisim::acs::mgm::MgmId::Mgm0,
|
||||
MgmId::_1 => satrs_minisim::acs::mgm::MgmId::Mgm1,
|
||||
MgmId::_0 => sim_mgm::Id::Mgm0,
|
||||
MgmId::_1 => sim_mgm::Id::Mgm1,
|
||||
};
|
||||
let sim_request = SimRequestWithTime::new_with_epoch_time(SimRequest::Mgm {
|
||||
id: sim_id,
|
||||
request: MgmRequestLis3Mdl::RequestSensorData,
|
||||
request: sim_mgm::Request::RequestSensorData,
|
||||
});
|
||||
if let Err(e) = self.sim_request_tx.send(sim_request) {
|
||||
log::error!("failed to send MGM LIS3 request: {e}");
|
||||
@@ -652,7 +652,7 @@ mod tests {
|
||||
use arbitrary_int::u11;
|
||||
use satrs::health::{HealthState, HealthTableProvider};
|
||||
use satrs::spacepackets::SpacePacketHeader;
|
||||
use satrs_minisim::acs::mgm::RawValues;
|
||||
use satrs_minisim::acs::mgm as sim_mgm;
|
||||
use types::{
|
||||
Apid, ComponentId, TcHeader,
|
||||
acs::mgm::request::HkRequest,
|
||||
@@ -771,7 +771,7 @@ mod tests {
|
||||
}
|
||||
|
||||
pub fn inject_stuck_bus(&mut self) {
|
||||
self.test_spi_interface().next_mgm_data = RawValues {
|
||||
self.test_spi_interface().next_mgm_data = sim_mgm::RawValues {
|
||||
x: -1,
|
||||
y: -1,
|
||||
z: -1,
|
||||
@@ -912,7 +912,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_normal_handler_mgm_set_conversion() {
|
||||
let mut testbench = MgmTestbench::new();
|
||||
let raw_values = RawValues {
|
||||
let raw_values = sim_mgm::RawValues {
|
||||
x: 1000,
|
||||
y: -1000,
|
||||
z: 1000,
|
||||
@@ -1065,7 +1065,7 @@ mod tests {
|
||||
fn test_spi_fault_below_threshold_stays_healthy() {
|
||||
let mut testbench = MgmTestbench::new();
|
||||
testbench.switch_to_normal();
|
||||
testbench.test_spi_interface().next_mgm_data = RawValues {
|
||||
testbench.test_spi_interface().next_mgm_data = sim_mgm::RawValues {
|
||||
x: -1,
|
||||
y: -1,
|
||||
z: -1,
|
||||
@@ -1106,7 +1106,7 @@ mod tests {
|
||||
testbench.drain_switch_requests();
|
||||
testbench.mode_report_rx.try_iter().for_each(drop);
|
||||
testbench.exceed_spi_fault_threshold();
|
||||
testbench.test_spi_interface().next_mgm_data = RawValues::default();
|
||||
testbench.test_spi_interface().next_mgm_data = sim_mgm::RawValues::default();
|
||||
let call_count = testbench.test_spi_interface().call_count;
|
||||
|
||||
testbench.complete_power_cycle();
|
||||
@@ -1279,7 +1279,7 @@ mod tests {
|
||||
testbench.drain_events();
|
||||
testbench.mode_report_rx.try_iter().for_each(drop);
|
||||
testbench.exceed_spi_fault_threshold();
|
||||
testbench.test_spi_interface().next_mgm_data = RawValues::default();
|
||||
testbench.test_spi_interface().next_mgm_data = sim_mgm::RawValues::default();
|
||||
|
||||
// The switch never turns off. Every failed power cycle costs a recovery attempt.
|
||||
for _ in 0..RECOVERY_THRESHOLD {
|
||||
@@ -1317,7 +1317,7 @@ mod tests {
|
||||
let mut testbench = MgmTestbench::new();
|
||||
testbench.switch_to_normal();
|
||||
testbench.exceed_spi_fault_threshold();
|
||||
testbench.test_spi_interface().next_mgm_data = RawValues::default();
|
||||
testbench.test_spi_interface().next_mgm_data = sim_mgm::RawValues::default();
|
||||
testbench
|
||||
.tc_tx
|
||||
.send(create_request_tc(
|
||||
@@ -1382,7 +1382,7 @@ mod tests {
|
||||
testbench
|
||||
.health_table
|
||||
.set_health(ComponentId::AcsMgm0.into(), HealthState::ExternalControl);
|
||||
testbench.test_spi_interface().next_mgm_data = RawValues {
|
||||
testbench.test_spi_interface().next_mgm_data = sim_mgm::RawValues {
|
||||
x: -1,
|
||||
y: -1,
|
||||
z: -1,
|
||||
@@ -1401,7 +1401,7 @@ mod tests {
|
||||
fn test_recovering_from_spi_fault_clears_invalid_data_flag() {
|
||||
let mut testbench = MgmTestbench::new();
|
||||
testbench.switch_to_normal();
|
||||
testbench.test_spi_interface().next_mgm_data = RawValues {
|
||||
testbench.test_spi_interface().next_mgm_data = sim_mgm::RawValues {
|
||||
x: -1,
|
||||
y: -1,
|
||||
z: -1,
|
||||
@@ -1410,7 +1410,7 @@ mod tests {
|
||||
assert!(!testbench.handler.shared_mgm_set.lock().unwrap().valid);
|
||||
|
||||
// Bus recovers before the threshold is exceeded.
|
||||
testbench.test_spi_interface().next_mgm_data = RawValues::default();
|
||||
testbench.test_spi_interface().next_mgm_data = sim_mgm::RawValues::default();
|
||||
testbench.handler.periodic_operation();
|
||||
assert_eq!(
|
||||
testbench.health_table.health(ComponentId::AcsMgm0.into()),
|
||||
|
||||
Reference in New Issue
Block a user