Specialized interface code for the nRF24L01P wireless transceiver.

Dependents:   WalkingRobot PcRadioBridge FzeroXcontroller WalkingRobot ... more

Radio.cpp

Committer:
pclary
Date:
2012-12-23
Revision:
0:fb0cf6209cd3
Child:
1:32635715529f

File content as of revision 0:fb0cf6209cd3:

#include "Radio.h"
#include "nRF24L01P_defs.h"



Radio::Radio(PinName mosi, PinName miso, PinName sck, PinName csn, PinName ce, PinName irq) 
: _spi(mosi, miso, sck), _csn(csn), _ce(ce), _irq(irq)
{
    // Disable nRF24L01+
    _ce = 0;
    
    // Disable chip select
    _csn = 1;
    
    // Set up SPI
    _spi.frequency(SPI_FREQUENCY);
    _spi.format(8, 0);
    
    // Power up
    int config = getRegister(CONFIG);
    config |= CONFIG_PWR_UP;
    setRegister(CONFIG, config);
    wait_us(TIMING_Tpd2stby);
    
    // Set to use controller channel 0
    controller = 0;
    
    // Set up IRQ
    _irq.fall(this, &Radio::receive);
}



void Radio::reset()
{
    // Wait for power on reset
    wait_us(TIMING_Tpor);

    // Put into standby
    _ce = 0;
    
    // Configure registers
    setRegister(CONFIG, CONFIG_MASK_TX_DS | CONFIG_MASK_MAX_RT | CONFIG_EN_CRC | CONFIG_PWR_UP | CONFIG_PRIM_RX);
    setRegister(EN_AA, 0x00);
    setRegister(EN_RXADDR, ERX_P0 | ERX_P1);
    setRegister(SETUP_AW, SETUP_AW_3BYTES);
    setRegister(SETUP_RETR, 0x00);
    setRegister(RF_CH, RF_CHANNEL);
    setRegister(RF_SETUP, RF_SETUP_RF_DR_HIGH | RF_SETUP_RF_PWR_0);
    setRegister(STATUS, STATUS_RX_DR | STATUS_TX_DS | STATUS_MAX_RT);
    setRegister(RX_PW_P0, 4);
    setRegister(RX_PW_P1, 4);
    setRegister(DYNPD, 0x00);
    setRegister(FEATURE, 0x00);
    
    // Set addresses
    _csn = 0;
    _spi.write(W_REGISTER | RX_ADDR_P0);
    _spi.write(CTRL_BASE_ADDRESS_1 + (controller & 0xf));
    _spi.write(CTRL_BASE_ADDRESS_2);
    _spi.write(CTRL_BASE_ADDRESS_3);
    _csn = 1;
    _csn = 0;
    _spi.write(W_REGISTER | RX_ADDR_P1);
    _spi.write(ROBOT_ADDRESS_1);
    _spi.write(ROBOT_ADDRESS_2);
    _spi.write(ROBOT_ADDRESS_3);
    _csn = 1;
    _csn = 0;
    _spi.write(W_REGISTER | TX_ADDR);
    _spi.write(ROBOT_ADDRESS_1);
    _spi.write(ROBOT_ADDRESS_2);
    _spi.write(ROBOT_ADDRESS_3);
    _csn = 1;
    
    // Put into PRX
    _ce = 1;
    wait_us(TIMING_Tstby2a);
    
    // Flush FIFOs
    _csn = 0;
    _spi.write(FLUSH_TX);
    _csn = 1;
    _csn = 0;
    _spi.write(FLUSH_RX);
    _csn = 1;
}



void Radio::transmit(uint32_t data)
{
    // Put into standby
    _ce = 0;
    
    // Configure for PTX
    int config = getRegister(CONFIG);
    config &= ~CONFIG_PRIM_RX;
    setRegister(CONFIG, config);
    
    // Write packet data
    _csn = 0;
    _spi.write(W_TX_PAYLOAD);
    _spi.write( (data>>0) & 0xff );
    _spi.write( (data>>8) & 0xff );
    _spi.write( (data>>16) & 0xff );
    _spi.write( (data>>24) & 0xff );
    _csn = 1;
    
    // Put into PTX
    _ce = 1;
    wait_us(TIMING_Tstby2a);
    _ce = 0;
    
    // Wait for message transmission and put into PRX
    wait_us(TIMING_Toa);
    config = getRegister(CONFIG);
    config |= CONFIG_PRIM_RX;
    setRegister(CONFIG, config);
    setRegister(STATUS, STATUS_TX_DS);
    _ce = 1;
}



void Radio::receive()
{
    uint32_t data = 0;
    int pipe;
    
    // Reset IRQ pin
    setRegister(STATUS, STATUS_RX_DR);
    
    // Check data pipe
    wait_us(1000);
    pipe = getStatus() & STATUS_RN_P_MASK;
    
    // Read data
    _csn = 0;
    _spi.write(R_RX_PAYLOAD);
    data |= _spi.write(NOP)<<0;
    data |= _spi.write(NOP)<<8;
    data |= _spi.write(NOP)<<16;
    data |= _spi.write(NOP)<<24;
    _csn = 1;
    
    // Sort into recieve buffer
    switch(pipe)
    {
    case STATUS_RN_P_NO_P0:
        rx_controller = data;
        break;
        
    case STATUS_RN_P_NO_P1:
        rx_robot[rx_robot_pos++ % RX_BUFFER_SIZE] = data;
        break;
        
    default:
        break;
    }
}



int Radio::getRegister(int address)
{
    _csn = 0;
    int rc = R_REGISTER | (address & REGISTER_ADDRESS_MASK);
    _spi.write(rc);
    int data = _spi.write(NOP);
    _csn = 1;
    return data;
}



int Radio::getStatus()
{
    _csn = 0;
    int status = _spi.write(NOP);
    _csn = 1;
    return status;
}


void Radio::setRegister(int address, int data)
{
    bool enabled = false;
    if (_ce == 1)
    {
        enabled = true;
        _ce = 0;
    }
    
    _csn = 0;
    int rc = W_REGISTER | (address & REGISTER_ADDRESS_MASK);
    _spi.write(rc);
    _spi.write(data & 0xff);
    _csn = 1;
    
    if (enabled)
    {
        _ce = 1;
        wait_us(TIMING_Tpece2csn);
    }
    
}