diyembedded nrf24l01 tutorial 2 ported to mbed lpc1768
See diyembedded tutorials for more info
-Pull down p20 for receive mode
-Pull up p20 for transmitter mode
Revision 0:2286a98ea739, committed 2012-12-08
- 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
--- /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 + } + } +}
--- /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
--- /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); + } + } +} +
--- /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_*/