use display_types::cea861::hdmi_forum::HdmiForumFrl;
use hdmi_hal::phy::LtpPattern;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LtpReq {
None = 0,
Lfsr0 = 1,
Lfsr1 = 2,
Lfsr2 = 3,
Lfsr3 = 4,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FfeLevels {
Ffe0 = 0,
Ffe1 = 1,
Ffe2 = 2,
Ffe3 = 3,
Ffe4 = 4,
Ffe5 = 5,
Ffe6 = 6,
Ffe7 = 7,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FrlConfig {
pub rate: HdmiForumFrl,
pub ffe_levels: FfeLevels,
pub dsc_frl_max: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TrainingStatus {
pub flt_ready: bool,
pub frl_start: bool,
pub ltp_req: LtpReq,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CedCount(u16);
impl CedCount {
pub fn new(raw: u16) -> Self {
Self(raw & 0x7FFF)
}
pub fn value(self) -> u16 {
self.0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CedCounters {
pub lane0: Option<CedCount>,
pub lane1: Option<CedCount>,
pub lane2: Option<CedCount>,
pub lane3: Option<CedCount>,
}
impl From<LtpReq> for LtpPattern {
fn from(req: LtpReq) -> Self {
LtpPattern::new(req as u8)
}
}
#[cfg(test)]
mod tests {
use super::*;
use display_types::cea861::hdmi_forum::HdmiForumFrl;
#[test]
fn ltp_req_discriminants() {
assert_eq!(LtpReq::None as u8, 0);
assert_eq!(LtpReq::Lfsr0 as u8, 1);
assert_eq!(LtpReq::Lfsr1 as u8, 2);
assert_eq!(LtpReq::Lfsr2 as u8, 3);
assert_eq!(LtpReq::Lfsr3 as u8, 4);
}
#[test]
fn ltp_req_clone_eq() {
let a = LtpReq::Lfsr2;
assert_eq!(a, a.clone());
assert_ne!(LtpReq::Lfsr0, LtpReq::Lfsr1);
}
#[test]
fn ffe_levels_discriminants() {
assert_eq!(FfeLevels::Ffe0 as u8, 0);
assert_eq!(FfeLevels::Ffe7 as u8, 7);
}
#[test]
fn ffe_levels_clone_eq() {
let a = FfeLevels::Ffe3;
assert_eq!(a, a.clone());
assert_ne!(FfeLevels::Ffe0, FfeLevels::Ffe7);
}
#[test]
fn frl_config_fields() {
let cfg = FrlConfig {
rate: HdmiForumFrl::Rate6Gbps4Lanes,
ffe_levels: FfeLevels::Ffe2,
dsc_frl_max: true,
};
assert_eq!(cfg.rate, HdmiForumFrl::Rate6Gbps4Lanes);
assert_eq!(cfg.ffe_levels, FfeLevels::Ffe2);
assert!(cfg.dsc_frl_max);
}
#[test]
fn frl_config_clone_eq() {
let a = FrlConfig {
rate: HdmiForumFrl::Rate3Gbps3Lanes,
ffe_levels: FfeLevels::Ffe0,
dsc_frl_max: false,
};
assert_eq!(a, a.clone());
}
#[test]
fn training_status_fields() {
let s = TrainingStatus {
flt_ready: true,
frl_start: false,
ltp_req: LtpReq::Lfsr1,
};
assert!(s.flt_ready);
assert!(!s.frl_start);
assert_eq!(s.ltp_req, LtpReq::Lfsr1);
}
#[test]
fn training_status_clone_eq() {
let a = TrainingStatus {
flt_ready: true,
frl_start: true,
ltp_req: LtpReq::None,
};
assert_eq!(a, a.clone());
}
#[test]
fn ced_count_masks_validity_bit() {
let c = CedCount::new(0xFFFF);
assert_eq!(c.value(), 0x7FFF);
}
#[test]
fn ced_count_preserves_15_bit_value() {
let c = CedCount::new(0x0123);
assert_eq!(c.value(), 0x0123);
}
#[test]
fn ced_count_zero() {
assert_eq!(CedCount::new(0).value(), 0);
}
#[test]
fn ced_count_clone_eq() {
let a = CedCount::new(42);
assert_eq!(a, a.clone());
assert_ne!(CedCount::new(1), CedCount::new(2));
}
#[test]
fn ced_counters_all_none() {
let c = CedCounters {
lane0: None,
lane1: None,
lane2: None,
lane3: None,
};
assert!(c.lane0.is_none());
assert!(c.lane3.is_none());
}
#[test]
fn ced_counters_individual_lanes() {
let c = CedCounters {
lane0: Some(CedCount::new(10)),
lane1: Some(CedCount::new(20)),
lane2: None,
lane3: Some(CedCount::new(30)),
};
assert_eq!(c.lane0.unwrap().value(), 10);
assert_eq!(c.lane1.unwrap().value(), 20);
assert!(c.lane2.is_none());
assert_eq!(c.lane3.unwrap().value(), 30);
}
#[test]
fn ced_counters_clone_eq() {
let a = CedCounters {
lane0: Some(CedCount::new(5)),
lane1: None,
lane2: None,
lane3: None,
};
assert_eq!(a, a.clone());
}
#[test]
fn ltp_req_to_pattern_lfsr0() {
assert_eq!(LtpPattern::from(LtpReq::Lfsr0).value(), 1);
}
#[test]
fn ltp_req_to_pattern_lfsr1() {
assert_eq!(LtpPattern::from(LtpReq::Lfsr1).value(), 2);
}
#[test]
fn ltp_req_to_pattern_lfsr2() {
assert_eq!(LtpPattern::from(LtpReq::Lfsr2).value(), 3);
}
#[test]
fn ltp_req_to_pattern_lfsr3() {
assert_eq!(LtpPattern::from(LtpReq::Lfsr3).value(), 4);
}
}