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}