1use core::{
5 fmt::{Display, Formatter, Result},
6 write,
7};
8
9use bitfield_struct::bitfield;
10
11#[derive(Clone, Copy, Debug, PartialEq)]
14pub enum PaLevel {
15 Min,
19 Low,
23 High,
27 Max,
31}
32
33#[cfg(feature = "defmt")]
34#[cfg(target_os = "none")]
35impl defmt::Format for PaLevel {
36 fn format(&self, fmt: defmt::Formatter) {
37 match self {
38 PaLevel::Min => defmt::write!(fmt, "Min"),
39 PaLevel::Low => defmt::write!(fmt, "Low"),
40 PaLevel::High => defmt::write!(fmt, "High"),
41 PaLevel::Max => defmt::write!(fmt, "Max"),
42 }
43 }
44}
45
46impl PaLevel {
47 pub(crate) const MASK: u8 = 6;
48
49 pub(crate) const fn into_bits(self) -> u8 {
50 match self {
51 PaLevel::Min => 0,
52 PaLevel::Low => 2,
53 PaLevel::High => 4,
54 PaLevel::Max => 6,
55 }
56 }
57 pub(crate) const fn from_bits(value: u8) -> Self {
58 match value {
59 0 => PaLevel::Min,
60 2 => PaLevel::Low,
61 4 => PaLevel::High,
62 _ => PaLevel::Max,
63 }
64 }
65}
66
67impl Display for PaLevel {
68 fn fmt(&self, f: &mut Formatter) -> Result {
69 match self {
70 PaLevel::Min => write!(f, "Min"),
71 PaLevel::Low => write!(f, "Low"),
72 PaLevel::High => write!(f, "High"),
73 PaLevel::Max => write!(f, "Max"),
74 }
75 }
76}
77
78#[derive(Clone, Copy, Debug, PartialEq)]
80pub enum DataRate {
81 Mbps1,
83 Mbps2,
85 Kbps250,
87}
88
89impl DataRate {
90 pub(crate) const MASK: u8 = 0x28;
91
92 pub(crate) const fn into_bits(self) -> u8 {
93 match self {
94 DataRate::Mbps1 => 0,
95 DataRate::Mbps2 => 0x8,
96 DataRate::Kbps250 => 0x20,
97 }
98 }
99 pub(crate) const fn from_bits(value: u8) -> Self {
100 match value {
101 0x8 => DataRate::Mbps2,
102 0x20 => DataRate::Kbps250,
103 _ => DataRate::Mbps1,
104 }
105 }
106}
107
108#[cfg(feature = "defmt")]
109#[cfg(target_os = "none")]
110impl defmt::Format for DataRate {
111 fn format(&self, fmt: defmt::Formatter) {
112 match self {
113 DataRate::Mbps1 => defmt::write!(fmt, "1 Mbps"),
114 DataRate::Mbps2 => defmt::write!(fmt, "2 Mbps"),
115 DataRate::Kbps250 => defmt::write!(fmt, "250 Kbps"),
116 }
117 }
118}
119
120impl Display for DataRate {
121 fn fmt(&self, f: &mut Formatter) -> Result {
122 match self {
123 DataRate::Mbps1 => write!(f, "1 Mbps"),
124 DataRate::Mbps2 => write!(f, "2 Mbps"),
125 DataRate::Kbps250 => write!(f, "250 Kbps"),
126 }
127 }
128}
129
130#[derive(Clone, Copy, Debug, PartialEq)]
134pub enum CrcLength {
135 Disabled,
137 Bit8,
139 Bit16,
141}
142
143impl CrcLength {
144 pub(crate) const fn into_bits(self) -> u8 {
145 match self {
146 CrcLength::Disabled => 0,
147 CrcLength::Bit8 => 8,
148 CrcLength::Bit16 => 12,
149 }
150 }
151 pub(crate) const fn from_bits(value: u8) -> Self {
152 match value {
153 0 => CrcLength::Disabled,
154 8 => CrcLength::Bit8,
155 _ => CrcLength::Bit16,
156 }
157 }
158}
159
160#[cfg(feature = "defmt")]
161#[cfg(target_os = "none")]
162impl defmt::Format for CrcLength {
163 fn format(&self, fmt: defmt::Formatter) {
164 match self {
165 CrcLength::Disabled => defmt::write!(fmt, "disabled"),
166 CrcLength::Bit8 => defmt::write!(fmt, "8 bit"),
167 CrcLength::Bit16 => defmt::write!(fmt, "16 bit"),
168 }
169 }
170}
171
172impl Display for CrcLength {
173 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
174 match self {
175 CrcLength::Disabled => write!(f, "disabled"),
176 CrcLength::Bit8 => write!(f, "8 bit"),
177 CrcLength::Bit16 => write!(f, "16 bit"),
178 }
179 }
180}
181
182#[derive(Clone, Copy, Debug, PartialEq)]
184pub enum FifoState {
185 Full,
187 Empty,
189 Occupied,
191}
192
193#[cfg(feature = "defmt")]
194#[cfg(target_os = "none")]
195impl defmt::Format for FifoState {
196 #[cfg(feature = "defmt")]
197 fn format(&self, fmt: defmt::Formatter) {
198 match self {
199 FifoState::Empty => defmt::write!(fmt, "Empty"),
200 FifoState::Full => defmt::write!(fmt, "Full"),
201 FifoState::Occupied => defmt::write!(fmt, "Occupied"),
202 }
203 }
204}
205
206impl Display for FifoState {
207 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
208 match self {
209 FifoState::Empty => write!(f, "Empty"),
210 FifoState::Full => write!(f, "Full"),
211 FifoState::Occupied => write!(f, "Occupied"),
212 }
213 }
214}
215
216#[bitfield(u8, new = false, order = Msb)]
226pub struct StatusFlags {
227 #[bits(1)]
228 _padding: u8,
229
230 #[bits(1, access = RO)]
232 pub rx_dr: bool,
233
234 #[bits(1, access = RO)]
236 pub tx_ds: bool,
237
238 #[bits(1, access = RO)]
240 pub tx_df: bool,
241
242 #[bits(3, access = RO)]
243 pub(crate) rx_pipe: u8,
244
245 #[bits(1, access = RO)]
246 pub(crate) tx_full: bool,
247}
248
249#[cfg(feature = "defmt")]
250impl defmt::Format for StatusFlags {
251 fn format(&self, fmt: defmt::Formatter) {
252 defmt::write!(
253 fmt,
254 "StatusFlags rx_dr: {}, tx_ds: {}, tx_df: {}",
255 self.rx_dr,
256 self.tx_ds,
257 self.tx_df
258 )
259 }
260}
261
262impl StatusFlags {
263 pub(crate) const IRQ_MASK: u8 = 0x70;
265
266 pub fn new() -> Self {
269 Self::from_bits(0x70)
270 }
271
272 pub fn with_rx_dr(self, flag: bool) -> Self {
274 let new_val = self.into_bits() & !(1 << Self::RX_DR_OFFSET);
275 if flag {
276 Self::from_bits(new_val | (1 << Self::RX_DR_OFFSET))
277 } else {
278 Self::from_bits(new_val)
279 }
280 }
281
282 pub fn with_tx_ds(self, flag: bool) -> Self {
284 let new_val = self.into_bits() & !(1 << Self::TX_DS_OFFSET);
285 if flag {
286 Self::from_bits(new_val | (1 << Self::TX_DS_OFFSET))
287 } else {
288 Self::from_bits(new_val)
289 }
290 }
291
292 pub fn with_tx_df(self, flag: bool) -> Self {
294 let new_val = self.into_bits() & !(1 << Self::TX_DF_OFFSET);
295 if flag {
296 Self::from_bits(new_val | (1 << Self::TX_DF_OFFSET))
297 } else {
298 Self::from_bits(new_val)
299 }
300 }
301}
302
303impl Display for StatusFlags {
304 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
305 write!(
306 f,
307 "StatusFlags rx_dr: {}, tx_ds: {}, tx_df: {}",
308 self.rx_dr(),
309 self.tx_ds(),
310 self.tx_df()
311 )
312 }
313}
314
315#[cfg(test)]
316mod test {
317 use crate::StatusFlags;
318
319 use super::{CrcLength, DataRate, FifoState, PaLevel};
320 extern crate std;
321 use std::{format, string::String};
322
323 fn display_crc(param: CrcLength, expected: String) -> bool {
324 format!("{param}") == expected
325 }
326
327 #[test]
328 fn crc_8bit() {
329 assert!(display_crc(CrcLength::Bit8, String::from("8 bit")));
330 }
331
332 #[test]
333 fn crc_16bit() {
334 assert!(display_crc(CrcLength::Bit16, String::from("16 bit")));
335 }
336
337 #[test]
338 fn crc_disable() {
339 assert!(display_crc(CrcLength::Disabled, String::from("disabled")));
340 }
341
342 fn display_fifo_state(param: FifoState, expected: String) -> bool {
343 format!("{param}") == expected
344 }
345
346 #[test]
347 fn fifo_state_empty() {
348 assert!(display_fifo_state(FifoState::Empty, String::from("Empty")));
349 }
350
351 #[test]
352 fn fifo_state_full() {
353 assert!(display_fifo_state(FifoState::Full, String::from("Full")));
354 }
355
356 #[test]
357 fn fifo_state_occupied() {
358 assert!(display_fifo_state(
359 FifoState::Occupied,
360 String::from("Occupied")
361 ));
362 }
363
364 fn display_data_rate(param: DataRate, expected: String) -> bool {
365 format!("{param}") == expected
366 }
367
368 #[test]
369 fn data_rate_1mbps() {
370 assert!(display_data_rate(DataRate::Mbps1, String::from("1 Mbps")));
371 }
372
373 #[test]
374 fn data_rate_2mbps() {
375 assert!(display_data_rate(DataRate::Mbps2, String::from("2 Mbps")));
376 }
377
378 #[test]
379 fn data_rate_250kbps() {
380 assert!(display_data_rate(
381 DataRate::Kbps250,
382 String::from("250 Kbps")
383 ));
384 }
385
386 fn display_pa_level(param: PaLevel, expected: String) -> bool {
387 format!("{param}") == expected
388 }
389
390 #[test]
391 fn pa_level_min() {
392 assert!(display_pa_level(PaLevel::Min, String::from("Min")));
393 }
394
395 #[test]
396 fn pa_level_low() {
397 assert!(display_pa_level(PaLevel::Low, String::from("Low")));
398 }
399
400 #[test]
401 fn pa_level_high() {
402 assert!(display_pa_level(PaLevel::High, String::from("High")));
403 }
404
405 #[test]
406 fn pa_level_max() {
407 assert!(display_pa_level(PaLevel::Max, String::from("Max")));
408 }
409
410 #[test]
411 fn display_flags() {
412 assert_eq!(
413 format!("{}", StatusFlags::default()),
414 String::from("StatusFlags rx_dr: false, tx_ds: false, tx_df: false")
415 );
416 }
417
418 fn set_flags(rx_dr: bool, tx_ds: bool, tx_df: bool) {
419 let flags = StatusFlags::default()
420 .with_rx_dr(rx_dr)
421 .with_tx_ds(tx_ds)
422 .with_tx_df(tx_df);
423 assert_eq!(flags.rx_dr(), rx_dr);
424 assert_eq!(flags.tx_ds(), tx_ds);
425 assert_eq!(flags.tx_df(), tx_df);
426 }
427
428 #[test]
429 fn flags_0x50() {
430 set_flags(true, false, true);
431 }
432
433 #[test]
434 fn flags_0x20() {
435 set_flags(false, true, false);
436 }
437}