Skip to main content

rdif_reset/
lib.rs

1#![no_std]
2
3extern crate alloc;
4
5use rdif_base::def_driver;
6pub use rdif_base::{DriverGeneric, custom_type};
7
8custom_type!(
9    #[doc = "Reset signal id"],
10    ResetId, u64, "{:#x}");
11
12impl ResetId {
13    pub const fn new(value: u64) -> Self {
14        Self(value)
15    }
16}
17
18impl From<u32> for ResetId {
19    fn from(value: u32) -> Self {
20        Self(u64::from(value))
21    }
22}
23
24impl From<usize> for ResetId {
25    fn from(value: usize) -> Self {
26        Self(value as u64)
27    }
28}
29
30#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)]
31pub enum ResetError {
32    #[error("invalid reset id")]
33    InvalidId,
34    #[error("unsupported reset operation")]
35    Unsupported,
36    #[error("reset controller is busy")]
37    Busy,
38    #[error("reset controller error")]
39    Controller,
40}
41
42pub trait Interface: DriverGeneric {
43    fn assert(&mut self, id: ResetId) -> Result<(), ResetError>;
44
45    fn deassert(&mut self, id: ResetId) -> Result<(), ResetError>;
46
47    fn reset(&mut self, id: ResetId) -> Result<(), ResetError> {
48        self.assert(id)?;
49        self.deassert(id)
50    }
51}
52
53def_driver!(Reset, Interface);
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    struct RecordingReset {
60        calls: alloc::vec::Vec<(&'static str, ResetId)>,
61    }
62
63    impl DriverGeneric for RecordingReset {
64        fn name(&self) -> &str {
65            "recording-reset"
66        }
67    }
68
69    impl Interface for RecordingReset {
70        fn assert(&mut self, id: ResetId) -> Result<(), ResetError> {
71            self.calls.push(("assert", id));
72            Ok(())
73        }
74
75        fn deassert(&mut self, id: ResetId) -> Result<(), ResetError> {
76            self.calls.push(("deassert", id));
77            Ok(())
78        }
79    }
80
81    #[test]
82    fn reset_id_conversions_preserve_raw_value() {
83        assert_eq!(ResetId::new(7).raw(), 7);
84        assert_eq!(ResetId::from(8_u32).raw(), 8);
85        assert_eq!(ResetId::from(9_usize).raw(), 9);
86        assert_eq!(ResetId::from(10_u64).raw(), 10);
87    }
88
89    #[test]
90    fn reset_pulses_assert_then_deassert() {
91        let mut reset = RecordingReset {
92            calls: alloc::vec::Vec::new(),
93        };
94
95        reset.reset(ResetId::new(3)).unwrap();
96
97        assert_eq!(
98            reset.calls,
99            alloc::vec![("assert", ResetId::new(3)), ("deassert", ResetId::new(3))]
100        );
101    }
102
103    #[test]
104    fn reset_wrapper_exposes_typed_driver() {
105        let mut reset = Reset::new(RecordingReset {
106            calls: alloc::vec::Vec::new(),
107        });
108
109        assert!(reset.typed_ref::<RecordingReset>().is_some());
110        assert!(reset.typed_mut::<RecordingReset>().is_some());
111    }
112}