1use crate::regs::dma::status;
10
11#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
13#[cfg_attr(feature = "defmt", derive(defmt::Format))]
14pub struct InterruptStatus {
15 pub tx_complete: bool,
17 pub tx_stopped: bool,
19 pub tx_buf_unavailable: bool,
21 pub tx_underflow: bool,
23 pub rx_complete: bool,
25 pub rx_stopped: bool,
27 pub rx_buf_unavailable: bool,
29 pub rx_overflow: bool,
31 pub fatal_bus_error: bool,
33 pub normal_summary: bool,
35 pub abnormal_summary: bool,
37}
38
39impl InterruptStatus {
40 #[inline]
42 #[must_use]
43 pub fn from_raw(raw: u32) -> Self {
44 Self {
45 tx_complete: (raw & status::TI) != 0,
46 tx_stopped: (raw & status::TPS) != 0,
47 tx_buf_unavailable: (raw & status::TU) != 0,
48 tx_underflow: (raw & status::UNF) != 0,
49 rx_complete: (raw & status::RI) != 0,
50 rx_stopped: (raw & status::RPS) != 0,
51 rx_buf_unavailable: (raw & status::RU) != 0,
52 rx_overflow: (raw & status::OVF) != 0,
53 fatal_bus_error: (raw & status::FBI) != 0,
54 normal_summary: (raw & status::NIS) != 0,
55 abnormal_summary: (raw & status::AIS) != 0,
56 }
57 }
58
59 #[inline]
68 #[must_use]
69 pub fn to_raw(&self) -> u32 {
70 let mut v = 0u32;
71 if self.tx_complete {
72 v |= status::TI;
73 }
74 if self.tx_stopped {
75 v |= status::TPS;
76 }
77 if self.tx_buf_unavailable {
78 v |= status::TU;
79 }
80 if self.tx_underflow {
81 v |= status::UNF;
82 }
83 if self.rx_complete {
84 v |= status::RI;
85 }
86 if self.rx_stopped {
87 v |= status::RPS;
88 }
89 if self.rx_buf_unavailable {
90 v |= status::RU;
91 }
92 if self.rx_overflow {
93 v |= status::OVF;
94 }
95 if self.fatal_bus_error {
96 v |= status::FBI;
97 }
98 if self.normal_summary {
99 v |= status::NIS;
100 }
101 if self.abnormal_summary {
102 v |= status::AIS;
103 }
104 v
105 }
106
107 #[inline]
109 #[must_use]
110 pub fn any(&self) -> bool {
111 self.tx_complete
112 || self.tx_stopped
113 || self.tx_buf_unavailable
114 || self.tx_underflow
115 || self.rx_complete
116 || self.rx_stopped
117 || self.rx_buf_unavailable
118 || self.rx_overflow
119 || self.fatal_bus_error
120 }
121
122 #[inline]
124 #[must_use]
125 pub fn has_error(&self) -> bool {
126 self.tx_underflow || self.rx_overflow || self.fatal_bus_error
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn from_raw_zero() {
136 let s = InterruptStatus::from_raw(0);
137 assert!(!s.any());
138 assert!(!s.has_error());
139 }
140
141 #[test]
142 fn tx_rx_complete() {
143 let s = InterruptStatus::from_raw(status::TI | status::RI | status::NIS);
144 assert!(s.tx_complete);
145 assert!(s.rx_complete);
146 assert!(s.normal_summary);
147 assert!(s.any());
148 assert!(!s.has_error());
149 }
150
151 #[test]
152 fn errors() {
153 let s = InterruptStatus::from_raw(status::FBI | status::OVF);
154 assert!(s.fatal_bus_error);
155 assert!(s.rx_overflow);
156 assert!(s.has_error());
157 }
158
159 #[test]
160 fn roundtrip() {
161 let raw = status::TI | status::RI | status::NIS | status::AIS | status::FBI;
162 let s = InterruptStatus::from_raw(raw);
163 assert_eq!(s.to_raw(), raw);
164 }
165
166 #[test]
167 fn any_excludes_summary_bits() {
168 let s = InterruptStatus::from_raw(status::NIS | status::AIS);
169 assert!(!s.any());
170 }
171}