use crate::error::ProtocolError;
use crate::register::{
CedCount, CedCounters, ClearableUpdateFlags, Config0, FfeLevels, FrlConfig, LtpReq,
LtpRequests, RsCorrectionCount, ScramblerStatus, SourceTestConfig, StatusFlags, TmdsConfig,
UpdateFlags,
};
pub const SINK_VERSION: u8 = 0x01;
pub const SOURCE_VERSION: u8 = 0x02;
pub const UPDATE_0: u8 = 0x10;
pub const TMDS_CONFIG: u8 = 0x20;
pub const SCRAMBLER_STATUS: u8 = 0x21;
pub const CONFIG_0: u8 = 0x30;
pub const CONFIG_1: u8 = 0x31;
pub const SOURCE_TEST_CONFIG: u8 = 0x35;
pub const STATUS_FLAGS_0: u8 = 0x40;
pub const STATUS_FLAGS_1: u8 = 0x41;
pub const STATUS_FLAGS_2: u8 = 0x42;
pub const ERR_DET_0_L: u8 = 0x50;
pub const ERR_DET_0_H: u8 = 0x51;
pub const ERR_DET_1_L: u8 = 0x52;
pub const ERR_DET_1_H: u8 = 0x53;
pub const ERR_DET_2_L: u8 = 0x54;
pub const ERR_DET_2_H: u8 = 0x55;
pub const ERR_DET_CHECKSUM: u8 = 0x56;
pub const ERR_DET_3_L: u8 = 0x57;
pub const ERR_DET_3_H: u8 = 0x58;
pub const RS_CORRECTION_L: u8 = 0x59;
pub const RS_CORRECTION_H: u8 = 0x5A;
pub const CED_REGISTERS: [u8; 8] = [
ERR_DET_0_L,
ERR_DET_0_H,
ERR_DET_1_L,
ERR_DET_1_H,
ERR_DET_2_L,
ERR_DET_2_H,
ERR_DET_3_L,
ERR_DET_3_H,
];
pub fn encode_tmds_config(config: TmdsConfig) -> u8 {
(config.scrambling_enable as u8) | ((config.high_tmds_clock_ratio as u8) << 1)
}
pub fn decode_scrambler_status(byte: u8) -> ScramblerStatus {
ScramblerStatus {
scrambling_active: byte & 0x01 != 0,
}
}
pub fn decode_update_flags(update_0: u8) -> UpdateFlags {
UpdateFlags {
status_update: update_0 & 0x01 != 0,
ced_update: update_0 & 0x02 != 0,
rr_test: update_0 & 0x04 != 0,
source_test_update: update_0 & 0x08 != 0,
frl_start: update_0 & 0x10 != 0,
flt_update: update_0 & 0x20 != 0,
rsed_update: update_0 & 0x40 != 0,
}
}
pub fn encode_clear_update_flags(flags: ClearableUpdateFlags) -> u8 {
(flags.status_update as u8)
| ((flags.ced_update as u8) << 1)
| ((flags.source_test_update as u8) << 3)
| ((flags.frl_start as u8) << 4)
| ((flags.flt_update as u8) << 5)
| ((flags.rsed_update as u8) << 6)
}
pub fn encode_config_0(config: Config0) -> u8 {
(config.rr_enable as u8) | ((config.flt_no_retrain as u8) << 1)
}
pub fn encode_config_1(config: FrlConfig) -> Result<u8, ProtocolError> {
if config.ffe_levels.value() > FfeLevels::max_for(config.frl_rate).value() {
return Err(ProtocolError::FfeLevelsOutOfRange {
rate: config.frl_rate,
levels: config.ffe_levels.value(),
});
}
Ok((config.frl_rate as u8) | (config.ffe_levels.value() << 4))
}
pub fn decode_source_test_config(byte: u8) -> SourceTestConfig {
SourceTestConfig {
txffe_pre_shoot_only: byte & 0x02 != 0,
txffe_de_emphasis_only: byte & 0x04 != 0,
txffe_no_ffe: byte & 0x08 != 0,
flt_no_timeout: byte & 0x20 != 0,
dsc_frl_max: byte & 0x40 != 0,
frl_max: byte & 0x80 != 0,
}
}
pub fn decode_status_flags(status_flags_0: u8) -> StatusFlags {
StatusFlags {
clock_detected: status_flags_0 & 0x01 != 0,
ch0_locked: status_flags_0 & 0x02 != 0,
ch1_locked: status_flags_0 & 0x04 != 0,
ch2_locked: status_flags_0 & 0x08 != 0,
ln3_locked: status_flags_0 & 0x10 != 0,
flt_ready: status_flags_0 & 0x40 != 0,
dsc_decode_fail: status_flags_0 & 0x80 != 0,
}
}
pub fn decode_ltp_requests(status_flags_1: u8, status_flags_2: u8) -> LtpRequests {
LtpRequests {
lane0: LtpReq::from_nibble(status_flags_1),
lane1: LtpReq::from_nibble(status_flags_1 >> 4),
lane2: LtpReq::from_nibble(status_flags_2),
lane3: LtpReq::from_nibble(status_flags_2 >> 4),
}
}
pub fn decode_ced(bytes: [u8; 8]) -> CedCounters {
let [l0, h0, l1, h1, l2, h2, l3, h3] = bytes;
let decode = |lo: u8, hi: u8| -> Option<CedCount> {
(hi & 0x80 != 0).then(|| CedCount::new(((hi as u16) << 8) | lo as u16))
};
CedCounters {
lane0: decode(l0, h0),
lane1: decode(l1, h1),
lane2: decode(l2, h2),
lane3: decode(l3, h3),
}
}
pub fn decode_rs_correction(low: u8, high: u8) -> Option<RsCorrectionCount> {
(high & 0x80 != 0).then(|| RsCorrectionCount::new(((high as u16) << 8) | low as u16))
}