1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! Status datastructures.
use crate::config::DataPipe;
#[cfg(feature = "micro-fmt")]
use ufmt::{uDebug, uWrite, Formatter};

/// Wrapper for the status value returned from the device.
/// Provides convenience methods and debug implemantions.
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct Status(u8);

/// Wrapper around the FIFO status.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct FIFOStatus(u8);

impl Status {
    /// Create a status obj with all the flags turned on.
    pub fn flags() -> Self {
        Self(0b01110000)
    }
    /// Returns the raw value represented by this struct.
    pub fn value(&self) -> u8 {
        self.0
    }
    /// Checks if the status is valid.
    pub fn is_valid(&self) -> bool {
        (self.0 >> 7) & 1 == 0
    }
    /// Indicates if there is data ready to be read.
    pub fn data_ready(&self) -> bool {
        (self.0 >> 6) & 1 != 0
    }
    /// Indicates whether data has been sent.
    pub fn data_sent(&self) -> bool {
        (self.0 >> 5) & 1 != 0
    }
    /// Indicates whether the max retries has been reached.
    /// Can only be true if auto acknowledgement is enabled.
    pub fn reached_max_retries(&self) -> bool {
        (self.0 >> 4) & 1 != 0
    }
    /// Returns data pipe number for the payload availbe for reading
    /// or None if RX FIFO is empty.
    pub fn data_pipe_available(&self) -> Option<DataPipe> {
        match (self.0 >> 1) & 0b111 {
            x @ 0..=5 => Some(x.into()),
            6 => panic!(),
            7 => None,
            _ => unreachable!(), // because we AND the value
        }
    }
    /// Indicates whether the transmission queue is full or not.
    pub fn tx_full(&self) -> bool {
        (self.0 & 0b1) != 0
    }
}

impl FIFOStatus {
    /// Returns `true` if there are availbe locations in transmission queue
    pub fn tx_full(&self) -> bool {
        (self.0 >> 5) & 1 != 0
    }

    /// Returns `true` if the transmission queue is empty
    pub fn tx_empty(&self) -> bool {
        (self.0 >> 4) & 1 != 0
    }

    /// Returns `true` if there are availbe locations in receive queue
    pub fn rx_full(&self) -> bool {
        (self.0 >> 1) & 1 != 0
    }

    /// Returns `true` if the receive queue is empty
    pub fn rx_empty(&self) -> bool {
        self.0 & 1 != 0
    }
}

impl From<u8> for Status {
    fn from(t: u8) -> Self {
        Status(t)
    }
}

impl From<u8> for FIFOStatus {
    fn from(t: u8) -> Self {
        FIFOStatus(t)
    }
}

impl core::fmt::Debug for Status {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        if !&self.is_valid() {
            f.write_str("Invalid status. Something went wrong during communication with nrf24l01")
        } else {
            let mut s = f.debug_struct("Status");
            let s = s.field("Data ready", &self.data_ready());
            let s = s.field("Data sent", &self.data_sent());
            let s = s.field("Reached max retries", &self.reached_max_retries());
            let s = match &self.data_pipe_available() {
                None => s.field("No data ready to be read in FIFO", &true),
                Some(pipe) => s.field("Data ready to be read on pipe", &pipe.pipe()),
            };
            let s = s.field("Transmission FIFO full", &self.tx_full());
            s.finish()
        }
    }
}

#[cfg(feature = "micro-fmt")]
impl uDebug for Status {
    fn fmt<W: ?Sized>(&self, f: &mut Formatter<'_, W>) -> core::result::Result<(), W::Error>
    where
        W: uWrite,
    {
        if !&self.is_valid() {
            f.write_str("Invalid status. Something went wrong during communication with nrf24l01")
        } else {
            let mut s = f.debug_struct("Status")?;
            let s = s.field("Data ready", &self.data_ready())?;
            let s = s.field("Data sent", &self.data_sent())?;
            let s = s.field("Reached max retries", &self.reached_max_retries())?;
            let s = match &self.data_pipe_available() {
                None => s.field("No data ready to be read in FIFO", &true)?,
                Some(pipe) => s.field("Data ready to be read on pipe", &pipe.pipe())?,
            };
            let s = s.field("Transmission FIFO full", &self.tx_full())?;
            s.finish()
        }
    }
}