Port of the nRF24l01+ library of these dudes. Not GPLed, so yeah, you can use it. Copyright (c) 2007 Stefan Engelke <mbox@stefanengelke.de> Some parts copyright (c) 2012 Eric Brundick <spirilis [at] linux dot com>

Files at this revision

API Documentation at this revision

Comitter:
heroic
Date:
Tue May 28 03:48:04 2013 +0000
Commit message:
Initial commit to mbedland: port of the Energia nRF24l01+ library as ported to mbed.; ; This is what happens if you use a GPLv3 license, guys: people who want to use the chip have to write their own, or port someone else's MIT licensed one.

Changed in this revision

Enrf24.cpp Show annotated file Show diff for this revision Revisions of this file
Enrf24.h Show annotated file Show diff for this revision Revisions of this file
nRF24L01.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Enrf24.cpp	Tue May 28 03:48:04 2013 +0000
@@ -0,0 +1,556 @@
+/* nRF24L01+ I/O for mbed
+ * Ported by Jas Strong <jasmine@heroicrobotics.com>
+ *
+ * Copyright (c) 2013 Eric Brundick <spirilis [at] linux dot com>
+ *  Permission is hereby granted, free of charge, to any person 
+ *  obtaining a copy of this software and associated documentation 
+ *  files (the "Software"), to deal in the Software without 
+ *  restriction, including without limitation the rights to use, copy, 
+ *  modify, merge, publish, distribute, sublicense, and/or sell copies 
+ *  of the Software, and to permit persons to whom the Software is 
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be 
+ *  included in all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+ *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+ *  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+ *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ *  DEALINGS IN THE SOFTWARE.
+ */
+
+#include "mbed.h"
+#include <stdint.h>
+#include "Enrf24.h"
+
+/* Constructor */
+Enrf24::Enrf24(PinName cePin, PinName csnPin, PinName irqPin, PinName miso, PinName mosi, PinName sck) :
+    _cePin(cePin),
+    _csnPin(csnPin),
+    _irqPin(irqPin),
+    _miso(miso),
+    _mosi(mosi),
+    _sck(sck),
+    _spi(mosi, miso, sck)
+{
+
+  rf_status = 0;
+  rf_addr_width = 5;
+  txbuf_len = 0;
+  readpending = 0;
+}
+
+/* Initialization */
+void Enrf24::begin(uint32_t datarate, uint8_t channel)
+{
+  _cePin = 0;
+  _csnPin = 1;
+
+  _spi.format(8,0);
+  _spi.frequency(2000000);
+    
+  _spi.write(0);  // Strawman transfer, fixes USCI issue on G2553
+
+  // Is the transceiver present/alive?
+  if (!_isAlive())
+    return;  // Nothing more to do here...
+
+  // Init certain registers
+  _writeReg(RF24_CONFIG, 0x00);  // Deep power-down, everything disabled
+  _writeReg(RF24_EN_AA, 0x03);
+  _writeReg(RF24_EN_RXADDR, 0x03);
+  _writeReg(RF24_RF_SETUP, 0x00);
+  _writeReg(RF24_STATUS, ENRF24_IRQ_MASK);  // Clear all IRQs
+  _writeReg(RF24_DYNPD, 0x03);
+  _writeReg(RF24_FEATURE, RF24_EN_DPL);  // Dynamic payloads enabled by default
+
+  // Set all parameters
+  if (channel > 125)
+    channel = 125;
+  deepsleep();
+  _issueCmd(RF24_FLUSH_TX);
+  _issueCmd(RF24_FLUSH_RX);
+  readpending = 0;
+  _irq_clear(ENRF24_IRQ_MASK);
+  setChannel(channel);
+  setSpeed(datarate);
+  setTXpower();
+  setAutoAckParams();
+  setAddressLength(rf_addr_width);
+  setCRC(true);  // Default = CRC on, 8-bit
+}
+
+/* Formal shut-down/clearing of library state */
+void Enrf24::end()
+{
+  txbuf_len = 0;
+  rf_status = 0;
+  rf_addr_width = 5;
+
+  if (!_isAlive())
+    return;
+  deepsleep();
+  _issueCmd(RF24_FLUSH_TX);
+  _issueCmd(RF24_FLUSH_RX);
+  readpending = 0;
+  _irq_clear(ENRF24_IRQ_MASK);
+  _cePin = 0;
+  _csnPin = 1;
+}
+
+/* Basic SPI I/O */
+uint8_t Enrf24::_readReg(uint8_t addr)
+{
+  uint8_t result;
+
+  _csnPin = 0;
+  rf_status = _spi.write(RF24_R_REGISTER | addr);
+  result = _spi.write(RF24_NOP);
+  _csnPin = 1;
+  return result;
+}
+
+void Enrf24::_readRegMultiLSB(uint8_t addr, uint8_t *buf, size_t len)
+{
+  uint8_t i;
+  _csnPin = 0;
+  rf_status = _spi.write(RF24_R_REGISTER | addr);
+  for (i=0; i<len; i++) {
+    buf[len-i-1] = _spi.write(RF24_NOP);
+  }
+  _csnPin = 1;
+}
+
+void Enrf24::_writeReg(uint8_t addr, uint8_t val)
+{
+  _csnPin=0;
+  rf_status = _spi.write(RF24_W_REGISTER | addr);
+  _spi.write(val);
+  _csnPin=1;
+}
+
+void Enrf24::_writeRegMultiLSB(uint8_t addr, uint8_t *buf, size_t len)
+{
+  size_t i;
+
+  _csnPin = 0;
+  rf_status = _spi.write(RF24_W_REGISTER | addr);
+  for (i=0; i<len; i++) {
+    _spi.write(buf[len-i-1]);
+  }
+  _csnPin = 1;
+}
+
+void Enrf24::_issueCmd(uint8_t cmd)
+{
+  _csnPin=0;
+  rf_status = _spi.write(cmd);
+  _csnPin=1;
+}
+
+void Enrf24::_issueCmdPayload(uint8_t cmd, uint8_t *buf, size_t len)
+{
+  size_t i;
+
+  _csnPin = 0;
+  rf_status = _spi.write(cmd);
+  for (i=0; i<len; i++) {
+    _spi.write(buf[i]);
+  }
+  _csnPin = 1;
+}
+
+void Enrf24::_readCmdPayload(uint8_t cmd, uint8_t *buf, size_t len, size_t maxlen)
+{
+  size_t i;
+
+  _csnPin = 0;
+  rf_status = _spi.write(cmd);
+  for (i=0; i<len; i++) {
+    if (i < maxlen) {
+      buf[i] = _spi.write(RF24_NOP);
+    } else {
+      _spi.write(RF24_NOP);  // Beyond maxlen bytes, just discard the remaining data.
+    }
+  }
+  _csnPin = 1;
+}
+
+boolean Enrf24::_isAlive()
+{
+  uint8_t aw;
+
+  aw = _readReg(RF24_SETUP_AW);
+  return ((aw & 0xFC) == 0x00 && (aw & 0x03) != 0x00);
+}
+
+uint8_t Enrf24::_irq_getreason()
+{
+  lastirq = _readReg(RF24_STATUS) & ENRF24_IRQ_MASK;
+  return lastirq;
+}
+
+// Get IRQ from last known rf_status update without querying module over SPI.
+uint8_t Enrf24::_irq_derivereason()
+{
+  lastirq = rf_status & ENRF24_IRQ_MASK;
+  return lastirq;
+}
+
+void Enrf24::_irq_clear(uint8_t irq)
+{
+  _writeReg(RF24_STATUS, irq & ENRF24_IRQ_MASK);
+}
+
+#define ENRF24_CFGMASK_CRC(a) (a & (RF24_EN_CRC | RF24_CRCO))
+
+void Enrf24::_readTXaddr(uint8_t *buf)
+{
+  _readRegMultiLSB(RF24_TX_ADDR, buf, rf_addr_width);
+}
+
+void Enrf24::_writeRXaddrP0(uint8_t *buf)
+{
+  _writeRegMultiLSB(RF24_RX_ADDR_P0, buf, rf_addr_width);
+}
+
+
+/* nRF24 I/O maintenance--called as a "hook" inside other I/O functions to give
+ * the library a chance to take care of its buffers et al
+ */
+void Enrf24::_maintenanceHook()
+{
+  uint8_t i;
+
+  _irq_getreason();
+
+  if (lastirq & ENRF24_IRQ_TXFAILED) {
+    lastTXfailed = true;
+    _issueCmd(RF24_FLUSH_TX);
+    _irq_clear(ENRF24_IRQ_TXFAILED);
+  }
+
+  if (lastirq & ENRF24_IRQ_TX) {
+    lastTXfailed = false;
+    _irq_clear(ENRF24_IRQ_TX);
+  }
+
+  if (lastirq & ENRF24_IRQ_RX) {
+    if ( !(_readReg(RF24_FIFO_STATUS) & RF24_RX_FULL) ) {  /* Don't feel it's necessary
+                                                            * to be notified of new
+                                                            * incoming packets if the RX
+                                                            * queue is full.
+                                                            */
+      _irq_clear(ENRF24_IRQ_RX);
+    }
+
+    /* Check if RX payload is 0-byte or >32byte (erroneous conditions)
+     * Also check if data was received on pipe#0, which we are ignoring.
+     * The reason for this is pipe#0 is needed for receiving AutoACK acknowledgements,
+     * its address gets reset to the module's default and we do not care about data
+     * coming in to that address...
+     */
+    _readCmdPayload(RF24_R_RX_PL_WID, &i, 1, 1);
+    if (i == 0 || i > 32 || ((rf_status & 0x0E) >> 1) == 0) {
+                             /* Zero-width RX payload is an error that happens a lot
+                              * with non-AutoAck, and must be cleared with FLUSH_RX.
+                              * Erroneous >32byte packets are a similar phenomenon.
+                              */
+      _issueCmd(RF24_FLUSH_RX);
+      _irq_clear(ENRF24_IRQ_RX);
+      readpending = 0;
+    } else {
+      readpending = 1;
+    }
+    // Actual scavenging of RX queues is performed by user-directed use of read().
+  }
+}
+
+
+
+/* Public functions */
+boolean Enrf24::available(boolean checkIrq)
+{
+  if (checkIrq && _irqPin && readpending == 0)
+    return false;
+  _maintenanceHook();
+  if ( !(_readReg(RF24_FIFO_STATUS) & RF24_RX_EMPTY) ) {
+    return true;
+  }
+  if (readpending) {
+    return true;
+  }
+  return false;
+}
+
+size_t Enrf24::read(void *inbuf, uint8_t maxlen)
+{
+  uint8_t *buf = (uint8_t *)inbuf;
+  uint8_t plwidth;
+
+  _maintenanceHook();
+  readpending = 0;
+  if ((_readReg(RF24_FIFO_STATUS) & RF24_RX_EMPTY) || maxlen < 1) {
+    return 0;
+  }
+  _readCmdPayload(RF24_R_RX_PL_WID, &plwidth, 1, 1);
+  _readCmdPayload(RF24_R_RX_PAYLOAD, buf, plwidth, maxlen);
+  buf[plwidth] = '\0';  // Zero-terminate in case this is a string.
+  if (_irq_derivereason() & ENRF24_IRQ_RX) {
+    _irq_clear(ENRF24_IRQ_RX);
+  }
+
+  return (size_t) plwidth;
+}
+
+// Perform TX of current ring-buffer contents
+void Enrf24::flush()
+{
+  uint8_t reg, addrbuf[5];
+  boolean enaa=false, origrx=false;
+
+  if (!txbuf_len)
+    return;  // Zero-length buffer?  Nothing to send!
+
+  reg = _readReg(RF24_FIFO_STATUS);
+  if (reg & BIT5) {  // RF24_TX_FULL #define is BIT0, which is not the correct bit for FIFO_STATUS.
+    return;  // Should never happen, but nonetheless a precaution to take.
+  }
+
+  _maintenanceHook();
+
+  if (reg & RF24_TX_REUSE) {
+    // If somehow TX_REUSE is enabled, we need to flush the TX queue before loading our new payload.
+    _issueCmd(RF24_FLUSH_TX);
+  }
+
+  if (_readReg(RF24_EN_AA) & 0x01 && (_readReg(RF24_RF_SETUP) & 0x28) != 0x20) {
+    /* AutoACK enabled, must write TX addr to RX pipe#0
+     * Note that 250Kbps doesn't support auto-ack, so we check RF24_RF_SETUP to verify that.
+     */
+    enaa = true;
+    _readTXaddr(addrbuf);
+    _writeRXaddrP0(addrbuf);
+  }
+
+  reg = _readReg(RF24_CONFIG);
+  if ( !(reg & RF24_PWR_UP) ) {
+    _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP);
+    wait_us(5000);  // 5ms delay required for nRF24 oscillator start-up
+  }
+  if (reg & RF24_PRIM_RX) {
+    origrx=true;
+    _cePin = 0;
+    _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP);
+  }
+
+  _issueCmdPayload(RF24_W_TX_PAYLOAD, txbuf, txbuf_len);
+  _cePin = 1;
+  wait_us(30);
+  _cePin = 0;
+
+  txbuf_len = 0;  // Reset TX ring buffer
+
+  while (_irqPin)  // Wait until IRQ fires
+    ;
+  // IRQ fired
+  _maintenanceHook();  // Handle/clear IRQ
+
+  // Purge Pipe#0 address (set to module's power-up default)
+  if (enaa) {
+    addrbuf[0] = 0xE7; addrbuf[1] = 0xE7; addrbuf[2] = 0xE7; addrbuf[3] = 0xE7; addrbuf[4] = 0xE7;
+    _writeRXaddrP0(addrbuf);
+  }
+
+  // If we were in RX mode before writing, return back to RX mode.
+  if (origrx) {
+    enableRX();
+  }
+}
+
+void Enrf24::purge()
+{
+  txbuf_len = 0;
+}
+
+size_t Enrf24::write(uint8_t c)
+{
+  if (txbuf_len == 32) {  // If we're trying to stuff an already-full buffer...
+    flush();  // Blocking OTA TX
+  }
+
+  txbuf[txbuf_len] = c;
+  txbuf_len++;
+
+  return 1;
+}
+
+uint8_t Enrf24::radioState()
+{
+  uint8_t reg;
+
+  if (!_isAlive())
+    return ENRF24_STATE_NOTPRESENT;
+  
+  reg = _readReg(RF24_CONFIG);
+  if ( !(reg & RF24_PWR_UP) )
+    return ENRF24_STATE_DEEPSLEEP;
+
+  // At this point it's either Standby-I, II or PRX.
+  if (reg & RF24_PRIM_RX) {
+    if (_cePin)
+      return ENRF24_STATE_PRX;
+    // PRIM_RX=1 but CE=0 is a form of idle state.
+    return ENRF24_STATE_IDLE;
+  }
+  // Check if TX queue is empty, if so it's idle, if not it's PTX.
+  if (_readReg(RF24_FIFO_STATUS) & RF24_TX_EMPTY)
+    return ENRF24_STATE_IDLE;
+  return ENRF24_STATE_PTX;
+}
+
+void Enrf24::deepsleep()
+{
+  uint8_t reg;
+
+  reg = _readReg(RF24_CONFIG);
+  if (reg & (RF24_PWR_UP | RF24_PRIM_RX)) {
+    _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg));
+  }
+  _cePin = 0;
+}
+
+void Enrf24::enableRX()
+{
+  uint8_t reg;
+
+  reg = _readReg(RF24_CONFIG);
+  _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP | RF24_PRIM_RX);
+  _cePin = 1;
+
+  if ( !(reg & RF24_PWR_UP) ) {  // Powering up from deep-sleep requires 5ms oscillator start delay
+    wait(5 / 1000);
+  }
+}
+
+void Enrf24::disableRX()
+{
+  uint8_t reg;
+
+  _cePin = 0;
+
+  reg = _readReg(RF24_CONFIG);
+  if (reg & RF24_PWR_UP) {  /* Keep us in standby-I if we're coming from RX mode, otherwise stay
+                             * in deep-sleep if we call this while already in PWR_UP=0 mode.
+                             */
+    _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP);
+  } else {
+    _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg));
+  }
+}
+
+void Enrf24::autoAck(boolean onoff)
+{
+  uint8_t reg;
+
+  reg = _readReg(RF24_EN_AA);
+  if (onoff) {
+    if ( !(reg & 0x01) || !(reg & 0x02) ) {
+      _writeReg(RF24_EN_AA, 0x03);
+    }
+  } else {
+    if (reg & 0x03) {
+      _writeReg(RF24_EN_AA, 0x00);
+    }
+  }
+}
+
+void Enrf24::setChannel(uint8_t channel)
+{
+  if (channel > 125)
+    channel = 125;
+  _writeReg(RF24_RF_CH, channel);
+}
+
+void Enrf24::setTXpower(int8_t dBm)
+{
+  uint8_t reg, pwr;
+
+  reg = _readReg(RF24_RF_SETUP) & 0xF8;  // preserve RF speed settings
+  pwr = 0x03;
+  if (dBm < 0)
+    pwr = 0x02;
+  if (dBm < -6)
+    pwr = 0x01;
+  if (dBm < -12)
+    pwr = 0x00;
+  _writeReg(RF24_RF_SETUP, reg | (pwr << 1));
+}
+
+void Enrf24::setSpeed(uint32_t rfspeed)
+{
+  uint8_t reg, spd;
+
+  reg = _readReg(RF24_RF_SETUP) & 0xD7;  // preserve RF power settings
+  spd = 0x01;
+  if (rfspeed < 2000000)
+    spd = 0x00;
+  if (rfspeed < 1000000)
+    spd = 0x04;
+  _writeReg(RF24_RF_SETUP, reg | (spd << 3));
+}
+
+void Enrf24::setCRC(boolean onoff, boolean crc16bit)
+{
+  uint8_t reg, crcbits=0;
+
+  reg = _readReg(RF24_CONFIG) & 0xF3;  // preserve IRQ mask, PWR_UP/PRIM_RX settings
+  if (onoff)
+    crcbits |= RF24_EN_CRC;
+  if (crc16bit)
+    crcbits |= RF24_CRCO;
+  _writeReg(RF24_CONFIG, reg | crcbits);
+}
+
+void Enrf24::setAutoAckParams(uint8_t autoretry_count, uint16_t autoretry_timeout)
+{
+  uint8_t setup_retr=0;
+
+  setup_retr = autoretry_count & 0x0F;
+  autoretry_timeout -= 250;
+  setup_retr |= ((autoretry_timeout / 250) & 0x0F) << 4;
+  _writeReg(RF24_SETUP_RETR, setup_retr);
+}
+
+void Enrf24::setAddressLength(size_t len)
+{
+  if (len < 3)
+    len = 3;
+  if (len > 5)
+    len = 5;
+
+  _writeReg(RF24_SETUP_AW, len-2);
+  rf_addr_width = len;
+}
+
+void Enrf24::setRXaddress(void *rxaddr)
+{
+  _writeRegMultiLSB(RF24_RX_ADDR_P1, (uint8_t*)rxaddr, rf_addr_width);
+}
+
+void Enrf24::setTXaddress(void *rxaddr)
+{
+  _writeRegMultiLSB(RF24_TX_ADDR, (uint8_t*)rxaddr, rf_addr_width);
+}
+
+boolean Enrf24::rfSignalDetected()
+{
+  uint8_t rpd;
+
+  rpd = _readReg(RF24_RPD);
+  return (boolean)rpd;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Enrf24.h	Tue May 28 03:48:04 2013 +0000
@@ -0,0 +1,164 @@
+/* nRF24L01+ I/O for mbed
+ * Ported by Jas Strong <jasmine@heroicrobotics.com>
+ *
+ * Copyright (c) 2013 Eric Brundick <spirilis [at] linux dot com>
+ *  Permission is hereby granted, free of charge, to any person 
+ *  obtaining a copy of this software and associated documentation 
+ *  files (the "Software"), to deal in the Software without 
+ *  restriction, including without limitation the rights to use, copy, 
+ *  modify, merge, publish, distribute, sublicense, and/or sell copies 
+ *  of the Software, and to permit persons to whom the Software is 
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be 
+ *  included in all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+ *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+ *  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+ *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ *  DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _ENRF24_H
+#define _ENRF24_H
+
+#define ENRF24_LIBRARY_VERSION 1.5
+
+#include "mbed.h"
+#include <stdint.h>
+#include "nRF24L01.h"
+
+#ifndef BITF
+  #define BIT0                (0x0001)
+  #define BIT1                (0x0002)
+  #define BIT2                (0x0004)
+  #define BIT3                (0x0008)
+  #define BIT4                (0x0010)
+  #define BIT5                (0x0020)
+  #define BIT6                (0x0040)
+  #define BIT7                (0x0080)
+  #define BIT8                (0x0100)
+  #define BIT9                (0x0200)
+  #define BITA                (0x0400)
+  #define BITB                (0x0800)
+  #define BITC                (0x1000)
+  #define BITD                (0x2000)
+  #define BITE                (0x4000)
+  #define BITF                (0x8000)
+#endif
+
+/* Constants for speed, radio state */
+#define ENRF24_STATE_NOTPRESENT 0
+#define ENRF24_STATE_DEEPSLEEP 1
+#define ENRF24_STATE_IDLE 2
+#define ENRF24_STATE_PTX 3
+#define ENRF24_STATE_PRX 4
+
+/* Internal IRQ handling */
+#define ENRF24_IRQ_TX       0x20
+#define ENRF24_IRQ_RX       0x40
+#define ENRF24_IRQ_TXFAILED 0x10
+#define ENRF24_IRQ_MASK     0x70
+
+#define ENRF24_CFGMASK_IRQ 0
+
+typedef uint8_t boolean;
+
+
+
+/* Class definition--inherits from Print so we have .print() functions */
+class Enrf24 {
+  public:
+    boolean lastTXfailed;
+
+    Enrf24(PinName cePin, PinName csnPin, PinName irqPin, PinName miso, PinName mosi, PinName sck);
+    void begin(uint32_t datarate=1000000, uint8_t channel=0);  // Specify bitrate & channel
+    void end();      // Shut it off, clear the library's state
+
+    // I/O
+    boolean available(boolean checkIrq=false);  // Check if incoming data is ready to be read
+    size_t read(void *inbuf, uint8_t maxlen=32);  /* Read contents of RX buffer up to
+                                                   * 'maxlen' bytes, return final length.
+                                                   * 'inbuf' should be maxlen+1 since a
+                                                   * null '\0' is tacked onto the end.
+                                                   */
+    virtual size_t write(uint8_t);  // Single-byte write, implements TX ring-buffer & auto-send
+    //using Print::write;  // Includes the multi-byte write for repeatedly hitting write(uint8_t)
+    void flush();    // Force transmission of TX ring buffer contents
+    void purge();    // Ignore TX ring buffer contents, return ring pointer to 0.
+
+    // Power-state related stuff-
+    uint8_t radioState();  // Evaluate current state of the transceiver (see ENRF24_STATE_* defines)
+    void deepsleep();  // Enter POWERDOWN mode, ~0.9uA power consumption
+    void enableRX();   // Enter PRX mode (~14mA)
+    void disableRX();  /* Disable PRX mode (PRIM_RX bit in CONFIG register)
+                        * Note this won't necessarily push the transceiver into deep sleep, but rather
+                        * an idle standby mode where its internal oscillators are ready & running but
+                        * the RF transceiver PLL is disabled.  ~26uA power consumption.
+                        */
+
+    // Custom tweaks to RF parameters, packet parameters
+    void autoAck(boolean onoff=true);  // Enable/disable auto-acknowledgements (enabled by default)
+    void setChannel(uint8_t channel);
+    void setTXpower(int8_t dBm=0);  // Only a few values supported by this (0, -6, -12, -18 dBm)
+    void setSpeed(uint32_t rfspeed);  // Set 250000, 1000000, 2000000 speeds.
+    void setCRC(boolean onoff, boolean crc16bit=false); /* Enable/disable CRC usage inside nRF24's
+                                                         * hardware packet engine, specify 8 or
+                                                         * 16-bit CRC.
+                                                         */
+    // Set AutoACK retry count, timeout params (0-15, 250-4000 respectively)
+    void setAutoAckParams(uint8_t autoretry_count=15, uint16_t autoretry_timeout=2000);
+
+    // Protocol addressing -- receive, transmit addresses
+    void setAddressLength(size_t len);  // Valid parameters = 3, 4 or 5.  Defaults to 5.
+    void setRXaddress(void *rxaddr);    // 3-5 byte RX address loaded into pipe#1
+    void setTXaddress(void *txaddr);    // 3-5 byte TX address loaded into TXaddr register
+    
+    // Miscellaneous feature
+    boolean rfSignalDetected();  /* Read RPD register to determine if transceiver has presently detected an RF signal
+                                  * of -64dBm or greater.  Only works in PRX (enableRX()) mode.
+                                  */
+
+  private:
+    uint8_t rf_status;
+    uint8_t rf_channel;
+    uint8_t rf_speed;  // Stored in native RF_SETUP register format
+    uint8_t rf_addr_width;
+    uint8_t txbuf_len;
+    uint8_t txbuf[32];
+    uint8_t lastirq, readpending;
+    DigitalOut _cePin, _csnPin, _mosi, _sck;
+    DigitalIn _miso, _irqPin;
+    SPI _spi;
+
+    uint8_t _readReg(uint8_t addr);
+    void _readRegMultiLSB(uint8_t addr, uint8_t *buf, size_t len);
+    void _writeReg(uint8_t addr, uint8_t val);
+    void _writeRegMultiLSB(uint8_t addr, uint8_t *buf, size_t len);
+    void _issueCmd(uint8_t cmd);
+    void _readCmdPayload(uint8_t addr, uint8_t *buf, size_t len, size_t maxlen);
+    void _issueCmdPayload(uint8_t cmd, uint8_t *buf, size_t len);
+    uint8_t _irq_getreason();
+    uint8_t _irq_derivereason();  // Get IRQ status from rf_status w/o querying module over SPI.
+    void _irq_clear(uint8_t irq);
+    boolean _isAlive();
+    void _readTXaddr(uint8_t *buf);
+    void _writeRXaddrP0(uint8_t *buf);
+    void _maintenanceHook();  // Handles IRQs and purges RX queue when erroneous contents exist.
+
+/* Private planning:
+   Need to keep track of:
+    RF status (since we get it after every SPI communication, might as well store it)
+    RF channel (to refresh in order to reset PLOS_CNT)
+    RF speed (to determine if autoAck makes any sense, since it doesn't @ 250Kbps)
+    Address Length (to determine how many bytes to read out of set(RX|TX)address())
+    32-byte TX ring buffer
+    Ring buffer position
+ */
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nRF24L01.h	Tue May 28 03:48:04 2013 +0000
@@ -0,0 +1,121 @@
+/* nRF24L01.h
+ * Register definitions for manipulating the Nordic Semiconductor
+ * nRF24L01+ RF transceiver chipsets.
+ *
+
+    Copyright (c) 2007 Stefan Engelke <mbox@stefanengelke.de>
+    Some parts copyright (c) 2012 Eric Brundick <spirilis [at] linux dot com>
+
+    Permission is hereby granted, free of charge, to any person 
+    obtaining a copy of this software and associated documentation 
+    files (the "Software"), to deal in the Software without 
+    restriction, including without limitation the rights to use, copy, 
+    modify, merge, publish, distribute, sublicense, and/or sell copies 
+    of the Software, and to permit persons to whom the Software is 
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be 
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+    DEALINGS IN THE SOFTWARE.
+ */
+#ifndef _NRF24L01_H
+#define _NRF24L01_H
+
+/* Register Map */
+#define RF24_CONFIG      0x00
+#define RF24_EN_AA       0x01
+#define RF24_EN_RXADDR   0x02
+#define RF24_SETUP_AW    0x03
+#define RF24_SETUP_RETR  0x04
+#define RF24_RF_CH       0x05
+#define RF24_RF_SETUP    0x06
+#define RF24_STATUS      0x07
+#define RF24_OBSERVE_TX  0x08
+#define RF24_CD          0x09
+#define RF24_RPD         0x09
+#define RF24_RX_ADDR_P0  0x0A
+#define RF24_RX_ADDR_P1  0x0B
+#define RF24_RX_ADDR_P2  0x0C
+#define RF24_RX_ADDR_P3  0x0D
+#define RF24_RX_ADDR_P4  0x0E
+#define RF24_RX_ADDR_P5  0x0F
+#define RF24_TX_ADDR     0x10
+#define RF24_RX_PW_P0    0x11
+#define RF24_RX_PW_P1    0x12
+#define RF24_RX_PW_P2    0x13
+#define RF24_RX_PW_P3    0x14
+#define RF24_RX_PW_P4    0x15
+#define RF24_RX_PW_P5    0x16
+#define RF24_FIFO_STATUS 0x17
+#define RF24_DYNPD       0x1C
+#define RF24_FEATURE     0x1D
+
+/* Register Bits */
+#define RF24_MASK_RX_DR  BIT6
+#define RF24_MASK_TX_DS  BIT5
+#define RF24_MASK_MAX_RT BIT4
+#define RF24_EN_CRC      BIT3
+#define RF24_CRCO        BIT2
+#define RF24_PWR_UP      BIT1
+#define RF24_PRIM_RX     BIT0
+#define RF24_ENAA_P5     BIT5
+#define RF24_ENAA_P4     BIT4
+#define RF24_ENAA_P3     BIT3
+#define RF24_ENAA_P2     BIT2
+#define RF24_ENAA_P1     BIT1
+#define RF24_ENAA_P0     BIT0
+#define RF24_ERX_P5      BIT5
+#define RF24_ERX_P4      BIT4
+#define RF24_ERX_P3      BIT3
+#define RF24_ERX_P2      BIT2
+#define RF24_ERX_P1      BIT1
+#define RF24_ERX_P0      BIT0
+#define RF24_AW          BIT0
+#define RF24_ARD         BIT4
+#define RF24_ARC         BIT0
+#define RF24_PLL_LOCK    BIT4
+#define RF24_CONT_WAVE   BIT7
+#define RF24_RF_DR       BIT3
+#define RF24_RF_DR_LOW   BIT5
+#define RF24_RF_DR_HIGH  BIT3
+#define RF24_RF_PWR      BIT1
+#define RF24_LNA_HCURR   BIT0
+#define RF24_RX_DR       BIT6
+#define RF24_TX_DS       BIT5
+#define RF24_MAX_RT      BIT4
+#define RF24_RX_P_NO     BIT1
+#define RF24_TX_FULL     BIT0
+#define RF24_PLOS_CNT    BIT4
+#define RF24_ARC_CNT     BIT0
+#define RF24_TX_REUSE    BIT6
+#define RF24_FIFO_FULL   BIT5
+#define RF24_TX_EMPTY    BIT4
+#define RF24_RX_FULL     BIT1
+#define RF24_RX_EMPTY    BIT0
+#define RF24_EN_DPL      BIT2
+#define RF24_EN_ACK_PAY  BIT1
+#define RF24_EN_DYN_ACK  BIT0
+
+/* Instructions */
+#define RF24_R_REGISTER    0x00
+#define RF24_W_REGISTER    0x20
+#define RF24_REGISTER_MASK 0x1F
+#define RF24_R_RX_PAYLOAD  0x61
+#define RF24_W_TX_PAYLOAD  0xA0
+#define RF24_FLUSH_TX      0xE1
+#define RF24_FLUSH_RX      0xE2
+#define RF24_REUSE_TX_PL   0xE3
+#define RF24_R_RX_PL_WID   0x60
+#define RF24_W_ACK_PAYLOAD 0xA8
+#define RF24_W_TX_PAYLOAD_NOACK 0xB0
+#define RF24_NOP           0xFF
+
+#endif