culvert_async/client/
scrambling.rs1use hdmi_hal_async::scdc::ScdcTransport;
2
3use crate::ScdcError;
4use crate::{ScramblerStatus, TmdsConfig};
5use culvert::codec;
6
7use super::Scdc;
8
9impl<T: ScdcTransport> Scdc<T> {
10 pub async fn write_tmds_config(
14 &mut self,
15 config: TmdsConfig,
16 ) -> Result<(), ScdcError<T::Error>> {
17 self.transport
18 .write(codec::TMDS_CONFIG, codec::encode_tmds_config(config))
19 .await
20 .map_err(ScdcError::Transport)
21 }
22
23 pub async fn read_scrambler_status(&mut self) -> Result<ScramblerStatus, ScdcError<T::Error>> {
28 let byte = self
29 .transport
30 .read(codec::SCRAMBLER_STATUS)
31 .await
32 .map_err(ScdcError::Transport)?;
33 Ok(codec::decode_scrambler_status(byte))
34 }
35}
36
37#[cfg(test)]
38mod tests {
39 use super::super::Scdc;
40 use super::super::test_transport::TestTransport;
41 use crate::ScdcError;
42 use crate::{ScramblerStatus, TmdsConfig};
43
44 #[pollster::test]
45 async fn tmds_config_scrambling_only() {
46 let mut scdc = Scdc::new(TestTransport::new());
47 scdc.write_tmds_config(TmdsConfig {
48 scrambling_enable: true,
49 high_tmds_clock_ratio: false,
50 })
51 .await
52 .unwrap();
53 assert_eq!(scdc.into_transport().get(0x20), 0x01);
54 }
55
56 #[pollster::test]
57 async fn tmds_config_clock_ratio_only() {
58 let mut scdc = Scdc::new(TestTransport::new());
59 scdc.write_tmds_config(TmdsConfig {
60 scrambling_enable: false,
61 high_tmds_clock_ratio: true,
62 })
63 .await
64 .unwrap();
65 assert_eq!(scdc.into_transport().get(0x20), 0x02);
66 }
67
68 #[pollster::test]
69 async fn tmds_config_both_clear() {
70 let mut scdc = Scdc::new(TestTransport::new());
71 scdc.write_tmds_config(TmdsConfig {
72 scrambling_enable: false,
73 high_tmds_clock_ratio: false,
74 })
75 .await
76 .unwrap();
77 assert_eq!(scdc.into_transport().get(0x20), 0x00);
78 }
79
80 #[pollster::test]
81 async fn scrambler_status_bit0_set() {
82 let mut sim = TestTransport::new();
83 sim.set(0x21, 0xFF); assert_eq!(
85 Scdc::new(sim).read_scrambler_status().await.unwrap(),
86 ScramblerStatus::new(true)
87 );
88 }
89
90 #[pollster::test]
91 async fn scrambler_status_bit0_clear() {
92 let mut sim = TestTransport::new();
93 sim.set(0x21, 0xFE); assert_eq!(
95 Scdc::new(sim).read_scrambler_status().await.unwrap(),
96 ScramblerStatus::new(false)
97 );
98 }
99
100 #[pollster::test]
101 async fn transport_error_propagates() {
102 assert!(
103 Scdc::new(TestTransport::failing_after(0))
104 .write_tmds_config(TmdsConfig {
105 scrambling_enable: false,
106 high_tmds_clock_ratio: false
107 })
108 .await
109 .is_err_and(|error| matches!(error, ScdcError::Transport(())))
110 );
111 assert!(
112 Scdc::new(TestTransport::failing_after(0))
113 .read_scrambler_status()
114 .await
115 .is_err_and(|error| matches!(error, ScdcError::Transport(())))
116 );
117 }
118}