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
use table::table;

/// nRF24l01 configuration
#[repr(C)]
pub struct Config {
    /// Channel in MHz as offset to 2.4 GHz
    pub channel: u8,
    /// TX addr
    pub txmac: [u8; 5],
    /// RX addr0
    pub mac0: [u8; 5],
    /// RX addr1
    pub mac1: [u8; 5],
    /// RX addr2..5
    pub mac2345: [u8; 4],
    /// Number of addrs to enable
    pub nrmacs: u8,
    /// Expected payload lengths
    pub maclen: [u8; 5],
}

/// Set configuration
pub fn set_config(config: &Config) {
    (table().nrf_config_set)(config as *const Config as *const ());
}

const R_CONFIG_EN_CRC: u8 = 0x08;

/// Start RX mode
pub fn rx(crc: bool) -> Rx {
    let config = if crc {
        R_CONFIG_EN_CRC
    } else {
        0
    };
    (table().nrf_rcv_pkt_start)(config);

    Rx
}

/// Do not construct yourself but use `rx()`
///
/// The instance of this types signifies that the radio is in RX mode.
pub struct Rx;

impl Drop for Rx {
    /// End RX mode
    fn drop(&mut self) {
        (table().nrf_rcv_pkt_end)();
    }
}

/// `Rx.poll()` result
pub enum RxError {
    /// No pkt received
    WouldBlock,
    /// No packet error while receiving
    NoPacket,
    /// Packet too large or corrupted
    Invalid,
}

impl Rx {
    /// Poll for next (non-encrypted) packet
    pub fn poll(&self) -> Result<Payload, RxError> {
        let mut buf = [0u8; 32];
        let maxsize = buf.len();
        let ptr = buf.as_mut_ptr();
        let len = (table().nrf_rcv_pkt_poll)(maxsize as isize, ptr);
        match len {
            _ if len > 0 && len <= maxsize as isize =>
                Ok(Payload::new(len as u8, buf)),
            0 => Err(RxError::WouldBlock),
            -1 => Err(RxError::Invalid),
            -2 => Err(RxError::NoPacket),
            _ => Err(RxError::Invalid),
        }
    }
}

/// Packet payload up to 32 bytes
pub struct Payload {
    buf: [u8; 32],
    len: u8,
}

impl Payload {
    /// Create packet from 32 bytes buffer and a length
    pub fn new(len: u8, buf: [u8; 32]) -> Self {
        Payload { buf, len }
    }

    /// Payload length
    pub fn len(&self) -> usize {
        self.len.into()
    }
}

impl AsRef<[u8]> for Payload {
    fn as_ref(&self) -> &[u8] {
        &self.buf[0..self.len()]
    }
}