pub(crate) mod address;
use display_types::HdmiForumFrl;
pub use display_types::HdmiForumFrl as FrlRate;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TmdsConfig {
pub scrambling_enable: bool,
pub high_tmds_clock_ratio: bool,
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ScramblerStatus {
pub scrambling_active: bool,
}
impl ScramblerStatus {
pub fn new(scrambling_active: bool) -> Self {
Self { scrambling_active }
}
}
#[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 frl_rate: HdmiForumFrl,
pub dsc_frl_max: bool,
pub ffe_levels: FfeLevels,
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LtpReq {
None = 0,
Lfsr0 = 1,
Lfsr1 = 2,
Lfsr2 = 3,
Lfsr3 = 4,
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StatusFlags {
pub clock_detected: bool,
pub cable_connected: bool,
pub ch0_locked: bool,
pub ch1_locked: bool,
pub ch2_locked: bool,
pub ch3_locked: bool,
pub flt_ready: bool,
pub frl_start: bool,
pub ltp_req: LtpReq,
}
impl StatusFlags {
#[allow(clippy::too_many_arguments)]
pub fn new(
clock_detected: bool,
cable_connected: bool,
ch0_locked: bool,
ch1_locked: bool,
ch2_locked: bool,
ch3_locked: bool,
flt_ready: bool,
frl_start: bool,
ltp_req: LtpReq,
) -> Self {
Self {
clock_detected,
cable_connected,
ch0_locked,
ch1_locked,
ch2_locked,
ch3_locked,
flt_ready,
frl_start,
ltp_req,
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct UpdateFlags {
pub frl_update: bool,
pub ced_update: bool,
pub status_update: bool,
pub dsc_update: bool,
}
impl UpdateFlags {
pub fn new(status_update: bool, ced_update: bool, frl_update: bool, dsc_update: bool) -> Self {
Self {
status_update,
ced_update,
frl_update,
dsc_update,
}
}
}
#[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
}
}
#[non_exhaustive]
#[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 CedCounters {
pub fn new(
lane0: Option<CedCount>,
lane1: Option<CedCount>,
lane2: Option<CedCount>,
lane3: Option<CedCount>,
) -> Self {
Self {
lane0,
lane1,
lane2,
lane3,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ced_count_masks_validity_bit() {
assert_eq!(CedCount::new(0xFFFF).value(), 0x7FFF);
assert_eq!(CedCount::new(0x8000).value(), 0x0000);
}
#[test]
fn ced_count_preserves_15_bit_value() {
assert_eq!(CedCount::new(0x0000).value(), 0x0000);
assert_eq!(CedCount::new(0x0001).value(), 0x0001);
assert_eq!(CedCount::new(0x7FFF).value(), 0x7FFF);
}
fn status_flags_all_false() -> StatusFlags {
StatusFlags::new(
false,
false,
false,
false,
false,
false,
false,
false,
LtpReq::None,
)
}
#[test]
fn status_flags_new_field_order() {
assert!(
StatusFlags::new(
true,
false,
false,
false,
false,
false,
false,
false,
LtpReq::None
)
.clock_detected
);
assert!(
StatusFlags::new(
false,
true,
false,
false,
false,
false,
false,
false,
LtpReq::None
)
.cable_connected
);
assert!(
StatusFlags::new(
false,
false,
true,
false,
false,
false,
false,
false,
LtpReq::None
)
.ch0_locked
);
assert!(
StatusFlags::new(
false,
false,
false,
true,
false,
false,
false,
false,
LtpReq::None
)
.ch1_locked
);
assert!(
StatusFlags::new(
false,
false,
false,
false,
true,
false,
false,
false,
LtpReq::None
)
.ch2_locked
);
assert!(
StatusFlags::new(
false,
false,
false,
false,
false,
true,
false,
false,
LtpReq::None
)
.ch3_locked
);
assert!(
StatusFlags::new(
false,
false,
false,
false,
false,
false,
true,
false,
LtpReq::None
)
.flt_ready
);
assert!(
StatusFlags::new(
false,
false,
false,
false,
false,
false,
false,
true,
LtpReq::None
)
.frl_start
);
assert_eq!(status_flags_all_false().ltp_req, LtpReq::None);
assert_eq!(
StatusFlags::new(
false,
false,
false,
false,
false,
false,
false,
false,
LtpReq::Lfsr2
)
.ltp_req,
LtpReq::Lfsr2
);
}
#[test]
fn ced_counters_new_field_order() {
let a = CedCount::new(1);
let b = CedCount::new(2);
let c = CedCount::new(3);
let d = CedCount::new(4);
let counters = CedCounters::new(Some(a), Some(b), Some(c), Some(d));
assert_eq!(counters.lane0.unwrap().value(), 1);
assert_eq!(counters.lane1.unwrap().value(), 2);
assert_eq!(counters.lane2.unwrap().value(), 3);
assert_eq!(counters.lane3.unwrap().value(), 4);
}
#[test]
fn ced_counters_new_lane3_none() {
let counters = CedCounters::new(
Some(CedCount::new(0)),
Some(CedCount::new(0)),
Some(CedCount::new(0)),
None,
);
assert!(counters.lane3.is_none());
}
#[test]
fn scrambler_status_new() {
assert!(ScramblerStatus::new(true).scrambling_active);
assert!(!ScramblerStatus::new(false).scrambling_active);
}
#[test]
fn update_flags_new_field_order() {
let f = UpdateFlags::new(true, false, false, false);
assert!(f.status_update);
assert!(!f.ced_update && !f.frl_update && !f.dsc_update);
let f = UpdateFlags::new(false, true, false, false);
assert!(f.ced_update);
assert!(!f.status_update && !f.frl_update && !f.dsc_update);
let f = UpdateFlags::new(false, false, true, false);
assert!(f.frl_update);
assert!(!f.status_update && !f.ced_update && !f.dsc_update);
let f = UpdateFlags::new(false, false, false, true);
assert!(f.dsc_update);
assert!(!f.status_update && !f.ced_update && !f.frl_update);
}
}