use heterob::{bit_numbering::Lsb, endianness::Le, Seq, P2, P3, P4};
use super::{ExtendedCapabilityDataError, ExtendedCapabilityHeader};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ReadinessTimeReporting {
pub reset_time: ReadinessTime,
pub dl_up_time: ReadinessTime,
pub valid: bool,
pub flr_time: ReadinessTime,
pub d3hot_to_d0_time: ReadinessTime,
}
impl ReadinessTimeReporting {
pub const SIZE: usize = 0x0c;
}
impl TryFrom<&[u8]> for ReadinessTimeReporting {
type Error = ExtendedCapabilityDataError;
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
let slice = slice
.get(ExtendedCapabilityHeader::SIZE..)
.unwrap_or_default();
let Seq {
head: Le((r1, r2)), ..
} = P2(slice)
.try_into()
.map_err(|_| ExtendedCapabilityDataError {
name: "Readiness Time Reporting",
size: Self::SIZE,
})?;
let Lsb((reset_time, dl_up_time, (), valid)) = P4::<u32, 12, 12, 7, 1>(r1).into();
let Lsb((flr_time, d3hot_to_d0_time, ())) = P3::<u32, 12, 12, 8>(r2).into();
Ok(Self {
reset_time: From::<u16>::from(reset_time),
dl_up_time: From::<u16>::from(dl_up_time),
valid,
flr_time: From::<u16>::from(flr_time),
d3hot_to_d0_time: From::<u16>::from(d3hot_to_d0_time),
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ReadinessTime {
pub value: u16,
pub scale: u8,
}
impl ReadinessTime {
pub fn actual_time_value(&self) -> u64 {
(self.value as u64) << (self.scale * 5)
}
}
impl From<u16> for ReadinessTime {
fn from(word: u16) -> Self {
let Lsb((value, scale, ())) = P3::<_, 9, 3, 4>(word).into();
Self { value, scale }
}
}