continue mode tree execution helper

This commit is contained in:
Robin Müller 2024-12-09 17:28:28 +01:00
parent 0dacad0bbc
commit f34f8304d4
Signed by: muellerr
GPG Key ID: A649FB78196E3849
6 changed files with 169 additions and 51 deletions

View File

@ -110,6 +110,7 @@ impl PusReplyHandler<ActivePusRequestStd, ModeReply> for ModeReplyHandler {
), ),
)?; )?;
} }
ModeReply::ModeInfo(_mode_and_submode) => (),
}; };
Ok(true) Ok(true)
} }

View File

@ -28,6 +28,9 @@ pub struct ModeAndSubmode {
submode: Submode, submode: Submode,
} }
pub const INVALID_MODE: ModeAndSubmode = ModeAndSubmode::new(u32::MAX, 0);
pub const UNKNOWN_MODE: ModeAndSubmode = ModeAndSubmode::new(u32::MAX - 1, 0);
impl ModeAndSubmode { impl ModeAndSubmode {
pub const RAW_LEN: usize = size_of::<Mode>() + size_of::<Submode>(); pub const RAW_LEN: usize = size_of::<Mode>() + size_of::<Submode>();

View File

@ -105,7 +105,6 @@ impl TargetTableEntry {
name: &'static str, name: &'static str,
target_id: ComponentId, target_id: ComponentId,
mode_submode: ModeAndSubmode, mode_submode: ModeAndSubmode,
monitor_state: bool,
allowed_submode_mask: Option<Submode>, allowed_submode_mask: Option<Submode>,
) -> Self { ) -> Self {
Self { Self {
@ -115,7 +114,7 @@ impl TargetTableEntry {
mode_submode, mode_submode,
allowed_submode_mask, allowed_submode_mask,
}, },
monitor_state, monitor_state: true,
} }
} }
@ -123,7 +122,6 @@ impl TargetTableEntry {
name: &'static str, name: &'static str,
target_id: ComponentId, target_id: ComponentId,
mode_submode: ModeAndSubmode, mode_submode: ModeAndSubmode,
monitor_state: bool,
) -> Self { ) -> Self {
Self { Self {
common: ModeTableEntryCommon { common: ModeTableEntryCommon {
@ -132,7 +130,7 @@ impl TargetTableEntry {
mode_submode, mode_submode,
allowed_submode_mask: None, allowed_submode_mask: None,
}, },
monitor_state, monitor_state: true,
} }
} }
@ -214,14 +212,17 @@ pub mod alloc_mod {
pub struct TargetTablesMapValue { pub struct TargetTablesMapValue {
/// Name for a given mode table entry. /// Name for a given mode table entry.
pub name: &'static str, pub name: &'static str,
/// Optional fallback mode if the target mode can not be kept.
pub fallback_mode: Option<Mode>,
/// These are the rows of the a target table. /// These are the rows of the a target table.
pub entries: Vec<TargetTableEntry>, pub entries: Vec<TargetTableEntry>,
} }
impl TargetTablesMapValue { impl TargetTablesMapValue {
pub fn new(name: &'static str) -> Self { pub fn new(name: &'static str, fallback_mode: Option<Mode>) -> Self {
Self { Self {
name, name,
fallback_mode,
entries: Default::default(), entries: Default::default(),
} }
} }
@ -278,24 +279,49 @@ pub mod alloc_mod {
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct SequenceModeTables(pub HashMap<Mode, SequenceTablesMapValue>); pub struct SequenceModeTables(pub HashMap<Mode, SequenceTablesMapValue>);
#[derive(Debug)]
pub struct ModeStoreVecValue {
id: ComponentId,
mode_and_submode: ModeAndSubmode,
pub awaiting_reply: bool,
}
impl ModeStoreVecValue {
pub fn new(id: ComponentId, mode_and_submode: ModeAndSubmode) -> Self {
Self {
id,
mode_and_submode,
awaiting_reply: false,
}
}
pub fn id(&self) -> ComponentId {
self.id
}
pub fn mode_and_submode(&self) -> ModeAndSubmode {
self.mode_and_submode
}
}
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct ModeStoreVec(pub alloc::vec::Vec<(ComponentId, ModeAndSubmode)>); pub struct ModeStoreVec(pub alloc::vec::Vec<ModeStoreVecValue>);
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct ModeStoreMap(pub hashbrown::HashMap<ComponentId, ModeAndSubmode>); pub struct ModeStoreMap(pub hashbrown::HashMap<ComponentId, ModeAndSubmode>);
impl ModeStoreProvider for ModeStoreVec { impl ModeStoreProvider for ModeStoreVec {
fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode) { fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode) {
self.0.push((target_id, mode)); self.0.push(ModeStoreVecValue::new(target_id, mode));
} }
fn has_component(&self, target_id: ComponentId) -> bool { fn has_component(&self, target_id: ComponentId) -> bool {
self.0.iter().any(|(id, _)| *id == target_id) self.0.iter().any(|val| val.id == target_id)
} }
fn get_mode(&self, target_id: ComponentId) -> Option<ModeAndSubmode> { fn get_mode(&self, target_id: ComponentId) -> Option<ModeAndSubmode> {
self.0.iter().find_map(|(id, mode)| { self.0.iter().find_map(|val| {
if *id == target_id { if val.id == target_id {
return Some(*mode); return Some(val.mode_and_submode);
} }
None None
}) })
@ -306,9 +332,9 @@ pub mod alloc_mod {
target_id: ComponentId, target_id: ComponentId,
mode_to_set: ModeAndSubmode, mode_to_set: ModeAndSubmode,
) { ) {
self.0.iter_mut().for_each(|(id, mode)| { self.0.iter_mut().for_each(|val| {
if *id == target_id { if val.id == target_id {
*mode = mode_to_set; val.mode_and_submode = mode_to_set;
} }
}); });
} }

View File

@ -39,7 +39,7 @@ mod tests {
use crate::{ use crate::{
mode::{ mode::{
ModeAndSubmode, ModeReply, ModeReplySender, ModeRequest, ModeRequestSender, ModeAndSubmode, ModeReply, ModeReplySender, ModeRequest, ModeRequestSender,
ModeRequestorAndHandlerOneParentMpsc, ModeRequestorOneChildMpsc, ModeRequestorAndHandlerMpsc, ModeRequestorOneChildMpsc,
}, },
request::{GenericMessage, MessageMetadata}, request::{GenericMessage, MessageMetadata},
}; };
@ -90,7 +90,7 @@ mod tests {
let (request_sender_to_channel_1, request_receiver_channel_1) = mpsc::channel(); let (request_sender_to_channel_1, request_receiver_channel_1) = mpsc::channel();
//let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel(); //let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel();
let mut mode_connector = ModeRequestorAndHandlerOneParentMpsc::new( let mut mode_connector = ModeRequestorAndHandlerMpsc::new(
TEST_COMPONENT_ID_0, TEST_COMPONENT_ID_0,
request_receiver_of_connector, request_receiver_of_connector,
reply_receiver_of_connector, reply_receiver_of_connector,
@ -129,7 +129,7 @@ mod tests {
let (_request_sender_to_connector, request_receiver_of_connector) = mpsc::channel(); let (_request_sender_to_connector, request_receiver_of_connector) = mpsc::channel();
let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel(); let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel();
let mut mode_connector = ModeRequestorAndHandlerOneParentMpsc::new( let mut mode_connector = ModeRequestorAndHandlerMpsc::new(
TEST_COMPONENT_ID_0, TEST_COMPONENT_ID_0,
request_receiver_of_connector, request_receiver_of_connector,
reply_receiver_of_connector, reply_receiver_of_connector,

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
mode::{Mode, ModeAndSubmode, ModeRequest, ModeRequestSender}, mode::{Mode, ModeAndSubmode, ModeRequest, ModeRequestSender},
mode_tree::{SequenceModeTables, SequenceTableMapTable, SequenceTablesMapValue}, mode_tree::{ModeStoreVec, SequenceModeTables, SequenceTableMapTable, SequenceTablesMapValue},
queue::GenericTargetedMessagingError, queue::GenericTargetedMessagingError,
request::RequestId, request::RequestId,
ComponentId, ComponentId,
@ -21,6 +21,12 @@ pub trait CheckSuccessProvider {
); );
} }
#[derive(Debug)]
pub enum TargetKeepingResult {
Ok,
Violated { fallback_mode: Option<Mode> },
}
#[derive(Debug)] #[derive(Debug)]
pub enum SequenceHandlerResult { pub enum SequenceHandlerResult {
SequenceDone, SequenceDone,
@ -92,6 +98,7 @@ impl SequenceExecutionHelper {
&mut self, &mut self,
table: &SequenceModeTables, table: &SequenceModeTables,
sender: &impl ModeRequestSender, sender: &impl ModeRequestSender,
mode_store_vec: &mut ModeStoreVec,
) -> Result<SequenceHandlerResult, GenericTargetedMessagingError> { ) -> Result<SequenceHandlerResult, GenericTargetedMessagingError> {
if self.state == SequenceExecutionHelperStates::AwaitingCheckSuccess { if self.state == SequenceExecutionHelperStates::AwaitingCheckSuccess {
return Ok(SequenceHandlerResult::AwaitingSuccessCheck); return Ok(SequenceHandlerResult::AwaitingSuccessCheck);
@ -100,7 +107,12 @@ impl SequenceExecutionHelper {
Some(idx) => { Some(idx) => {
// Execute the sequence. // Execute the sequence.
let seq_table_value = table.0.get(&self.target_mode).unwrap(); let seq_table_value = table.0.get(&self.target_mode).unwrap();
self.execute_sequence_and_map_to_result(seq_table_value, idx, sender) self.execute_sequence_and_map_to_result(
seq_table_value,
idx,
sender,
mode_store_vec,
)
} }
None => { None => {
// Find the first sequence // Find the first sequence
@ -109,7 +121,12 @@ impl SequenceExecutionHelper {
Ok(SequenceHandlerResult::SequenceDone) Ok(SequenceHandlerResult::SequenceDone)
} else { } else {
self.current_sequence_index = Some(0); self.current_sequence_index = Some(0);
self.execute_sequence_and_map_to_result(seq_table_value, 0, sender) self.execute_sequence_and_map_to_result(
seq_table_value,
0,
sender,
mode_store_vec,
)
} }
} }
} }
@ -120,11 +137,13 @@ impl SequenceExecutionHelper {
seq_table_value: &SequenceTablesMapValue, seq_table_value: &SequenceTablesMapValue,
sequence_idx: usize, sequence_idx: usize,
sender: &impl ModeRequestSender, sender: &impl ModeRequestSender,
mode_store_vec: &mut ModeStoreVec,
) -> Result<SequenceHandlerResult, GenericTargetedMessagingError> { ) -> Result<SequenceHandlerResult, GenericTargetedMessagingError> {
if Self::execute_sequence( if Self::execute_sequence(
self.request_id, self.request_id,
&seq_table_value.entries[sequence_idx], &seq_table_value.entries[sequence_idx],
sender, sender,
mode_store_vec,
)? { )? {
self.state = SequenceExecutionHelperStates::AwaitingCheckSuccess; self.state = SequenceExecutionHelperStates::AwaitingCheckSuccess;
Ok(SequenceHandlerResult::AwaitingSuccessCheck) Ok(SequenceHandlerResult::AwaitingSuccessCheck)
@ -140,6 +159,7 @@ impl SequenceExecutionHelper {
request_id: RequestId, request_id: RequestId,
map_table: &SequenceTableMapTable, map_table: &SequenceTableMapTable,
sender: &impl ModeRequestSender, sender: &impl ModeRequestSender,
mode_store_vec: &mut ModeStoreVec,
) -> Result<bool, GenericTargetedMessagingError> { ) -> Result<bool, GenericTargetedMessagingError> {
let mut some_succes_check_required = false; let mut some_succes_check_required = false;
for entry in &map_table.entries { for entry in &map_table.entries {
@ -148,6 +168,11 @@ impl SequenceExecutionHelper {
entry.common.target_id, entry.common.target_id,
ModeRequest::SetMode(entry.common.mode_submode), ModeRequest::SetMode(entry.common.mode_submode),
)?; )?;
mode_store_vec.0.iter_mut().for_each(|val| {
if val.id() == entry.common.target_id {
val.awaiting_reply = true;
}
});
if entry.check_success { if entry.check_success {
some_succes_check_required = true; some_succes_check_required = true;
} }

View File

@ -2,7 +2,8 @@ use core::cell::Cell;
use satrs::mode::{ use satrs::mode::{
Mode, ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler, Mode, ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler,
ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestSender, ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestSender,
ModeRequestorAndHandlerMpscBounded, ModeRequestorOneChildBoundedMpsc, ModeRequestorAndHandlerMpscBounded, ModeRequestorOneChildBoundedMpsc, INVALID_MODE,
UNKNOWN_MODE,
}; };
use satrs::mode_tree::{ use satrs::mode_tree::{
connect_mode_nodes, ModeChild, ModeNode, ModeParent, ModeStoreProvider, SequenceTableEntry, connect_mode_nodes, ModeChild, ModeNode, ModeParent, ModeStoreProvider, SequenceTableEntry,
@ -13,7 +14,7 @@ use satrs::mode_tree::{
TargetTablesMapValue, TargetTablesMapValue,
}; };
use satrs::request::MessageMetadata; use satrs::request::MessageMetadata;
use satrs::subsystem::{SequenceExecutionHelper, SequenceHandlerResult}; use satrs::subsystem::{SequenceExecutionHelper, SequenceHandlerResult, TargetKeepingResult};
use satrs::{ use satrs::{
mode::{ModeAndSubmode, ModeReply, ModeRequest}, mode::{ModeAndSubmode, ModeReply, ModeRequest},
queue::GenericTargetedMessagingError, queue::GenericTargetedMessagingError,
@ -25,9 +26,6 @@ use std::collections::VecDeque;
use std::convert::Infallible; use std::convert::Infallible;
use std::{println, sync::mpsc}; use std::{println, sync::mpsc};
const INVALID_MODE: ModeAndSubmode = ModeAndSubmode::new(0xffffffff, 0);
const UNKNOWN_MODE: ModeAndSubmode = ModeAndSubmode::new(0xffffffff - 1, 0);
pub enum DefaultMode { pub enum DefaultMode {
OFF = 0, OFF = 0,
ON = 1, ON = 1,
@ -58,8 +56,9 @@ pub enum TestComponentId {
pub type RequestSenderType = mpsc::SyncSender<GenericMessage<ModeRequest>>; pub type RequestSenderType = mpsc::SyncSender<GenericMessage<ModeRequest>>;
pub type ReplySenderType = mpsc::SyncSender<GenericMessage<ModeReply>>; pub type ReplySenderType = mpsc::SyncSender<GenericMessage<ModeReply>>;
#[derive(Debug)] #[derive(Debug, Default)]
pub enum ModeTreeHelperState { pub enum ModeTreeHelperState {
#[default]
Idle, Idle,
TargetKeeping = 1, TargetKeeping = 1,
SequenceCommanding = 2, SequenceCommanding = 2,
@ -68,10 +67,16 @@ pub enum ModeTreeHelperState {
#[derive(Debug)] #[derive(Debug)]
pub enum ModeTreeHelperResult { pub enum ModeTreeHelperResult {
Idle, Idle,
TargetKeeping, TargetKeeping(TargetKeepingResult),
SequenceCommanding(SequenceHandlerResult), SequenceCommanding(SequenceHandlerResult),
} }
impl From<TargetKeepingResult> for ModeTreeHelperResult {
fn from(value: TargetKeepingResult) -> Self {
Self::TargetKeeping(value)
}
}
impl From<SequenceHandlerResult> for ModeTreeHelperResult { impl From<SequenceHandlerResult> for ModeTreeHelperResult {
fn from(value: SequenceHandlerResult) -> Self { fn from(value: SequenceHandlerResult) -> Self {
Self::SequenceCommanding(value) Self::SequenceCommanding(value)
@ -82,12 +87,16 @@ impl From<SequenceHandlerResult> for ModeTreeHelperResult {
pub enum ModeTreeHelperError { pub enum ModeTreeHelperError {
#[error("generic targeted messaging error: {0}")] #[error("generic targeted messaging error: {0}")]
Message(#[from] GenericTargetedMessagingError), Message(#[from] GenericTargetedMessagingError),
#[error("current mode {0} is not contained in target table")]
CurrentModeNotInTargetTable(Mode),
} }
// TODO: // TODO:
// //
// 1. Fallback mode? Needs to be a part of the target mode table.. // 1. Fallback mode? Needs to be a part of the target mode table..
// 2. State to determine whether we are in sequence execution mode or in target keeping mode. // 2. State to determine whether we are in sequence execution mode or in target keeping mode.
pub struct ModeTreeCommandingHelper { pub struct ModeTreeCommandingHelper {
pub current_mode: ModeAndSubmode,
pub state: ModeTreeHelperState, pub state: ModeTreeHelperState,
pub children_mode_store: ModeStoreVec, pub children_mode_store: ModeStoreVec,
pub target_tables: TargetModeTables, pub target_tables: TargetModeTables,
@ -95,6 +104,19 @@ pub struct ModeTreeCommandingHelper {
pub helper: SequenceExecutionHelper, pub helper: SequenceExecutionHelper,
} }
impl Default for ModeTreeCommandingHelper {
fn default() -> Self {
Self {
current_mode: UNKNOWN_MODE,
state: Default::default(),
children_mode_store: Default::default(),
target_tables: Default::default(),
sequence_tables: Default::default(),
helper: Default::default(),
}
}
}
impl ModeTreeCommandingHelper { impl ModeTreeCommandingHelper {
pub fn new( pub fn new(
children_mode_store: ModeStoreVec, children_mode_store: ModeStoreVec,
@ -102,6 +124,7 @@ impl ModeTreeCommandingHelper {
sequence_tables: SequenceModeTables, sequence_tables: SequenceModeTables,
) -> Self { ) -> Self {
Self { Self {
current_mode: UNKNOWN_MODE,
state: ModeTreeHelperState::Idle, state: ModeTreeHelperState::Idle,
children_mode_store, children_mode_store,
target_tables, target_tables,
@ -135,13 +158,24 @@ impl ModeTreeCommandingHelper {
} }
self.children_mode_store self.children_mode_store
.set_mode_for_contained_component(target_id, mode_and_submode); .set_mode_for_contained_component(target_id, mode_and_submode);
// TODO: match self.state {
// 1. If we are in IDLE Mode, we are done. ModeTreeHelperState::Idle => (),
// 2. If we are in sequencing mode, check whether this completes the sequence. How do ModeTreeHelperState::TargetKeeping => {}
// we best do this? We would have to remember which IDs need a mode confirmation. ModeTreeHelperState::SequenceCommanding => {
// We could extend the mode store for this. let mut still_awating_replies = false;
// 3. If we are in target keeping mode, we have to check whether the target keeping was self.children_mode_store.0.iter_mut().for_each(|val| {
// violated. if val.id() == target_id {
val.awaiting_reply = false;
}
if val.awaiting_reply {
still_awating_replies = true;
}
});
if !still_awating_replies {
self.helper.confirm_sequence_done();
}
}
}
}; };
match reply.message { match reply.message {
ModeReply::ModeInfo(mode_and_submode) => { ModeReply::ModeInfo(mode_and_submode) => {
@ -166,24 +200,51 @@ impl ModeTreeCommandingHelper {
self.handle_mode_reply(reply); self.handle_mode_reply(reply);
} }
match self.state { match self.state {
ModeTreeHelperState::Idle => todo!(), ModeTreeHelperState::Idle => Ok(ModeTreeHelperResult::Idle),
ModeTreeHelperState::TargetKeeping => { ModeTreeHelperState::TargetKeeping => {
// TODO: Verify children modes against target table where applicable. // We check whether the current mode is modelled by a target table first.
Ok(ModeTreeHelperResult::TargetKeeping) if let Some(target_table) = self.target_tables.0.get(&self.current_mode.mode()) {
for entry in &target_table.entries {
if !entry.monitor_state {
continue;
} }
ModeTreeHelperState::SequenceCommanding => { let mut target_mode_violated = false;
Ok(self.helper.run(&self.sequence_tables, req_sender)?.into()) self.children_mode_store.0.iter().for_each(|val| {
if val.id() == entry.common.target_id {
target_mode_violated = if let Some(allowed_submode_mask) =
entry.allowed_submode_mask()
{
let fixed_bits = !allowed_submode_mask;
(val.mode_and_submode().mode()
!= entry.common.mode_submode.mode())
&& (val.mode_and_submode().submode() & fixed_bits
!= entry.common.mode_submode.submode() & fixed_bits)
} else {
val.mode_and_submode() != entry.common.mode_submode
};
}
})
}
// Target keeping violated. Report violation and fallback mode to user.
return Ok(TargetKeepingResult::Violated {
fallback_mode: None,
}
.into());
}
Ok(ModeTreeHelperResult::TargetKeeping(TargetKeepingResult::Ok))
}
ModeTreeHelperState::SequenceCommanding => Ok(self
.helper
.run(
&self.sequence_tables,
req_sender,
&mut self.children_mode_store,
)?
.into()),
} }
} }
} }
//pub fn check_current_sequence_against_mode_store(&self) {
// TODO: Check whether current sequence requires success checks and if some are required,
// check mode store content against the sequence target mode.
//}
}
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct ModeRequestHandlerMock { pub struct ModeRequestHandlerMock {
get_mode_calls: RefCell<u32>, get_mode_calls: RefCell<u32>,
@ -266,6 +327,9 @@ impl ModeRequestHandler for ModeRequestHandlerMock {
} }
} }
#[derive(Default, Debug)]
pub struct ModeReplyHandlerMock {}
struct PusModeService { struct PusModeService {
pub request_id_counter: Cell<u32>, pub request_id_counter: Cell<u32>,
pub mode_node: ModeRequestorOneChildBoundedMpsc, pub mode_node: ModeRequestorOneChildBoundedMpsc,
@ -316,7 +380,7 @@ impl AcsSubsystem {
mode_requestor_info: None, mode_requestor_info: None,
mode_and_submode: UNKNOWN_MODE, mode_and_submode: UNKNOWN_MODE,
target_mode_and_submode: None, target_mode_and_submode: None,
subsystem_helper: Default::default(), subsystem_helper: ModeTreeCommandingHelper::default(),
mode_req_handler_mock: Default::default(), mode_req_handler_mock: Default::default(),
mode_req_recvd: 0, mode_req_recvd: 0,
} }
@ -506,6 +570,7 @@ impl MgmAssembly {
} }
pub fn check_mode_replies(&mut self) -> Result<(), GenericTargetedMessagingError> { pub fn check_mode_replies(&mut self) -> Result<(), GenericTargetedMessagingError> {
// TODO: Call mode reply handler mock.
if let Some(reply_and_id) = self.mode_node.try_recv_mode_reply()? { if let Some(reply_and_id) = self.mode_node.try_recv_mode_reply()? {
match reply_and_id.message { match reply_and_id.message {
ModeReply::ModeReply(reply) => { ModeReply::ModeReply(reply) => {
@ -524,6 +589,7 @@ impl MgmAssembly {
expected expected
); );
} }
ModeReply::ModeInfo(_mode_and_submode) => {}
} }
} }
Ok(()) Ok(())
@ -1136,12 +1202,11 @@ impl TreeTestbench {
}; };
// ACS subsystem tables // ACS subsystem tables
let mut target_table_safe = TargetTablesMapValue::new("SAFE_TARGET_TBL"); let mut target_table_safe = TargetTablesMapValue::new("SAFE_TARGET_TBL", None);
target_table_safe.add_entry(TargetTableEntry::new( target_table_safe.add_entry(TargetTableEntry::new(
"CTRL_SAFE", "CTRL_SAFE",
TestComponentId::AcsController as u64, TestComponentId::AcsController as u64,
ModeAndSubmode::new(AcsMode::SAFE as u32, 0), ModeAndSubmode::new(AcsMode::SAFE as u32, 0),
true,
// All submodes allowed. // All submodes allowed.
Some(0xffff), Some(0xffff),
)); ));
@ -1149,13 +1214,11 @@ impl TreeTestbench {
"MGM_A_NML", "MGM_A_NML",
TestComponentId::MagnetometerAssembly as u64, TestComponentId::MagnetometerAssembly as u64,
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0), ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
true,
)); ));
target_table_safe.add_entry(TargetTableEntry::new_with_precise_submode( target_table_safe.add_entry(TargetTableEntry::new_with_precise_submode(
"MGT_MAN_NML", "MGT_MAN_NML",
TestComponentId::MgtDevManager as u64, TestComponentId::MgtDevManager as u64,
ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0), ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0),
true,
)); ));
let mut sequence_tbl_safe_0 = SequenceTableMapTable::new("SAFE_SEQ_0_TBL"); let mut sequence_tbl_safe_0 = SequenceTableMapTable::new("SAFE_SEQ_0_TBL");
sequence_tbl_safe_0.add_entry(SequenceTableEntry::new( sequence_tbl_safe_0.add_entry(SequenceTableEntry::new(