1use bitflags::bitflags;
2
3bitflags! {
4 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
6 pub struct SerialEventSet: u32 {
7 const RX_DATA = 1 << 0;
8 const RX_TIMEOUT = 1 << 1;
9 const RX_STATUS = 1 << 2;
10 const TX_SPACE = 1 << 3;
11 const MODEM_STATUS = 1 << 4;
12 const BUSY_DETECT = 1 << 5;
13 const FAULT = 1 << 6;
14
15 const RX = Self::RX_DATA.bits() | Self::RX_TIMEOUT.bits() | Self::RX_STATUS.bits();
16 }
17}
18
19impl SerialEventSet {
20 pub const fn has_rx(self) -> bool {
22 self.intersects(Self::RX)
23 }
24
25 pub const fn has_tx(self) -> bool {
27 self.contains(Self::TX_SPACE)
28 }
29}
30
31bitflags! {
32 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
34 pub struct RxErrorFlags: u32 {
35 const BREAK = 1 << 0;
36 const PARITY = 1 << 1;
37 const FRAMING = 1 << 2;
38 const OVERRUN = 1 << 3;
39 }
40}
41
42#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
44pub struct SerialIrqEvent {
45 pub events: SerialEventSet,
46 pub rx_errors: RxErrorFlags,
47 pub rearm: SerialEventSet,
49}
50
51#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
52pub enum RxFlag {
53 #[default]
54 Normal,
55 Break,
56 Parity,
57 Framing,
58}
59
60#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
62pub struct RxSample {
63 pub byte: Option<u8>,
64 pub flag: RxFlag,
65 pub overrun: bool,
66}
67
68pub const IRQ_RX_BATCH_CAPACITY: usize = 64;
74
75const EMPTY_RX_SAMPLE: RxSample = RxSample {
76 byte: None,
77 flag: RxFlag::Normal,
78 overrun: false,
79};
80
81#[derive(Clone, Copy, Debug, PartialEq, Eq)]
87pub struct IrqRxBatch {
88 samples: [RxSample; IRQ_RX_BATCH_CAPACITY],
89 len: usize,
90}
91
92impl IrqRxBatch {
93 pub const fn new() -> Self {
95 Self {
96 samples: [EMPTY_RX_SAMPLE; IRQ_RX_BATCH_CAPACITY],
97 len: 0,
98 }
99 }
100
101 pub fn try_push(&mut self, sample: RxSample) -> Result<(), RxSample> {
103 let Some(slot) = self.samples.get_mut(self.len) else {
104 return Err(sample);
105 };
106 *slot = sample;
107 self.len += 1;
108 Ok(())
109 }
110
111 pub const fn len(&self) -> usize {
113 self.len
114 }
115
116 pub const fn is_empty(&self) -> bool {
118 self.len == 0
119 }
120
121 pub fn as_slice(&self) -> &[RxSample] {
123 &self.samples[..self.len]
124 }
125}
126
127impl Default for IrqRxBatch {
128 fn default() -> Self {
129 Self::new()
130 }
131}
132
133#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
135pub struct SerialIrqReport {
136 pub event: SerialIrqEvent,
137 pub rx: IrqRxBatch,
138}
139
140impl SerialIrqReport {
141 pub const fn new(event: SerialIrqEvent, rx: IrqRxBatch) -> Self {
143 Self { event, rx }
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150
151 #[test]
152 fn irq_rx_batch_rejects_samples_beyond_its_fixed_capacity() {
153 let mut batch = IrqRxBatch::new();
154 let sample = RxSample {
155 byte: Some(b'x'),
156 ..RxSample::default()
157 };
158
159 for _ in 0..IRQ_RX_BATCH_CAPACITY {
160 assert_eq!(batch.try_push(sample), Ok(()));
161 }
162
163 assert_eq!(batch.try_push(sample), Err(sample));
164 assert_eq!(batch.len(), IRQ_RX_BATCH_CAPACITY);
165 assert_eq!(batch.as_slice(), &[sample; IRQ_RX_BATCH_CAPACITY]);
166 }
167}