use hdmi_hal_async::scdc::ScdcTransport;
use crate::ScdcError;
use crate::{ClearableUpdateFlags, UpdateFlags};
use culvert::codec;
use super::Scdc;
impl<T: ScdcTransport> Scdc<T> {
pub async fn read_update_flags(&mut self) -> Result<UpdateFlags, ScdcError<T::Error>> {
let update_0 = self
.transport
.read(codec::UPDATE_0)
.await
.map_err(ScdcError::Transport)?;
Ok(codec::decode_update_flags(update_0))
}
pub async fn clear_update_flags(
&mut self,
flags: ClearableUpdateFlags,
) -> Result<(), ScdcError<T::Error>> {
let byte = codec::encode_clear_update_flags(flags);
self.transport
.write(codec::UPDATE_0, byte)
.await
.map_err(ScdcError::Transport)
}
}
#[cfg(test)]
mod tests {
use super::super::Scdc;
use super::super::test_transport::{Op, TestTransport};
use crate::ScdcError;
use crate::{ClearableUpdateFlags, UpdateFlags};
fn read(byte: u8) -> UpdateFlags {
let mut sim = TestTransport::new();
sim.set(0x10, byte);
pollster::block_on(Scdc::new(sim).read_update_flags()).unwrap()
}
#[pollster::test]
async fn update_flags_individual_bits() {
assert!(read(0x01).status_update);
assert!(read(0x02).ced_update);
assert!(read(0x04).rr_test);
assert!(read(0x08).source_test_update);
assert!(read(0x10).frl_start);
assert!(read(0x20).flt_update);
assert!(read(0x40).rsed_update);
assert_eq!(
read(0x00),
UpdateFlags::new(false, false, false, false, false, false, false)
);
}
#[pollster::test]
async fn update_1_is_not_read() {
let mut sim = TestTransport::new();
sim.set(0x11, 0xFF);
assert_eq!(
Scdc::new(sim).read_update_flags().await.unwrap(),
UpdateFlags::new(false, false, false, false, false, false, false)
);
}
#[pollster::test]
async fn clear_update_flags_w1c() {
let mut scdc = Scdc::new(TestTransport::new());
scdc.clear_update_flags(ClearableUpdateFlags::new(
true, true, true, true, true, true,
))
.await
.unwrap();
let t = scdc.into_transport();
assert_eq!(t.get(0x10), 0x7B); assert_eq!(t.get(0x11), 0x00);
}
#[pollster::test]
async fn read_then_clear_acknowledges_every_flag_but_rr_test() {
let mut sim = TestTransport::new();
sim.set(0x10, 0x24); let mut scdc = Scdc::new(sim);
let flags = scdc.read_update_flags().await.unwrap();
assert!(flags.rr_test && flags.flt_update);
scdc.clear_update_flags(flags.clearable()).await.unwrap();
assert_eq!(scdc.into_transport().get(0x10), 0x20);
}
#[pollster::test]
async fn clear_update_flags_partial() {
let mut scdc = Scdc::new(TestTransport::new());
scdc.clear_update_flags(ClearableUpdateFlags::new(
false, false, false, false, true, false,
))
.await
.unwrap();
assert_eq!(scdc.into_transport().get(0x10), 0x20);
}
#[pollster::test]
async fn clear_update_flags_is_one_write() {
let mut scdc = Scdc::new(TestTransport::new());
scdc.clear_update_flags(ClearableUpdateFlags::new(
false, false, false, true, true, false,
))
.await
.unwrap();
assert_eq!(
scdc.into_transport().log()[..2],
[Some(Op::Write(0x10, 0x30)), None]
);
}
#[pollster::test]
async fn transport_error_propagates() {
assert!(
Scdc::new(TestTransport::failing_after(0))
.read_update_flags()
.await
.is_err_and(|error| matches!(error, ScdcError::Transport(())))
);
assert!(
Scdc::new(TestTransport::failing_after(0))
.clear_update_flags(ClearableUpdateFlags::default())
.await
.is_err_and(|error| matches!(error, ScdcError::Transport(())))
);
}
}