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
*
*}
Committer:
epgmdm
Date:
Thu Jun 11 23:19:52 2015 +0000
Revision:
2:ca0a3c0bba70
Parent:
1:ff53b1ac3bad
Child:
3:afe8d307b5c3
Ack working

Who changed what in which revision?

UserRevisionLine numberNew contents of line
epgmdm 0:8fd0531ae0be 1 /**
epgmdm 0:8fd0531ae0be 2 *@section DESCRIPTION
epgmdm 0:8fd0531ae0be 3 * mbed NRF2401+ Library
epgmdm 0:8fd0531ae0be 4 *@section LICENSE
epgmdm 0:8fd0531ae0be 5 * Copyright (c) 2015, Malcolm McCulloch
epgmdm 0:8fd0531ae0be 6 *
epgmdm 0:8fd0531ae0be 7 * Permission is hereby granted, free of charge, to any person obtaining a copy
epgmdm 0:8fd0531ae0be 8 * of this software and associated documentation files (the "Software"), to deal
epgmdm 0:8fd0531ae0be 9 * in the Software without restriction, including without limitation the rights
epgmdm 0:8fd0531ae0be 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
epgmdm 0:8fd0531ae0be 11 * copies of the Software, and to permit persons to whom the Software is
epgmdm 0:8fd0531ae0be 12 * furnished to do so, subject to the following conditions:
epgmdm 0:8fd0531ae0be 13 *
epgmdm 0:8fd0531ae0be 14 * The above copyright notice and this permission notice shall be included in
epgmdm 0:8fd0531ae0be 15 * all copies or substantial portions of the Software.
epgmdm 0:8fd0531ae0be 16 *
epgmdm 0:8fd0531ae0be 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
epgmdm 0:8fd0531ae0be 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
epgmdm 0:8fd0531ae0be 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
epgmdm 0:8fd0531ae0be 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
epgmdm 0:8fd0531ae0be 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
epgmdm 0:8fd0531ae0be 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
epgmdm 0:8fd0531ae0be 23 * THE SOFTWARE.
epgmdm 0:8fd0531ae0be 24 * @file "NRF2401P.cpp"
epgmdm 0:8fd0531ae0be 25 */
epgmdm 2:ca0a3c0bba70 26 #include "mbed.h"
epgmdm 2:ca0a3c0bba70 27 #include "NRF2401P.h"
epgmdm 2:ca0a3c0bba70 28 #include "nRF24l01.h"
epgmdm 0:8fd0531ae0be 29
epgmdm 0:8fd0531ae0be 30
epgmdm 0:8fd0531ae0be 31 NRF2401P::NRF2401P ( PinName mosi, PinName miso, PinName sclk, PinName _csn, PinName _ce ) :
epgmdm 0:8fd0531ae0be 32 csn( DigitalOut( _csn ) ), ce( DigitalOut( _ce ) )
epgmdm 0:8fd0531ae0be 33 {
epgmdm 0:8fd0531ae0be 34 addressWidth = 5;
epgmdm 0:8fd0531ae0be 35 pc = new Serial( USBTX, USBRX ); // tx, rx
epgmdm 0:8fd0531ae0be 36 sprintf(logMsg, "Initialise " );
epgmdm 0:8fd0531ae0be 37 log(logMsg);
epgmdm 0:8fd0531ae0be 38 spi = new SPI( mosi, miso, sclk, NC ); //SPI (PinName mosi, PinName miso, PinName sclk, PinName _unused=NC)
epgmdm 0:8fd0531ae0be 39 spi->frequency( 10000000 ); // 1MHZ max 10 MHz
epgmdm 0:8fd0531ae0be 40 spi->format( 8, 0 ); // 0: 0e 08; 1: 0e 00; 2:0e 00 ;3:1c 00
epgmdm 0:8fd0531ae0be 41 csn = 1;
epgmdm 0:8fd0531ae0be 42 ce = 0;
epgmdm 0:8fd0531ae0be 43 dynamic = false;
epgmdm 1:ff53b1ac3bad 44 debug=1|false;
epgmdm 0:8fd0531ae0be 45
epgmdm 0:8fd0531ae0be 46 };
epgmdm 0:8fd0531ae0be 47
epgmdm 0:8fd0531ae0be 48 /**
epgmdm 0:8fd0531ae0be 49 * writes to pc and waits
epgmdm 0:8fd0531ae0be 50 */
epgmdm 0:8fd0531ae0be 51 void NRF2401P::log (char *msg)
epgmdm 0:8fd0531ae0be 52 {
epgmdm 0:8fd0531ae0be 53 if(debug) {
epgmdm 2:ca0a3c0bba70 54 printf("\t <%s \t %s>\n\r",statusString(), msg);
epgmdm 1:ff53b1ac3bad 55 wait(0.01);
epgmdm 0:8fd0531ae0be 56 };
epgmdm 0:8fd0531ae0be 57 }
epgmdm 0:8fd0531ae0be 58
epgmdm 0:8fd0531ae0be 59 void NRF2401P::scratch()
epgmdm 0:8fd0531ae0be 60 {
epgmdm 0:8fd0531ae0be 61 int status = 0;
epgmdm 0:8fd0531ae0be 62 int register1 = 0;
epgmdm 0:8fd0531ae0be 63 ce = 0;
epgmdm 0:8fd0531ae0be 64 for ( char i = 0; i < 24; i++ ) {
epgmdm 0:8fd0531ae0be 65 csn = 0;
epgmdm 0:8fd0531ae0be 66 //wait_us(100);
epgmdm 0:8fd0531ae0be 67 status = spi->write( i );
epgmdm 0:8fd0531ae0be 68 register1 = spi->write( 0x00 );
epgmdm 0:8fd0531ae0be 69 csn = 1;
epgmdm 0:8fd0531ae0be 70 sprintf(logMsg, " register %02x (%02x) = %02x", i, status, register1 );
epgmdm 0:8fd0531ae0be 71 log(logMsg);
epgmdm 0:8fd0531ae0be 72 }
epgmdm 0:8fd0531ae0be 73
epgmdm 0:8fd0531ae0be 74 }
epgmdm 0:8fd0531ae0be 75 /**
epgmdm 2:ca0a3c0bba70 76 * start here to configure the basics of the NRF
epgmdm 2:ca0a3c0bba70 77 */
epgmdm 2:ca0a3c0bba70 78
epgmdm 2:ca0a3c0bba70 79 void NRF2401P::start()
epgmdm 2:ca0a3c0bba70 80 {
epgmdm 2:ca0a3c0bba70 81 writeReg( CONFIG, 0x0c ); // set 16 bit crc
epgmdm 2:ca0a3c0bba70 82 setTxRetry(0x01,0x0f); // 500 uS, 15 retries
epgmdm 2:ca0a3c0bba70 83 setRadio(0,0x03); // 1MB/S 0dB
epgmdm 2:ca0a3c0bba70 84 setDynamicPayload();
epgmdm 2:ca0a3c0bba70 85 setChannel(76); // should be clear?
epgmdm 2:ca0a3c0bba70 86 setAddressWidth(5);
epgmdm 2:ca0a3c0bba70 87 flushRx();
epgmdm 2:ca0a3c0bba70 88 flushTx();
epgmdm 2:ca0a3c0bba70 89 setPwrUp();
epgmdm 2:ca0a3c0bba70 90 setTxMode(); // just make sure no spurious reads....
epgmdm 2:ca0a3c0bba70 91
epgmdm 2:ca0a3c0bba70 92 }
epgmdm 2:ca0a3c0bba70 93 /**
epgmdm 0:8fd0531ae0be 94 * Sets up a reciever using shockburst and dynamic payload. Uses pipe 1
epgmdm 0:8fd0531ae0be 95 * defaults to 5 bytes
epgmdm 0:8fd0531ae0be 96 */
epgmdm 2:ca0a3c0bba70 97 void NRF2401P::quickRxSetup(int channel,long long addrRx)
epgmdm 0:8fd0531ae0be 98 {
epgmdm 2:ca0a3c0bba70 99 start();
epgmdm 0:8fd0531ae0be 100 setChannel(channel);
epgmdm 2:ca0a3c0bba70 101 setRxAddress(addrRx,1);
epgmdm 0:8fd0531ae0be 102 setRxMode();
epgmdm 0:8fd0531ae0be 103 ce=1;
epgmdm 2:ca0a3c0bba70 104 wait (0.001f);
epgmdm 0:8fd0531ae0be 105 }
epgmdm 0:8fd0531ae0be 106 /**
epgmdm 0:8fd0531ae0be 107 * Sets up for receive of a message to address 0XA0A0A0
epgmdm 0:8fd0531ae0be 108 */
epgmdm 0:8fd0531ae0be 109
epgmdm 0:8fd0531ae0be 110 char NRF2401P::testReceive()
epgmdm 0:8fd0531ae0be 111 {
epgmdm 0:8fd0531ae0be 112 char message[64];
epgmdm 0:8fd0531ae0be 113 char width;
epgmdm 0:8fd0531ae0be 114 int channel = 0x12;
epgmdm 0:8fd0531ae0be 115 long long addr=0xA0B0C0;
epgmdm 0:8fd0531ae0be 116 debug = true;
epgmdm 0:8fd0531ae0be 117 quickRxSetup(channel, addr);
epgmdm 0:8fd0531ae0be 118
epgmdm 0:8fd0531ae0be 119 while (1) {
epgmdm 0:8fd0531ae0be 120 while (!isRxData()) {
epgmdm 0:8fd0531ae0be 121 //wait(0.5);
epgmdm 0:8fd0531ae0be 122 };
epgmdm 0:8fd0531ae0be 123 width=getRxData(message);
epgmdm 0:8fd0531ae0be 124 message[width]='\0';
epgmdm 0:8fd0531ae0be 125 sprintf(logMsg,"Received= [%s]",message);
epgmdm 0:8fd0531ae0be 126 log(logMsg);
epgmdm 0:8fd0531ae0be 127 };
epgmdm 0:8fd0531ae0be 128 }
epgmdm 0:8fd0531ae0be 129
epgmdm 0:8fd0531ae0be 130 /**
epgmdm 2:ca0a3c0bba70 131 * Sets the number and the timimg of TX retries
epgmdm 2:ca0a3c0bba70 132 */
epgmdm 2:ca0a3c0bba70 133
epgmdm 2:ca0a3c0bba70 134 void NRF2401P::setTxRetry(char delay, char numTries)
epgmdm 2:ca0a3c0bba70 135 {
epgmdm 2:ca0a3c0bba70 136 char val = (delay&0xf)<<4 | (numTries&0xf);
epgmdm 2:ca0a3c0bba70 137 writeReg (SETUP_RETR, val);
epgmdm 2:ca0a3c0bba70 138 }
epgmdm 2:ca0a3c0bba70 139
epgmdm 2:ca0a3c0bba70 140
epgmdm 2:ca0a3c0bba70 141 /**
epgmdm 0:8fd0531ae0be 142 * Sets up a transmitter using shockburst and dynamic payload. Uses pipe 1
epgmdm 0:8fd0531ae0be 143 * defaults to 5 bytes
epgmdm 0:8fd0531ae0be 144 */
epgmdm 0:8fd0531ae0be 145 void NRF2401P::quickTxSetup(int channel,long long addr)
epgmdm 0:8fd0531ae0be 146 {
epgmdm 2:ca0a3c0bba70 147 start();
epgmdm 0:8fd0531ae0be 148 setChannel(channel);
epgmdm 2:ca0a3c0bba70 149 setTxAddress(addr);
epgmdm 0:8fd0531ae0be 150 setTxMode();
epgmdm 0:8fd0531ae0be 151 ce=1;
epgmdm 0:8fd0531ae0be 152 wait (0.0016f); // wait for pll to settle
epgmdm 0:8fd0531ae0be 153 }
epgmdm 0:8fd0531ae0be 154
epgmdm 0:8fd0531ae0be 155 /**
epgmdm 0:8fd0531ae0be 156 * Sets up for transmit of a message to address 0XA0A0A0
epgmdm 0:8fd0531ae0be 157 */
epgmdm 0:8fd0531ae0be 158
epgmdm 0:8fd0531ae0be 159 char NRF2401P::testTransmit()
epgmdm 0:8fd0531ae0be 160 {
epgmdm 0:8fd0531ae0be 161 long long addr=0xA0B0C0;
epgmdm 0:8fd0531ae0be 162 int channel = 0x12;
epgmdm 0:8fd0531ae0be 163 char data[32] ;
epgmdm 0:8fd0531ae0be 164 int i=0;
epgmdm 0:8fd0531ae0be 165 quickRxSetup(channel, addr);
epgmdm 0:8fd0531ae0be 166 while (1) {
epgmdm 0:8fd0531ae0be 167 sprintf(data," packet %03d", i++ |100);
epgmdm 0:8fd0531ae0be 168 transmitData(data,18);
epgmdm 0:8fd0531ae0be 169 wait (1.0);
epgmdm 0:8fd0531ae0be 170 }
epgmdm 0:8fd0531ae0be 171
epgmdm 0:8fd0531ae0be 172 }
epgmdm 0:8fd0531ae0be 173 /**
epgmdm 0:8fd0531ae0be 174 *Speed :
epgmdm 0:8fd0531ae0be 175 ‘0x00’ – 1Mbps
epgmdm 0:8fd0531ae0be 176 ‘0x01’ – 2Mbps
epgmdm 0:8fd0531ae0be 177 ‘0x02’ – 250kbps
epgmdm 0:8fd0531ae0be 178 ‘0x03’ – Reserved
epgmdm 0:8fd0531ae0be 179 Power:
epgmdm 0:8fd0531ae0be 180 '0x00' – -18dBm
epgmdm 0:8fd0531ae0be 181 '0x01' – -12dBm
epgmdm 0:8fd0531ae0be 182 '0x02' – -6dBm
epgmdm 0:8fd0531ae0be 183 '0x03' – 0dBm
epgmdm 0:8fd0531ae0be 184 */
epgmdm 0:8fd0531ae0be 185 char NRF2401P::setRadio(char speed,char power)
epgmdm 0:8fd0531ae0be 186 {
epgmdm 0:8fd0531ae0be 187 char val=0;
epgmdm 0:8fd0531ae0be 188 sprintf(logMsg, "Set radio");
epgmdm 0:8fd0531ae0be 189 log(logMsg);
epgmdm 0:8fd0531ae0be 190 if (speed & 0x02) {
epgmdm 0:8fd0531ae0be 191 val |= (1<<5);
epgmdm 0:8fd0531ae0be 192 }
epgmdm 0:8fd0531ae0be 193 val |= (speed & 0x01)<<3;
epgmdm 0:8fd0531ae0be 194
epgmdm 0:8fd0531ae0be 195 val |= ((power &0x03)<<1);
epgmdm 0:8fd0531ae0be 196 writeReg (0x06,val);
epgmdm 0:8fd0531ae0be 197
epgmdm 0:8fd0531ae0be 198 }
epgmdm 0:8fd0531ae0be 199 /**
epgmdm 0:8fd0531ae0be 200 Set RF_CH = chan;
epgmdm 0:8fd0531ae0be 201
epgmdm 0:8fd0531ae0be 202 F0= 2400 + chan [MHz]
epgmdm 0:8fd0531ae0be 203 */
epgmdm 0:8fd0531ae0be 204 char NRF2401P::setChannel(char chan)
epgmdm 0:8fd0531ae0be 205 {
epgmdm 0:8fd0531ae0be 206 sprintf(logMsg, "Set channel");
epgmdm 0:8fd0531ae0be 207 log(logMsg);
epgmdm 0:8fd0531ae0be 208 writeReg (0x05,(chan&0x7f));
epgmdm 0:8fd0531ae0be 209 }
epgmdm 0:8fd0531ae0be 210 /**
epgmdm 0:8fd0531ae0be 211 * Transmits width bytes of data. width <32
epgmdm 0:8fd0531ae0be 212 */
epgmdm 0:8fd0531ae0be 213 char NRF2401P::transmitData( char *data, char width )
epgmdm 0:8fd0531ae0be 214 {
epgmdm 2:ca0a3c0bba70 215 //clearStatus();
epgmdm 2:ca0a3c0bba70 216 //ce = 1;
epgmdm 0:8fd0531ae0be 217 csn = 0;
epgmdm 0:8fd0531ae0be 218 char address = 0XA0;
epgmdm 0:8fd0531ae0be 219 int i;
epgmdm 0:8fd0531ae0be 220 // set up for writing
epgmdm 0:8fd0531ae0be 221 status = spi->write( address );
epgmdm 0:8fd0531ae0be 222 for ( i = 0; i <width; i++ ) {
epgmdm 0:8fd0531ae0be 223 spi->write( data[ i ] );
epgmdm 0:8fd0531ae0be 224 }
epgmdm 0:8fd0531ae0be 225 csn = 1;
epgmdm 2:ca0a3c0bba70 226 if (debug){
epgmdm 2:ca0a3c0bba70 227 sprintf(logMsg, " Transmit data %d bytes to %02x (%02x) = %10s", width, address, status, *data );
epgmdm 0:8fd0531ae0be 228 log(logMsg);
epgmdm 2:ca0a3c0bba70 229 }
epgmdm 0:8fd0531ae0be 230 return status;
epgmdm 0:8fd0531ae0be 231
epgmdm 0:8fd0531ae0be 232 }
epgmdm 0:8fd0531ae0be 233
epgmdm 0:8fd0531ae0be 234 /**
epgmdm 0:8fd0531ae0be 235 * sets acknowledge data width bytes of data. width <32
epgmdm 0:8fd0531ae0be 236 */
epgmdm 1:ff53b1ac3bad 237 char NRF2401P::acknowledgeData( char *data, char width, char pipe )
epgmdm 0:8fd0531ae0be 238 {
epgmdm 0:8fd0531ae0be 239 ce = 1;
epgmdm 0:8fd0531ae0be 240 csn = 0;
epgmdm 2:ca0a3c0bba70 241 //writeReg(0x1d,0x06); // enable payload with ack
epgmdm 2:ca0a3c0bba70 242 char address = W_ACK_PAYLOAD | (pipe&0x07);
epgmdm 0:8fd0531ae0be 243 int i;
epgmdm 0:8fd0531ae0be 244 // set up for writing
epgmdm 2:ca0a3c0bba70 245 csn = 0;
epgmdm 0:8fd0531ae0be 246 status = spi->write( address );
epgmdm 0:8fd0531ae0be 247 for ( i = 0; i <width; i++ ) {
epgmdm 0:8fd0531ae0be 248 spi->write( data[ i ] );
epgmdm 0:8fd0531ae0be 249 }
epgmdm 0:8fd0531ae0be 250 csn = 1;
epgmdm 2:ca0a3c0bba70 251 if (debug){
epgmdm 2:ca0a3c0bba70 252 sprintf(logMsg, " acknowledge data %d bytes to %02x (%02x) = %c", width, address, status, *data );
epgmdm 0:8fd0531ae0be 253 log(logMsg);
epgmdm 2:ca0a3c0bba70 254 }
epgmdm 0:8fd0531ae0be 255 return status;
epgmdm 0:8fd0531ae0be 256
epgmdm 0:8fd0531ae0be 257 }
epgmdm 0:8fd0531ae0be 258 /**
epgmdm 0:8fd0531ae0be 259 * Writes 1 byte data to a register
epgmdm 0:8fd0531ae0be 260 **/
epgmdm 0:8fd0531ae0be 261 char NRF2401P::writeReg( char address, char data )
epgmdm 0:8fd0531ae0be 262 {
epgmdm 0:8fd0531ae0be 263 char status = 0;
epgmdm 0:8fd0531ae0be 264 char reg;
epgmdm 0:8fd0531ae0be 265 csn = 0;
epgmdm 0:8fd0531ae0be 266 address &= 0x1F;
epgmdm 0:8fd0531ae0be 267 reg = address | 0x20;
epgmdm 0:8fd0531ae0be 268 status = spi->write( reg );
epgmdm 0:8fd0531ae0be 269 spi->write( data );
epgmdm 0:8fd0531ae0be 270 csn = 1;
epgmdm 0:8fd0531ae0be 271 sprintf(logMsg, " register write %02x (%02x) = %02x", address, status, data );
epgmdm 0:8fd0531ae0be 272 log(logMsg);
epgmdm 0:8fd0531ae0be 273 return status;
epgmdm 0:8fd0531ae0be 274 }
epgmdm 0:8fd0531ae0be 275 /**
epgmdm 0:8fd0531ae0be 276 * Writes width bytes data to a register, ls byte to ms byte /for adressess
epgmdm 0:8fd0531ae0be 277 **/
epgmdm 0:8fd0531ae0be 278 char NRF2401P::writeReg( char address, char *data, char width )
epgmdm 0:8fd0531ae0be 279 {
epgmdm 0:8fd0531ae0be 280 char reg;
epgmdm 0:8fd0531ae0be 281 csn = 0;
epgmdm 0:8fd0531ae0be 282 int i;
epgmdm 0:8fd0531ae0be 283 // set up for writing
epgmdm 0:8fd0531ae0be 284 address &= 0x1F;
epgmdm 0:8fd0531ae0be 285 reg = address| 0x20;
epgmdm 0:8fd0531ae0be 286 status = spi->write( reg );
epgmdm 0:8fd0531ae0be 287 for ( i = width - 1; i >= 0; i-- ) {
epgmdm 0:8fd0531ae0be 288 spi->write( data[ i ] );
epgmdm 0:8fd0531ae0be 289 }
epgmdm 0:8fd0531ae0be 290 csn = 1;
epgmdm 2:ca0a3c0bba70 291 if (debug) {
epgmdm 2:ca0a3c0bba70 292 sprintf(logMsg, " register write %d bytes to %02x (%02x) = %02x %02x %02x", width, address, status, data[0], data[1], data[2] );
epgmdm 2:ca0a3c0bba70 293 log(logMsg);
epgmdm 2:ca0a3c0bba70 294 }
epgmdm 0:8fd0531ae0be 295 return status;
epgmdm 0:8fd0531ae0be 296 }
epgmdm 0:8fd0531ae0be 297 /**
epgmdm 0:8fd0531ae0be 298 * Reads 1 byte from a register
epgmdm 0:8fd0531ae0be 299 **/
epgmdm 0:8fd0531ae0be 300 char NRF2401P::readReg( char address, char *data )
epgmdm 0:8fd0531ae0be 301 {
epgmdm 0:8fd0531ae0be 302 csn = 0;
epgmdm 0:8fd0531ae0be 303 address &= 0x1F;
epgmdm 0:8fd0531ae0be 304 status = spi->write( address );
epgmdm 0:8fd0531ae0be 305 *data = spi->write( 0x00 );
epgmdm 0:8fd0531ae0be 306 csn = 1;
epgmdm 0:8fd0531ae0be 307 // sprintf(logMsg, " register read %02x (%02x) = %02x", address, status, *data );
epgmdm 0:8fd0531ae0be 308 // log(logMsg);
epgmdm 0:8fd0531ae0be 309 return status;
epgmdm 0:8fd0531ae0be 310 }
epgmdm 0:8fd0531ae0be 311 /**
epgmdm 0:8fd0531ae0be 312 * Clears the status flags RX_DR, TX_DS, MAX_RT
epgmdm 0:8fd0531ae0be 313 */
epgmdm 0:8fd0531ae0be 314 bool NRF2401P::clearStatus()
epgmdm 0:8fd0531ae0be 315 {
epgmdm 2:ca0a3c0bba70 316 status = writeReg(STATUS,0x70);
epgmdm 2:ca0a3c0bba70 317 if (debug) {
epgmdm 2:ca0a3c0bba70 318 sprintf(logMsg, "Clear status (%02x)", status );
epgmdm 2:ca0a3c0bba70 319 log(logMsg);
epgmdm 2:ca0a3c0bba70 320 }
epgmdm 0:8fd0531ae0be 321 }
epgmdm 0:8fd0531ae0be 322 /**
epgmdm 0:8fd0531ae0be 323 * flushes TX FIFO and resets status flags
epgmdm 0:8fd0531ae0be 324 */
epgmdm 0:8fd0531ae0be 325 bool NRF2401P::flushTx()
epgmdm 0:8fd0531ae0be 326 {
epgmdm 0:8fd0531ae0be 327 csn = 0;
epgmdm 2:ca0a3c0bba70 328 status = spi->write( FLUSH_TX );
epgmdm 0:8fd0531ae0be 329 csn = 1;
epgmdm 0:8fd0531ae0be 330 clearStatus();
epgmdm 2:ca0a3c0bba70 331 if (debug) {
epgmdm 2:ca0a3c0bba70 332 sprintf(logMsg, "Flush TX FIFO (%02x)", status );
epgmdm 2:ca0a3c0bba70 333 log(logMsg);
epgmdm 2:ca0a3c0bba70 334 }
epgmdm 0:8fd0531ae0be 335 return;
epgmdm 0:8fd0531ae0be 336 }
epgmdm 0:8fd0531ae0be 337
epgmdm 0:8fd0531ae0be 338 /**
epgmdm 0:8fd0531ae0be 339 * flushes RX FIFO and resets status flags
epgmdm 0:8fd0531ae0be 340 */
epgmdm 0:8fd0531ae0be 341 bool NRF2401P::flushRx()
epgmdm 0:8fd0531ae0be 342 {
epgmdm 0:8fd0531ae0be 343 csn = 0;
epgmdm 2:ca0a3c0bba70 344 status = spi->write( FLUSH_RX );
epgmdm 0:8fd0531ae0be 345 csn = 1;
epgmdm 2:ca0a3c0bba70 346 clearStatus();
epgmdm 2:ca0a3c0bba70 347 if (debug) {
epgmdm 2:ca0a3c0bba70 348 sprintf(logMsg, "Flush RX FIFO (%02x)", status );
epgmdm 2:ca0a3c0bba70 349 log(logMsg);
epgmdm 2:ca0a3c0bba70 350 }
epgmdm 0:8fd0531ae0be 351 }
epgmdm 0:8fd0531ae0be 352 /**
epgmdm 0:8fd0531ae0be 353 * Sets PRIM_RX = 0;
epgmdm 0:8fd0531ae0be 354 */
epgmdm 0:8fd0531ae0be 355 bool NRF2401P::setTxMode()
epgmdm 0:8fd0531ae0be 356 {
epgmdm 0:8fd0531ae0be 357 char data;
epgmdm 0:8fd0531ae0be 358 char bit;
epgmdm 2:ca0a3c0bba70 359 if (debug) {
epgmdm 2:ca0a3c0bba70 360 sprintf(logMsg, "Set Tx Mode");
epgmdm 2:ca0a3c0bba70 361 log(logMsg);
epgmdm 2:ca0a3c0bba70 362 }
epgmdm 2:ca0a3c0bba70 363 readReg( CONFIG, &data );
epgmdm 0:8fd0531ae0be 364 data &= ~( 1 << 0 );
epgmdm 2:ca0a3c0bba70 365 flushTx();
epgmdm 2:ca0a3c0bba70 366 flushRx();
epgmdm 2:ca0a3c0bba70 367 writeReg( CONFIG, data );
epgmdm 2:ca0a3c0bba70 368 writeReg( RX_ADDR_P0, txAdd, addressWidth ); // reset p0
epgmdm 2:ca0a3c0bba70 369 writeReg(EN_RXADDR,0x01); // enable pipe 0 for reading
epgmdm 0:8fd0531ae0be 370 // check
epgmdm 0:8fd0531ae0be 371 readReg( 0x00, &data );
epgmdm 0:8fd0531ae0be 372 bit = ( data >> 0 ) & 1;
epgmdm 2:ca0a3c0bba70 373
epgmdm 0:8fd0531ae0be 374 ce=1;
epgmdm 0:8fd0531ae0be 375 wait(0.003);
epgmdm 0:8fd0531ae0be 376 return ( bit == 0 );
epgmdm 0:8fd0531ae0be 377 }
epgmdm 0:8fd0531ae0be 378
epgmdm 0:8fd0531ae0be 379 /**
epgmdm 0:8fd0531ae0be 380 * Sets the number of bytes of the address width = 3,4,5
epgmdm 0:8fd0531ae0be 381 */
epgmdm 0:8fd0531ae0be 382 bool NRF2401P::setAddressWidth( char width )
epgmdm 0:8fd0531ae0be 383 {
epgmdm 0:8fd0531ae0be 384 addressWidth = width;
epgmdm 0:8fd0531ae0be 385 if ( ( width > 5 ) || ( width < 3 ) )
epgmdm 0:8fd0531ae0be 386 return false;
epgmdm 0:8fd0531ae0be 387 width -= 2;
epgmdm 0:8fd0531ae0be 388 return writeReg( 0x03, width );
epgmdm 0:8fd0531ae0be 389
epgmdm 0:8fd0531ae0be 390 }
epgmdm 0:8fd0531ae0be 391 /**
epgmdm 0:8fd0531ae0be 392 * Sets the address, uses addess width set (either 3,4 or 5)
epgmdm 0:8fd0531ae0be 393 */
epgmdm 0:8fd0531ae0be 394 char NRF2401P::setTxAddress( char *address )
epgmdm 0:8fd0531ae0be 395 {
epgmdm 2:ca0a3c0bba70 396 memcpy (txAdd,address, addressWidth);
epgmdm 0:8fd0531ae0be 397 writeReg( 0x0A, address, addressWidth ); //Write to RX_ADDR_P0
epgmdm 0:8fd0531ae0be 398 return writeReg( 0x10, address, addressWidth ); //Write to TX_ADDR
epgmdm 0:8fd0531ae0be 399
epgmdm 0:8fd0531ae0be 400 }
epgmdm 0:8fd0531ae0be 401
epgmdm 0:8fd0531ae0be 402 /**
epgmdm 0:8fd0531ae0be 403 * Sets the address, uses addess width set (either 3,4 or 5)
epgmdm 0:8fd0531ae0be 404 */
epgmdm 0:8fd0531ae0be 405 char NRF2401P::setTxAddress( long long address )
epgmdm 0:8fd0531ae0be 406 {
epgmdm 0:8fd0531ae0be 407
epgmdm 0:8fd0531ae0be 408 char buff[ 5 ];
epgmdm 0:8fd0531ae0be 409 buff[ 0 ] = address & 0xff;
epgmdm 0:8fd0531ae0be 410 buff[ 1 ] = ( address >> 8 ) & 0xFF;
epgmdm 0:8fd0531ae0be 411 buff[ 2 ] = ( address >> 16 ) & 0xFF;
epgmdm 0:8fd0531ae0be 412 buff[ 3 ] = ( address >> 24 ) & 0xFF;
epgmdm 0:8fd0531ae0be 413 buff[ 4 ] = ( address >> 32 ) & 0xFF;
epgmdm 0:8fd0531ae0be 414 return setTxAddress( buff );
epgmdm 0:8fd0531ae0be 415
epgmdm 0:8fd0531ae0be 416 }
epgmdm 0:8fd0531ae0be 417
epgmdm 0:8fd0531ae0be 418 /**
epgmdm 0:8fd0531ae0be 419 * Sets the address, uses addess width set (either 3,4 or 5)
epgmdm 2:ca0a3c0bba70 420 * Enables pipe for receiving;
epgmdm 0:8fd0531ae0be 421 */
epgmdm 0:8fd0531ae0be 422 char NRF2401P::setRxAddress( char *address, char pipe )
epgmdm 0:8fd0531ae0be 423 {
epgmdm 2:ca0a3c0bba70 424 if(debug) {
epgmdm 2:ca0a3c0bba70 425 log ("Set Rx Address");
epgmdm 2:ca0a3c0bba70 426 }
epgmdm 2:ca0a3c0bba70 427 if (pipe>5) return 0xff;
epgmdm 2:ca0a3c0bba70 428 if (pipe ==0) {
epgmdm 2:ca0a3c0bba70 429 memcpy (pipe0Add,address, addressWidth);
epgmdm 2:ca0a3c0bba70 430 }
epgmdm 2:ca0a3c0bba70 431
epgmdm 0:8fd0531ae0be 432 char reg = 0x0A + pipe;
epgmdm 0:8fd0531ae0be 433 switch ( pipe ) {
epgmdm 0:8fd0531ae0be 434 case ( 0 ) :
epgmdm 0:8fd0531ae0be 435 case ( 1 ) : {
epgmdm 0:8fd0531ae0be 436 status = writeReg( reg, address, addressWidth ); //Write to RX_ADDR_P0 or _P1
epgmdm 0:8fd0531ae0be 437 break;
epgmdm 0:8fd0531ae0be 438 }
epgmdm 0:8fd0531ae0be 439 case ( 2 ) :
epgmdm 0:8fd0531ae0be 440 case ( 3 ) :
epgmdm 0:8fd0531ae0be 441 case ( 4 ) :
epgmdm 0:8fd0531ae0be 442 case ( 5 ) : {
epgmdm 0:8fd0531ae0be 443 status = writeReg( reg, address, 1 ); //Write to RX_ADDR_P2 ... _P5
epgmdm 0:8fd0531ae0be 444 break;
epgmdm 0:8fd0531ae0be 445 }
epgmdm 0:8fd0531ae0be 446
epgmdm 0:8fd0531ae0be 447 }
epgmdm 2:ca0a3c0bba70 448 readReg(EN_RXADDR,&reg);
epgmdm 2:ca0a3c0bba70 449 reg |= (1<<pipe);
epgmdm 2:ca0a3c0bba70 450 writeReg( EN_RXADDR,reg ); //Enable the pipe
epgmdm 0:8fd0531ae0be 451 return status;
epgmdm 0:8fd0531ae0be 452
epgmdm 0:8fd0531ae0be 453 }
epgmdm 0:8fd0531ae0be 454
epgmdm 0:8fd0531ae0be 455 /**
epgmdm 0:8fd0531ae0be 456 * Sets the address of pipe (<=5), uses addess width set (either 3,4 or 5)
epgmdm 0:8fd0531ae0be 457 */
epgmdm 0:8fd0531ae0be 458 char NRF2401P::setRxAddress( long long address, char pipe )
epgmdm 0:8fd0531ae0be 459 {
epgmdm 0:8fd0531ae0be 460 char buff[ 5 ];
epgmdm 0:8fd0531ae0be 461 buff[ 0 ] = address & 0xff;
epgmdm 0:8fd0531ae0be 462 buff[ 1 ] = ( address >> 8 ) & 0xFF;
epgmdm 0:8fd0531ae0be 463 buff[ 2 ] = ( address >> 16 ) & 0xFF;
epgmdm 0:8fd0531ae0be 464 buff[ 3 ] = ( address >> 24 ) & 0xFF;
epgmdm 0:8fd0531ae0be 465 buff[ 4 ] = ( address >> 32 ) & 0xFF;
epgmdm 0:8fd0531ae0be 466 return setRxAddress( buff, pipe );
epgmdm 0:8fd0531ae0be 467 }
epgmdm 1:ff53b1ac3bad 468 /**
epgmdm 1:ff53b1ac3bad 469 *checks the status flag
epgmdm 1:ff53b1ac3bad 470 */
epgmdm 1:ff53b1ac3bad 471 char NRF2401P::checkStatus()
epgmdm 1:ff53b1ac3bad 472 {
epgmdm 1:ff53b1ac3bad 473 readReg(0x07,&status);
epgmdm 1:ff53b1ac3bad 474 return status;
epgmdm 1:ff53b1ac3bad 475 }
epgmdm 1:ff53b1ac3bad 476 /**
epgmdm 1:ff53b1ac3bad 477 * checks if Ack data available.
epgmdm 1:ff53b1ac3bad 478 */
epgmdm 1:ff53b1ac3bad 479 bool NRF2401P::isAckData()
epgmdm 1:ff53b1ac3bad 480 {
epgmdm 1:ff53b1ac3bad 481 char fifo;
epgmdm 1:ff53b1ac3bad 482 readReg(0x17,&fifo);
epgmdm 1:ff53b1ac3bad 483 bool isData = !(fifo&0x01);
epgmdm 1:ff53b1ac3bad 484 return isData;
epgmdm 1:ff53b1ac3bad 485 }
epgmdm 0:8fd0531ae0be 486
epgmdm 1:ff53b1ac3bad 487 /**
epgmdm 1:ff53b1ac3bad 488 * checks if RX data available.
epgmdm 1:ff53b1ac3bad 489 */
epgmdm 0:8fd0531ae0be 490 bool NRF2401P::isRxData()
epgmdm 0:8fd0531ae0be 491 {
epgmdm 1:ff53b1ac3bad 492 checkStatus();
epgmdm 0:8fd0531ae0be 493 bool isData = (status>>6)&0x01;
epgmdm 0:8fd0531ae0be 494 return isData;
epgmdm 0:8fd0531ae0be 495 }
epgmdm 0:8fd0531ae0be 496 /**
epgmdm 0:8fd0531ae0be 497 * returns the width of the dynamic payload
epgmdm 0:8fd0531ae0be 498 */
epgmdm 0:8fd0531ae0be 499 char NRF2401P::getRxWidth()
epgmdm 0:8fd0531ae0be 500 {
epgmdm 0:8fd0531ae0be 501 char width;
epgmdm 0:8fd0531ae0be 502 if (dynamic) {
epgmdm 0:8fd0531ae0be 503 csn = 0;
epgmdm 0:8fd0531ae0be 504 status = spi->write( 0x60 );
epgmdm 0:8fd0531ae0be 505 width = spi->write(0x00);
epgmdm 0:8fd0531ae0be 506 csn = 1;
epgmdm 0:8fd0531ae0be 507
epgmdm 0:8fd0531ae0be 508 if (width>32) {
epgmdm 0:8fd0531ae0be 509 flushRx();
epgmdm 0:8fd0531ae0be 510 width=0;
epgmdm 0:8fd0531ae0be 511 }
epgmdm 0:8fd0531ae0be 512 } else {
epgmdm 0:8fd0531ae0be 513 status = readReg(0x12,&width); // width of p1
epgmdm 0:8fd0531ae0be 514
epgmdm 0:8fd0531ae0be 515 }
epgmdm 1:ff53b1ac3bad 516 // width=18;
epgmdm 0:8fd0531ae0be 517 return width;
epgmdm 0:8fd0531ae0be 518 }
epgmdm 0:8fd0531ae0be 519 /**
epgmdm 0:8fd0531ae0be 520 * return message in buffer, mem for buffer must have been allocated.
epgmdm 0:8fd0531ae0be 521 * Return value is number of bytes of buffer
epgmdm 0:8fd0531ae0be 522 */
epgmdm 0:8fd0531ae0be 523 char NRF2401P::getRxData(char * buffer)
epgmdm 0:8fd0531ae0be 524 {
epgmdm 0:8fd0531ae0be 525 char address = 0x61;
epgmdm 0:8fd0531ae0be 526 char width;
epgmdm 0:8fd0531ae0be 527 width = getRxWidth();
epgmdm 0:8fd0531ae0be 528 bool isData = (status>>6)&0x01;
epgmdm 0:8fd0531ae0be 529 if (isData) {
epgmdm 0:8fd0531ae0be 530 csn = 0;
epgmdm 0:8fd0531ae0be 531 int i;
epgmdm 0:8fd0531ae0be 532 // set up for reading
epgmdm 0:8fd0531ae0be 533 status = spi->write( address );
epgmdm 0:8fd0531ae0be 534 for ( i = 0; i <= width; i++ ) {
epgmdm 0:8fd0531ae0be 535 buffer[i]=spi->write(0x00 );
epgmdm 0:8fd0531ae0be 536 }
epgmdm 0:8fd0531ae0be 537 csn = 1;
epgmdm 0:8fd0531ae0be 538 sprintf(logMsg, "Receive data %d bytes", width );
epgmdm 0:8fd0531ae0be 539 log(logMsg);
epgmdm 0:8fd0531ae0be 540 clearStatus();
epgmdm 0:8fd0531ae0be 541 return width;
epgmdm 0:8fd0531ae0be 542
epgmdm 0:8fd0531ae0be 543 } else {
epgmdm 0:8fd0531ae0be 544 sprintf(logMsg, "Receive NO data %d bytes", width );
epgmdm 0:8fd0531ae0be 545 log(logMsg);
epgmdm 0:8fd0531ae0be 546 clearStatus();
epgmdm 0:8fd0531ae0be 547 return 0;
epgmdm 0:8fd0531ae0be 548 }
epgmdm 0:8fd0531ae0be 549
epgmdm 0:8fd0531ae0be 550 }
epgmdm 0:8fd0531ae0be 551
epgmdm 0:8fd0531ae0be 552 /**
epgmdm 0:8fd0531ae0be 553 * Sets all the receive pipes to dynamic payload length
epgmdm 0:8fd0531ae0be 554 */
epgmdm 2:ca0a3c0bba70 555 void NRF2401P::setDynamicPayload()
epgmdm 0:8fd0531ae0be 556 {
epgmdm 0:8fd0531ae0be 557 dynamic = true;
epgmdm 1:ff53b1ac3bad 558
epgmdm 2:ca0a3c0bba70 559 writeReg(FEATURE,0x07); // Enable Dyn payload, Payload with Ack and w_tx_noack command
epgmdm 2:ca0a3c0bba70 560 writeReg(EN_AA,0x3f); // EN_AA regi for P1 and P0
epgmdm 2:ca0a3c0bba70 561 writeReg(DYNPD, 0x1F);
epgmdm 0:8fd0531ae0be 562 }
epgmdm 2:ca0a3c0bba70 563
epgmdm 0:8fd0531ae0be 564 /**
epgmdm 0:8fd0531ae0be 565 * Sets PWR_UP = 1;
epgmdm 0:8fd0531ae0be 566 */
epgmdm 0:8fd0531ae0be 567 bool NRF2401P::setPwrUp()
epgmdm 0:8fd0531ae0be 568 {
epgmdm 0:8fd0531ae0be 569 char data;
epgmdm 0:8fd0531ae0be 570 char bit;
epgmdm 0:8fd0531ae0be 571 ce=1;
epgmdm 2:ca0a3c0bba70 572 readReg( CONFIG, &data );
epgmdm 2:ca0a3c0bba70 573 if ((data>>1) &0x01) {
epgmdm 2:ca0a3c0bba70 574 return true; // Already powered up
epgmdm 2:ca0a3c0bba70 575 };
epgmdm 0:8fd0531ae0be 576 data |= ( 0x02 );
epgmdm 0:8fd0531ae0be 577 writeReg( 0x00, data );
epgmdm 0:8fd0531ae0be 578 // check
epgmdm 0:8fd0531ae0be 579 readReg( 0x00, &data );
epgmdm 0:8fd0531ae0be 580 bit = ( data >> 1 ) & 1;
epgmdm 2:ca0a3c0bba70 581
epgmdm 0:8fd0531ae0be 582 wait(0.005); // wait 5ms
epgmdm 2:ca0a3c0bba70 583 if(debug) {
epgmdm 2:ca0a3c0bba70 584 sprintf(logMsg, "Set PWR_UP to %x", bit);
epgmdm 2:ca0a3c0bba70 585 log(logMsg);
epgmdm 2:ca0a3c0bba70 586 }
epgmdm 2:ca0a3c0bba70 587
epgmdm 0:8fd0531ae0be 588 return ( bit == 1 );
epgmdm 0:8fd0531ae0be 589 }
epgmdm 0:8fd0531ae0be 590 /**
epgmdm 0:8fd0531ae0be 591 * Sets PRIM_RX = 0;
epgmdm 0:8fd0531ae0be 592 */
epgmdm 0:8fd0531ae0be 593 bool NRF2401P::setRxMode()
epgmdm 0:8fd0531ae0be 594 {
epgmdm 0:8fd0531ae0be 595 char data;
epgmdm 0:8fd0531ae0be 596 char bit;
epgmdm 0:8fd0531ae0be 597 ce=1;
epgmdm 0:8fd0531ae0be 598 readReg( 0x00, &data );
epgmdm 2:ca0a3c0bba70 599 data |= ( 0x01 );
epgmdm 2:ca0a3c0bba70 600
epgmdm 0:8fd0531ae0be 601 writeReg( 0x00, data );
epgmdm 2:ca0a3c0bba70 602 if (pipe0Add[0]|pipe0Add[1]|pipe0Add[2]|pipe0Add[3]|pipe0Add[4] >0){
epgmdm 2:ca0a3c0bba70 603 setRxAddress(pipe0Add,0);
epgmdm 2:ca0a3c0bba70 604 }
epgmdm 0:8fd0531ae0be 605 // check
epgmdm 0:8fd0531ae0be 606 readReg( 0x00, &data );
epgmdm 0:8fd0531ae0be 607 bit = ( data >> 0 ) & 1;
epgmdm 2:ca0a3c0bba70 608
epgmdm 2:ca0a3c0bba70 609 wait (0.001);
epgmdm 0:8fd0531ae0be 610 flushRx();
epgmdm 2:ca0a3c0bba70 611 flushTx();
epgmdm 2:ca0a3c0bba70 612 if (debug) {
epgmdm 2:ca0a3c0bba70 613 sprintf(logMsg, " set PRIM_RX to %x", bit);
epgmdm 2:ca0a3c0bba70 614 log(logMsg);
epgmdm 2:ca0a3c0bba70 615 }
epgmdm 0:8fd0531ae0be 616 return ( bit == 1 );
epgmdm 0:8fd0531ae0be 617 }
epgmdm 0:8fd0531ae0be 618 /**
epgmdm 0:8fd0531ae0be 619 * Prints status string
epgmdm 0:8fd0531ae0be 620 */
epgmdm 0:8fd0531ae0be 621 char * NRF2401P::statusString()
epgmdm 0:8fd0531ae0be 622 {
epgmdm 0:8fd0531ae0be 623 char *msg;
epgmdm 0:8fd0531ae0be 624 msg = statusS;
epgmdm 0:8fd0531ae0be 625 if (((status>>1) & 0x07)==0x07) {
epgmdm 0:8fd0531ae0be 626 sprintf(msg,"RX empty");
epgmdm 0:8fd0531ae0be 627 } else {
epgmdm 0:8fd0531ae0be 628 sprintf(msg,"pipe %02x",(status>>1) & 0x07);
epgmdm 0:8fd0531ae0be 629 }
epgmdm 0:8fd0531ae0be 630
epgmdm 0:8fd0531ae0be 631 if ((status>>6)&0x01) strcat(msg," RX_DR,");
epgmdm 0:8fd0531ae0be 632 if ((status>>5)&0x01) strcat(msg," TX_DS,");
epgmdm 0:8fd0531ae0be 633 if ((status>>4)&0x01) strcat(msg," MAX_RT,");
epgmdm 0:8fd0531ae0be 634 if ((status>>0)&0x01) strcat(msg," TX_FLL,");
epgmdm 0:8fd0531ae0be 635
epgmdm 0:8fd0531ae0be 636 return msg;
epgmdm 0:8fd0531ae0be 637 }