Skip to main content

culvert_async/client/
update.rs

1use hdmi_hal_async::scdc::ScdcTransport;
2
3use crate::{ScdcError, UpdateFlags};
4
5use super::Scdc;
6use super::address;
7
8impl<T: ScdcTransport> Scdc<T> {
9    /// Reads update flags from `Update_0` (0x10) and `Update_1` (0x11).
10    pub async fn read_update_flags(&mut self) -> Result<UpdateFlags, ScdcError<T::Error>> {
11        let u0 = self
12            .transport
13            .read(address::UPDATE_0)
14            .await
15            .map_err(ScdcError::Transport)?;
16        let u1 = self
17            .transport
18            .read(address::UPDATE_1)
19            .await
20            .map_err(ScdcError::Transport)?;
21        Ok(UpdateFlags::new(
22            u0 & 0x01 != 0,
23            u0 & 0x02 != 0,
24            u0 & 0x04 != 0,
25            u1 & 0x01 != 0,
26        ))
27    }
28
29    /// Clears the specified update flags in `Update_0` (0x10) and `Update_1` (0x11).
30    ///
31    /// Each flag set to `true` in `flags` is cleared (write-1-to-clear). Flags
32    /// set to `false` are left unchanged.
33    pub async fn clear_update_flags(
34        &mut self,
35        flags: UpdateFlags,
36    ) -> Result<(), ScdcError<T::Error>> {
37        let u0 = (flags.status_update as u8)
38            | ((flags.ced_update as u8) << 1)
39            | ((flags.frl_update as u8) << 2);
40        let u1 = flags.dsc_update as u8;
41        self.transport
42            .write(address::UPDATE_0, u0)
43            .await
44            .map_err(ScdcError::Transport)?;
45        self.transport
46            .write(address::UPDATE_1, u1)
47            .await
48            .map_err(ScdcError::Transport)
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use super::super::Scdc;
55    use super::super::test_transport::TestTransport;
56    use crate::UpdateFlags;
57
58    #[pollster::test]
59    async fn update_flags_individual_bits() {
60        // status_update = bit 0 of Update_0
61        let mut sim = TestTransport::new();
62        sim.set(0x10, 0x01);
63        assert!(
64            Scdc::new(sim)
65                .read_update_flags()
66                .await
67                .unwrap()
68                .status_update
69        );
70
71        // ced_update = bit 1
72        let mut sim = TestTransport::new();
73        sim.set(0x10, 0x02);
74        assert!(Scdc::new(sim).read_update_flags().await.unwrap().ced_update);
75
76        // frl_update = bit 2
77        let mut sim = TestTransport::new();
78        sim.set(0x10, 0x04);
79        assert!(Scdc::new(sim).read_update_flags().await.unwrap().frl_update);
80
81        // dsc_update = bit 0 of Update_1
82        let mut sim = TestTransport::new();
83        sim.set(0x11, 0x01);
84        assert!(Scdc::new(sim).read_update_flags().await.unwrap().dsc_update);
85    }
86
87    #[pollster::test]
88    async fn clear_update_flags_w1c() {
89        let mut scdc = Scdc::new(TestTransport::new());
90        scdc.clear_update_flags(UpdateFlags::new(true, true, true, true))
91            .await
92            .unwrap();
93        let t = scdc.into_transport();
94        assert_eq!(t.get(0x10), 0x07);
95        assert_eq!(t.get(0x11), 0x01);
96    }
97
98    #[pollster::test]
99    async fn clear_update_flags_partial() {
100        let mut scdc = Scdc::new(TestTransport::new());
101        scdc.clear_update_flags(UpdateFlags::new(false, true, false, false))
102            .await
103            .unwrap();
104        let t = scdc.into_transport();
105        assert_eq!(t.get(0x10), 0x02); // only ced_update bit
106        assert_eq!(t.get(0x11), 0x00);
107    }
108
109    #[pollster::test]
110    async fn transport_error_propagates() {
111        // First read fails.
112        assert!(
113            Scdc::new(TestTransport::failing_after(0))
114                .read_update_flags()
115                .await
116                .is_err()
117        );
118        // Second read (Update_1) fails.
119        assert!(
120            Scdc::new(TestTransport::failing_after(1))
121                .read_update_flags()
122                .await
123                .is_err()
124        );
125        // First write fails.
126        assert!(
127            Scdc::new(TestTransport::failing_after(0))
128                .clear_update_flags(UpdateFlags::new(false, false, false, false))
129                .await
130                .is_err()
131        );
132        // Second write (Update_1) fails.
133        assert!(
134            Scdc::new(TestTransport::failing_after(1))
135                .clear_update_flags(UpdateFlags::new(false, false, false, false))
136                .await
137                .is_err()
138        );
139    }
140}