use onerom_metadata::{
OneromAlgAddrConfig, OneromAlgCsConfig, OneromAlgDataConfig, OneromAlgDmaConfig,
};
use super::cs_data_layout::AlgCs2Config;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum CsAlgPreference {
AlgCs0 = 0,
AlgCs1 = 1,
AlgCs2 = 2,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum AddrAlgPreference {
AlgAddr0 = 0,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum DataAlgPreference {
AlgData0 = 0,
AlgData1 = 1,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum DmaAlgPreference {
AlgDma0 = 0,
}
pub type CombinedAlgPreference = (
CsAlgPreference,
AddrAlgPreference,
DataAlgPreference,
DmaAlgPreference,
);
pub fn cs_alg_preference(
cs_ignore_index: Option<u8>,
alg_cs2: Option<&AlgCs2Config>,
) -> CsAlgPreference {
if alg_cs2.is_some() {
CsAlgPreference::AlgCs2
} else if cs_ignore_index.is_some() {
CsAlgPreference::AlgCs1
} else {
CsAlgPreference::AlgCs0
}
}
impl From<&OneromAlgCsConfig> for CsAlgPreference {
fn from(alg: &OneromAlgCsConfig) -> Self {
match alg {
OneromAlgCsConfig::AlgCs0 { .. } => Self::AlgCs0,
OneromAlgCsConfig::AlgCs1 { .. } => Self::AlgCs1,
OneromAlgCsConfig::AlgCs2 { .. } => Self::AlgCs2,
}
}
}
impl From<&OneromAlgAddrConfig> for AddrAlgPreference {
fn from(alg: &OneromAlgAddrConfig) -> Self {
match alg {
OneromAlgAddrConfig::AlgAddr0 { .. } => Self::AlgAddr0,
}
}
}
impl From<&OneromAlgDataConfig> for DataAlgPreference {
fn from(alg: &OneromAlgDataConfig) -> Self {
match alg {
OneromAlgDataConfig::AlgData0 { .. } => Self::AlgData0,
OneromAlgDataConfig::AlgData1 { .. } => Self::AlgData1,
}
}
}
impl From<&OneromAlgDmaConfig> for DmaAlgPreference {
fn from(alg: &OneromAlgDmaConfig) -> Self {
match alg {
OneromAlgDmaConfig::AlgDma0 { .. } => Self::AlgDma0,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cs_preference_ordering() {
assert!(CsAlgPreference::AlgCs0 < CsAlgPreference::AlgCs1);
assert!(CsAlgPreference::AlgCs1 < CsAlgPreference::AlgCs2);
}
#[test]
fn data_preference_ordering() {
assert!(DataAlgPreference::AlgData0 < DataAlgPreference::AlgData1);
}
#[test]
fn combined_preference_cs_is_primary() {
let better: CombinedAlgPreference = (
CsAlgPreference::AlgCs0,
AddrAlgPreference::AlgAddr0,
DataAlgPreference::AlgData1, DmaAlgPreference::AlgDma0,
);
let worse: CombinedAlgPreference = (
CsAlgPreference::AlgCs1, AddrAlgPreference::AlgAddr0,
DataAlgPreference::AlgData0, DmaAlgPreference::AlgDma0,
);
assert!(better < worse);
}
#[test]
fn gpio_spread_tiebreaker() {
let pref: CombinedAlgPreference = (
CsAlgPreference::AlgCs0,
AddrAlgPreference::AlgAddr0,
DataAlgPreference::AlgData0,
DmaAlgPreference::AlgDma0,
);
let tight_spread: (CombinedAlgPreference, u32) = (pref, 10);
let wide_spread: (CombinedAlgPreference, u32) = (pref, 20);
assert!(tight_spread < wide_spread);
}
#[test]
fn cs_alg_preference_inference() {
assert_eq!(cs_alg_preference(None, None), CsAlgPreference::AlgCs0);
assert_eq!(cs_alg_preference(Some(1), None), CsAlgPreference::AlgCs1);
assert_eq!(
cs_alg_preference(
None,
Some(&AlgCs2Config {
base_qualifier_pin: 0,
num_qualifier_pins: 2,
qualifier_inactive_pattern: 0b11,
})
),
CsAlgPreference::AlgCs2
);
assert_eq!(
cs_alg_preference(
Some(1),
Some(&AlgCs2Config {
base_qualifier_pin: 0,
num_qualifier_pins: 2,
qualifier_inactive_pattern: 0b11,
})
),
CsAlgPreference::AlgCs2
);
}
}