stable library for the Nordic NRF24L01+ radio transciever

nrf24l01p.cpp

Committer:
emoninet2
Date:
2016-11-21
Revision:
0:795de307e97f

File content as of revision 0:795de307e97f:

/* 
* nrf24l01p.cpp
*
* Created: 29-Mar-16 10:57:13 PM
* Author: emon1
*/

#include "nrf24l01p.h"

// default constructor
//nrf24l01p::nrf24l01p()
//{
//  init();
//} //nrf24l01p

nrf24l01p::nrf24l01p(PinName mosi, 
                     PinName miso, 
                     PinName sck, 
                     PinName csn,
                     PinName ce,
                     PinName irq) 
: spi_(mosi, miso, sck), nCS_(csn), ce_(ce), nIRQ_(irq) {

}

void nrf24l01p::arch_nrf24l01p_ce_pin(bool state){
    ce_ = state;
}   
void nrf24l01p::arch_nrf24l01p_csn_pin(bool state){
    nCS_ = state;
}   
void nrf24l01p::arch_nrf24l01p_initialize(){
}

void nrf24l01p::arch_spi_master_transcieve(uint8_t *data, int len){
    int i=0;
    for(i=0;i<len;i++){
        data[i] = spi_.write(data[i]);   
    }


}




void nrf24l01p::ce_pin(bool state){
    arch_nrf24l01p_ce_pin(state);
    if(state) _nrf24l01p_delay_us(_NRF24L01P_TIMING_Thce_us);
    //_nrf24l01p_ce_value = state;
}
void nrf24l01p::csn_pin(bool state){

    arch_nrf24l01p_csn_pin(state);
    //_nrf24l01p_csn_value = state;
}






void nrf24l01p::read_register(uint8_t address, uint8_t *data, int len){

    csn_pin(0);
    uint8_t temp = (address&(_NRF24L01P_REG_ADDRESS_MASK));
    arch_spi_master_transcieve(&temp,1);
    arch_spi_master_transcieve(data,len);
    csn_pin(1);
}

void nrf24l01p::write_register(uint8_t address, uint8_t *data, int len){
    csn_pin(0);
    uint8_t temp = (( _NRF24L01P_SPI_CMD_WR_REG | (address&(_NRF24L01P_REG_ADDRESS_MASK))));
    arch_spi_master_transcieve(&temp,1);
    arch_spi_master_transcieve(data,len);
    csn_pin(1);
}



void nrf24l01p::read_rx_payload(uint8_t *data, int pay_len){
    csn_pin(0);
    uint8_t temp = (_NRF24L01P_SPI_CMD_RD_RX_PAYLOAD);
    arch_spi_master_transcieve(&temp,1);
    arch_spi_master_transcieve(data,pay_len);
    csn_pin(1);
}
void nrf24l01p::write_tx_payload(uint8_t *data, int pay_len){
    csn_pin(0);
    uint8_t temp = (_NRF24L01P_SPI_CMD_WR_TX_PAYLOAD);
    arch_spi_master_transcieve(&temp,1);
    arch_spi_master_transcieve(data,pay_len);
    csn_pin(1);
}

void nrf24l01p::flush_tx(){
    csn_pin(0);
    uint8_t temp = (_NRF24L01P_SPI_CMD_FLUSH_TX);
    arch_spi_master_transcieve(&temp,1);
    csn_pin(1);
}
void nrf24l01p::flush_rx(){
    csn_pin(0);
    uint8_t temp = (_NRF24L01P_SPI_CMD_FLUSH_RX);
    arch_spi_master_transcieve(&temp,1);
    csn_pin(1);
}
void nrf24l01p::reuse_tx_payload(){
    csn_pin(0);
    uint8_t temp = (_NRF24L01P_SPI_CMD_REUSE_TX_PL);
    arch_spi_master_transcieve(&temp,1);
    csn_pin(1);
}
int nrf24l01p::read_rx_payload_width(){
    csn_pin(0);
    uint8_t temp = (_NRF24L01P_SPI_CMD_R_RX_PL_WID);
    uint8_t temp2 = 0xff;
    arch_spi_master_transcieve(&temp,1);
    arch_spi_master_transcieve(&temp2,1);
    csn_pin(1);
    return temp2;
}

void nrf24l01p::write_ack_payload(_nrf24l01p_pipe_t pipe, uint8_t *data, int pay_len){
    csn_pin(0);
    uint8_t temp = (_NRF24L01P_SPI_CMD_W_ACK_PAYLOAD | pipe);
    arch_spi_master_transcieve(&temp,1);
    arch_spi_master_transcieve(data,pay_len);
    csn_pin(1);
}
void nrf24l01p::write_tx_payload_noack(uint8_t *data, int pay_len){
    csn_pin(0);
    uint8_t temp = (_NRF24L01P_SPI_CMD_W_TX_PYLD_NO_ACK);
    arch_spi_master_transcieve(&temp,1);
    arch_spi_master_transcieve(data,pay_len);
    csn_pin(1);
}

int nrf24l01p::get_status(){
    csn_pin(0);
    uint8_t temp = (_NRF24L01P_SPI_CMD_NOP );
    arch_spi_master_transcieve(&temp,1);
    csn_pin(1);
    return temp;
}



void nrf24l01p::power_up(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_CONFIG,&temp,sizeof(temp));
    temp |= _NRF24L01P_CONFIG_PWR_UP;
    write_register(_NRF24L01P_REG_CONFIG,&temp,sizeof(temp));

}
void nrf24l01p::power_down(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_CONFIG,&temp,sizeof(temp));
    temp &= ~_NRF24L01P_CONFIG_PWR_UP;
    write_register(_NRF24L01P_REG_CONFIG,&temp,sizeof(temp));

}
void nrf24l01p::rx_mode(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_CONFIG,&temp,sizeof(temp));
    temp |= _NRF24L01P_CONFIG_PRIM_RX;
    write_register(_NRF24L01P_REG_CONFIG,&temp,sizeof(temp));
    
}
void nrf24l01p::tx_mode(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_CONFIG,&temp,sizeof(temp));
    temp &= ~_NRF24L01P_CONFIG_PRIM_RX;
    write_register(_NRF24L01P_REG_CONFIG,&temp,sizeof(temp));
    
}
void nrf24l01p::set_CRC(_nrf24l01p_crc_t opt){
    uint8_t temp;
    read_register(_NRF24L01P_REG_CONFIG,&temp,sizeof(temp));
    temp &= ~(_NRF24L01P_CONFIG_CRC_MASK);
    temp |= opt;
    write_register(_NRF24L01P_REG_CONFIG,&temp,sizeof(temp));
}

void nrf24l01p::enable_auto_ack(_nrf24l01p_pipe_t pipe){
    uint8_t temp;
    read_register(_NRF24L01P_REG_EN_AA,&temp,sizeof(temp));
    set_bit(temp,pipe);
    write_register(_NRF24L01P_REG_EN_AA,&temp,sizeof(temp));
}
void nrf24l01p::disable_auto_ack(_nrf24l01p_pipe_t pipe){
    uint8_t temp;
    read_register(_NRF24L01P_REG_EN_AA,&temp,sizeof(temp));
    clr_bit(temp,pipe);
    write_register(_NRF24L01P_REG_EN_AA,&temp,sizeof(temp));
}
void nrf24l01p::disable_auto_ack_all_pipes(){
    uint8_t temp = 0;
    write_register(_NRF24L01P_REG_EN_AA,&temp,sizeof(temp));
}

void nrf24l01p::enable_rx_on_pipe(_nrf24l01p_pipe_t pipe){
    uint8_t temp;
    read_register(_NRF24L01P_REG_EN_RXADDR,&temp,sizeof(temp));
    set_bit(temp,pipe);
    write_register(_NRF24L01P_REG_EN_RXADDR,&temp,sizeof(temp));
}
void nrf24l01p::disable_rx_on_pipe(_nrf24l01p_pipe_t pipe){
    uint8_t temp;
    read_register(_NRF24L01P_REG_EN_RXADDR,&temp,sizeof(temp));
    clr_bit(temp,pipe);
    write_register(_NRF24L01P_REG_EN_RXADDR,&temp,sizeof(temp));
}


void nrf24l01p::set_address_width(_nrf24l01p_aw_t width){
    uint8_t temp = width;
    write_register(_NRF24L01P_REG_SETUP_AW,&temp,sizeof(temp));
}

_nrf24l01p_aw_t nrf24l01p::get_address_width(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_SETUP_AW,&temp,sizeof(temp));
    return (_nrf24l01p_aw_t) temp;
}

void nrf24l01p::set_auto_retransmission_count(uint8_t count){
    uint8_t temp;
    read_register(_NRF24L01P_REG_SETUP_RETR,&temp,sizeof(temp));
    temp &= ~ 0x0F;
    temp |= (count<<0);
    write_register(_NRF24L01P_REG_SETUP_RETR,&temp,sizeof(temp));
}
uint8_t nrf24l01p::read_auto_retransmission_count(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_SETUP_RETR,&temp,sizeof(temp));
    return temp & 0x0F;
}
void nrf24l01p::set_auto_retransmission_delay(uint8_t times250us){
    uint8_t temp;
    read_register(_NRF24L01P_REG_SETUP_RETR,&temp,sizeof(temp));
    temp &= ~(0xF0);
    temp |= (times250us<<4);
    write_register(_NRF24L01P_REG_SETUP_RETR,&temp,sizeof(temp));
}
uint8_t nrf24l01p::read_auto_retransmission_delay(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_SETUP_RETR,&temp,sizeof(temp));
    return temp & 0xF0;
}



void nrf24l01p::set_frequency_offset(uint8_t offset){
    if( (offset >=0)  && ( offset <= 125)){
        write_register(_NRF24L01P_REG_RF_CH,&offset,sizeof(offset));
    }
}
uint8_t nrf24l01p::get_frequency_offset(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_RF_CH,&temp,sizeof(temp));
    return temp;
}

void nrf24l01p::set_DataRate(_nrf24l01p_datarate_t DataRate){
    uint8_t temp;
    read_register(_NRF24L01P_REG_RF_SETUP,&temp,sizeof(temp));
    temp &= ~_NRF24L01P_RF_SETUP_RF_DR_MASK;
    temp |= DataRate;
    write_register(_NRF24L01P_REG_RF_SETUP,&temp,sizeof(temp));
    
}
_nrf24l01p_datarate_t nrf24l01p::get_DataRate(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_RF_SETUP,&temp,sizeof(temp));
    temp &= _NRF24L01P_RF_SETUP_RF_DR_MASK;
    return (_nrf24l01p_datarate_t) temp;
}
void nrf24l01p::set_RF_Power(_nrf24l01p_RFpower_t RFpower){
    uint8_t temp;
    read_register(_NRF24L01P_REG_RF_SETUP,&temp,sizeof(temp));
    temp &= ~_NRF24L01P_RF_SETUP_RF_PWR_MASK;
    temp |= RFpower;
    write_register(_NRF24L01P_REG_RF_SETUP,&temp,sizeof(temp));
}
_nrf24l01p_RFpower_t nrf24l01p::get_RF_Power(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_RF_SETUP,&temp,sizeof(temp));
    temp &= _NRF24L01P_RF_SETUP_RF_PWR_MASK;
    return (_nrf24l01p_RFpower_t) temp;
}


bool nrf24l01p::get_tx_fifo_full_flag(){
    bool flag;
    //(get_status()&_NRF24L01P_STATUS_TX_FULL)?flag = 1 : flag = 0;
    
    if(get_status()&_NRF24L01P_STATUS_TX_FULL) flag = 1;
    else flag = 0;

    return flag;
}
bool nrf24l01p::get_max_retry_flag(){
    bool flag;
    //(get_status()&_NRF24L01P_STATUS_MAX_RT)?flag = 1 : flag = 0;
    if(get_status()&_NRF24L01P_STATUS_MAX_RT) flag = 1;
    else flag  = 0;
    return flag;
}


void nrf24l01p::clear_max_retry_flag(){
    uint8_t temp = get_status();
    temp |= _NRF24L01P_STATUS_MAX_RT;
    write_register(_NRF24L01P_REG_STATUS,&temp,sizeof(temp));
}

bool nrf24l01p::get_data_sent_flag(){
    bool flag;
    //(get_status()&_NRF24L01P_STATUS_TX_DS)?flag = 1 : flag = 0;
    if(get_status()&_NRF24L01P_STATUS_TX_DS) flag = 1;
    else flag  = 0;
    return flag;
}

void nrf24l01p::clear_data_sent_flag(){
    uint8_t temp = get_status();
    temp |= _NRF24L01P_STATUS_TX_DS;
    write_register(_NRF24L01P_REG_STATUS,&temp,sizeof(temp));
}

bool nrf24l01p::get_data_ready_flag(){
    bool flag;
    if(get_status()&_NRF24L01P_STATUS_RX_DR)flag = 1  ;
    else flag = 0;
    return flag;
}

void nrf24l01p::clear_data_ready_flag(){
    uint8_t temp = get_status();
    temp |= _NRF24L01P_STATUS_RX_DR;
    write_register(_NRF24L01P_REG_STATUS,&temp,sizeof(temp));
}

_nrf24l01p_pipe_t nrf24l01p::get_rx_payload_pipe(){
    _nrf24l01p_pipe_t pipe = (_nrf24l01p_pipe_t) ((get_status()&_NRF24L01P_STATUS_RX_P_NO)>>1);
    return pipe;
}

uint8_t nrf24l01p::get_arc_count(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_OBSERVE_TX,&temp,sizeof(temp));
    return ((temp>>_NRF24L01P_OBSERVE_TX_ARC_CNT_BP)&_NRF24L01P_OBSERVE_TX_ARC_CNT_MASK);

}
uint8_t nrf24l01p::get_plos_count(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_OBSERVE_TX,&temp,sizeof(temp));
    return ((temp>>_NRF24L01P_OBSERVE_TX_PLOS_CNT_BP)&_NRF24L01P_OBSERVE_TX_PLOS_CNT_MASK);
}

bool nrf24l01p::get_rpd(){
    uint8_t temp;
    bool flag;
    read_register(_NRF24L01P_REG_RPD,&temp,sizeof(temp));
    if(temp!=0) flag = 1  ;
    else flag = 0;
    return flag;
}

void nrf24l01p::set_RX_pipe_address(_nrf24l01p_pipe_t pipe,uint64_t address){
    int max_pipe_addr_width = 0;

    if((pipe>=0) && (pipe<=1)   )
    {
        max_pipe_addr_width = 5;
    }
    else if ((pipe>=2) && (pipe<=5)   ){
        max_pipe_addr_width = 1;
    }
    
    
    
    uint8_t temp[5];
    int i;
    for(i=0;i<max_pipe_addr_width;i++){
        temp[i] = (address>>(8*i))&0xFF;
    }
    write_register(_NRF24L01P_REG_RX_ADDR_P0 + pipe,temp,max_pipe_addr_width);
    
}
uint64_t nrf24l01p::get_RX_pipe_address(_nrf24l01p_pipe_t pipe){
    
    int max_pipe_addr_width = 0;

    if((pipe>=0) && (pipe<=1)   )
    {
        max_pipe_addr_width = 5;
    }
    else if ((pipe>=2) && (pipe<=5)   ){
        max_pipe_addr_width = 1;
    }
    
    uint8_t temp[5];
    read_register(_NRF24L01P_REG_RX_ADDR_P0 + pipe,temp,max_pipe_addr_width);
    
    uint64_t temp_addr = 0;
    uint8_t *temp_addr_ptr = (uint8_t*) &temp_addr;
    int i;
    for(i=0;i<max_pipe_addr_width;i++){
        *(temp_addr_ptr+i)|= (temp[i]);
    }
    
    return temp_addr;   
}

void nrf24l01p::set_TX_pipe_address(uint64_t address){
    uint8_t temp[5];
    int i;
    for( i=0;i<5;i++){
        temp[i] = (address>>(8*i))&0xFF;
    }
    write_register(_NRF24L01P_REG_TX_ADDR,temp,5);
}

uint64_t nrf24l01p::get_TX_pipe_address(){
    uint8_t temp[5];
    read_register(_NRF24L01P_REG_TX_ADDR,temp,5);
    
    uint64_t temp_addr = 0;
    uint8_t *temp_addr_ptr = (uint8_t*) &temp_addr;
    int i;
    for(i=0;i<5;i++){
        *(temp_addr_ptr+i)|= (temp[i]);
    }

    return temp_addr;
    
}
uint8_t nrf24l01p::get_RX_pipe_width(_nrf24l01p_pipe_t pipe){
    uint8_t temp;
    read_register((_NRF24L01P_REG_RX_PW_P0+pipe),&temp,sizeof(temp));
    return (temp&(0x3F));
}
bool nrf24l01p::get_fifo_flag_rx_empty(){
    uint8_t temp;
    bool flag;
    read_register(_NRF24L01P_REG_FIFO_STATUS,&temp,sizeof(temp));
    if(temp&_NRF24L01P_FIFO_STATUS_RX_EMPTY) flag = 1 ;
    else flag = 0;
    return flag;
    
}
bool nrf24l01p::get_fifo_flag_rx_full(){
    uint8_t temp;
    bool flag;
    read_register(_NRF24L01P_REG_FIFO_STATUS,&temp,sizeof(temp));
    if(temp&_NRF24L01P_FIFO_STATUS_RX_FULL) flag = 1 ;
    else flag = 0;
    return flag;
}
bool nrf24l01p::get_fifo_flag_tx_empty(){
    uint8_t temp;
    bool flag;
    read_register(_NRF24L01P_REG_FIFO_STATUS,&temp,sizeof(temp));
    if(temp&_NRF24L01P_FIFO_STATUS_TX_EMPTY) flag = 1 ;
    else flag = 0;
    return flag;
}

bool nrf24l01p::get_fifo_flag_tx_full(){
    uint8_t temp;
    bool flag;
    read_register(_NRF24L01P_REG_FIFO_STATUS,&temp,sizeof(temp));
    if(temp&_NRF24L01P_FIFO_STATUS_TX_FULL) flag = 1 ;
    else flag = 0;
    return flag;
}
bool nrf24l01p::get_fifo_flag_tx_reuse(){
    uint8_t temp;
    bool flag;
    read_register(_NRF24L01P_REG_FIFO_STATUS,&temp,sizeof(temp));
    if(temp&_NRF24L01P_FIFO_STATUS_RX_REUSE) flag = 1 ;
    else flag = 0;
    return flag;
}

void nrf24l01p::enable_dynamic_payload_pipe(_nrf24l01p_pipe_t pipe){
    uint8_t temp;
    read_register(_NRF24L01P_REG_DYNPD,&temp,sizeof(temp));
    temp |= (1<<pipe);
    write_register(_NRF24L01P_REG_DYNPD,&temp,sizeof(temp));
}
void nrf24l01p::disable_dynamic_payload_pipe(_nrf24l01p_pipe_t pipe){
    uint8_t temp;
    read_register(_NRF24L01P_REG_DYNPD,&temp,sizeof(temp));
    temp &= ~(1<<pipe);
    write_register(_NRF24L01P_REG_DYNPD,&temp,sizeof(temp));
}
void nrf24l01p::disable_dynamic_payload_all_pipe(){
    uint8_t temp = 0x00;
    write_register(_NRF24L01P_REG_DYNPD,&temp,sizeof(temp)); 
}
void nrf24l01p::enable_dynamic_payload(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_FEATURE,&temp,sizeof(temp));
    temp |= _NRF24L01_FEATURE_EN_DPL;
    write_register(_NRF24L01P_REG_FEATURE,&temp,sizeof(temp));
}
void nrf24l01p::disable_dynamic_payload(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_FEATURE,&temp,sizeof(temp));
    temp &= ~_NRF24L01_FEATURE_EN_DPL;
    write_register(_NRF24L01P_REG_FEATURE,&temp,sizeof(temp));
}
void nrf24l01p::enable_payload_with_ack(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_FEATURE,&temp,sizeof(temp));
    temp |= _NRF24L01_FEATURE_EN_ACK_PAY;
    write_register(_NRF24L01P_REG_FEATURE,&temp,sizeof(temp));
}
void nrf24l01p::disable_payload_with_ack(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_FEATURE,&temp,sizeof(temp));
    temp &= ~_NRF24L01_FEATURE_EN_ACK_PAY;
    write_register(_NRF24L01P_REG_FEATURE,&temp,sizeof(temp));
}
void nrf24l01p::enable_dynamic_payload_with_ack(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_FEATURE,&temp,sizeof(temp));
    temp |= _NRF24L01_FEATURE_EN_DYN_ACK;
    write_register(_NRF24L01P_REG_FEATURE,&temp,sizeof(temp));
}
void nrf24l01p::disable_dynamic_payload_with_ack(){
    uint8_t temp;
    read_register(_NRF24L01P_REG_FEATURE,&temp,sizeof(temp));
    temp &= ~_NRF24L01_FEATURE_EN_DYN_ACK;
    write_register(_NRF24L01P_REG_FEATURE,&temp,sizeof(temp));
}

void nrf24l01p::init(){
    arch_nrf24l01p_initialize();
    
    startup();
    default_config();
}

int nrf24l01p::startup(){
    ce_pin(0);
    csn_pin(0);
    
    _nrf24l01p_delay_ms(_NRF24L01P_TIMING_PowerOnReset_ms);
    
    stateMode(_NRF24L01P_MODE_POWER_DOWN);
    stateMode(_NRF24L01P_MODE_RX);
    
    clear_data_ready_flag();
    flush_rx();
    flush_tx();
    
    uint8_t status_rst_val = 0x0e;//reset status
    write_register(_NRF24L01P_REG_STATUS, &status_rst_val,1);
    uint8_t config_rst_val = 0x0b;//reset config
    write_register(_NRF24L01P_REG_CONFIG, &config_rst_val,1);
    
    return 0;
}

int nrf24l01p::default_config(){
    
    disable_auto_ack_all_pipes();
    disable_dynamic_payload_all_pipe();/////////ALSO CREEATE FOR DISABLE AUTO ACK FOR ALL PIPE
    //_nrf24l01p_startup();
    
    
    enable_dynamic_payload();
    enable_payload_with_ack();

    enable_auto_ack(_NRF24L01P_PIPE_P0);
    enable_auto_ack(_NRF24L01P_PIPE_P1);
    enable_auto_ack(_NRF24L01P_PIPE_P2);
    enable_auto_ack(_NRF24L01P_PIPE_P3);
    enable_auto_ack(_NRF24L01P_PIPE_P4);
    enable_auto_ack(_NRF24L01P_PIPE_P5);

    enable_dynamic_payload_pipe(_NRF24L01P_PIPE_P0);
    enable_dynamic_payload_pipe(_NRF24L01P_PIPE_P1);
    enable_dynamic_payload_pipe(_NRF24L01P_PIPE_P2);
    enable_dynamic_payload_pipe(_NRF24L01P_PIPE_P3);
    enable_dynamic_payload_pipe(_NRF24L01P_PIPE_P4);
    enable_dynamic_payload_pipe(_NRF24L01P_PIPE_P5);

    enable_rx_on_pipe(_NRF24L01P_PIPE_P0);
    enable_rx_on_pipe(_NRF24L01P_PIPE_P1);
    enable_rx_on_pipe(_NRF24L01P_PIPE_P2);
    enable_rx_on_pipe(_NRF24L01P_PIPE_P3);
    enable_rx_on_pipe(_NRF24L01P_PIPE_P4);
    enable_rx_on_pipe(_NRF24L01P_PIPE_P5);

    set_auto_retransmission_count(15);
    set_auto_retransmission_delay(15);
    set_DataRate(_NRF24L01P_RF_SETUP_RF_DR_250KBPS);
    
    return 0;
}

int nrf24l01p::stateMode(nRF24L01P_Mode_Type mode){
    switch(mode){
        case _NRF24L01P_MODE_POWER_DOWN: {
            power_down();
            ce_pin(0);
            _nrf24l01p_mode = _NRF24L01P_MODE_POWER_DOWN;
            break;
        }
        case _NRF24L01P_MODE_STANDBY: {
            if(_nrf24l01p_mode == _NRF24L01P_MODE_POWER_DOWN){
                power_up();
                _nrf24l01p_delay_us(_NRF24L01P_TIMING_Tpd2stby_us);
            }
            else{
                ce_pin(0);
            }
            _nrf24l01p_mode = _NRF24L01P_MODE_STANDBY;
            break;
        }
        case _NRF24L01P_MODE_RX: {
            rx_mode();
            ce_pin(1);
            _nrf24l01p_delay_us(_NRF24L01P_TIMING_Tstby2a_us);
            _nrf24l01p_mode = _NRF24L01P_MODE_RX;
            break;
        }
        case _NRF24L01P_MODE_TX: {
            tx_mode();
            ce_pin(1);
            _nrf24l01p_delay_us(_NRF24L01P_TIMING_Tstby2a_us);
            mode = _NRF24L01P_MODE_TX;
            break;
        }       
    }
    
    return 0;
}


bool nrf24l01p::readable(){
    bool HasData = 0;
    HasData = !get_fifo_flag_rx_empty();
    return HasData;
}
bool nrf24l01p::writable(){
    bool HasData = 0;
    HasData = !get_fifo_flag_tx_empty();
    return HasData; 
}




int nrf24l01p::send(uint8_t *data, int datalen){

    if ( datalen <= 0 ) return 0;
    if ( datalen > _NRF24L01P_TX_FIFO_SIZE ) datalen = _NRF24L01P_TX_FIFO_SIZE;

    if(get_tx_fifo_full_flag()) return -1;
    //while(_nrf24l01p_get_tx_fifo_full_flag());

    write_tx_payload(data,datalen);

        
    return 0;
}

int nrf24l01p::send_to_address(uint64_t address, uint8_t *data, int datalen){
    //_nrf24l01p_disable_payload_with_ack();
    set_TX_pipe_address(address);
    return send(data,datalen);
    
}
int nrf24l01p::send_to_address_ack(uint64_t address, uint8_t *data, int datalen){
    //_nrf24l01p_enable_payload_with_ack();
    set_TX_pipe_address(address);
    set_RX_pipe_address(_NRF24L01P_PIPE_P0, address);
    return send(data,datalen);
}





bool nrf24l01p::readableOnPipe(_nrf24l01p_pipe_t pipe){
    bool flag = 0;
    if((pipe >=0)   && (pipe <=5)){
        int status = get_status();
        if(   (status&_NRF24L01P_STATUS_RX_DR)  && ((status&_NRF24L01P_STATUS_RX_P_NO)>>1)==pipe){
            flag = 1;
        }
        else{
            flag = 0;
        }
    }
    return flag;
}


int nrf24l01p::read(_nrf24l01p_pipe_t pipe, uint8_t *data, int datalen){

    int rxPayloadWidth;
    
    if ( ( pipe < 0 ) || ( pipe > 5 ) ) {
        return -1;
    }
    
    if (readableOnPipe(pipe) ) {
        asm("nop");
        rxPayloadWidth = _NRF24L01P_TX_FIFO_SIZE;
        
        if ( ( rxPayloadWidth < 0 ) || ( rxPayloadWidth > _NRF24L01P_RX_FIFO_SIZE ) ) {
            flush_rx();
        }
        else{
            read_rx_payload(data,rxPayloadWidth);
            
            if(get_fifo_flag_rx_empty()) {
                clear_data_ready_flag();
            }
        }

        return rxPayloadWidth;
    }

    //if RX FIFO is full even after reading data, then flush RX FIFO
    if(get_fifo_flag_rx_full()){
        clear_data_ready_flag();
        flush_rx();
    }
    return 0;   
}

int nrf24l01p::read_dyn_pld(_nrf24l01p_pipe_t pipe, uint8_t *data){
    
    int rxPayloadWidth;
    
    if ( ( pipe < 0 ) || ( pipe > 5 ) ) {
        return -1;
    }
    
    if (readableOnPipe(pipe) ) {
        asm("nop");
        rxPayloadWidth = read_rx_payload_width();
    
        if ( ( rxPayloadWidth < 0 ) || ( rxPayloadWidth > _NRF24L01P_RX_FIFO_SIZE ) ) {
            flush_rx();
        }
        else{
            read_rx_payload(data,rxPayloadWidth);
                    
            if(get_fifo_flag_rx_empty()) {
                clear_data_ready_flag();
            }
        }

        return rxPayloadWidth;
    }
    else {//if pipe not readable
        return 0;
    }
    return 0;
}




void nrf24l01p::PTX(){
    

    //backup original machine state
    nRF24L01P_Mode_Type originalMode = _nrf24l01p_mode;
    
    //switching to STANDBY to avoid data reception during state check (ATOMIC state check)
    stateMode(_NRF24L01P_MODE_STANDBY);
    
    //has data to write and no data to read. Do not enter PTX with data in PRX payload.
    //This is because, if the PRX is full, then sending a data and will forever wait for ACK 
    //and it will never get the ACK because the PRX fifo is full 
    if(writable() && !readable()){

        //blocked until data sent
        while(1){
            //clear data sent flag before the next packet is sent
            clear_data_sent_flag();  
            
           //strobe CE for single transmission
           stateMode(_NRF24L01P_MODE_TX);
           _nrf24l01p_delay_us(_NRF24L01P_TIMING_Tstby2a_us);
           stateMode(_NRF24L01P_MODE_STANDBY);
           
           //break when DS flag is set and a single payload is sent or all data on RX FIFO sent
           if(get_data_sent_flag() || !writable()  ) break; 
              
           //if max retry flag is set
           if(get_max_retry_flag() ) {
               break; 
           }
           
           
        }
        //clear data sent flag
        clear_data_sent_flag();   
        
        //if got ack packet, just flush it
        if(get_data_ready_flag()){
            //do what needs to be done with the ACK payload here
            flush_rx();
        }
    }
    //restore original machine state
    stateMode(originalMode);
   
}


void nrf24l01p::PRX(){

    //backup original machine state
    nRF24L01P_Mode_Type originalMode = _nrf24l01p_mode;
    
    //switching to STANDBY to avoid data reception during state check (ATOMIC state check)
    stateMode(_NRF24L01P_MODE_STANDBY);
    
    //if readable (if RX payload data in RX FIFO)
    if(readable()){
        
        while(1){

            char rxData[32];
            _nrf24l01p_pipe_t pipe = get_rx_payload_pipe();
            int width = read_dyn_pld(pipe, (uint8_t*)rxData);
            rxData[width] = '\0';

            //what needs to be done with the data read
            printf("MESG: %s\n", rxData);

            if(!readable()) break; 
            

        }
    }
    //restore original machine state
    stateMode(originalMode);
    
    
}
// default destructor
nrf24l01p::~nrf24l01p()
{
} //~nrf24l01p