diyembedded nrf24l01 tutorial 2 ported to mbed lpc1768

Dependencies:   mbed

See diyembedded tutorials for more info

-Pull down p20 for receive mode

-Pull up p20 for transmitter mode

Files at this revision

API Documentation at this revision

Comitter:
jeroen3
Date:
Sat Dec 08 22:11:23 2012 +0000
Commit message:
diyembedded.com nrf24l01 lib with shockburs tutorial 2 on mbed

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
nRF24L01P/nrf24l01.cpp Show annotated file Show diff for this revision Revisions of this file
nRF24L01P/nrf24l01.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 2286a98ea739 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Dec 08 22:11:23 2012 +0000
@@ -0,0 +1,129 @@
+#include "mbed.h"
+#include "nrf24l01.h"
+
+Serial pc(USBTX, USBRX); // tx, rx
+
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+DigitalIn     mode(p20);
+
+DigitalOut     nRF_CSN(p8);
+DigitalOut     nRF_CE(p11);
+DigitalIn     nRF_IRQ(p12);
+SPI                    nRF_spi(p5, p6, p7);
+
+int main() {
+    uint8_t dump[35];
+    unsigned char scratch[5];
+    pc.baud(115200);
+    pc.printf("mbed: nRF24L01 tranceiver\r\n");
+
+    #define _NRF24L01P_SPI_MAX_DATA_RATE     10000000
+    nRF_spi.frequency(_NRF24L01P_SPI_MAX_DATA_RATE/5);     // 2Mbit, 1/5th the maximum transfer rate for the SPI bus
+  nRF_spi.format(8,0);                                   // 8-bit, ClockPhase = 0, ClockPolarity = 0
+
+    //scratch[0] = 0x01;
+    //nrf24l01_write_register(nrf24l01_RF_SETUP, scratch , 1);    // -18 dbm, air rate 1 mbps
+    
+    pc.printf("Reading all registers:\r\n");
+    nrf24l01_get_all_registers(dump);
+    for(int i=0; i<sizeof(dump); i++){
+        pc.printf("0x%02x\r\n",dump[i]);
+    }
+    
+    /* "fork" */
+    if(mode){
+        // TX Mode
+        pc.printf("Set to transmitter mode p20 high\r\n");
+        //vars
+        unsigned char data; //register to hold letter sent and received
+        unsigned int count; //counter for for loop
+        // init
+        nrf24l01_initialize_debug(false, 1, true); //initialize the 24L01 to the debug configuration as TX, 1 data byte, and auto-ack enabled
+        //main program loop
+        while(1)
+        {
+            //check UART status register to see if data has been received.  if so, process
+            while(pc.readable())
+            {
+                data = pc.getc(); //get data from UART
+                nrf24l01_write_tx_payload(&data, 1, true); //transmit received char over RF
+
+                //wait until the packet has been sent or the maximum number of retries has been active
+                while(!(nrf24l01_irq_pin_active() && (nrf24l01_irq_tx_ds_active() || nrf24l01_irq_max_rt_active())));
+
+                //check to see if the maximum number of retries has been hit.  if not, wait for the RX device
+                // to send the char back.  if so, assume the packet is lost and send "*" back to UART
+                if(!nrf24l01_irq_max_rt_active())
+                {
+                    nrf24l01_irq_clear_all(); //clear all interrupts in the 24L01
+                    nrf24l01_set_as_rx(true); //change the device to an RX to get the character back from the other 24L01
+
+                    //wait a while to see if we get the data back (change the loop maximum and the lower if
+                    //  argument (should be loop maximum - 1) to lengthen or shorten this time frame
+                    for(count = 0; count < 25000; count++)
+                    {
+                        //check to see if the data has been received.  if so, get the data and exit the loop.
+                        //  if the loop is at its last count, assume the packet has been lost and set the data
+                        //  to go to the UART to "?".  If neither of these is true, keep looping.
+                        if((nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active()))
+                        {
+                            nrf24l01_read_rx_payload(&data, 1); //get the payload into data
+                            break;
+                        }
+                        
+                        //if loop is on its last iteration, assume packet has been lost.
+                        if(count == 24999)
+                            data = '?';
+                    }
+                    
+                    nrf24l01_irq_clear_all(); //clear interrupts again
+                    pc.printf("%c", data); //print the received data (or ? if none) to the screen
+                
+                    wait_us(130); //wait for receiver to come from standby to RX
+                    nrf24l01_set_as_tx(); //resume normal operation as a TX
+                }
+                else
+                {
+                    nrf24l01_flush_tx(); //get the unsent character out of the TX FIFO
+                    nrf24l01_irq_clear_all(); //clear all interrupts
+                    pc.printf("*"); //print "*" to the screen to show that the receiver did not receive the packet
+                }
+                                        
+                led1 = !led1; //toggle the on-board LED as visual indication that the loop has completed
+            }
+        }
+/* ########################################################################## */        
+    }else{
+        // RX Mode
+        pc.printf("Set to receiver mode p20 low\r\n");
+        unsigned char data; //register to hold letter received and sent
+        // Init
+        nrf24l01_initialize_debug(true, 1, true); //initialize the 24L01 to the debug configuration as RX, 1 data byte, and auto-ack enabled        
+        //main program loop
+        while(1)
+        {
+            //wait until a packet has been received
+            while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active()));
+            
+            nrf24l01_read_rx_payload(&data, 1); //read the packet into data
+            nrf24l01_irq_clear_all(); //clear all interrupts in the 24L01
+            
+            pc.putc(data);
+            wait_us(130); //wait for the other 24L01 to come from standby to RX
+            
+            nrf24l01_set_as_tx(); //change the device to a TX to send back from the other 24L01
+            nrf24l01_write_tx_payload(&data, 1, true); //transmit received char over RF
+            
+            //wait until the packet has been sent or the maximum number of retries has been reached
+            while(!(nrf24l01_irq_pin_active() && (nrf24l01_irq_tx_ds_active() || nrf24l01_irq_max_rt_active())));
+
+            nrf24l01_irq_clear_all(); //clear interrupts again
+            nrf24l01_set_as_rx(true); //resume normal operation as an RX
+
+            led1 = !led1; //toggle the on-board LED as visual indication that the loop has completed
+        }
+    }
+}
diff -r 000000000000 -r 2286a98ea739 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sat Dec 08 22:11:23 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/63cdd78b2dc1
\ No newline at end of file
diff -r 000000000000 -r 2286a98ea739 nRF24L01P/nrf24l01.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nRF24L01P/nrf24l01.cpp	Sat Dec 08 22:11:23 2012 +0000
@@ -0,0 +1,1037 @@
+/******************************************************************************
+*
+* File: nrf24l01.c
+* 
+* Copyright S. Brennen Ball, 2006-2007
+* 
+* The author provides no guarantees, warantees, or promises, implied or
+*    otherwise.  By using this software you agree to indemnify the author
+*     of any damages incurred by using it.
+*
+*****************************************************************************/
+
+#include "nrf24l01.h"
+#include "mbed.h"
+
+/* Extern DigitalPin objects for csn, irq and ce */
+extern DigitalOut     nRF_CSN;
+extern DigitalOut     nRF_CE;
+extern DigitalIn         nRF_IRQ;
+extern SPI                    nRF_spi;
+
+//Arguments except opt_rx_standby_mode fill the actual register they are named 
+//  after. Registers that do not need to be initialized are not included here.
+//The argument opt_rx_active_mode is only used if the user is initializing the
+//  24L01 as a receiver.  If the argument is false, the receiver will remain in
+//  standby mode and not monitor for packets.  If the argument is true, the CE
+//  pin will be set and the 24L01 will monitor for packets.  In TX mode, the value
+//  of this argument is insignificant.
+//If the user wants to leave any 1-byte register in its default state, simply put
+//  as that register's argument nrf24l01_<reg>_DEFAULT_VAL, where <reg> is the register
+//  name.
+//If the user wants to leave any of the 5-byte registers RX_ADDR_P0, RX_ADDR_P1, or 
+//  TX_ADDR in its default state, simply put NULL in the argument for that address value.
+void nrf24l01_initialize(unsigned char config,
+                         unsigned char opt_rx_active_mode,  
+                         unsigned char en_aa, 
+                         unsigned char en_rxaddr, 
+                         unsigned char setup_aw, 
+                         unsigned char setup_retr, 
+                         unsigned char rf_ch, 
+                         unsigned char rf_setup, 
+                         unsigned char * rx_addr_p0, 
+                         unsigned char * rx_addr_p1, 
+                         unsigned char rx_addr_p2, 
+                         unsigned char rx_addr_p3, 
+                         unsigned char rx_addr_p4, 
+                         unsigned char rx_addr_p5, 
+                         unsigned char * tx_addr, 
+                         unsigned char rx_pw_p0, 
+                         unsigned char rx_pw_p1, 
+                         unsigned char rx_pw_p2, 
+                         unsigned char rx_pw_p3, 
+                         unsigned char rx_pw_p4, 
+                         unsigned char rx_pw_p5)
+{
+    unsigned char data[5];
+
+    data[0] = en_aa;
+    nrf24l01_write_register(nrf24l01_EN_AA, data, 1);
+
+    data[0] = en_rxaddr;
+    nrf24l01_write_register(nrf24l01_EN_RXADDR, data, 1);
+
+    data[0] = setup_aw;
+    nrf24l01_write_register(nrf24l01_SETUP_AW, data, 1);
+
+    data[0] = setup_retr;
+    nrf24l01_write_register(nrf24l01_SETUP_RETR, data, 1);
+
+    data[0] = rf_ch;
+    nrf24l01_write_register(nrf24l01_RF_CH, data, 1);
+
+    data[0] = rf_setup;
+    nrf24l01_write_register(nrf24l01_RF_SETUP, data, 1);
+
+    if(rx_addr_p0 != NULL)
+        nrf24l01_set_rx_addr(rx_addr_p0, 5, 0);
+    else
+    {
+        data[0] = nrf24l01_RX_ADDR_P0_B0_DEFAULT_VAL;
+        data[1] = nrf24l01_RX_ADDR_P0_B1_DEFAULT_VAL;
+        data[2] = nrf24l01_RX_ADDR_P0_B2_DEFAULT_VAL;
+        data[3] = nrf24l01_RX_ADDR_P0_B3_DEFAULT_VAL;
+        data[4] = nrf24l01_RX_ADDR_P0_B4_DEFAULT_VAL;
+        
+        nrf24l01_set_rx_addr(data, 5, 0);
+    }
+
+    if(rx_addr_p1 != NULL)
+        nrf24l01_set_rx_addr(rx_addr_p1, 5, 1);
+    else
+    {
+        data[0] = nrf24l01_RX_ADDR_P1_B0_DEFAULT_VAL;
+        data[1] = nrf24l01_RX_ADDR_P1_B1_DEFAULT_VAL;
+        data[2] = nrf24l01_RX_ADDR_P1_B2_DEFAULT_VAL;
+        data[3] = nrf24l01_RX_ADDR_P1_B3_DEFAULT_VAL;
+        data[4] = nrf24l01_RX_ADDR_P1_B4_DEFAULT_VAL;
+        
+        nrf24l01_set_rx_addr(data, 5, 1);
+    }
+
+    data[0] = rx_addr_p2;
+    nrf24l01_set_rx_addr(data, 1, 2);
+
+    data[0] = rx_addr_p3;
+    nrf24l01_set_rx_addr(data, 1, 3);
+
+    data[0] = rx_addr_p4;
+    nrf24l01_set_rx_addr(data, 1, 4);
+
+    data[0] = rx_addr_p5;
+    nrf24l01_set_rx_addr(data, 1, 5);
+
+    if(tx_addr != NULL)
+        nrf24l01_set_tx_addr(tx_addr, 5);
+    else
+    {
+        data[0] = nrf24l01_TX_ADDR_B0_DEFAULT_VAL;
+        data[1] = nrf24l01_TX_ADDR_B1_DEFAULT_VAL;
+        data[2] = nrf24l01_TX_ADDR_B2_DEFAULT_VAL;
+        data[3] = nrf24l01_TX_ADDR_B3_DEFAULT_VAL;
+        data[4] = nrf24l01_TX_ADDR_B4_DEFAULT_VAL;
+        
+        nrf24l01_set_tx_addr(data, 5);
+    }
+
+    data[0] = rx_pw_p0;
+    nrf24l01_write_register(nrf24l01_RX_PW_P0, data, 1);
+
+    data[0] = rx_pw_p1;
+    nrf24l01_write_register(nrf24l01_RX_PW_P1, data, 1);
+
+    data[0] = rx_pw_p2;
+    nrf24l01_write_register(nrf24l01_RX_PW_P2, data, 1);
+
+    data[0] = rx_pw_p3;
+    nrf24l01_write_register(nrf24l01_RX_PW_P3, data, 1);
+
+    data[0] = rx_pw_p4;
+    nrf24l01_write_register(nrf24l01_RX_PW_P4, data, 1);
+
+    data[0] = rx_pw_p5;
+    nrf24l01_write_register(nrf24l01_RX_PW_P5, data, 1);
+
+    if((config & nrf24l01_CONFIG_PWR_UP) != 0)
+        nrf24l01_power_up_param(opt_rx_active_mode, config);
+    else
+        nrf24l01_power_down_param(config);
+}
+
+//initializes the 24L01 to all default values except the PWR_UP and PRIM_RX bits
+//this function also disables the auto-ack feature on the chip (EN_AA register is 0)
+//bool rx is true if the device should be a receiver and false if it should be
+//  a transmitter.
+//unsigned char payload_width is the payload width for pipe 0.  All other pipes
+//  are left in their default (disabled) state.
+//bool enable_auto_ack controls the auto ack feature on pipe 0.  If true, auto-ack will
+//  be enabled.  If false, auto-ack is disabled.
+void nrf24l01_initialize_debug(bool rx, unsigned char p0_payload_width, bool enable_auto_ack)
+{
+    unsigned char config;
+    unsigned char en_aa;
+    
+    config = nrf24l01_CONFIG_DEFAULT_VAL | nrf24l01_CONFIG_PWR_UP;
+    
+    if(enable_auto_ack != false)
+        en_aa = nrf24l01_EN_AA_ENAA_P0;
+    else
+        en_aa = nrf24l01_EN_AA_ENAA_NONE;
+    
+    if(rx == true)
+        config = config | nrf24l01_CONFIG_PRIM_RX;
+        
+    nrf24l01_initialize(config, 
+                        true,
+                        en_aa, 
+                        nrf24l01_EN_RXADDR_DEFAULT_VAL, 
+                        nrf24l01_SETUP_AW_DEFAULT_VAL, 
+                        nrf24l01_SETUP_RETR_DEFAULT_VAL, 
+                        nrf24l01_RF_CH_DEFAULT_VAL, 
+                        nrf24l01_RF_SETUP_DEFAULT_VAL,  
+                        NULL, 
+                        NULL, 
+                        nrf24l01_RX_ADDR_P2_DEFAULT_VAL, 
+                        nrf24l01_RX_ADDR_P3_DEFAULT_VAL, 
+                        nrf24l01_RX_ADDR_P4_DEFAULT_VAL, 
+                        nrf24l01_RX_ADDR_P5_DEFAULT_VAL, 
+                        NULL, 
+                        p0_payload_width, 
+                        nrf24l01_RX_PW_P1_DEFAULT_VAL, 
+                        nrf24l01_RX_PW_P2_DEFAULT_VAL, 
+                        nrf24l01_RX_PW_P3_DEFAULT_VAL, 
+                        nrf24l01_RX_PW_P4_DEFAULT_VAL, 
+                        nrf24l01_RX_PW_P5_DEFAULT_VAL);
+}
+
+//initializes only the CONFIG register and pipe 0's payload width
+//the primary purpose of this function is to allow users with microcontrollers with
+//  extremely small program memories to still be able to init their 24L01.  This code
+//  should have a smaller footprint than the above init functions.
+//when using this method, the 24L01 MUST have its default configuration loaded
+//  in all registers to work.  It is recommended that the device be reset or
+//  have its power cycled immediately before this code is run.
+//in normal circumstances, the user should use nrf24l01_initialize() rather than this
+//  function, since this function does not set all of the register values.
+void nrf24l01_initialize_debug_lite(bool rx, unsigned char p0_payload_width)
+{
+    unsigned char config;
+    
+    config = nrf24l01_CONFIG_DEFAULT_VAL;
+    
+    if(rx != false)
+        config |= nrf24l01_CONFIG_PRIM_RX;
+        
+    nrf24l01_write_register(nrf24l01_RX_PW_P0, &p0_payload_width, 1);
+    nrf24l01_power_up_param(true, config);
+}
+
+//powers up the 24L01 with all necessary delays
+//this function takes the existing contents of the CONFIG register and sets the PWR_UP 
+//the argument rx_active_mode is only used if the user is setting up the
+//  24L01 as a receiver.  If the argument is false, the receiver will remain in
+//  standby mode and not monitor for packets.  If the argument is true, the CE
+//  pin will be set and the 24L01 will monitor for packets.  In TX mode, the value
+//  of this argument is insignificant.
+//note: if the read value of the CONFIG register already has the PWR_UP bit set, this function
+//  exits in order to not make an unecessary register write.
+void nrf24l01_power_up(bool rx_active_mode)
+{
+    unsigned char config;
+    
+    nrf24l01_read_register(nrf24l01_CONFIG, &config, 1);
+    
+    if((config & nrf24l01_CONFIG_PWR_UP) != 0)
+        return;
+        
+    config |= nrf24l01_CONFIG_PWR_UP;
+    
+    nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
+    
+    delay_us(1500);
+    
+    if((config & nrf24l01_CONFIG_PRIM_RX) == 0)
+        nrf24l01_clear_ce();
+    else
+    {
+        if(rx_active_mode != false)
+            nrf24l01_set_ce();
+        else
+            nrf24l01_clear_ce();
+    }
+}
+
+//powers up the 24L01 with all necessary delays
+//this function allows the user to set the contents of the CONFIG register, but the function
+//  sets the PWR_UP bit in the CONFIG register, so the user does not need to.
+//the argument rx_active_mode is only used if the user is setting up the
+//  24L01 as a receiver.  If the argument is false, the receiver will remain in
+//  standby mode and not monitor for packets.  If the argument is true, the CE
+//  pin will be set and the 24L01 will monitor for packets.  In TX mode, the value
+//  of this argument is insignificant.
+void nrf24l01_power_up_param(bool rx_active_mode, unsigned char config)
+{
+//    unsigned char test, test2;
+    
+    config |= nrf24l01_CONFIG_PWR_UP;
+    
+    nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
+
+    delay_us(1500);
+
+    if((config & nrf24l01_CONFIG_PRIM_RX) == 0)
+        nrf24l01_clear_ce();
+    else
+    {
+        if(rx_active_mode != false)
+            nrf24l01_set_ce();
+        else
+            nrf24l01_clear_ce();
+    }
+}
+
+//powers down the 24L01
+//this function takes the existing contents of the CONFIG register and simply
+//  clears the PWR_UP bit in the CONFIG register.
+//note: if the read value of the CONFIG register already has the PWR_UP bit cleared, this 
+//  function exits in order to not make an unecessary register write.
+void nrf24l01_power_down()
+{
+    unsigned char config;
+    
+    nrf24l01_read_register(nrf24l01_CONFIG, &config, 1);
+    
+    if((config & nrf24l01_CONFIG_PWR_UP) == 0)
+        return;
+    
+    config &= (~nrf24l01_CONFIG_PWR_UP);
+    
+    nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
+
+    nrf24l01_clear_ce();
+}
+
+//powers down the 24L01
+//this function allows the user to set the contents of the CONFIG register, but the function
+//  clears the PWR_UP bit in the CONFIG register, so the user does not need to.
+void nrf24l01_power_down_param(unsigned char config)
+{
+    config &= (~nrf24l01_CONFIG_PWR_UP);
+    
+    nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
+
+    nrf24l01_clear_ce();
+}
+
+
+//sets up the 24L01 as a receiver with all necessary delays
+//this function takes the existing contents of the CONFIG register and sets the PRIM_RX 
+//  bit in the CONFIG register.
+//if the argument rx_active_mode is false, the receiver will remain in standby mode
+//  and not monitor for packets.  If the argument is true, the CE pin will be set 
+//  and the 24L01 will monitor for packets.
+//note: if the read value of the CONFIG register already has the PRIM_RX bit set, this function
+//  exits in order to not make an unecessary register write.
+void nrf24l01_set_as_rx(bool rx_active_mode)
+{
+    unsigned char config;
+    volatile unsigned char status;
+    
+    status = nrf24l01_read_register(0, &config, 1);
+
+    if((config & nrf24l01_CONFIG_PRIM_RX) != 0)
+        return;
+
+    config |= nrf24l01_CONFIG_PRIM_RX;
+    
+    nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
+
+    if(rx_active_mode != false)
+        nrf24l01_set_ce();
+    else
+        nrf24l01_clear_ce();
+}
+
+//sets up the 24L01 as a receiver with all necessary delays
+//this function allows the user to set the contents of the CONFIG register, but the function
+//  sets the PRIM_RX bit in the CONFIG register, so the user does not need to.
+//if the argument rx_active_mode is false, the receiver will remain in standby mode
+//  and not monitor for packets.  If the argument is true, the CE pin will be set 
+//  and the 24L01 will monitor for packets.
+void nrf24l01_set_as_rx_param(bool rx_active_mode, unsigned char config)
+{
+    config |= nrf24l01_CONFIG_PRIM_RX;
+    
+    if((config & nrf24l01_CONFIG_PWR_UP) != 0)
+        nrf24l01_power_up_param(rx_active_mode, config);
+    else
+        nrf24l01_power_down_param(config);
+}
+
+//takes a 24L01 that is already in RX standby mode and puts it in active RX mode
+void nrf24l01_rx_standby_to_active()
+{
+    nrf24l01_set_ce();
+}
+
+//takes a 24L01 that is already in active RX mode and puts it in RX standy mode
+void nrf24l01_rx_active_to_standby()
+{
+    nrf24l01_clear_ce();
+}
+
+//sets up the 24L01 as a transmitter
+//this function takes the existing contents of the CONFIG register and simply
+//  clears the PRIM_RX bit in the CONFIG register.
+//note: if the read value of the CONFIG register already has the PRIM_RX bit cleared, this 
+//  function exits in order to not make an unecessary register write.
+void nrf24l01_set_as_tx()
+{
+    unsigned char config;
+    
+    nrf24l01_read_register(nrf24l01_CONFIG, &config, 1);
+    
+    if((config & nrf24l01_CONFIG_PRIM_RX) == 0)
+        return;
+    
+    config &= (~nrf24l01_CONFIG_PRIM_RX);
+    
+    nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
+
+    nrf24l01_clear_ce();
+}
+
+//sets up the 24L01 as a transmitter
+//this function allows the user to set the contents of the CONFIG register, but the function
+//  clears the PRIM_RX bit in the CONFIG register, so the user does not need to.
+void nrf24l01_set_as_tx_param(unsigned char config)
+{
+    config &= ~(nrf24l01_CONFIG_PRIM_RX);
+    
+    if((config & nrf24l01_CONFIG_PWR_UP) != 0)
+        nrf24l01_power_up_param(false, config);
+    else
+        nrf24l01_power_down_param(config);
+}
+
+//executes the W_REGISTER SPI operation
+//unsigned char regnumber indicates the register number assigned by the nrf24l01 specification.
+//  For regnumber values, see section titled "register definitions" in nrf24l01.h.
+//unsigned char * data should be of size 1 for all register writes except for RX_ADDR_P0, RX_ADDR_P1,
+//    and TX_ADDR.  The size of data should be set according to the user-specified size of the address
+//  length for the register the address is being sent to.
+//unsigned int len is always the size of unsigned char * data.  For example, if data is declared as
+//  data[6], len should equal 6.
+//returns the value of the STATUS register
+unsigned char nrf24l01_write_register(unsigned char regnumber, unsigned char * data, unsigned int len)
+{
+    return nrf24l01_execute_command(nrf24l01_W_REGISTER | (regnumber & nrf24l01_W_REGISTER_DATA), data, len, false);
+}
+
+//executes the R_REGISTER SPI operation
+//unsigned char regnumber indicates the register number assigned by the nrf24l01 specification.
+//  For regnumber values, see section titled "register definitions" in nrf24l01.h.
+//unsigned char * data should be of size 1 for all register writes except for RX_ADDR_P0, RX_ADDR_P1,
+//    and TX_ADDR.  The size of data should be set according to the user-specified size of the address
+//  length for the register the address is being read from.
+//unsigned int len is always the size of unsigned char * data.  For example, if data is declared as 
+//  data[6], len = 6.
+//returns the value of the STATUS register
+unsigned char nrf24l01_read_register(unsigned char regnumber, unsigned char * data, unsigned int len)
+{
+    return nrf24l01_execute_command(regnumber & nrf24l01_R_REGISTER_DATA, data, len, true);
+}
+
+//executes the W_TX_PAYLOAD operation
+//unsigned char * data is the actual payload to be sent to the nrf24l01.
+//unsigned int len is the length of the payload being sent (this should be sized
+//    according to the payload length specified by the receiving nrf24l01).
+//if bool transmit is true, the nrf24l01 immediately transmits the data in the payload.
+//    if false, the user must use the nrf24l01_transmit() function to send the payload.
+//returns the value of the STATUS register
+unsigned char nrf24l01_write_tx_payload(unsigned char * data, unsigned int len, bool transmit)
+{
+    unsigned char status;
+    
+    status = nrf24l01_execute_command(nrf24l01_W_TX_PAYLOAD, data, len, false);
+    
+    if(transmit == true)
+        nrf24l01_transmit();
+    
+    return status;
+}
+
+//executes the R_RX_PAYLOAD instruction
+//unsigned char * data is the actual payload that has been received by the nrf24l01.
+//    The user must size data according to the payload width specified to the nrf24l01.
+//    This variable is filled by this function, so individual byte values need not be
+//    initialized by the user.
+//unsigned int len is the length of the payload being clocked out of the nrf24l01 (this
+//    should be sized according to the payload length specified to the nrf24l01).
+//returns the value of the STATUS register
+unsigned char nrf24l01_read_rx_payload(unsigned char * data, unsigned int len)
+{
+    unsigned char status;
+    
+    nrf24l01_clear_ce();
+    status = nrf24l01_execute_command(nrf24l01_R_RX_PAYLOAD, data, len, true);
+    nrf24l01_set_ce();
+    
+    return status;
+}
+
+//executes the FLUSH_TX SPI operation
+//this funciton empties the contents of the TX FIFO
+//returns the value of the STATUS register
+unsigned char nrf24l01_flush_tx()
+{
+    return nrf24l01_execute_command(nrf24l01_FLUSH_TX, NULL, 0, true);
+}
+
+//executes the FLUSH_RX SPI operation
+//this funciton empties the contents of the RX FIFO
+//returns the value of the STATUS register
+unsigned char nrf24l01_flush_rx()
+{
+    return nrf24l01_execute_command(nrf24l01_FLUSH_RX, NULL, 0, true);
+}
+
+//executes the REUSE_TX_PL SPI operation
+//this funciton allows the user to constantly send a packet repeatedly when issued.
+//returns the value of the STATUS register
+unsigned char nrf24l01_reuse_tx_pl()
+{
+    return nrf24l01_execute_command(nrf24l01_REUSE_TX_PL, NULL, 0, true);
+}
+
+//executes the FLUSH_TX SPI operation
+//this funciton does nothing
+//returns the value of the STATUS register
+unsigned char nrf24l01_nop()
+{
+    return nrf24l01_execute_command(nrf24l01_NOP, NULL, 0, true);
+}
+
+//transmits the current tx payload
+void nrf24l01_transmit()
+{
+    nrf24l01_set_ce();
+    delay_us(10);
+    nrf24l01_clear_ce();
+}
+
+//clears the pin on the host microcontroller that is attached to the 24l01's CE pin
+void nrf24l01_clear_ce()
+{
+    nRF_CE = 0;
+    //nrf24l01_CE_IOREGISTER &= ~nrf24l01_CE_PINMASK;
+}
+
+//sets the pin on the host microcontroller that is attached to the 24l01's CE pin
+void nrf24l01_set_ce()
+{
+    nRF_CE = 1;
+    //nrf24l01_CE_IOREGISTER |= nrf24l01_CE_PINMASK;
+}
+
+//returns true if CE is high, false if not
+bool nrf24l01_ce_pin_active()
+{
+    return nRF_CE.read();
+    /*    
+    if((nrf24l01_CE_IOREGISTER & nrf24l01_CE_PINMASK) != 0)
+        return true;
+    else
+        return false;
+    */
+}
+
+//sets the pin on the host microcontroller that is attached to the 24l01's CSN pin
+void nrf24l01_clear_csn()
+{
+    nRF_CSN = 0;
+    //nrf24l01_CSN_IOREGISTER &= ~nrf24l01_CSN_PINMASK;
+}
+
+//clears the pin on the host microcontroller that is attached to the 24l01's CSN pin
+void nrf24l01_set_csn()
+{
+    nRF_CSN = 1;
+    //nrf24l01_CSN_IOREGISTER |= nrf24l01_CSN_PINMASK;
+}
+
+//returns true if CSN is high, false if not
+bool nrf24l01_csn_pin_active()
+{
+    return nRF_CSN.read();
+    /*
+    if((nrf24l01_CSN_IOREGISTER & nrf24l01_CSN_PINMASK) != 0)
+        return true;
+    else
+        return false;    
+    */
+}
+
+//sets the TX address in the TX_ADDR register
+//unsigned char * address is the actual address to be used.  It should be sized
+//    according to the tx_addr length specified to the nrf24l01.
+//unsigned int len is the length of the address.  Its value should be specified
+//    according to the tx_addr length specified to the nrf24l01.
+void nrf24l01_set_tx_addr(unsigned char * address, unsigned int len)
+{        
+    nrf24l01_write_register(nrf24l01_TX_ADDR, address, len);
+}
+
+//sets the RX address in the RX_ADDR register that is offset by rxpipenum
+//unsigned char * address is the actual address to be used.  It should be sized
+//    according to the rx_addr length that is being filled.
+//unsigned int len is the length of the address.  Its value should be specified
+//    according to the rx_addr length specified to the nrf24l01.
+//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
+//    specified.  If an invalid address (greater than five) is supplied, the function
+//  does nothing.
+void nrf24l01_set_rx_addr(unsigned char * address, unsigned int len, unsigned char rxpipenum)
+{    
+    if(rxpipenum > 5)
+        return;
+        
+    nrf24l01_write_register(nrf24l01_RX_ADDR_P0 + rxpipenum, address, len);
+}
+
+//sets the RX payload width on the pipe offset by rxpipenum
+//unsigned char payloadwidth is the length of the payload for the pipe referenced in
+//  rxpipenum.  It must be less than or equal to 32.  If an invalid payload width is
+//  specified, the function does nothing.
+//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
+//    specified.  If an invalid address (greater than five) is supplied, the function
+//  does nothing.
+void nrf24l01_set_rx_pw(unsigned char payloadwidth, unsigned char rxpipenum)
+{
+    if((rxpipenum > 5) || (payloadwidth > 32))
+        return;
+        
+    nrf24l01_write_register(nrf24l01_RX_PW_P0 + rxpipenum, &payloadwidth, 1);
+}
+
+//gets the RX payload width on the pipe offset by rxpipenum
+//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
+//    specified.  If an invalid address (greater than five) is supplied, the function
+//  does nothing.
+unsigned char nrf24l01_get_rx_pw(unsigned char rxpipenum)
+{
+    unsigned char data;
+    
+    if((rxpipenum > 5))
+        return 0;
+        
+    nrf24l01_read_register(nrf24l01_RX_PW_P0 + rxpipenum, &data, 1);
+    
+    return data;
+}
+
+//returns the value of the CONFIG register
+unsigned char nrf24l01_get_config()
+{
+    unsigned char data;
+    
+    nrf24l01_read_register(nrf24l01_CONFIG, &data, 1);
+    
+    return data;
+}
+
+//sets the value of the CONFIG register
+void nrf24l01_set_config(unsigned char config)
+{
+    nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
+}
+
+//returns the current RF channel in RF_CH register
+unsigned char nrf24l01_get_rf_ch()
+{
+    unsigned char data;
+    
+    nrf24l01_read_register(nrf24l01_RF_CH, &data, 1);
+    
+    return data;
+}
+
+//unsigned char channel is the channel to be changed to.
+void nrf24l01_set_rf_ch(unsigned char channel)
+{
+    unsigned char data;
+    
+    data = channel & ~nrf24l01_RF_CH_RESERVED;
+    
+    nrf24l01_write_register(nrf24l01_RF_CH, &data, 1);
+}
+
+//returns the value of the OBSERVE_TX register
+unsigned char nrf24l01_get_observe_tx()
+{
+    unsigned char data;
+    
+    nrf24l01_read_register(nrf24l01_OBSERVE_TX, &data, 1);
+    
+    return data;
+}
+
+//returns the current PLOS_CNT value in OBSERVE_TX register
+unsigned char nrf24l01_get_plos_cnt()
+{
+    unsigned char data;
+    
+    nrf24l01_read_register(nrf24l01_OBSERVE_TX, &data, 1);
+    
+    return ((data & nrf24l01_OBSERVE_TX_PLOS_CNT) >> 4);
+}
+
+//clears the PLOS_CNT field of the OBSERVE_TX register
+//this function makes a read of the current value of RF_CH and
+//  simply writes it back to the register, clearing PLOS_CNT
+void nrf24l01_clear_plos_cnt()
+{
+    unsigned char data;
+    
+    nrf24l01_read_register(nrf24l01_RF_CH, &data, 1);
+    nrf24l01_write_register(nrf24l01_RF_CH, &data, 1);
+}
+
+//clears the PLOS_CNT field of the OBSERVE_TX register
+//this function allows the user to set the RF_CH register by using
+//  the argument in the function during the PLOS_CNT clearing process
+void nrf24l01_clear_plos_cnt_param(unsigned char rf_ch)
+{
+    nrf24l01_write_register(nrf24l01_RF_CH, &rf_ch, 1);
+}
+
+//returns the current ARC_CNT value in OBSERVE_TX register
+unsigned char nrf24l01_get_arc_cnt()
+{
+    unsigned char data;
+    
+    nrf24l01_read_register(nrf24l01_OBSERVE_TX, &data, 1);
+    
+    return (data & nrf24l01_OBSERVE_TX_ARC_CNT);
+}
+
+//returns true if auto-ack is enabled on the pipe that is offset by rxpipenum
+//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
+//    specified.  If an invalid address (greater than five) is supplied, the function
+//  returns false.
+bool nrf24l01_aa_enabled(unsigned char rxpipenum)
+{
+    unsigned char data;
+    
+    if(rxpipenum > 5)
+        return false;
+        
+    nrf24l01_read_register(nrf24l01_EN_AA, &data, 1);
+    
+    return (data & (0x01 << rxpipenum));
+}
+
+//enables auto-ack is enabled on the pipe that is offset by rxpipenum
+//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
+//    does nothing.
+void nrf24l01_aa_enable(unsigned char rxpipenum)
+{
+    unsigned char data;
+    
+    if(rxpipenum > 5)
+        return;
+        
+    nrf24l01_read_register(nrf24l01_EN_AA, &data, 1);
+    
+    if((data & (0x01 << rxpipenum)) != 0)
+        return;
+    
+    data |= 0x01 << rxpipenum;
+        
+    nrf24l01_write_register(nrf24l01_EN_AA, &data, 1);
+}
+
+//disables auto-ack is enabled on the pipe that is offset by rxpipenum
+//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
+//    does nothing.
+void nrf24l01_aa_disable(unsigned char rxpipenum)
+{
+    unsigned char data;
+    
+    if(rxpipenum > 5)
+        return;
+        
+    nrf24l01_read_register(nrf24l01_EN_AA, &data, 1);
+    
+    if((data & (0x01 << rxpipenum)) == 0)
+        return;
+    
+    data &= ~(0x01 << rxpipenum);
+        
+    nrf24l01_write_register(nrf24l01_EN_AA, &data, 1);
+}
+
+//returns true if the pipe is enabled that is offset by rxpipenum
+//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
+//    specified.  If an invalid address (greater than five) is supplied, the function
+//  returns false.
+bool nrf24l01_rx_pipe_enabled(unsigned char rxpipenum)
+{
+    unsigned char data;
+    
+    if((rxpipenum > 5))
+        return false;
+        
+    nrf24l01_read_register(nrf24l01_EN_RXADDR, &data, 1);
+    
+    return (data & (0x01 << rxpipenum));
+}
+
+//enables the pipe that is offset by rxpipenum
+//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
+//    specified.  If an invalid address (greater than five) is supplied, the function
+//  does nothing.
+void nrf24l01_rx_pipe_enable(unsigned char rxpipenum)
+{
+    unsigned char data;
+    
+    if(rxpipenum > 5)
+        return;
+        
+    nrf24l01_read_register(nrf24l01_EN_RXADDR, &data, 1);
+    
+    if((data & (0x01 << rxpipenum)) != 0)
+        return;
+    
+    data |= 0x01 << rxpipenum;
+        
+    nrf24l01_write_register(nrf24l01_EN_RXADDR, &data, 1);
+}
+
+//disables the pipe that is offset by rxpipenum
+//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
+//    specified.  If an invalid address (greater than five) is supplied, the function
+//  does nothing.
+void nrf24l01_rx_pipe_disable(unsigned char rxpipenum)
+{
+    unsigned char data;
+    
+    if(rxpipenum > 5)
+        return;
+        
+    nrf24l01_read_register(nrf24l01_EN_RXADDR, &data, 1);
+    
+    if((data & (0x01 << rxpipenum)) == 0)
+        return;
+    
+    data &= ~(0x01 << rxpipenum);
+        
+    nrf24l01_write_register(nrf24l01_EN_RXADDR, &data, 1);
+}
+
+//returns the status of the CD register (true if carrier detect [CD] is
+//  active, false if not)
+bool nrf24l01_cd_active()
+{
+    unsigned char data;
+    
+    nrf24l01_read_register(nrf24l01_CD, &data, 1);
+    
+    return data;
+}
+
+//returns the value of the FIFO_STATUS register
+unsigned char nrf24l01_get_fifo_status()
+{
+    unsigned char data;
+    
+    nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1);
+    
+    return data;
+}
+
+//return the value of the status register
+unsigned char nrf24l01_get_status()
+{
+    return nrf24l01_nop();
+}
+
+//returns true if TX_REUSE bit in FIFO_STATUS register is set, false otherwise
+bool nrf24l01_fifo_tx_reuse()
+{
+    unsigned char data;
+    
+    nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1);
+    
+    return (bool)(data & nrf24l01_FIFO_STATUS_TX_REUSE);
+}
+
+//returns true if TX_FULL bit in FIFO_STATUS register is set, false otherwise
+bool nrf24l01_fifo_tx_full()
+{
+    unsigned char data;
+    
+    nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1);
+    
+    return (bool)(data & nrf24l01_FIFO_STATUS_TX_FULL);
+}
+
+//returns true if TX_EMPTY bit in FIFO_STATUS register is set, false otherwise
+bool nrf24l01_fifo_tx_empty()
+{
+    unsigned char data;
+    
+    nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1);
+    
+    return (bool)(data & nrf24l01_FIFO_STATUS_TX_EMPTY);
+}
+
+//returns true if RX_FULL bit in FIFO_STATUS register is set, false otherwise
+bool nrf24l01_fifo_rx_full()
+{
+    unsigned char data;
+    
+    nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1);
+    
+    return (bool)(data & nrf24l01_FIFO_STATUS_RX_FULL);
+}
+
+//returns true if RX_EMPTYE bit in FIFO_STATUS register is set, false otherwise
+bool nrf24l01_fifo_rx_empty()
+{
+    unsigned char data;
+    
+    nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1);
+    
+    return (bool)(data & nrf24l01_FIFO_STATUS_RX_EMPTY);
+}
+
+//returns true if IRQ pin is low, false otherwise
+bool nrf24l01_irq_pin_active()
+{
+    return !nRF_IRQ.read();
+    /*
+    if((nrf24l01_IRQ_IOREGISTER & nrf24l01_IRQ_PINMASK) != 0)
+        return false;
+    else
+        return true;
+    */
+}
+
+//returns true if RX_DR interrupt is active, false otherwise
+bool nrf24l01_irq_rx_dr_active()
+{
+    return (nrf24l01_get_status() & nrf24l01_STATUS_RX_DR);
+}
+
+//returns true if TX_DS interrupt is active, false otherwise
+bool nrf24l01_irq_tx_ds_active()
+{
+    return (nrf24l01_get_status() & nrf24l01_STATUS_TX_DS);
+}
+
+//returns true if MAX_RT interrupt is active, false otherwise
+bool nrf24l01_irq_max_rt_active()
+{
+    return (nrf24l01_get_status() & nrf24l01_STATUS_MAX_RT);
+}
+
+//clear all interrupts in the status register
+void nrf24l01_irq_clear_all()
+{
+    unsigned char data = nrf24l01_STATUS_RX_DR | nrf24l01_STATUS_TX_DS | nrf24l01_STATUS_MAX_RT;
+    
+    nrf24l01_write_register(nrf24l01_STATUS, &data, 1); 
+}
+
+//clears only the RX_DR interrupt
+void nrf24l01_irq_clear_rx_dr()
+{
+    unsigned char data = nrf24l01_STATUS_RX_DR;
+    
+    nrf24l01_write_register(nrf24l01_STATUS, &data, 1); 
+}
+
+//clears only the TX_DS interrupt
+void nrf24l01_irq_clear_tx_ds()
+{
+    unsigned char data = nrf24l01_STATUS_TX_DS;
+    
+    nrf24l01_write_register(nrf24l01_STATUS, &data, 1); 
+}
+
+//clears only the MAX_RT interrupt
+void nrf24l01_irq_clear_max_rt()
+{
+    unsigned char data = nrf24l01_STATUS_MAX_RT;
+    
+    nrf24l01_write_register(nrf24l01_STATUS, &data, 1); 
+}
+
+//returns the current pipe in the 24L01's STATUS register
+unsigned char nrf24l01_get_rx_pipe()
+{
+    return nrf24l01_get_rx_pipe_from_status(nrf24l01_get_status());
+}
+
+unsigned char nrf24l01_get_rx_pipe_from_status(unsigned char status)
+{
+    return ((status & 0xE) >> 1);
+}
+
+//flush both fifos and clear interrupts
+void nrf24l01_clear_flush()
+{
+    nrf24l01_flush_rx();
+    nrf24l01_flush_tx();
+    nrf24l01_irq_clear_all();
+}
+
+//unsigned char * data must be at least 35 bytes long
+void nrf24l01_get_all_registers(unsigned char * data)
+{
+    unsigned int outer;
+    unsigned int inner;
+    unsigned int dataloc = 0;
+    unsigned char buffer[5];
+    
+    for(outer = 0; outer <= 0x17; outer++)
+    {
+        nrf24l01_read_register(outer, buffer, 5);
+        
+        for(inner = 0; inner < 5; inner++)
+        {
+            if(inner >= 1 && (outer != 0x0A && outer != 0x0B && outer != 0x10))
+                break;
+                
+            data[dataloc] = buffer[inner];
+            dataloc++;
+        }
+    }
+}
+
+//low-level spi send function for library use
+//the user should not call this function directly, but rather use one of the 8 SPI data instructions
+unsigned char nrf24l01_execute_command(unsigned char instruction, unsigned char * data, unsigned int len, bool copydata)
+{
+    unsigned char status;
+    
+    nrf24l01_clear_csn();
+
+    status = instruction;
+    nrf24l01_spi_send_read(&status, 1, true);
+    nrf24l01_spi_send_read(data, len, copydata);
+    
+    nrf24l01_set_csn();        
+
+    return status;
+}
+
+//low-level spi send function for library use
+//the user should not call this function directly, but rather use one of the 8 SPI data instructions
+void nrf24l01_spi_send_read(unsigned char * data, unsigned int len, bool copydata)
+{
+    unsigned int count;
+    unsigned char tempbyte;
+
+    for(count = 0; count < len; count++)
+    {
+        if(copydata != false)
+            data[count] = spi_send_read_byte(data[count]);
+        else
+        {
+            tempbyte = data[count];
+            spi_send_read_byte(tempbyte);
+        }
+    }
+}
+
diff -r 000000000000 -r 2286a98ea739 nRF24L01P/nrf24l01.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nRF24L01P/nrf24l01.h	Sat Dec 08 22:11:23 2012 +0000
@@ -0,0 +1,482 @@
+/******************************************************************************
+*
+* File: nrf24l01.h
+* 
+* Copyright S. Brennen Ball, 2006-2007
+* 
+* The author provides no guarantees, warantees, or promises, implied or
+*    otherwise.  By using this software you agree to indemnify the author
+*     of any damages incurred by using it.
+*
+*****************************************************************************/
+
+#ifndef NRF24L01_H_
+#define NRF24L01_H_
+
+#include <stddef.h>
+
+#ifndef bool
+#define bool unsigned char
+#endif
+#ifndef false
+#define false 0
+#endif
+#ifndef true
+#define true !false
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////
+// SPI function requirements
+//
+// The user must define a function to send one byte of data and also return the
+//   resulting byte of data data through the SPI port. The function used here 
+//   has the function prototype
+//
+//        unsigned char spi_send_read_byte(unsigned char byte);
+//
+// This function should take the argument unsigned char byte and send it through
+//   the SPI port to the 24L01.  Then, it should wait until the 24L01 has returned
+//   its response over SPI.  This received byte should be the return value of the
+//   function.
+//
+// You should also change the include file name below to whatever the name of your 
+//   SPI include file is.
+//////////////////////////////////////////////////////////////////////////////////
+//#include "spi1.h"
+#define spi_send_read_byte(byte)    nRF_spi.write(byte)
+
+
+/////////////////////////////////////////////////////////////////////////////////
+// Delay function requirements
+//
+// The user must define a function that delays for the specified number of 
+//     microseconds. This function needs to be as precise as possible, and the use
+//   of a timer module within your microcontroller is highly recommended. The 
+//   function used here has the prototype
+//
+//        void delay_us(unsigned int microseconds);
+//
+// You should also change the include file name below to whatever the name of your 
+//   delay include file is.
+//////////////////////////////////////////////////////////////////////////////////
+//#include "delays.h"
+#define delay_us(microseconds)        wait_us(microseconds)
+
+
+//////////////////////////////////////////////////////////////////////////////////
+// IO pin definitions
+//
+// Below you will find several definitions and includes.  The first is an #include
+//   for your microcontroller's include file to allow you to use register names 
+//   rather than numbers.  The next three are to allow you to control the pins on
+//   the 24L01 that aren't automatically handled by SPI.  These are CE, CSN, and
+//   IRQ.
+//
+// The general format of these defines is a define for the IO register the pin is
+//   attached to.  The second define is a mask for the pin.  For example, say that
+//   your CE pin is tied to an IO port with the register name IOPORT1. Also, let's
+//   say that the IO port is 8-bits wide, and you have attached the pin to pin 0 of
+//   the port.  Then your define would look like this:
+//
+//     #define nrf24l01_CE_IOREGISTER        IOPORT1
+//   #define nrf24l01_CE_PINMASK        0x01
+//
+// If you have defines in your include file for individual IO pins, you could use
+//   this define in this file, as well.  Using the previous example, assume that in
+//   your microcontroller's include file, pin 0 of IOPORT1 has a define like this
+//
+//   #define IOPORT1_PIN0    0x01
+//
+// Then, you could make your defines for the CE pin in this file look like this:
+//
+//     #define nrf24l01_CE_IOREGISTER        IOPORT1
+//   #define nrf24l01_CE_PINMASK        IOPORT1_PIN0
+//
+// You should also change the include file name below to whatever the name of your 
+//   processor's register definition include file is.
+/////////////////////////////////////////////////////////////////////////////////////
+//#include "lpc214x.h"
+
+//defines for uC pins CE pin is connected to
+//This is used so that the routines can send TX payload data and 
+//    properly initialize the nrf24l01 in TX and RX states.
+//Change these definitions (and then recompile) to suit your particular application.
+#define nrf24l01_CE_IOREGISTER        pinCE
+#define nrf24l01_CE_PINMASK                1
+
+//defines for uC pins CSN pin is connected to
+//This is used so that the routines can send properly operate the SPI interface
+// on the nrf24l01.
+//Change these definitions (and then recompile) to suit your particular application.
+#define nrf24l01_CSN_IOREGISTER        pinCSN
+#define nrf24l01_CSN_PINMASK            1
+
+//defines for uC pins IRQ pin is connected to
+//This is used so that the routines can poll for IRQ or create an ISR.
+//Change these definitions (and then recompile) to suit your particular application.
+#define nrf24l01_IRQ_IOREGISTER        pinIRQ
+#define nrf24l01_IRQ_PINMASK            1
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// SPI commands
+//
+// The following are defines for all of the commands and data masks on the SPI 
+//   interface.
+////////////////////////////////////////////////////////////////////////////////////
+//SPI command defines
+#define nrf24l01_R_REGISTER        0x00
+#define nrf24l01_W_REGISTER        0x20
+#define nrf24l01_R_RX_PAYLOAD    0x61
+#define nrf24l01_W_TX_PAYLOAD    0xA0
+#define nrf24l01_FLUSH_TX        0xE1
+#define nrf24l01_FLUSH_RX        0xE2
+#define nrf24l01_REUSE_TX_PL    0xE3
+#define nrf24l01_NOP            0xFF
+
+//SPI command data mask defines
+#define nrf24l01_R_REGISTER_DATA    0x1F
+#define nrf24l01_W_REGISTER_DATA    0x1F
+
+////////////////////////////////////////////////////////////////////////////////////
+// Register definitions
+//
+// Below are the defines for each register's address in the 24L01.
+////////////////////////////////////////////////////////////////////////////////////
+#define nrf24l01_CONFIG            0x00
+#define nrf24l01_EN_AA            0x01
+#define nrf24l01_EN_RXADDR        0x02
+#define nrf24l01_SETUP_AW        0x03
+#define nrf24l01_SETUP_RETR        0x04
+#define nrf24l01_RF_CH            0x05
+#define nrf24l01_RF_SETUP        0x06
+#define nrf24l01_STATUS            0x07
+#define nrf24l01_OBSERVE_TX        0x08
+#define nrf24l01_CD                0x09
+#define nrf24l01_RX_ADDR_P0        0x0A
+#define nrf24l01_RX_ADDR_P1        0x0B
+#define nrf24l01_RX_ADDR_P2        0x0C
+#define nrf24l01_RX_ADDR_P3        0x0D
+#define nrf24l01_RX_ADDR_P4        0x0E
+#define nrf24l01_RX_ADDR_P5        0x0F
+#define nrf24l01_TX_ADDR        0x10
+#define nrf24l01_RX_PW_P0        0x11
+#define nrf24l01_RX_PW_P1        0x12
+#define nrf24l01_RX_PW_P2        0x13
+#define nrf24l01_RX_PW_P3        0x14
+#define nrf24l01_RX_PW_P4        0x15
+#define nrf24l01_RX_PW_P5        0x16
+#define nrf24l01_FIFO_STATUS    0x17
+
+////////////////////////////////////////////////////////////////////////////////////
+// Default register values
+//
+// Below are the defines for each register's default value in the 24L01. Multi-byte
+//   registers use notation B<X>, where "B" represents "byte" and <X> is the byte
+//   number.
+////////////////////////////////////////////////////////////////////////////////////
+#define nrf24l01_CONFIG_DEFAULT_VAL            0x08
+#define nrf24l01_EN_AA_DEFAULT_VAL            0x3F
+#define nrf24l01_EN_RXADDR_DEFAULT_VAL        0x03
+#define nrf24l01_SETUP_AW_DEFAULT_VAL        0x03
+#define nrf24l01_SETUP_RETR_DEFAULT_VAL        0x03
+#define nrf24l01_RF_CH_DEFAULT_VAL            0x02
+#define nrf24l01_RF_SETUP_DEFAULT_VAL        0x0F
+#define nrf24l01_STATUS_DEFAULT_VAL            0x0E
+#define nrf24l01_OBSERVE_TX_DEFAULT_VAL        0x00
+#define nrf24l01_CD_DEFAULT_VAL                0x00
+#define nrf24l01_RX_ADDR_P0_B0_DEFAULT_VAL    0xE7
+#define nrf24l01_RX_ADDR_P0_B1_DEFAULT_VAL    0xE7
+#define nrf24l01_RX_ADDR_P0_B2_DEFAULT_VAL    0xE7
+#define nrf24l01_RX_ADDR_P0_B3_DEFAULT_VAL    0xE7
+#define nrf24l01_RX_ADDR_P0_B4_DEFAULT_VAL    0xE7
+#define nrf24l01_RX_ADDR_P1_B0_DEFAULT_VAL    0xC2
+#define nrf24l01_RX_ADDR_P1_B1_DEFAULT_VAL    0xC2
+#define nrf24l01_RX_ADDR_P1_B2_DEFAULT_VAL    0xC2
+#define nrf24l01_RX_ADDR_P1_B3_DEFAULT_VAL    0xC2
+#define nrf24l01_RX_ADDR_P1_B4_DEFAULT_VAL    0xC2
+#define nrf24l01_RX_ADDR_P2_DEFAULT_VAL        0xC3
+#define nrf24l01_RX_ADDR_P3_DEFAULT_VAL        0xC4
+#define nrf24l01_RX_ADDR_P4_DEFAULT_VAL        0xC5
+#define nrf24l01_RX_ADDR_P5_DEFAULT_VAL        0xC6
+#define nrf24l01_TX_ADDR_B0_DEFAULT_VAL        0xE7
+#define nrf24l01_TX_ADDR_B1_DEFAULT_VAL        0xE7
+#define nrf24l01_TX_ADDR_B2_DEFAULT_VAL        0xE7
+#define nrf24l01_TX_ADDR_B3_DEFAULT_VAL        0xE7
+#define nrf24l01_TX_ADDR_B4_DEFAULT_VAL        0xE7
+#define nrf24l01_RX_PW_P0_DEFAULT_VAL        0x00
+#define nrf24l01_RX_PW_P1_DEFAULT_VAL        0x00
+#define nrf24l01_RX_PW_P2_DEFAULT_VAL        0x00
+#define nrf24l01_RX_PW_P3_DEFAULT_VAL        0x00
+#define nrf24l01_RX_PW_P4_DEFAULT_VAL        0x00
+#define nrf24l01_RX_PW_P5_DEFAULT_VAL        0x00
+#define nrf24l01_FIFO_STATUS_DEFAULT_VAL    0x11
+
+////////////////////////////////////////////////////////////////////////////////////
+// Register bitwise definitions
+//
+// Below are the defines for each register's bitwise fields in the 24L01.
+////////////////////////////////////////////////////////////////////////////////////
+//CONFIG register bitwise definitions
+#define nrf24l01_CONFIG_RESERVED    0x80
+#define    nrf24l01_CONFIG_MASK_RX_DR    0x40
+#define    nrf24l01_CONFIG_MASK_TX_DS    0x20
+#define    nrf24l01_CONFIG_MASK_MAX_RT    0x10
+#define    nrf24l01_CONFIG_EN_CRC        0x08
+#define    nrf24l01_CONFIG_CRCO        0x04
+#define    nrf24l01_CONFIG_PWR_UP        0x02
+#define    nrf24l01_CONFIG_PRIM_RX        0x01
+
+//EN_AA register bitwise definitions
+#define nrf24l01_EN_AA_RESERVED        0xC0
+#define nrf24l01_EN_AA_ENAA_ALL        0x3F
+#define nrf24l01_EN_AA_ENAA_P5        0x20
+#define nrf24l01_EN_AA_ENAA_P4        0x10
+#define nrf24l01_EN_AA_ENAA_P3        0x08
+#define nrf24l01_EN_AA_ENAA_P2        0x04
+#define nrf24l01_EN_AA_ENAA_P1        0x02
+#define nrf24l01_EN_AA_ENAA_P0        0x01
+#define nrf24l01_EN_AA_ENAA_NONE    0x00
+
+//EN_RXADDR register bitwise definitions
+#define nrf24l01_EN_RXADDR_RESERVED    0xC0
+#define nrf24l01_EN_RXADDR_ERX_ALL    0x3F
+#define nrf24l01_EN_RXADDR_ERX_P5    0x20
+#define nrf24l01_EN_RXADDR_ERX_P4    0x10
+#define nrf24l01_EN_RXADDR_ERX_P3    0x08
+#define nrf24l01_EN_RXADDR_ERX_P2    0x04
+#define nrf24l01_EN_RXADDR_ERX_P1    0x02
+#define nrf24l01_EN_RXADDR_ERX_P0    0x01
+#define nrf24l01_EN_RXADDR_ERX_NONE    0x00
+
+//SETUP_AW register bitwise definitions
+#define nrf24l01_SETUP_AW_RESERVED    0xFC
+#define nrf24l01_SETUP_AW            0x03
+#define nrf24l01_SETUP_AW_5BYTES    0x03
+#define nrf24l01_SETUP_AW_4BYTES    0x02
+#define nrf24l01_SETUP_AW_3BYTES    0x01
+#define nrf24l01_SETUP_AW_ILLEGAL    0x00
+
+//SETUP_RETR register bitwise definitions
+#define nrf24l01_SETUP_RETR_ARD            0xF0
+#define nrf24l01_SETUP_RETR_ARD_4000    0xF0
+#define nrf24l01_SETUP_RETR_ARD_3750    0xE0
+#define nrf24l01_SETUP_RETR_ARD_3500    0xD0
+#define nrf24l01_SETUP_RETR_ARD_3250    0xC0
+#define nrf24l01_SETUP_RETR_ARD_3000    0xB0
+#define nrf24l01_SETUP_RETR_ARD_2750    0xA0
+#define nrf24l01_SETUP_RETR_ARD_2500    0x90
+#define nrf24l01_SETUP_RETR_ARD_2250    0x80
+#define nrf24l01_SETUP_RETR_ARD_2000    0x70
+#define nrf24l01_SETUP_RETR_ARD_1750    0x60
+#define nrf24l01_SETUP_RETR_ARD_1500    0x50
+#define nrf24l01_SETUP_RETR_ARD_1250    0x40
+#define nrf24l01_SETUP_RETR_ARD_1000    0x30
+#define nrf24l01_SETUP_RETR_ARD_750        0x20
+#define nrf24l01_SETUP_RETR_ARD_500        0x10
+#define nrf24l01_SETUP_RETR_ARD_250        0x00
+#define nrf24l01_SETUP_RETR_ARC            0x0F
+#define nrf24l01_SETUP_RETR_ARC_15        0x0F
+#define nrf24l01_SETUP_RETR_ARC_14        0x0E
+#define nrf24l01_SETUP_RETR_ARC_13        0x0D
+#define nrf24l01_SETUP_RETR_ARC_12        0x0C
+#define nrf24l01_SETUP_RETR_ARC_11        0x0B
+#define nrf24l01_SETUP_RETR_ARC_10        0x0A
+#define nrf24l01_SETUP_RETR_ARC_9        0x09
+#define nrf24l01_SETUP_RETR_ARC_8        0x08
+#define nrf24l01_SETUP_RETR_ARC_7        0x07
+#define nrf24l01_SETUP_RETR_ARC_6        0x06
+#define nrf24l01_SETUP_RETR_ARC_5        0x05
+#define nrf24l01_SETUP_RETR_ARC_4        0x04
+#define nrf24l01_SETUP_RETR_ARC_3        0x03
+#define nrf24l01_SETUP_RETR_ARC_2        0x02
+#define nrf24l01_SETUP_RETR_ARC_1        0x01
+#define nrf24l01_SETUP_RETR_ARC_0        0x00
+
+//RF_CH register bitwise definitions
+#define nrf24l01_RF_CH_RESERVED    0x80
+
+//RF_SETUP register bitwise definitions
+#define nrf24l01_RF_SETUP_RESERVED    0xE0
+#define nrf24l01_RF_SETUP_PLL_LOCK    0x10
+#define nrf24l01_RF_SETUP_RF_DR        0x08
+#define nrf24l01_RF_SETUP_RF_PWR    0x06
+#define nrf24l01_RF_SETUP_RF_PWR_0    0x06
+#define nrf24l01_RF_SETUP_RF_PWR_6     0x04
+#define nrf24l01_RF_SETUP_RF_PWR_12    0x02
+#define nrf24l01_RF_SETUP_RF_PWR_18    0x00
+#define nrf24l01_RF_SETUP_LNA_HCURR    0x01
+
+//STATUS register bitwise definitions
+#define nrf24l01_STATUS_RESERVED                    0x80
+#define nrf24l01_STATUS_RX_DR                        0x40
+#define nrf24l01_STATUS_TX_DS                        0x20
+#define nrf24l01_STATUS_MAX_RT                        0x10
+#define nrf24l01_STATUS_RX_P_NO                        0x0E
+#define nrf24l01_STATUS_RX_P_NO_RX_FIFO_NOT_EMPTY    0x0E
+#define nrf24l01_STATUS_RX_P_NO_UNUSED                0x0C
+#define nrf24l01_STATUS_RX_P_NO_5                    0x0A
+#define nrf24l01_STATUS_RX_P_NO_4                    0x08
+#define nrf24l01_STATUS_RX_P_NO_3                    0x06
+#define nrf24l01_STATUS_RX_P_NO_2                    0x04
+#define nrf24l01_STATUS_RX_P_NO_1                    0x02
+#define nrf24l01_STATUS_RX_P_NO_0                    0x00
+#define nrf24l01_STATUS_TX_FULL                        0x01
+
+//OBSERVE_TX register bitwise definitions
+#define nrf24l01_OBSERVE_TX_PLOS_CNT    0xF0
+#define nrf24l01_OBSERVE_TX_ARC_CNT        0x0F
+
+//CD register bitwise definitions
+#define nrf24l01_CD_RESERVED    0xFE
+#define nrf24l01_CD_CD            0x01
+
+//RX_PW_P0 register bitwise definitions
+#define nrf24l01_RX_PW_P0_RESERVED    0xC0
+
+//RX_PW_P0 register bitwise definitions
+#define nrf24l01_RX_PW_P0_RESERVED    0xC0
+
+//RX_PW_P1 register bitwise definitions
+#define nrf24l01_RX_PW_P1_RESERVED    0xC0
+
+//RX_PW_P2 register bitwise definitions
+#define nrf24l01_RX_PW_P2_RESERVED    0xC0
+
+//RX_PW_P3 register bitwise definitions
+#define nrf24l01_RX_PW_P3_RESERVED    0xC0
+
+//RX_PW_P4 register bitwise definitions
+#define nrf24l01_RX_PW_P4_RESERVED    0xC0
+
+//RX_PW_P5 register bitwise definitions
+#define nrf24l01_RX_PW_P5_RESERVED    0xC0
+
+//FIFO_STATUS register bitwise definitions
+#define nrf24l01_FIFO_STATUS_RESERVED    0x8C
+#define nrf24l01_FIFO_STATUS_TX_REUSE    0x40
+#define nrf24l01_FIFO_STATUS_TX_FULL    0x20
+#define nrf24l01_FIFO_STATUS_TX_EMPTY    0x10
+#define nrf24l01_FIFO_STATUS_RX_FULL    0x02
+#define nrf24l01_FIFO_STATUS_RX_EMPTY    0x01
+
+////////////////////////////////////////////////////////////////////////////////////
+// Function declarations
+//
+// Below are all function definitions contained in the library.  Please see
+//   nrf24l01.c for comments regarding the usage of each function.
+////////////////////////////////////////////////////////////////////////////////////
+//initialization functions
+void nrf24l01_initialize(unsigned char config,
+                         unsigned char opt_rx_standby_mode, 
+                         unsigned char en_aa, 
+                         unsigned char en_rxaddr, 
+                         unsigned char setup_aw, 
+                         unsigned char setup_retr, 
+                         unsigned char rf_ch, 
+                         unsigned char rf_setup, 
+                         unsigned char * rx_addr_p0, 
+                         unsigned char * rx_addr_p1, 
+                         unsigned char rx_addr_p2, 
+                         unsigned char rx_addr_p3, 
+                         unsigned char rx_addr_p4, 
+                         unsigned char rx_addr_p5, 
+                         unsigned char * tx_addr, 
+                         unsigned char rx_pw_p0, 
+                         unsigned char rx_pw_p1, 
+                         unsigned char rx_pw_p2, 
+                         unsigned char rx_pw_p3, 
+                         unsigned char rx_pw_p4, 
+                         unsigned char rx_pw_p5);
+void nrf24l01_initialize_debug(bool rx, unsigned char p0_payload_width, bool enable_auto_ack);
+void nrf24l01_initialize_debug_lite(bool rx, unsigned char p0_payload_width);
+
+//power-up, power-down functions
+void nrf24l01_power_up(bool rx_active_mode);
+void nrf24l01_power_up_param(bool rx_active_mode, unsigned char config);
+void nrf24l01_power_down(void);
+void nrf24l01_power_down_param(unsigned char config);
+
+//SPI commands defined by the spec
+//for regnumber values, see section above titled "register definitions"
+//all functions return the STATUS register
+unsigned char nrf24l01_write_register(unsigned char regnumber, unsigned char * data, unsigned int len);
+unsigned char nrf24l01_read_register(unsigned char regnumber, unsigned char * data, unsigned int len);
+unsigned char nrf24l01_write_tx_payload(unsigned char * data, unsigned int len, bool transmit);
+unsigned char nrf24l01_read_rx_payload(unsigned char * data, unsigned int len);
+unsigned char nrf24l01_flush_tx(void);
+unsigned char nrf24l01_flush_rx(void);
+unsigned char nrf24l01_reuse_tx_pl(void);
+unsigned char nrf24l01_nop(void);
+
+//RX/TX setting functions
+void nrf24l01_set_as_rx(bool rx_active_mode);
+void nrf24l01_set_as_rx_param(bool rx_active_mode, unsigned char config);
+void nrf24l01_rx_standby_to_active(void);
+void nrf24l01_rx_active_to_standby(void);
+void nrf24l01_set_as_tx(void);
+void nrf24l01_set_as_tx_param(unsigned char config);
+
+//register-oriented get/set functions for commonly-used registers during operation
+unsigned char nrf24l01_get_config(void);
+void nrf24l01_set_config(unsigned char config);
+unsigned char nrf24l01_get_rf_ch(void);
+void nrf24l01_set_rf_ch(unsigned char channel);
+unsigned char nrf24l01_get_status(void);
+unsigned char nrf24l01_get_observe_tx(void);
+void nrf24l01_set_rx_addr(unsigned char * address, unsigned int len, unsigned char rxpipenum);
+void nrf24l01_set_tx_addr(unsigned char * address, unsigned int len);
+void nrf24l01_set_rx_pw(unsigned char payloadwidth, unsigned char rxpipenum);
+unsigned char nrf24l01_get_rx_pw(unsigned char rxpipenum);
+unsigned char nrf24l01_get_fifo_status(void);
+
+//auto-ack and pipe-related functions
+bool nrf24l01_aa_enabled(unsigned char rxpipenum);
+void nrf24l01_aa_enable(unsigned char rxpipenum);
+void nrf24l01_aa_disable(unsigned char rxpipenum);
+bool nrf24l01_rx_pipe_enabled(unsigned char rxpipenum);
+void nrf24l01_rx_pipe_enable(unsigned char rxpipenum);
+void nrf24l01_rx_pipe_disable(unsigned char rxpipenum);
+unsigned char nrf24l01_get_plos_cnt(void);
+void nrf24l01_clear_plos_cnt(void);
+void nrf24l01_clear_plos_cnt_param(unsigned char rf_ch);
+unsigned char nrf24l01_get_arc_cnt(void);
+
+//utility functions
+bool nrf24l01_cd_active(void);
+void nrf24l01_clear_flush(void);
+unsigned char nrf24l01_get_rx_pipe(void);
+unsigned char nrf24l01_get_rx_pipe_from_status(unsigned char status);
+void nrf24l01_get_all_registers(unsigned char * data);
+
+//interrupt check/clear functions
+bool nrf24l01_irq_pin_active(void);
+bool nrf24l01_irq_rx_dr_active(void);
+bool nrf24l01_irq_tx_ds_active(void);
+bool nrf24l01_irq_max_rt_active(void);
+void nrf24l01_irq_clear_all(void);
+void nrf24l01_irq_clear_rx_dr(void);
+void nrf24l01_irq_clear_tx_ds(void);
+void nrf24l01_irq_clear_max_rt(void);
+
+//FIFO_STATUS check functions
+bool nrf24l01_fifo_tx_reuse(void);
+bool nrf24l01_fifo_tx_full(void);
+bool nrf24l01_fifo_tx_empty(void);
+bool nrf24l01_fifo_rx_full(void);
+bool nrf24l01_fifo_rx_empty(void);
+
+//IO interface-related functions
+void nrf24l01_transmit(void);
+void nrf24l01_clear_ce(void);
+void nrf24l01_set_ce(void);
+void nrf24l01_clear_csn(void);
+void nrf24l01_set_csn(void);
+bool nrf24l01_ce_pin_active(void);
+bool nrf24l01_csn_pin_active(void);
+
+//low-level functions for library use only
+unsigned char nrf24l01_execute_command(unsigned char instruction, unsigned char * data, unsigned int len, bool copydata);
+void nrf24l01_spi_send_read(unsigned char * data, unsigned int len, bool copydata);
+
+#endif /*NRF24L01_H_*/