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
nRF24L01P/nrf24l01.cpp
- Committer:
- jeroen3
- Date:
- 2012-12-08
- Revision:
- 0:2286a98ea739
File content as of revision 0:2286a98ea739:
/****************************************************************************** * * 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); } } }