This is a work in progress for an NRF2401P

Dependents:   NRF_receiver sender locker4 Weather_Station_Ofiicial ... more

About

This is a simple library to drive the nRF24l01+.

Hardware

This uses the commonly available breakout. The connections are shown below /media/uploads/epgmdm/nrf24l01pinout.png

Software

Use case: For a simple transmitter

tx code snipet

#include "NRF2401P.h"
int main() {
*
*  long long addr1=0xAB00CD; // setup address - any 5 byte number - same as RX
*  int channel =0x12;  // [0-126] setup channel, must be same as RX
*  bool txOK;
*  char msg[32];
*  char ackData[32];
*  char len;
*
*  // Setup 
*  NRF2401P nrf1(PTD6,PTD7, PTD5,PTD4, PTC12); //mosi, miso, sclk, csn, ce)
*  nrf1.quickTxSetup(channel, addr1); // sets nrf24l01+ as transmitter
*
*  // transmit
*  strcpy (msg, "Hello"); 
*  txOK= nrf1.transmitData(msg,strlen(msg));
*
*  // read ack data if available
*  if (nrf1.isAckData()) { 
*      len= nrf1.getRxData(ackData); // len is number of bytes in ackData
*   }
*}

Use case: For a simple receiver

rx code snipet

#include "NRF2401P.h"
*int main(){
*        
*  long long addr1=0xAB00CD; // setup address - any 5 byte number - same as TX
*  int channel =0x12;  // [0-126] setup channel, must be same as TX
*  bool txOK;
*  char msg[32];
*  char ackData[32];
*  char len;
*
*  // Setup 
*  NRF2401P nrf1(PTD6,PTD7, PTD5,PTD4, PTC12); //mosi, miso, sclk, csn, ce)
*  nrf1.quickRxSetup(channel, addr1); // sets nrf24l01+ as  receiver, using pipe 1
*
*  // set ack data
*  sprintf(ackData,"Ack data");
*  nrf1.acknowledgeData(ackData, strlen(ackData),1); // ack for pipe 1
*    
*  // receive
*  while (! nrf1.isRxData()); // note this blocks until RX data
*  len= nrf1.getRxData(msg); // gets the message, len is length of msg
*
*}
Revision:
0:8fd0531ae0be
Child:
1:ff53b1ac3bad
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NRF2401P.cpp	Thu Jun 11 11:19:57 2015 +0000
@@ -0,0 +1,550 @@
+#include "mbed.h"
+#include "NRF2401P.h"
+
+/**
+ *@section DESCRIPTION
+ * mbed NRF2401+  Library
+ *@section LICENSE
+ * Copyright (c) 2015, Malcolm McCulloch
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ * @file "NRF2401P.cpp"
+ */
+
+
+
+NRF2401P::NRF2401P ( PinName mosi, PinName miso, PinName sclk, PinName _csn, PinName _ce ) :
+    csn( DigitalOut( _csn ) ), ce( DigitalOut( _ce ) )
+{
+    addressWidth = 5;
+    pc = new Serial( USBTX, USBRX ); // tx, rx
+    sprintf(logMsg, "Initialise " );
+    log(logMsg);
+    spi = new SPI( mosi, miso, sclk, NC );  //SPI (PinName mosi, PinName miso, PinName sclk, PinName _unused=NC)
+    spi->frequency( 10000000 ); // 1MHZ max 10 MHz
+    spi->format( 8, 0 ); // 0: 0e 08; 1: 0e 00; 2:0e 00 ;3:1c 00
+    csn = 1;
+    ce = 0;
+    dynamic = false;
+    debug=false;
+
+};
+
+/**
+* writes to pc and waits
+*/
+void NRF2401P::log (char *msg)
+{
+    if(debug) {
+        pc->printf("%s \t %s\n\r",statusString(), msg);
+        wait(0.1);
+    };
+}
+
+void NRF2401P::scratch()
+{
+    int status = 0;
+    int register1 = 0;
+    ce = 0;
+    for ( char i = 0; i < 24; i++ ) {
+        csn = 0;
+        //wait_us(100);
+        status = spi->write( i );
+        register1 = spi->write( 0x00 );
+        csn = 1;
+        sprintf(logMsg, "  register %02x (%02x) = %02x", i, status, register1 );
+        log(logMsg);
+    }
+
+}
+/**
+* Sets up a reciever using shockburst and dynamic payload. Uses pipe 1
+* defaults to 5 bytes
+*/
+void NRF2401P::quickRxSetup(int channel,long long addr)
+{
+    setRadio(0,3);
+    setChannel(channel);
+    setRxMode();
+    setPwrUp();
+    setAddressWidth(3);
+    setRxAddress(addr,1);
+    setDynamicPayload();
+    writeReg(0x02,0x03); // EN_RXADDR for P1 and P0
+    writeReg(0x01,0x3f); // EN_AA regi for P1 and P0
+
+    ce=1;
+    wait (0.1f);
+}
+/**
+* Sets up for receive of a message to address 0XA0A0A0
+*/
+
+char NRF2401P::testReceive()
+{
+    char message[64];
+    char width;
+    int channel = 0x12;
+    long long addr=0xA0B0C0;
+    debug = true;
+    quickRxSetup(channel, addr);
+
+    while (1) {
+        while (!isRxData()) {
+            //wait(0.5);
+        };
+        width=getRxData(message);
+        message[width]='\0';
+        sprintf(logMsg,"Received= [%s]",message);
+        log(logMsg);
+    };
+}
+
+/**
+* Sets up a transmitter using shockburst and dynamic payload. Uses pipe 1
+* defaults to 5 bytes
+*/
+void NRF2401P::quickTxSetup(int channel,long long addr)
+{
+    setRadio(0,3);
+    setChannel(channel);
+
+    setTxMode();
+    setPwrUp();
+    setDynamicPayload();
+    setAddressWidth(3);
+    setTxAddress(addr);
+    ce=1;
+    wait (0.0016f); // wait for pll to settle
+}
+
+/**
+* Sets up for transmit of a message to address 0XA0A0A0
+*/
+
+char NRF2401P::testTransmit()
+{
+    long long addr=0xA0B0C0;
+    int channel = 0x12;
+    char data[32] ;
+    int i=0;
+    quickRxSetup(channel, addr);
+    while (1) {
+        sprintf(data," packet %03d", i++ |100);
+        transmitData(data,18);
+        wait (1.0);
+    }
+
+}
+/**
+*Speed :
+‘0x00’ – 1Mbps
+‘0x01’ – 2Mbps
+‘0x02’ – 250kbps
+‘0x03’ – Reserved
+Power:
+'0x00' – -18dBm
+'0x01' – -12dBm
+'0x02' – -6dBm
+'0x03' – 0dBm
+*/
+char NRF2401P::setRadio(char speed,char power)
+{
+    char val=0;
+    sprintf(logMsg, "Set radio");
+    log(logMsg);
+    if (speed & 0x02) {
+        val |= (1<<5);
+    }
+    val |= (speed & 0x01)<<3;
+
+    val |= ((power &0x03)<<1);
+    writeReg (0x06,val);
+
+}
+/**
+Set RF_CH = chan;
+
+F0= 2400 + chan [MHz]
+*/
+char NRF2401P::setChannel(char chan)
+{
+    sprintf(logMsg, "Set channel");
+    log(logMsg);
+    writeReg (0x05,(chan&0x7f));
+}
+/**
+* Transmits width bytes of data. width <32
+*/
+char NRF2401P::transmitData( char *data, char width )
+{
+    ce = 1;
+    csn = 0;
+    char address = 0XA0;
+    int i;
+    // set up for writing
+    status = spi->write( address );
+    for ( i = 0; i <width; i++ ) {
+        spi->write( data[ i ] );
+    }
+    csn = 1;
+    sprintf(logMsg, "  Transmit data %d bytes to %02x (%02x) = %02x", width, address, status, data );
+    log(logMsg);
+    return status;
+
+}
+
+/**
+* sets acknowledge data width bytes of data. width <32
+*/
+char NRF2401P::acknowledgeData( char *data, char width, char pipe=1 )
+{
+    ce = 1;
+    csn = 0;
+    writeReg(0x1d,0x06); // enable payload with ack
+    char address = 0XA8| (pipe&0x07);
+    int i;
+    // set up for writing
+    status = spi->write( address );
+    for ( i = 0; i <width; i++ ) {
+        spi->write( data[ i ] );
+    }
+    csn = 1;
+    sprintf(logMsg, "  acknowledge data %d bytes to %02x (%02x) = %02x", width, address, status, *data );
+    log(logMsg);
+    return status;
+
+}
+/**
+* Writes 1 byte data to a register
+**/
+char NRF2401P::writeReg( char address, char data )
+{
+    char status = 0;
+    char reg;
+    csn = 0;
+    address &= 0x1F;
+    reg = address | 0x20;
+    status = spi->write( reg );
+    spi->write( data );
+    csn = 1;
+    sprintf(logMsg, "  register write %02x (%02x) = %02x", address, status, data );
+    log(logMsg);
+    return status;
+}
+/**
+* Writes width bytes data to a register, ls byte to ms byte /for adressess
+**/
+char NRF2401P::writeReg( char address, char *data, char width )
+{
+    char reg;
+    csn = 0;
+    int i;
+    // set up for writing
+    address &= 0x1F;
+    reg = address| 0x20;
+    status = spi->write( reg );
+    for ( i = width - 1; i >= 0; i-- ) {
+        spi->write( data[ i ] );
+    }
+    csn = 1;
+    sprintf(logMsg, "  register write %d bytes to %02x (%02x) = %02x %02x %02x", width, address, status, data[0], data[1], data[2] );
+    log(logMsg);
+    return status;
+}
+/**
+* Reads 1 byte from a register
+**/
+char NRF2401P::readReg( char address, char *data )
+{
+    csn = 0;
+    address &= 0x1F;
+    status = spi->write( address );
+    *data = spi->write( 0x00 );
+    csn = 1;
+    // sprintf(logMsg, "  register read %02x (%02x) = %02x", address, status, *data );
+    // log(logMsg);
+    return status;
+}
+/**
+* Clears the status flags RX_DR, TX_DS, MAX_RT
+*/
+bool NRF2401P::clearStatus()
+{
+    status = writeReg(0x07,0x70);
+    sprintf(logMsg, "Clear status (%02x)", status );
+    log(logMsg);
+}
+/**
+* flushes TX FIFO and resets status flags
+*/
+bool NRF2401P::flushTx()
+{
+    csn = 0;
+    status = spi->write( 0xE1 );
+    csn = 1;
+    clearStatus();
+    sprintf(logMsg, "Flush TX FIFO (%02x)", status );
+    log(logMsg);
+    return;
+}
+
+/**
+* flushes RX FIFO and resets status flags
+*/
+bool NRF2401P::flushRx()
+{
+    csn = 0;
+    status = spi->write( 0xE2 );
+    status = spi->write( 0xFF ); //Update status
+    csn = 1;
+    sprintf(logMsg, "Flush RX FIFO (%02x)", status );
+    log(logMsg);
+}
+/**
+* Sets PRIM_RX = 0;
+*/
+bool NRF2401P::setTxMode()
+{
+    char data;
+    char bit;
+    sprintf(logMsg, "Set Tx Mode");
+    log(logMsg);
+    readReg( 0x00, &data );
+    data &= ~( 1 << 0 );
+    writeReg( 0x00, data );
+    // check
+    readReg( 0x00, &data );
+    bit = ( data >> 0 ) & 1;
+    ce=1;
+    clearStatus();
+    flushTx();
+    wait(0.003);
+    return ( bit == 0 );
+}
+
+/**
+* Sets the number of bytes of the address width = 3,4,5
+*/
+bool NRF2401P::setAddressWidth( char width )
+{
+    addressWidth = width;
+    if ( ( width > 5 ) || ( width < 3 ) )
+        return false;
+    width -= 2;
+    return writeReg( 0x03, width );
+
+}
+/**
+* Sets the address, uses addess width set (either 3,4 or 5)
+*/
+char NRF2401P::setTxAddress( char *address )
+{
+    writeReg( 0x0A, address, addressWidth ); //Write to RX_ADDR_P0
+    return writeReg( 0x10, address, addressWidth );  //Write to TX_ADDR
+
+}
+
+/**
+* Sets the address, uses addess width set (either 3,4 or 5)
+*/
+char NRF2401P::setTxAddress( long long address )
+{
+
+    char buff[ 5 ];
+    buff[ 0 ] = address & 0xff;
+    buff[ 1 ] = ( address >> 8 ) & 0xFF;
+    buff[ 2 ] = ( address >> 16 ) & 0xFF;
+    buff[ 3 ] = ( address >> 24 ) & 0xFF;
+    buff[ 4 ] = ( address >> 32 ) & 0xFF;
+    return setTxAddress( buff );
+
+}
+
+/**
+* Sets the address, uses addess width set (either 3,4 or 5)
+*/
+char NRF2401P::setRxAddress( char *address, char pipe )
+{
+    log ("Set Rx Address");
+    char reg = 0x0A + pipe;
+    switch ( pipe ) {
+        case ( 0 ) :
+        case ( 1 ) : {
+            status = writeReg( reg, address, addressWidth ); //Write to RX_ADDR_P0 or _P1
+            break;
+        }
+        case ( 2 ) :
+        case ( 3 ) :
+        case ( 4 ) :
+        case ( 5 ) : {
+            status = writeReg( reg, address, 1 ); //Write to RX_ADDR_P2 ... _P5
+            break;
+        }
+
+    }
+    // writeReg( 0x0A, address, addressWidth ); //Write to RX_ADDR_P0
+    return status;
+
+}
+
+/**
+* Sets the address of pipe (<=5), uses addess width set (either 3,4 or 5)
+*/
+char NRF2401P::setRxAddress( long long address, char pipe )
+{
+    char buff[ 5 ];
+    buff[ 0 ] = address & 0xff;
+    buff[ 1 ] = ( address >> 8 ) & 0xFF;
+    buff[ 2 ] = ( address >> 16 ) & 0xFF;
+    buff[ 3 ] = ( address >> 24 ) & 0xFF;
+    buff[ 4 ] = ( address >> 32 ) & 0xFF;
+    return setRxAddress( buff, pipe );
+}
+
+bool NRF2401P::isRxData()
+{
+    readReg(0x07,&status);
+    bool isData = (status>>6)&0x01;
+    return isData;
+}
+/**
+* returns the width of the dynamic payload
+*/
+char NRF2401P::getRxWidth()
+{
+    char width;
+    if (dynamic) {
+        csn = 0;
+        status = spi->write( 0x60 );
+        width = spi->write(0x00);
+        csn = 1;
+
+        if (width>32) {
+            flushRx();
+            width=0;
+        }
+    } else {
+        status = readReg(0x12,&width); // width of p1
+
+    }
+   // width=18;
+    return width;
+}
+/**
+* return message in buffer, mem for buffer must have been allocated.
+* Return value is number of bytes of buffer
+*/
+char  NRF2401P::getRxData(char * buffer)
+{
+    char address = 0x61;
+    char width;
+    width = getRxWidth();
+    bool isData = (status>>6)&0x01;
+    if (isData) {
+        csn = 0;
+        int i;
+        // set up for reading
+        status = spi->write( address );
+        for ( i = 0; i <= width; i++ ) {
+            buffer[i]=spi->write(0x00 );
+        }
+        csn = 1;
+        sprintf(logMsg, "Receive data %d bytes", width );
+        log(logMsg);
+        clearStatus();
+        return width;
+
+    } else {
+        sprintf(logMsg, "Receive NO data %d bytes", width );
+        log(logMsg);
+        clearStatus();
+        return 0;
+    }
+
+}
+
+/**
+* Sets all the receive pipes to dynamic payload length
+*/
+char NRF2401P::setDynamicPayload()
+{
+    dynamic = true;
+    writeReg (0x1D,0x04);
+    return(writeReg(0x1C, 0x1F));
+}
+/**
+* Sets PWR_UP = 1;
+*/
+bool NRF2401P::setPwrUp()
+{
+    char data;
+    char bit;
+    ce=1;
+    readReg( 0x00, &data );
+    data |= ( 0x02 );
+    writeReg( 0x00, data );
+    // check
+    readReg( 0x00, &data );
+    bit = ( data >> 1 ) & 1;
+    sprintf(logMsg, "Set PWR_UP to %x", bit);
+    log(logMsg);
+    wait(0.005); // wait 5ms
+    return ( bit == 1 );
+}
+/**
+* Sets PRIM_RX = 0;
+*/
+bool NRF2401P::setRxMode()
+{
+    char data;
+    char bit;
+    ce=1;
+    readReg( 0x00, &data );
+    data |= ( 0x03 );
+    writeReg( 0x00, data );
+    // check
+    readReg( 0x00, &data );
+    bit = ( data >> 0 ) & 1;
+    sprintf(logMsg, " set PRIM_RX to %x", bit);
+    log(logMsg);
+    clearStatus();
+    flushRx();
+    return ( bit == 1 );
+}
+/**
+* Prints status string
+*/
+char * NRF2401P::statusString()
+{
+    char *msg;
+    msg = statusS;
+    if (((status>>1) & 0x07)==0x07) {
+        sprintf(msg,"RX empty");
+    } else {
+        sprintf(msg,"pipe %02x",(status>>1) & 0x07);
+    }
+
+    if ((status>>6)&0x01) strcat(msg," RX_DR,");
+    if ((status>>5)&0x01) strcat(msg," TX_DS,");
+    if ((status>>4)&0x01) strcat(msg," MAX_RT,");
+    if ((status>>0)&0x01) strcat(msg," TX_FLL,");
+
+    return msg;
+}
\ No newline at end of file