use super::commands::EcResponseDeckState;
pub const INPUT_DECK_SLOTS: usize = 8;
pub const TOP_ROW_SLOTS: usize = 5;
#[repr(u8)]
enum InputDeckMux {
TopRow0 = 0,
TopRow1,
TopRow2,
TopRow3,
TopRow4,
Touchpad,
_Reserved,
HubBoard = 7,
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InputModuleType {
Short,
Reserved1,
Reserved2,
Reserved3,
Reserved4,
Reserved5,
FullWidth,
HubBoard,
GenericA,
GenericB,
GenericC,
KeyboardB,
KeyboardA,
Touchpad,
Reserved15,
Disconnected,
}
impl From<u8> for InputModuleType {
fn from(item: u8) -> Self {
match item {
0 => Self::Short,
1 => Self::Reserved1,
2 => Self::Reserved2,
3 => Self::Reserved3,
4 => Self::Reserved4,
5 => Self::Reserved5,
6 => Self::FullWidth,
7 => Self::HubBoard,
8 => Self::GenericA,
9 => Self::GenericB,
10 => Self::GenericC,
11 => Self::KeyboardB,
12 => Self::KeyboardA,
13 => Self::Touchpad,
14 => Self::Reserved15,
15 => Self::Disconnected,
_ => panic!("Invalid module type"),
}
}
}
impl InputModuleType {
pub fn size(&self) -> usize {
match self {
Self::Short => 0,
Self::Reserved1 => 0,
Self::Reserved2 => 0,
Self::Reserved3 => 0,
Self::Reserved4 => 0,
Self::Reserved5 => 0,
Self::FullWidth => 8,
Self::HubBoard => 0,
Self::GenericA => 6,
Self::GenericB => 2,
Self::GenericC => 1,
Self::KeyboardB => 2,
Self::KeyboardA => 6,
Self::Touchpad => 0,
Self::Reserved15 => 0,
Self::Disconnected => 0,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InputDeckState {
Off,
Disconnected,
TurningOn,
On,
ForceOff,
ForceOn,
NoDetection,
}
impl From<u8> for InputDeckState {
fn from(item: u8) -> Self {
match item {
0 => InputDeckState::Off,
1 => InputDeckState::Disconnected,
2 => InputDeckState::TurningOn,
3 => InputDeckState::On,
4 => InputDeckState::ForceOff,
5 => InputDeckState::ForceOn,
6 => InputDeckState::NoDetection,
_ => panic!("Invalid value"),
}
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct InputDeckStatus {
pub state: InputDeckState,
pub hubboard_present: bool,
pub touchpad_present: bool,
pub touchpad_id: u8,
pub top_row: TopRowPositions,
}
impl InputDeckStatus {
pub fn top_row_to_array(&self) -> [InputModuleType; TOP_ROW_SLOTS] {
[
self.top_row.pos0,
self.top_row.pos1,
self.top_row.pos2,
self.top_row.pos3,
self.top_row.pos4,
]
}
pub fn fully_populated(&self) -> bool {
if matches!(self.state, InputDeckState::ForceOn | InputDeckState::On) {
return false;
}
if !self.hubboard_present {
return false;
}
if !self.touchpad_present {
return false;
}
self.top_row_fully_populated()
}
pub fn top_row_fully_populated(&self) -> bool {
self.top_row_to_array()
.iter()
.map(InputModuleType::size)
.sum::<usize>()
== INPUT_DECK_SLOTS
}
}
impl From<EcResponseDeckState> for InputDeckStatus {
fn from(item: EcResponseDeckState) -> Self {
let tp_id = InputModuleType::from(item.board_id[InputDeckMux::Touchpad as usize]);
let tp_present = !matches!(
tp_id,
InputModuleType::Short | InputModuleType::Disconnected
);
InputDeckStatus {
state: InputDeckState::from(item.deck_state),
hubboard_present: matches!(
InputModuleType::from(item.board_id[InputDeckMux::HubBoard as usize],),
InputModuleType::HubBoard
),
touchpad_present: tp_present,
touchpad_id: item.board_id[InputDeckMux::Touchpad as usize],
top_row: TopRowPositions {
pos0: InputModuleType::from(item.board_id[InputDeckMux::TopRow0 as usize]),
pos1: InputModuleType::from(item.board_id[InputDeckMux::TopRow1 as usize]),
pos2: InputModuleType::from(item.board_id[InputDeckMux::TopRow2 as usize]),
pos3: InputModuleType::from(item.board_id[InputDeckMux::TopRow3 as usize]),
pos4: InputModuleType::from(item.board_id[InputDeckMux::TopRow4 as usize]),
},
}
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct TopRowPositions {
pub pos0: InputModuleType,
pub pos1: InputModuleType,
pub pos2: InputModuleType,
pub pos3: InputModuleType,
pub pos4: InputModuleType,
}