TMRh20 ported to MBED

Fork of TMRh20 by BME SmartLab

Committer:
gume
Date:
Thu Mar 10 14:40:30 2016 +0000
Revision:
0:163155b607df
Child:
1:8f889354678f
Initial commit. Imported from the Arduino project

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gume 0:163155b607df 1 /*
gume 0:163155b607df 2 Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
gume 0:163155b607df 3
gume 0:163155b607df 4 This program is free software; you can redistribute it and/or
gume 0:163155b607df 5 modify it under the terms of the GNU General Public License
gume 0:163155b607df 6 version 2 as published by the Free Software Foundation.
gume 0:163155b607df 7 */
gume 0:163155b607df 8
gume 0:163155b607df 9 #include "nRF24L01.h"
gume 0:163155b607df 10 #include "RF24_config.h"
gume 0:163155b607df 11 #include "RF24.h"
gume 0:163155b607df 12
gume 0:163155b607df 13 /****************************************************************************/
gume 0:163155b607df 14
gume 0:163155b607df 15 void RF24::csn(bool mode)
gume 0:163155b607df 16 {
gume 0:163155b607df 17 csn_pin = mode;
gume 0:163155b607df 18 wait_us(5);
gume 0:163155b607df 19
gume 0:163155b607df 20 }
gume 0:163155b607df 21
gume 0:163155b607df 22 /****************************************************************************/
gume 0:163155b607df 23
gume 0:163155b607df 24 void RF24::ce(bool level)
gume 0:163155b607df 25 {
gume 0:163155b607df 26 ce_pin = level;
gume 0:163155b607df 27 }
gume 0:163155b607df 28
gume 0:163155b607df 29 /****************************************************************************/
gume 0:163155b607df 30
gume 0:163155b607df 31 inline void RF24::beginTransaction()
gume 0:163155b607df 32 {
gume 0:163155b607df 33 //#if defined (RF24_SPI_TRANSACTIONS)
gume 0:163155b607df 34 //_SPI.beginTransaction(SPISettings(RF24_SPI_SPEED, MSBFIRST, SPI_MODE0));
gume 0:163155b607df 35 //#endif
gume 0:163155b607df 36 csn(LOW);
gume 0:163155b607df 37 }
gume 0:163155b607df 38
gume 0:163155b607df 39 /****************************************************************************/
gume 0:163155b607df 40
gume 0:163155b607df 41 inline void RF24::endTransaction()
gume 0:163155b607df 42 {
gume 0:163155b607df 43 csn(HIGH);
gume 0:163155b607df 44 //#if defined (RF24_SPI_TRANSACTIONS)
gume 0:163155b607df 45 //_SPI.endTransaction();
gume 0:163155b607df 46 //#endif
gume 0:163155b607df 47 }
gume 0:163155b607df 48
gume 0:163155b607df 49 /****************************************************************************/
gume 0:163155b607df 50
gume 0:163155b607df 51 uint8_t RF24::read_register(uint8_t reg, uint8_t* buf, uint8_t len)
gume 0:163155b607df 52 {
gume 0:163155b607df 53 uint8_t status;
gume 0:163155b607df 54
gume 0:163155b607df 55 beginTransaction(); //configures the spi settings for RPi, locks mutex and setting csn low
gume 0:163155b607df 56
gume 0:163155b607df 57 status = spi.write( R_REGISTER | ( REGISTER_MASK & reg ) );
gume 0:163155b607df 58 while ( len-- )
gume 0:163155b607df 59 *buf++ = spi.write(0xff);
gume 0:163155b607df 60
gume 0:163155b607df 61 endTransaction(); //unlocks mutex and setting csn high
gume 0:163155b607df 62
gume 0:163155b607df 63 return status;
gume 0:163155b607df 64 }
gume 0:163155b607df 65
gume 0:163155b607df 66 /****************************************************************************/
gume 0:163155b607df 67
gume 0:163155b607df 68 uint8_t RF24::read_register(uint8_t reg)
gume 0:163155b607df 69 {
gume 0:163155b607df 70 uint8_t result;
gume 0:163155b607df 71
gume 0:163155b607df 72 beginTransaction();
gume 0:163155b607df 73
gume 0:163155b607df 74 spi.write( R_REGISTER | ( REGISTER_MASK & reg ) );
gume 0:163155b607df 75 result = spi.write(0xff);
gume 0:163155b607df 76
gume 0:163155b607df 77 endTransaction();
gume 0:163155b607df 78
gume 0:163155b607df 79 return result;
gume 0:163155b607df 80 }
gume 0:163155b607df 81
gume 0:163155b607df 82 /****************************************************************************/
gume 0:163155b607df 83
gume 0:163155b607df 84 uint8_t RF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len)
gume 0:163155b607df 85 {
gume 0:163155b607df 86 uint8_t status;
gume 0:163155b607df 87
gume 0:163155b607df 88 beginTransaction();
gume 0:163155b607df 89
gume 0:163155b607df 90 status = spi.write( W_REGISTER | ( REGISTER_MASK & reg ) );
gume 0:163155b607df 91 while ( len-- )
gume 0:163155b607df 92 spi.write(*buf++);
gume 0:163155b607df 93
gume 0:163155b607df 94 endTransaction();
gume 0:163155b607df 95
gume 0:163155b607df 96 return status;
gume 0:163155b607df 97 }
gume 0:163155b607df 98
gume 0:163155b607df 99 /****************************************************************************/
gume 0:163155b607df 100
gume 0:163155b607df 101 uint8_t RF24::write_register(uint8_t reg, uint8_t value)
gume 0:163155b607df 102 {
gume 0:163155b607df 103 uint8_t status;
gume 0:163155b607df 104
gume 0:163155b607df 105 printf_P(PSTR("write_register(%02x,%02x)\r\n"),reg,value);
gume 0:163155b607df 106
gume 0:163155b607df 107 beginTransaction();
gume 0:163155b607df 108
gume 0:163155b607df 109 status = spi.write( W_REGISTER | ( REGISTER_MASK & reg ) );
gume 0:163155b607df 110 spi.write(value);
gume 0:163155b607df 111
gume 0:163155b607df 112 endTransaction();
gume 0:163155b607df 113
gume 0:163155b607df 114 return status;
gume 0:163155b607df 115 }
gume 0:163155b607df 116
gume 0:163155b607df 117 /****************************************************************************/
gume 0:163155b607df 118
gume 0:163155b607df 119 uint8_t RF24::write_payload(const void* buf, uint8_t data_len, const uint8_t writeType)
gume 0:163155b607df 120 {
gume 0:163155b607df 121 uint8_t status;
gume 0:163155b607df 122 const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);
gume 0:163155b607df 123
gume 0:163155b607df 124 data_len = rf24_min(data_len, payload_size);
gume 0:163155b607df 125 uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
gume 0:163155b607df 126
gume 0:163155b607df 127 printf_P("[Writing %u bytes %u blanks]\n",data_len,blank_len);
gume 0:163155b607df 128
gume 0:163155b607df 129 beginTransaction();
gume 0:163155b607df 130
gume 0:163155b607df 131 status = spi.write( W_TX_PAYLOAD );
gume 0:163155b607df 132 while ( data_len-- )
gume 0:163155b607df 133 spi.write(*current++);
gume 0:163155b607df 134 while ( blank_len-- )
gume 0:163155b607df 135 spi.write(0);
gume 0:163155b607df 136
gume 0:163155b607df 137 endTransaction();
gume 0:163155b607df 138
gume 0:163155b607df 139 return status;
gume 0:163155b607df 140 }
gume 0:163155b607df 141
gume 0:163155b607df 142 /****************************************************************************/
gume 0:163155b607df 143
gume 0:163155b607df 144 uint8_t RF24::read_payload(void* buf, uint8_t data_len)
gume 0:163155b607df 145 {
gume 0:163155b607df 146 uint8_t status;
gume 0:163155b607df 147 uint8_t* current = reinterpret_cast<uint8_t*>(buf);
gume 0:163155b607df 148
gume 0:163155b607df 149 if(data_len > payload_size) data_len = payload_size;
gume 0:163155b607df 150 uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
gume 0:163155b607df 151
gume 0:163155b607df 152 printf_P("[Reading %u bytes %u blanks]\n",data_len,blank_len);
gume 0:163155b607df 153
gume 0:163155b607df 154 beginTransaction();
gume 0:163155b607df 155
gume 0:163155b607df 156 status = spi.write( R_RX_PAYLOAD );
gume 0:163155b607df 157 while ( data_len-- )
gume 0:163155b607df 158 *current++ = spi.write(0xff);
gume 0:163155b607df 159 while ( blank_len-- )
gume 0:163155b607df 160 spi.write(0xff);
gume 0:163155b607df 161
gume 0:163155b607df 162 endTransaction();
gume 0:163155b607df 163
gume 0:163155b607df 164 return status;
gume 0:163155b607df 165 }
gume 0:163155b607df 166
gume 0:163155b607df 167 /****************************************************************************/
gume 0:163155b607df 168
gume 0:163155b607df 169 uint8_t RF24::flush_rx(void)
gume 0:163155b607df 170 {
gume 0:163155b607df 171 return spiTrans( FLUSH_RX );
gume 0:163155b607df 172 }
gume 0:163155b607df 173
gume 0:163155b607df 174 /****************************************************************************/
gume 0:163155b607df 175
gume 0:163155b607df 176 uint8_t RF24::flush_tx(void)
gume 0:163155b607df 177 {
gume 0:163155b607df 178 return spiTrans( FLUSH_TX );
gume 0:163155b607df 179 }
gume 0:163155b607df 180
gume 0:163155b607df 181 /****************************************************************************/
gume 0:163155b607df 182
gume 0:163155b607df 183 uint8_t RF24::spiTrans(uint8_t cmd)
gume 0:163155b607df 184 {
gume 0:163155b607df 185
gume 0:163155b607df 186 uint8_t status;
gume 0:163155b607df 187
gume 0:163155b607df 188 beginTransaction();
gume 0:163155b607df 189 status = spi.write(cmd);
gume 0:163155b607df 190 endTransaction();
gume 0:163155b607df 191
gume 0:163155b607df 192 return status;
gume 0:163155b607df 193 }
gume 0:163155b607df 194
gume 0:163155b607df 195 /****************************************************************************/
gume 0:163155b607df 196
gume 0:163155b607df 197 uint8_t RF24::get_status(void)
gume 0:163155b607df 198 {
gume 0:163155b607df 199 return spiTrans(NOP);
gume 0:163155b607df 200 }
gume 0:163155b607df 201
gume 0:163155b607df 202 /****************************************************************************/
gume 0:163155b607df 203 #if !defined (MINIMAL)
gume 0:163155b607df 204 void RF24::print_status(uint8_t status)
gume 0:163155b607df 205 {
gume 0:163155b607df 206 printf_P(PSTR("STATUS\t\t = 0x%02x RX_DR=%x TX_DS=%x MAX_RT=%x RX_P_NO=%x TX_FULL=%x\r\n"),
gume 0:163155b607df 207 status,
gume 0:163155b607df 208 (status & _BV(RX_DR))?1:0,
gume 0:163155b607df 209 (status & _BV(TX_DS))?1:0,
gume 0:163155b607df 210 (status & _BV(MAX_RT))?1:0,
gume 0:163155b607df 211 ((status >> RX_P_NO) & 0b111),
gume 0:163155b607df 212 (status & _BV(TX_FULL))?1:0
gume 0:163155b607df 213 );
gume 0:163155b607df 214 }
gume 0:163155b607df 215
gume 0:163155b607df 216 /****************************************************************************/
gume 0:163155b607df 217
gume 0:163155b607df 218 void RF24::print_observe_tx(uint8_t value)
gume 0:163155b607df 219 {
gume 0:163155b607df 220 printf_P(PSTR("OBSERVE_TX=%02x: POLS_CNT=%x ARC_CNT=%x\r\n"),
gume 0:163155b607df 221 value,
gume 0:163155b607df 222 (value >> PLOS_CNT) & 0b1111,
gume 0:163155b607df 223 (value >> ARC_CNT) & 0b1111
gume 0:163155b607df 224 );
gume 0:163155b607df 225 }
gume 0:163155b607df 226
gume 0:163155b607df 227 /****************************************************************************/
gume 0:163155b607df 228
gume 0:163155b607df 229 void RF24::print_byte_register(const char* name, uint8_t reg, uint8_t qty)
gume 0:163155b607df 230 {
gume 0:163155b607df 231 //char extra_tab = strlen_P(name) < 8 ? '\t' : 0;
gume 0:163155b607df 232 printf("%s\t =", name);
gume 0:163155b607df 233
gume 0:163155b607df 234 while (qty--)
gume 0:163155b607df 235 printf_P(PSTR(" 0x%02x"),read_register(reg++));
gume 0:163155b607df 236
gume 0:163155b607df 237 printf_P(PSTR("\r\n"));
gume 0:163155b607df 238 }
gume 0:163155b607df 239
gume 0:163155b607df 240 /****************************************************************************/
gume 0:163155b607df 241
gume 0:163155b607df 242 void RF24::print_address_register(const char* name, uint8_t reg, uint8_t qty)
gume 0:163155b607df 243 {
gume 0:163155b607df 244
gume 0:163155b607df 245 printf("%s\t =",name);
gume 0:163155b607df 246
gume 0:163155b607df 247 while (qty--) {
gume 0:163155b607df 248 uint8_t buffer[addr_width];
gume 0:163155b607df 249 read_register(reg++,buffer,sizeof buffer);
gume 0:163155b607df 250
gume 0:163155b607df 251 printf_P(PSTR(" 0x"));
gume 0:163155b607df 252 uint8_t* bufptr = buffer + sizeof buffer;
gume 0:163155b607df 253 while( --bufptr >= buffer )
gume 0:163155b607df 254 printf_P(PSTR("%02x"),*bufptr);
gume 0:163155b607df 255 }
gume 0:163155b607df 256
gume 0:163155b607df 257 printf_P(PSTR("\r\n"));
gume 0:163155b607df 258 }
gume 0:163155b607df 259 #endif // MINIMAL
gume 0:163155b607df 260
gume 0:163155b607df 261 /****************************************************************************/
gume 0:163155b607df 262
gume 0:163155b607df 263 RF24::RF24(PinName mosi, PinName miso, PinName sck, PinName _cepin, PinName _cspin):
gume 0:163155b607df 264 spi(mosi, miso, sck), ce_pin(_cepin), csn_pin(_cspin), p_variant(false),
gume 0:163155b607df 265 payload_size(32), dynamic_payloads_enabled(false), addr_width(5)//,pipe0_reading_address(0)
gume 0:163155b607df 266 {
gume 0:163155b607df 267 pipe0_reading_address[0]=0;
gume 0:163155b607df 268 }
gume 0:163155b607df 269
gume 0:163155b607df 270 /****************************************************************************/
gume 0:163155b607df 271
gume 0:163155b607df 272 void RF24::setChannel(uint8_t channel)
gume 0:163155b607df 273 {
gume 0:163155b607df 274 const uint8_t max_channel = 125;
gume 0:163155b607df 275 write_register(RF_CH,rf24_min(channel,max_channel));
gume 0:163155b607df 276 }
gume 0:163155b607df 277
gume 0:163155b607df 278 uint8_t RF24::getChannel()
gume 0:163155b607df 279 {
gume 0:163155b607df 280
gume 0:163155b607df 281 return read_register(RF_CH);
gume 0:163155b607df 282 }
gume 0:163155b607df 283 /****************************************************************************/
gume 0:163155b607df 284
gume 0:163155b607df 285 void RF24::setPayloadSize(uint8_t size)
gume 0:163155b607df 286 {
gume 0:163155b607df 287 payload_size = rf24_min(size,32);
gume 0:163155b607df 288 }
gume 0:163155b607df 289
gume 0:163155b607df 290 /****************************************************************************/
gume 0:163155b607df 291
gume 0:163155b607df 292 uint8_t RF24::getPayloadSize(void)
gume 0:163155b607df 293 {
gume 0:163155b607df 294 return payload_size;
gume 0:163155b607df 295 }
gume 0:163155b607df 296
gume 0:163155b607df 297 /****************************************************************************/
gume 0:163155b607df 298
gume 0:163155b607df 299 #if !defined (MINIMAL)
gume 0:163155b607df 300
gume 0:163155b607df 301 static const char rf24_datarate_e_str_0[] PROGMEM = "1MBPS";
gume 0:163155b607df 302 static const char rf24_datarate_e_str_1[] PROGMEM = "2MBPS";
gume 0:163155b607df 303 static const char rf24_datarate_e_str_2[] PROGMEM = "250KBPS";
gume 0:163155b607df 304 static const char * const rf24_datarate_e_str_P[] PROGMEM = {
gume 0:163155b607df 305 rf24_datarate_e_str_0,
gume 0:163155b607df 306 rf24_datarate_e_str_1,
gume 0:163155b607df 307 rf24_datarate_e_str_2,
gume 0:163155b607df 308 };
gume 0:163155b607df 309 static const char rf24_model_e_str_0[] PROGMEM = "nRF24L01";
gume 0:163155b607df 310 static const char rf24_model_e_str_1[] PROGMEM = "nRF24L01+";
gume 0:163155b607df 311 static const char * const rf24_model_e_str_P[] PROGMEM = {
gume 0:163155b607df 312 rf24_model_e_str_0,
gume 0:163155b607df 313 rf24_model_e_str_1,
gume 0:163155b607df 314 };
gume 0:163155b607df 315 static const char rf24_crclength_e_str_0[] PROGMEM = "Disabled";
gume 0:163155b607df 316 static const char rf24_crclength_e_str_1[] PROGMEM = "8 bits";
gume 0:163155b607df 317 static const char rf24_crclength_e_str_2[] PROGMEM = "16 bits" ;
gume 0:163155b607df 318 static const char * const rf24_crclength_e_str_P[] PROGMEM = {
gume 0:163155b607df 319 rf24_crclength_e_str_0,
gume 0:163155b607df 320 rf24_crclength_e_str_1,
gume 0:163155b607df 321 rf24_crclength_e_str_2,
gume 0:163155b607df 322 };
gume 0:163155b607df 323 static const char rf24_pa_dbm_e_str_0[] PROGMEM = "PA_MIN";
gume 0:163155b607df 324 static const char rf24_pa_dbm_e_str_1[] PROGMEM = "PA_LOW";
gume 0:163155b607df 325 static const char rf24_pa_dbm_e_str_2[] PROGMEM = "PA_HIGH";
gume 0:163155b607df 326 static const char rf24_pa_dbm_e_str_3[] PROGMEM = "PA_MAX";
gume 0:163155b607df 327 static const char * const rf24_pa_dbm_e_str_P[] PROGMEM = {
gume 0:163155b607df 328 rf24_pa_dbm_e_str_0,
gume 0:163155b607df 329 rf24_pa_dbm_e_str_1,
gume 0:163155b607df 330 rf24_pa_dbm_e_str_2,
gume 0:163155b607df 331 rf24_pa_dbm_e_str_3,
gume 0:163155b607df 332 };
gume 0:163155b607df 333
gume 0:163155b607df 334 void RF24::printDetails(void)
gume 0:163155b607df 335 {
gume 0:163155b607df 336
gume 0:163155b607df 337 print_status(get_status());
gume 0:163155b607df 338
gume 0:163155b607df 339 print_address_register(PSTR("RX_ADDR_P0-1"),RX_ADDR_P0,2);
gume 0:163155b607df 340 print_byte_register(PSTR("RX_ADDR_P2-5"),RX_ADDR_P2,4);
gume 0:163155b607df 341 print_address_register(PSTR("TX_ADDR\t"),TX_ADDR);
gume 0:163155b607df 342
gume 0:163155b607df 343 print_byte_register(PSTR("RX_PW_P0-6"),RX_PW_P0,6);
gume 0:163155b607df 344 print_byte_register(PSTR("EN_AA\t"),EN_AA);
gume 0:163155b607df 345 print_byte_register(PSTR("EN_RXADDR"),EN_RXADDR);
gume 0:163155b607df 346 print_byte_register(PSTR("RF_CH\t"),RF_CH);
gume 0:163155b607df 347 print_byte_register(PSTR("RF_SETUP"),RF_SETUP);
gume 0:163155b607df 348 print_byte_register(PSTR("CONFIG\t"),CONFIG);
gume 0:163155b607df 349 print_byte_register(PSTR("DYNPD/FEATURE"),DYNPD,2);
gume 0:163155b607df 350
gume 0:163155b607df 351 printf_P(PSTR("Data Rate\t = " PRIPSTR "\r\n"),pgm_read_word(&rf24_datarate_e_str_P[getDataRate()]));
gume 0:163155b607df 352 printf_P(PSTR("Model\t\t = " PRIPSTR "\r\n"),pgm_read_word(&rf24_model_e_str_P[isPVariant()]));
gume 0:163155b607df 353 printf_P(PSTR("CRC Length\t = " PRIPSTR "\r\n"),pgm_read_word(&rf24_crclength_e_str_P[getCRCLength()]));
gume 0:163155b607df 354 printf_P(PSTR("PA Power\t = " PRIPSTR "\r\n"), pgm_read_word(&rf24_pa_dbm_e_str_P[getPALevel()]));
gume 0:163155b607df 355
gume 0:163155b607df 356 }
gume 0:163155b607df 357
gume 0:163155b607df 358 #endif
gume 0:163155b607df 359 /****************************************************************************/
gume 0:163155b607df 360
gume 0:163155b607df 361 bool RF24::begin(void)
gume 0:163155b607df 362 {
gume 0:163155b607df 363
gume 0:163155b607df 364 uint8_t setup=0;
gume 0:163155b607df 365
gume 0:163155b607df 366 //_SPI.begin(csn_pin);
gume 0:163155b607df 367 spi.frequency(4000000); // 4Mbit
gume 0:163155b607df 368 spi.format(8,0); // 8-bit, ClockPhase = 0, ClockPolarity = 0
gume 0:163155b607df 369
gume 0:163155b607df 370 mainTimer.start();
gume 0:163155b607df 371
gume 0:163155b607df 372 ce(LOW);
gume 0:163155b607df 373
gume 0:163155b607df 374 wait_ms(100);
gume 0:163155b607df 375
gume 0:163155b607df 376 // Must allow the radio time to settle else configuration bits will not necessarily stick.
gume 0:163155b607df 377 // This is actually only required following power up but some settling time also appears to
gume 0:163155b607df 378 // be required after resets too. For full coverage, we'll always assume the worst.
gume 0:163155b607df 379 // Enabling 16b CRC is by far the most obvious case if the wrong timing is used - or skipped.
gume 0:163155b607df 380 // Technically we require 4.5ms + 14us as a worst case. We'll just call it 5ms for good measure.
gume 0:163155b607df 381 // WARNING: Delay is based on P-variant whereby non-P *may* require different timing.
gume 0:163155b607df 382 wait_ms( 5 ) ;
gume 0:163155b607df 383
gume 0:163155b607df 384 // Reset CONFIG and enable 16-bit CRC.
gume 0:163155b607df 385 write_register( CONFIG, 0b00001100 ) ;
gume 0:163155b607df 386
gume 0:163155b607df 387 // Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
gume 0:163155b607df 388 // WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
gume 0:163155b607df 389 // sizes must never be used. See documentation for a more complete explanation.
gume 0:163155b607df 390 setRetries(5,15);
gume 0:163155b607df 391
gume 0:163155b607df 392 // Reset value is MAX
gume 0:163155b607df 393 //setPALevel( RF24_PA_MAX ) ;
gume 0:163155b607df 394
gume 0:163155b607df 395 // check for connected module and if this is a p nRF24l01 variant
gume 0:163155b607df 396 //
gume 0:163155b607df 397 if( setDataRate( RF24_250KBPS ) ) {
gume 0:163155b607df 398 p_variant = true ;
gume 0:163155b607df 399 }
gume 0:163155b607df 400 setup = read_register(RF_SETUP);
gume 0:163155b607df 401 /*if( setup == 0b00001110 ) // register default for nRF24L01P
gume 0:163155b607df 402 {
gume 0:163155b607df 403 p_variant = true ;
gume 0:163155b607df 404 }*/
gume 0:163155b607df 405
gume 0:163155b607df 406 // Then set the data rate to the slowest (and most reliable) speed supported by all
gume 0:163155b607df 407 // hardware.
gume 0:163155b607df 408 setDataRate( RF24_1MBPS ) ;
gume 0:163155b607df 409
gume 0:163155b607df 410 // Initialize CRC and request 2-byte (16bit) CRC
gume 0:163155b607df 411 //setCRCLength( RF24_CRC_16 ) ;
gume 0:163155b607df 412
gume 0:163155b607df 413 // Disable dynamic payloads, to match dynamic_payloads_enabled setting - Reset value is 0
gume 0:163155b607df 414 toggle_features();
gume 0:163155b607df 415 write_register(FEATURE,0 );
gume 0:163155b607df 416 write_register(DYNPD,0);
gume 0:163155b607df 417
gume 0:163155b607df 418 // Reset current status
gume 0:163155b607df 419 // Notice reset and flush is the last thing we do
gume 0:163155b607df 420 write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
gume 0:163155b607df 421
gume 0:163155b607df 422 // Set up default configuration. Callers can always change it later.
gume 0:163155b607df 423 // This channel should be universally safe and not bleed over into adjacent
gume 0:163155b607df 424 // spectrum.
gume 0:163155b607df 425 setChannel(76);
gume 0:163155b607df 426
gume 0:163155b607df 427 // Flush buffers
gume 0:163155b607df 428 flush_rx();
gume 0:163155b607df 429 flush_tx();
gume 0:163155b607df 430
gume 0:163155b607df 431 powerUp(); //Power up by default when begin() is called
gume 0:163155b607df 432
gume 0:163155b607df 433 // Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX instead of 1500us from powerUp )
gume 0:163155b607df 434 // PTX should use only 22uA of power
gume 0:163155b607df 435 write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) );
gume 0:163155b607df 436
gume 0:163155b607df 437 // if setup is 0 or ff then there was no response from module
gume 0:163155b607df 438 return ( setup != 0 && setup != 0xff );
gume 0:163155b607df 439 }
gume 0:163155b607df 440
gume 0:163155b607df 441 /****************************************************************************/
gume 0:163155b607df 442
gume 0:163155b607df 443 void RF24::startListening(void)
gume 0:163155b607df 444 {
gume 0:163155b607df 445
gume 0:163155b607df 446 powerUp();
gume 0:163155b607df 447
gume 0:163155b607df 448 write_register(CONFIG, read_register(CONFIG) | _BV(PRIM_RX));
gume 0:163155b607df 449 write_register(NRF_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
gume 0:163155b607df 450 ce(HIGH);
gume 0:163155b607df 451 // Restore the pipe0 adddress, if exists
gume 0:163155b607df 452 if (pipe0_reading_address[0] > 0) {
gume 0:163155b607df 453 write_register(RX_ADDR_P0, pipe0_reading_address, addr_width);
gume 0:163155b607df 454 } else {
gume 0:163155b607df 455 closeReadingPipe(0);
gume 0:163155b607df 456 }
gume 0:163155b607df 457
gume 0:163155b607df 458 // Flush buffers
gume 0:163155b607df 459 //flush_rx();
gume 0:163155b607df 460 if(read_register(FEATURE) & _BV(EN_ACK_PAY)) {
gume 0:163155b607df 461 flush_tx();
gume 0:163155b607df 462 }
gume 0:163155b607df 463
gume 0:163155b607df 464 // Go!
gume 0:163155b607df 465 //delayMicroseconds(100);
gume 0:163155b607df 466 }
gume 0:163155b607df 467
gume 0:163155b607df 468 /****************************************************************************/
gume 0:163155b607df 469 static const uint8_t child_pipe_enable[] PROGMEM = {
gume 0:163155b607df 470 ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5
gume 0:163155b607df 471 };
gume 0:163155b607df 472
gume 0:163155b607df 473 void RF24::stopListening(void)
gume 0:163155b607df 474 {
gume 0:163155b607df 475 ce(LOW);
gume 0:163155b607df 476
gume 0:163155b607df 477 wait_us(txRxDelay);
gume 0:163155b607df 478
gume 0:163155b607df 479 if(read_register(FEATURE) & _BV(EN_ACK_PAY)) {
gume 0:163155b607df 480 wait_us(txRxDelay); //200
gume 0:163155b607df 481 flush_tx();
gume 0:163155b607df 482 }
gume 0:163155b607df 483 //flush_rx();
gume 0:163155b607df 484 write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) );
gume 0:163155b607df 485 write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[0]))); // Enable RX on pipe0
gume 0:163155b607df 486
gume 0:163155b607df 487 //delayMicroseconds(100);
gume 0:163155b607df 488
gume 0:163155b607df 489 }
gume 0:163155b607df 490
gume 0:163155b607df 491 /****************************************************************************/
gume 0:163155b607df 492
gume 0:163155b607df 493 void RF24::powerDown(void)
gume 0:163155b607df 494 {
gume 0:163155b607df 495 ce(LOW); // Guarantee CE is low on powerDown
gume 0:163155b607df 496 write_register(CONFIG,read_register(CONFIG) & ~_BV(PWR_UP));
gume 0:163155b607df 497 }
gume 0:163155b607df 498
gume 0:163155b607df 499 /****************************************************************************/
gume 0:163155b607df 500
gume 0:163155b607df 501 //Power up now. Radio will not power down unless instructed by MCU for config changes etc.
gume 0:163155b607df 502 void RF24::powerUp(void)
gume 0:163155b607df 503 {
gume 0:163155b607df 504 uint8_t cfg = read_register(CONFIG);
gume 0:163155b607df 505
gume 0:163155b607df 506 // if not powered up then power up and wait for the radio to initialize
gume 0:163155b607df 507 if (!(cfg & _BV(PWR_UP))) {
gume 0:163155b607df 508 write_register(CONFIG,read_register(CONFIG) | _BV(PWR_UP));
gume 0:163155b607df 509
gume 0:163155b607df 510 // For nRF24L01+ to go from power down mode to TX or RX mode it must first pass through stand-by mode.
gume 0:163155b607df 511 // There must be a delay of Tpd2stby (see Table 16.) after the nRF24L01+ leaves power down mode before
gume 0:163155b607df 512 // the CEis set high. - Tpd2stby can be up to 5ms per the 1.0 datasheet
gume 0:163155b607df 513 wait_ms(5);
gume 0:163155b607df 514 }
gume 0:163155b607df 515 }
gume 0:163155b607df 516
gume 0:163155b607df 517 /******************************************************************/
gume 0:163155b607df 518 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 519 void RF24::errNotify()
gume 0:163155b607df 520 {
gume 0:163155b607df 521 printf_P(PSTR("RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.\r\n"));
gume 0:163155b607df 522 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 523 failureDetected = 1;
gume 0:163155b607df 524 #else
gume 0:163155b607df 525 delay(5000);
gume 0:163155b607df 526 #endif
gume 0:163155b607df 527 }
gume 0:163155b607df 528 #endif
gume 0:163155b607df 529 /******************************************************************/
gume 0:163155b607df 530
gume 0:163155b607df 531 //Similar to the previous write, clears the interrupt flags
gume 0:163155b607df 532 bool RF24::write( const void* buf, uint8_t len, const bool multicast )
gume 0:163155b607df 533 {
gume 0:163155b607df 534 //Start Writing
gume 0:163155b607df 535 startFastWrite(buf,len,multicast);
gume 0:163155b607df 536
gume 0:163155b607df 537 //Wait until complete or failed
gume 0:163155b607df 538 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 539 uint32_t timer = millis();
gume 0:163155b607df 540 #endif
gume 0:163155b607df 541
gume 0:163155b607df 542 while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) {
gume 0:163155b607df 543 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 544 if(millis() - timer > 85) {
gume 0:163155b607df 545 errNotify();
gume 0:163155b607df 546 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 547 return 0;
gume 0:163155b607df 548 #else
gume 0:163155b607df 549 delay(100);
gume 0:163155b607df 550 #endif
gume 0:163155b607df 551 }
gume 0:163155b607df 552 #endif
gume 0:163155b607df 553 }
gume 0:163155b607df 554
gume 0:163155b607df 555 ce(LOW);
gume 0:163155b607df 556
gume 0:163155b607df 557 uint8_t status = write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
gume 0:163155b607df 558
gume 0:163155b607df 559 //Max retries exceeded
gume 0:163155b607df 560 if( status & _BV(MAX_RT)) {
gume 0:163155b607df 561 flush_tx(); //Only going to be 1 packet int the FIFO at a time using this method, so just flush
gume 0:163155b607df 562 return 0;
gume 0:163155b607df 563 }
gume 0:163155b607df 564 //TX OK 1 or 0
gume 0:163155b607df 565 return 1;
gume 0:163155b607df 566 }
gume 0:163155b607df 567
gume 0:163155b607df 568 bool RF24::write( const void* buf, uint8_t len )
gume 0:163155b607df 569 {
gume 0:163155b607df 570 return write(buf,len,0);
gume 0:163155b607df 571 }
gume 0:163155b607df 572 /****************************************************************************/
gume 0:163155b607df 573
gume 0:163155b607df 574 //For general use, the interrupt flags are not important to clear
gume 0:163155b607df 575 bool RF24::writeBlocking( const void* buf, uint8_t len, uint32_t timeout )
gume 0:163155b607df 576 {
gume 0:163155b607df 577 //Block until the FIFO is NOT full.
gume 0:163155b607df 578 //Keep track of the MAX retries and set auto-retry if seeing failures
gume 0:163155b607df 579 //This way the FIFO will fill up and allow blocking until packets go through
gume 0:163155b607df 580 //The radio will auto-clear everything in the FIFO as long as CE remains high
gume 0:163155b607df 581
gume 0:163155b607df 582 uint32_t timer = mainTimer.read_ms(); //Get the time that the payload transmission started
gume 0:163155b607df 583
gume 0:163155b607df 584 while( ( get_status() & ( _BV(TX_FULL) ))) { //Blocking only if FIFO is full. This will loop and block until TX is successful or timeout
gume 0:163155b607df 585
gume 0:163155b607df 586 if( get_status() & _BV(MAX_RT)) { //If MAX Retries have been reached
gume 0:163155b607df 587 reUseTX(); //Set re-transmit and clear the MAX_RT interrupt flag
gume 0:163155b607df 588 if(mainTimer.read_ms() - timer > timeout) {
gume 0:163155b607df 589 return 0; //If this payload has exceeded the user-defined timeout, exit and return 0
gume 0:163155b607df 590 }
gume 0:163155b607df 591 }
gume 0:163155b607df 592 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 593 if(mainTimer.read_ms() - timer > (timeout+85) ) {
gume 0:163155b607df 594 errNotify();
gume 0:163155b607df 595 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 596 return 0;
gume 0:163155b607df 597 #endif
gume 0:163155b607df 598 }
gume 0:163155b607df 599 #endif
gume 0:163155b607df 600
gume 0:163155b607df 601 }
gume 0:163155b607df 602
gume 0:163155b607df 603 //Start Writing
gume 0:163155b607df 604 startFastWrite(buf,len,0); //Write the payload if a buffer is clear
gume 0:163155b607df 605
gume 0:163155b607df 606 return 1; //Return 1 to indicate successful transmission
gume 0:163155b607df 607 }
gume 0:163155b607df 608
gume 0:163155b607df 609 /****************************************************************************/
gume 0:163155b607df 610
gume 0:163155b607df 611 void RF24::reUseTX()
gume 0:163155b607df 612 {
gume 0:163155b607df 613 write_register(NRF_STATUS,_BV(MAX_RT) ); //Clear max retry flag
gume 0:163155b607df 614 spiTrans( REUSE_TX_PL );
gume 0:163155b607df 615 ce(LOW); //Re-Transfer packet
gume 0:163155b607df 616 ce(HIGH);
gume 0:163155b607df 617 }
gume 0:163155b607df 618
gume 0:163155b607df 619 /****************************************************************************/
gume 0:163155b607df 620
gume 0:163155b607df 621 bool RF24::writeFast( const void* buf, uint8_t len, const bool multicast )
gume 0:163155b607df 622 {
gume 0:163155b607df 623 //Block until the FIFO is NOT full.
gume 0:163155b607df 624 //Keep track of the MAX retries and set auto-retry if seeing failures
gume 0:163155b607df 625 //Return 0 so the user can control the retrys and set a timer or failure counter if required
gume 0:163155b607df 626 //The radio will auto-clear everything in the FIFO as long as CE remains high
gume 0:163155b607df 627
gume 0:163155b607df 628 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 629 uint32_t timer = millis();
gume 0:163155b607df 630 #endif
gume 0:163155b607df 631
gume 0:163155b607df 632 while( ( get_status() & ( _BV(TX_FULL) ))) { //Blocking only if FIFO is full. This will loop and block until TX is successful or fail
gume 0:163155b607df 633
gume 0:163155b607df 634 if( get_status() & _BV(MAX_RT)) {
gume 0:163155b607df 635 //reUseTX(); //Set re-transmit
gume 0:163155b607df 636 write_register(NRF_STATUS,_BV(MAX_RT) ); //Clear max retry flag
gume 0:163155b607df 637 return 0; //Return 0. The previous payload has been retransmitted
gume 0:163155b607df 638 //From the user perspective, if you get a 0, just keep trying to send the same payload
gume 0:163155b607df 639 }
gume 0:163155b607df 640 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 641 if(millis() - timer > 85 ) {
gume 0:163155b607df 642 errNotify();
gume 0:163155b607df 643 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 644 return 0;
gume 0:163155b607df 645 #endif
gume 0:163155b607df 646 }
gume 0:163155b607df 647 #endif
gume 0:163155b607df 648 }
gume 0:163155b607df 649 //Start Writing
gume 0:163155b607df 650 startFastWrite(buf,len,multicast);
gume 0:163155b607df 651
gume 0:163155b607df 652 return 1;
gume 0:163155b607df 653 }
gume 0:163155b607df 654
gume 0:163155b607df 655 bool RF24::writeFast( const void* buf, uint8_t len )
gume 0:163155b607df 656 {
gume 0:163155b607df 657 return writeFast(buf,len,0);
gume 0:163155b607df 658 }
gume 0:163155b607df 659
gume 0:163155b607df 660 /****************************************************************************/
gume 0:163155b607df 661
gume 0:163155b607df 662 //Per the documentation, we want to set PTX Mode when not listening. Then all we do is write data and set CE high
gume 0:163155b607df 663 //In this mode, if we can keep the FIFO buffers loaded, packets will transmit immediately (no 130us delay)
gume 0:163155b607df 664 //Otherwise we enter Standby-II mode, which is still faster than standby mode
gume 0:163155b607df 665 //Also, we remove the need to keep writing the config register over and over and delaying for 150 us each time if sending a stream of data
gume 0:163155b607df 666
gume 0:163155b607df 667 void RF24::startFastWrite( const void* buf, uint8_t len, const bool multicast, bool startTx) //TMRh20
gume 0:163155b607df 668 {
gume 0:163155b607df 669
gume 0:163155b607df 670 //write_payload( buf,len);
gume 0:163155b607df 671 write_payload( buf, len,multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ;
gume 0:163155b607df 672 if(startTx) {
gume 0:163155b607df 673 ce(HIGH);
gume 0:163155b607df 674 }
gume 0:163155b607df 675
gume 0:163155b607df 676 }
gume 0:163155b607df 677
gume 0:163155b607df 678 /****************************************************************************/
gume 0:163155b607df 679
gume 0:163155b607df 680 //Added the original startWrite back in so users can still use interrupts, ack payloads, etc
gume 0:163155b607df 681 //Allows the library to pass all tests
gume 0:163155b607df 682 void RF24::startWrite( const void* buf, uint8_t len, const bool multicast )
gume 0:163155b607df 683 {
gume 0:163155b607df 684
gume 0:163155b607df 685 // Send the payload
gume 0:163155b607df 686
gume 0:163155b607df 687 //write_payload( buf, len );
gume 0:163155b607df 688 write_payload( buf, len,multicast? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ;
gume 0:163155b607df 689 ce(HIGH);
gume 0:163155b607df 690 // Maybe wait for 10 us
gume 0:163155b607df 691 // delayMicroseconds(10);
gume 0:163155b607df 692 ce(LOW);
gume 0:163155b607df 693
gume 0:163155b607df 694
gume 0:163155b607df 695 }
gume 0:163155b607df 696
gume 0:163155b607df 697 /****************************************************************************/
gume 0:163155b607df 698
gume 0:163155b607df 699 bool RF24::rxFifoFull()
gume 0:163155b607df 700 {
gume 0:163155b607df 701 return read_register(FIFO_STATUS) & _BV(RX_FULL);
gume 0:163155b607df 702 }
gume 0:163155b607df 703 /****************************************************************************/
gume 0:163155b607df 704
gume 0:163155b607df 705 bool RF24::txStandBy()
gume 0:163155b607df 706 {
gume 0:163155b607df 707
gume 0:163155b607df 708 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 709 uint32_t timeout = millis();
gume 0:163155b607df 710 #endif
gume 0:163155b607df 711 while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ) {
gume 0:163155b607df 712 if( get_status() & _BV(MAX_RT)) {
gume 0:163155b607df 713 write_register(NRF_STATUS,_BV(MAX_RT) );
gume 0:163155b607df 714 ce(LOW);
gume 0:163155b607df 715 flush_tx(); //Non blocking, flush the data
gume 0:163155b607df 716 return 0;
gume 0:163155b607df 717 }
gume 0:163155b607df 718 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 719 if( millis() - timeout > 85) {
gume 0:163155b607df 720 errNotify();
gume 0:163155b607df 721 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 722 return 0;
gume 0:163155b607df 723 #endif
gume 0:163155b607df 724 }
gume 0:163155b607df 725 #endif
gume 0:163155b607df 726 }
gume 0:163155b607df 727
gume 0:163155b607df 728 ce(LOW); //Set STANDBY-I mode
gume 0:163155b607df 729 return 1;
gume 0:163155b607df 730 }
gume 0:163155b607df 731
gume 0:163155b607df 732 /****************************************************************************/
gume 0:163155b607df 733
gume 0:163155b607df 734 bool RF24::txStandBy(uint32_t timeout, bool startTx)
gume 0:163155b607df 735 {
gume 0:163155b607df 736
gume 0:163155b607df 737 if(startTx) {
gume 0:163155b607df 738 stopListening();
gume 0:163155b607df 739 ce(HIGH);
gume 0:163155b607df 740 }
gume 0:163155b607df 741 uint32_t start = mainTimer.read_ms();
gume 0:163155b607df 742
gume 0:163155b607df 743 while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ) {
gume 0:163155b607df 744 if( get_status() & _BV(MAX_RT)) {
gume 0:163155b607df 745 write_register(NRF_STATUS,_BV(MAX_RT) );
gume 0:163155b607df 746 ce(LOW); //Set re-transmit
gume 0:163155b607df 747 ce(HIGH);
gume 0:163155b607df 748 if(mainTimer.read_ms() - start >= timeout) {
gume 0:163155b607df 749 ce(LOW);
gume 0:163155b607df 750 flush_tx();
gume 0:163155b607df 751 return 0;
gume 0:163155b607df 752 }
gume 0:163155b607df 753 }
gume 0:163155b607df 754 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 755 if( mainTimer.read_ms() - start > (timeout+85)) {
gume 0:163155b607df 756 errNotify();
gume 0:163155b607df 757 #if defined (FAILURE_HANDLING)
gume 0:163155b607df 758 return 0;
gume 0:163155b607df 759 #endif
gume 0:163155b607df 760 }
gume 0:163155b607df 761 #endif
gume 0:163155b607df 762 }
gume 0:163155b607df 763
gume 0:163155b607df 764 ce(LOW); //Set STANDBY-I mode
gume 0:163155b607df 765 return 1;
gume 0:163155b607df 766
gume 0:163155b607df 767 }
gume 0:163155b607df 768
gume 0:163155b607df 769 /****************************************************************************/
gume 0:163155b607df 770
gume 0:163155b607df 771 void RF24::maskIRQ(bool tx, bool fail, bool rx)
gume 0:163155b607df 772 {
gume 0:163155b607df 773
gume 0:163155b607df 774 uint8_t config = read_register(CONFIG);
gume 0:163155b607df 775 /* clear the interrupt flags */
gume 0:163155b607df 776 config &= ~(1 << MASK_MAX_RT | 1 << MASK_TX_DS | 1 << MASK_RX_DR);
gume 0:163155b607df 777 /* set the specified interrupt flags */
gume 0:163155b607df 778 config |= fail << MASK_MAX_RT | tx << MASK_TX_DS | rx << MASK_RX_DR;
gume 0:163155b607df 779 write_register(CONFIG, config);
gume 0:163155b607df 780 }
gume 0:163155b607df 781
gume 0:163155b607df 782 /****************************************************************************/
gume 0:163155b607df 783
gume 0:163155b607df 784 uint8_t RF24::getDynamicPayloadSize(void)
gume 0:163155b607df 785 {
gume 0:163155b607df 786 uint8_t result = 0;
gume 0:163155b607df 787
gume 0:163155b607df 788 beginTransaction();
gume 0:163155b607df 789
gume 0:163155b607df 790 spi.write( R_RX_PL_WID );
gume 0:163155b607df 791 result = spi.write(0xff);
gume 0:163155b607df 792
gume 0:163155b607df 793 endTransaction();
gume 0:163155b607df 794
gume 0:163155b607df 795 return result;
gume 0:163155b607df 796 }
gume 0:163155b607df 797
gume 0:163155b607df 798 /****************************************************************************/
gume 0:163155b607df 799
gume 0:163155b607df 800 bool RF24::available(void)
gume 0:163155b607df 801 {
gume 0:163155b607df 802 return available(NULL);
gume 0:163155b607df 803 }
gume 0:163155b607df 804
gume 0:163155b607df 805 /****************************************************************************/
gume 0:163155b607df 806
gume 0:163155b607df 807 bool RF24::available(uint8_t* pipe_num)
gume 0:163155b607df 808 {
gume 0:163155b607df 809 if (!( read_register(FIFO_STATUS) & _BV(RX_EMPTY) )) {
gume 0:163155b607df 810
gume 0:163155b607df 811 // If the caller wants the pipe number, include that
gume 0:163155b607df 812 if ( pipe_num ) {
gume 0:163155b607df 813 uint8_t status = get_status();
gume 0:163155b607df 814 *pipe_num = ( status >> RX_P_NO ) & 0b111;
gume 0:163155b607df 815 }
gume 0:163155b607df 816 return 1;
gume 0:163155b607df 817 }
gume 0:163155b607df 818
gume 0:163155b607df 819
gume 0:163155b607df 820 return 0;
gume 0:163155b607df 821
gume 0:163155b607df 822
gume 0:163155b607df 823 }
gume 0:163155b607df 824
gume 0:163155b607df 825 /****************************************************************************/
gume 0:163155b607df 826
gume 0:163155b607df 827 void RF24::read( void* buf, uint8_t len )
gume 0:163155b607df 828 {
gume 0:163155b607df 829
gume 0:163155b607df 830 // Fetch the payload
gume 0:163155b607df 831 read_payload( buf, len );
gume 0:163155b607df 832
gume 0:163155b607df 833 //Clear the two possible interrupt flags with one command
gume 0:163155b607df 834 write_register(NRF_STATUS,_BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS) );
gume 0:163155b607df 835
gume 0:163155b607df 836 }
gume 0:163155b607df 837
gume 0:163155b607df 838 /****************************************************************************/
gume 0:163155b607df 839
gume 0:163155b607df 840 void RF24::whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready)
gume 0:163155b607df 841 {
gume 0:163155b607df 842 // Read the status & reset the status in one easy call
gume 0:163155b607df 843 // Or is that such a good idea?
gume 0:163155b607df 844 uint8_t status = write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
gume 0:163155b607df 845
gume 0:163155b607df 846 // Report to the user what happened
gume 0:163155b607df 847 tx_ok = status & _BV(TX_DS);
gume 0:163155b607df 848 tx_fail = status & _BV(MAX_RT);
gume 0:163155b607df 849 rx_ready = status & _BV(RX_DR);
gume 0:163155b607df 850 }
gume 0:163155b607df 851
gume 0:163155b607df 852 /****************************************************************************/
gume 0:163155b607df 853
gume 0:163155b607df 854 void RF24::openWritingPipe(uint64_t value)
gume 0:163155b607df 855 {
gume 0:163155b607df 856 // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+)
gume 0:163155b607df 857 // expects it LSB first too, so we're good.
gume 0:163155b607df 858
gume 0:163155b607df 859 write_register(RX_ADDR_P0, reinterpret_cast<uint8_t*>(&value), addr_width);
gume 0:163155b607df 860 write_register(TX_ADDR, reinterpret_cast<uint8_t*>(&value), addr_width);
gume 0:163155b607df 861
gume 0:163155b607df 862
gume 0:163155b607df 863 //const uint8_t max_payload_size = 32;
gume 0:163155b607df 864 //write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size));
gume 0:163155b607df 865 write_register(RX_PW_P0,payload_size);
gume 0:163155b607df 866 }
gume 0:163155b607df 867
gume 0:163155b607df 868 /****************************************************************************/
gume 0:163155b607df 869 void RF24::openWritingPipe(const uint8_t *address)
gume 0:163155b607df 870 {
gume 0:163155b607df 871 // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+)
gume 0:163155b607df 872 // expects it LSB first too, so we're good.
gume 0:163155b607df 873
gume 0:163155b607df 874 write_register(RX_ADDR_P0,address, addr_width);
gume 0:163155b607df 875 write_register(TX_ADDR, address, addr_width);
gume 0:163155b607df 876
gume 0:163155b607df 877 //const uint8_t max_payload_size = 32;
gume 0:163155b607df 878 //write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size));
gume 0:163155b607df 879 write_register(RX_PW_P0,payload_size);
gume 0:163155b607df 880 }
gume 0:163155b607df 881
gume 0:163155b607df 882 /****************************************************************************/
gume 0:163155b607df 883 static const uint8_t child_pipe[] PROGMEM = {
gume 0:163155b607df 884 RX_ADDR_P0, RX_ADDR_P1, RX_ADDR_P2, RX_ADDR_P3, RX_ADDR_P4, RX_ADDR_P5
gume 0:163155b607df 885 };
gume 0:163155b607df 886 static const uint8_t child_payload_size[] PROGMEM = {
gume 0:163155b607df 887 RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5
gume 0:163155b607df 888 };
gume 0:163155b607df 889
gume 0:163155b607df 890
gume 0:163155b607df 891 void RF24::openReadingPipe(uint8_t child, uint64_t address)
gume 0:163155b607df 892 {
gume 0:163155b607df 893 // If this is pipe 0, cache the address. This is needed because
gume 0:163155b607df 894 // openWritingPipe() will overwrite the pipe 0 address, so
gume 0:163155b607df 895 // startListening() will have to restore it.
gume 0:163155b607df 896 if (child == 0) {
gume 0:163155b607df 897 memcpy(pipe0_reading_address,&address,addr_width);
gume 0:163155b607df 898 }
gume 0:163155b607df 899
gume 0:163155b607df 900 if (child <= 6) {
gume 0:163155b607df 901 // For pipes 2-5, only write the LSB
gume 0:163155b607df 902 if ( child < 2 )
gume 0:163155b607df 903 write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast<const uint8_t*>(&address), addr_width);
gume 0:163155b607df 904 else
gume 0:163155b607df 905 write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast<const uint8_t*>(&address), 1);
gume 0:163155b607df 906
gume 0:163155b607df 907 write_register(pgm_read_byte(&child_payload_size[child]),payload_size);
gume 0:163155b607df 908
gume 0:163155b607df 909 // Note it would be more efficient to set all of the bits for all open
gume 0:163155b607df 910 // pipes at once. However, I thought it would make the calling code
gume 0:163155b607df 911 // more simple to do it this way.
gume 0:163155b607df 912 write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child])));
gume 0:163155b607df 913 }
gume 0:163155b607df 914 }
gume 0:163155b607df 915
gume 0:163155b607df 916 /****************************************************************************/
gume 0:163155b607df 917 void RF24::setAddressWidth(uint8_t a_width)
gume 0:163155b607df 918 {
gume 0:163155b607df 919
gume 0:163155b607df 920 if(a_width -= 2) {
gume 0:163155b607df 921 write_register(SETUP_AW,a_width%4);
gume 0:163155b607df 922 addr_width = (a_width%4) + 2;
gume 0:163155b607df 923 }
gume 0:163155b607df 924
gume 0:163155b607df 925 }
gume 0:163155b607df 926
gume 0:163155b607df 927 /****************************************************************************/
gume 0:163155b607df 928
gume 0:163155b607df 929 void RF24::openReadingPipe(uint8_t child, const uint8_t *address)
gume 0:163155b607df 930 {
gume 0:163155b607df 931 // If this is pipe 0, cache the address. This is needed because
gume 0:163155b607df 932 // openWritingPipe() will overwrite the pipe 0 address, so
gume 0:163155b607df 933 // startListening() will have to restore it.
gume 0:163155b607df 934 if (child == 0) {
gume 0:163155b607df 935 memcpy(pipe0_reading_address,address,addr_width);
gume 0:163155b607df 936 }
gume 0:163155b607df 937 if (child <= 6) {
gume 0:163155b607df 938 // For pipes 2-5, only write the LSB
gume 0:163155b607df 939 if ( child < 2 ) {
gume 0:163155b607df 940 write_register(pgm_read_byte(&child_pipe[child]), address, addr_width);
gume 0:163155b607df 941 } else {
gume 0:163155b607df 942 write_register(pgm_read_byte(&child_pipe[child]), address, 1);
gume 0:163155b607df 943 }
gume 0:163155b607df 944 write_register(pgm_read_byte(&child_payload_size[child]),payload_size);
gume 0:163155b607df 945
gume 0:163155b607df 946 // Note it would be more efficient to set all of the bits for all open
gume 0:163155b607df 947 // pipes at once. However, I thought it would make the calling code
gume 0:163155b607df 948 // more simple to do it this way.
gume 0:163155b607df 949 write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child])));
gume 0:163155b607df 950
gume 0:163155b607df 951 }
gume 0:163155b607df 952 }
gume 0:163155b607df 953
gume 0:163155b607df 954 /****************************************************************************/
gume 0:163155b607df 955
gume 0:163155b607df 956 void RF24::closeReadingPipe( uint8_t pipe )
gume 0:163155b607df 957 {
gume 0:163155b607df 958 write_register(EN_RXADDR,read_register(EN_RXADDR) & ~_BV(pgm_read_byte(&child_pipe_enable[pipe])));
gume 0:163155b607df 959 }
gume 0:163155b607df 960
gume 0:163155b607df 961 /****************************************************************************/
gume 0:163155b607df 962
gume 0:163155b607df 963 void RF24::toggle_features(void)
gume 0:163155b607df 964 {
gume 0:163155b607df 965 beginTransaction();
gume 0:163155b607df 966
gume 0:163155b607df 967 spi.write( ACTIVATE );
gume 0:163155b607df 968 spi.write( 0x73 );
gume 0:163155b607df 969
gume 0:163155b607df 970 endTransaction();
gume 0:163155b607df 971 }
gume 0:163155b607df 972
gume 0:163155b607df 973 /****************************************************************************/
gume 0:163155b607df 974
gume 0:163155b607df 975 void RF24::enableDynamicPayloads(void)
gume 0:163155b607df 976 {
gume 0:163155b607df 977 // Enable dynamic payload throughout the system
gume 0:163155b607df 978
gume 0:163155b607df 979 //toggle_features();
gume 0:163155b607df 980 write_register(FEATURE,read_register(FEATURE) | _BV(EN_DPL) );
gume 0:163155b607df 981
gume 0:163155b607df 982
gume 0:163155b607df 983 printf_P("FEATURE=%i\r\n",read_register(FEATURE));
gume 0:163155b607df 984
gume 0:163155b607df 985 // Enable dynamic payload on all pipes
gume 0:163155b607df 986 //
gume 0:163155b607df 987 // Not sure the use case of only having dynamic payload on certain
gume 0:163155b607df 988 // pipes, so the library does not support it.
gume 0:163155b607df 989 write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P5) | _BV(DPL_P4) | _BV(DPL_P3) | _BV(DPL_P2) | _BV(DPL_P1) | _BV(DPL_P0));
gume 0:163155b607df 990
gume 0:163155b607df 991 dynamic_payloads_enabled = true;
gume 0:163155b607df 992 }
gume 0:163155b607df 993
gume 0:163155b607df 994 /****************************************************************************/
gume 0:163155b607df 995
gume 0:163155b607df 996 void RF24::enableAckPayload(void)
gume 0:163155b607df 997 {
gume 0:163155b607df 998 //
gume 0:163155b607df 999 // enable ack payload and dynamic payload features
gume 0:163155b607df 1000 //
gume 0:163155b607df 1001
gume 0:163155b607df 1002 //toggle_features();
gume 0:163155b607df 1003 write_register(FEATURE,read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL) );
gume 0:163155b607df 1004
gume 0:163155b607df 1005 printf_P("FEATURE=%i\r\n",read_register(FEATURE));
gume 0:163155b607df 1006
gume 0:163155b607df 1007 //
gume 0:163155b607df 1008 // Enable dynamic payload on pipes 0 & 1
gume 0:163155b607df 1009 //
gume 0:163155b607df 1010
gume 0:163155b607df 1011 write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P1) | _BV(DPL_P0));
gume 0:163155b607df 1012 dynamic_payloads_enabled = true;
gume 0:163155b607df 1013 }
gume 0:163155b607df 1014
gume 0:163155b607df 1015 /****************************************************************************/
gume 0:163155b607df 1016
gume 0:163155b607df 1017 void RF24::enableDynamicAck(void)
gume 0:163155b607df 1018 {
gume 0:163155b607df 1019 //
gume 0:163155b607df 1020 // enable dynamic ack features
gume 0:163155b607df 1021 //
gume 0:163155b607df 1022 //toggle_features();
gume 0:163155b607df 1023 write_register(FEATURE,read_register(FEATURE) | _BV(EN_DYN_ACK) );
gume 0:163155b607df 1024
gume 0:163155b607df 1025 printf_P("FEATURE=%i\r\n",read_register(FEATURE));
gume 0:163155b607df 1026
gume 0:163155b607df 1027
gume 0:163155b607df 1028 }
gume 0:163155b607df 1029
gume 0:163155b607df 1030 /****************************************************************************/
gume 0:163155b607df 1031
gume 0:163155b607df 1032 void RF24::writeAckPayload(uint8_t pipe, const void* buf, uint8_t len)
gume 0:163155b607df 1033 {
gume 0:163155b607df 1034 const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);
gume 0:163155b607df 1035
gume 0:163155b607df 1036 const uint8_t max_payload_size = 32;
gume 0:163155b607df 1037 uint8_t data_len = rf24_min(len, max_payload_size);
gume 0:163155b607df 1038
gume 0:163155b607df 1039 beginTransaction();
gume 0:163155b607df 1040
gume 0:163155b607df 1041 spi.write( W_ACK_PAYLOAD | ( pipe & 7 ) );
gume 0:163155b607df 1042 while ( data_len-- )
gume 0:163155b607df 1043 spi.write(*current++);
gume 0:163155b607df 1044
gume 0:163155b607df 1045 endTransaction();
gume 0:163155b607df 1046
gume 0:163155b607df 1047 }
gume 0:163155b607df 1048
gume 0:163155b607df 1049 /****************************************************************************/
gume 0:163155b607df 1050
gume 0:163155b607df 1051 bool RF24::isAckPayloadAvailable(void)
gume 0:163155b607df 1052 {
gume 0:163155b607df 1053 return ! (read_register(FIFO_STATUS) & _BV(RX_EMPTY));
gume 0:163155b607df 1054 }
gume 0:163155b607df 1055
gume 0:163155b607df 1056 /****************************************************************************/
gume 0:163155b607df 1057
gume 0:163155b607df 1058 bool RF24::isPVariant(void)
gume 0:163155b607df 1059 {
gume 0:163155b607df 1060 return p_variant ;
gume 0:163155b607df 1061 }
gume 0:163155b607df 1062
gume 0:163155b607df 1063 /****************************************************************************/
gume 0:163155b607df 1064
gume 0:163155b607df 1065 void RF24::setAutoAck(bool enable)
gume 0:163155b607df 1066 {
gume 0:163155b607df 1067 if ( enable )
gume 0:163155b607df 1068 write_register(EN_AA, 0b111111);
gume 0:163155b607df 1069 else
gume 0:163155b607df 1070 write_register(EN_AA, 0);
gume 0:163155b607df 1071 }
gume 0:163155b607df 1072
gume 0:163155b607df 1073 /****************************************************************************/
gume 0:163155b607df 1074
gume 0:163155b607df 1075 void RF24::setAutoAck( uint8_t pipe, bool enable )
gume 0:163155b607df 1076 {
gume 0:163155b607df 1077 if ( pipe <= 6 ) {
gume 0:163155b607df 1078 uint8_t en_aa = read_register( EN_AA ) ;
gume 0:163155b607df 1079 if( enable ) {
gume 0:163155b607df 1080 en_aa |= _BV(pipe) ;
gume 0:163155b607df 1081 } else {
gume 0:163155b607df 1082 en_aa &= ~_BV(pipe) ;
gume 0:163155b607df 1083 }
gume 0:163155b607df 1084 write_register( EN_AA, en_aa ) ;
gume 0:163155b607df 1085 }
gume 0:163155b607df 1086 }
gume 0:163155b607df 1087
gume 0:163155b607df 1088 /****************************************************************************/
gume 0:163155b607df 1089
gume 0:163155b607df 1090 bool RF24::testCarrier(void)
gume 0:163155b607df 1091 {
gume 0:163155b607df 1092 return ( read_register(CD) & 1 );
gume 0:163155b607df 1093 }
gume 0:163155b607df 1094
gume 0:163155b607df 1095 /****************************************************************************/
gume 0:163155b607df 1096
gume 0:163155b607df 1097 bool RF24::testRPD(void)
gume 0:163155b607df 1098 {
gume 0:163155b607df 1099 return ( read_register(RPD) & 1 ) ;
gume 0:163155b607df 1100 }
gume 0:163155b607df 1101
gume 0:163155b607df 1102 /****************************************************************************/
gume 0:163155b607df 1103
gume 0:163155b607df 1104 void RF24::setPALevel(uint8_t level)
gume 0:163155b607df 1105 {
gume 0:163155b607df 1106
gume 0:163155b607df 1107 uint8_t setup = read_register(RF_SETUP) & 0b11111000;
gume 0:163155b607df 1108
gume 0:163155b607df 1109 if(level > 3) { // If invalid level, go to max PA
gume 0:163155b607df 1110 level = (RF24_PA_MAX << 1) + 1; // +1 to support the SI24R1 chip extra bit
gume 0:163155b607df 1111 } else {
gume 0:163155b607df 1112 level = (level << 1) + 1; // Else set level as requested
gume 0:163155b607df 1113 }
gume 0:163155b607df 1114
gume 0:163155b607df 1115
gume 0:163155b607df 1116 write_register( RF_SETUP, setup |= level ) ; // Write it to the chip
gume 0:163155b607df 1117 }
gume 0:163155b607df 1118
gume 0:163155b607df 1119 /****************************************************************************/
gume 0:163155b607df 1120
gume 0:163155b607df 1121 uint8_t RF24::getPALevel(void)
gume 0:163155b607df 1122 {
gume 0:163155b607df 1123
gume 0:163155b607df 1124 return (read_register(RF_SETUP) & (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH))) >> 1 ;
gume 0:163155b607df 1125 }
gume 0:163155b607df 1126
gume 0:163155b607df 1127 /****************************************************************************/
gume 0:163155b607df 1128
gume 0:163155b607df 1129 bool RF24::setDataRate(rf24_datarate_e speed)
gume 0:163155b607df 1130 {
gume 0:163155b607df 1131 bool result = false;
gume 0:163155b607df 1132 uint8_t setup = read_register(RF_SETUP) ;
gume 0:163155b607df 1133
gume 0:163155b607df 1134 // HIGH and LOW '00' is 1Mbs - our default
gume 0:163155b607df 1135 setup &= ~(_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)) ;
gume 0:163155b607df 1136
gume 0:163155b607df 1137 txRxDelay=250;
gume 0:163155b607df 1138
gume 0:163155b607df 1139 if( speed == RF24_250KBPS ) {
gume 0:163155b607df 1140 // Must set the RF_DR_LOW to 1; RF_DR_HIGH (used to be RF_DR) is already 0
gume 0:163155b607df 1141 // Making it '10'.
gume 0:163155b607df 1142 setup |= _BV( RF_DR_LOW ) ;
gume 0:163155b607df 1143 txRxDelay=450;
gume 0:163155b607df 1144 } else {
gume 0:163155b607df 1145 // Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1
gume 0:163155b607df 1146 // Making it '01'
gume 0:163155b607df 1147 if ( speed == RF24_2MBPS ) {
gume 0:163155b607df 1148 setup |= _BV(RF_DR_HIGH);
gume 0:163155b607df 1149 txRxDelay=190;
gume 0:163155b607df 1150 }
gume 0:163155b607df 1151 }
gume 0:163155b607df 1152 write_register(RF_SETUP,setup);
gume 0:163155b607df 1153
gume 0:163155b607df 1154 // Verify our result
gume 0:163155b607df 1155 if ( read_register(RF_SETUP) == setup ) {
gume 0:163155b607df 1156 result = true;
gume 0:163155b607df 1157 }
gume 0:163155b607df 1158 return result;
gume 0:163155b607df 1159 }
gume 0:163155b607df 1160
gume 0:163155b607df 1161 /****************************************************************************/
gume 0:163155b607df 1162
gume 0:163155b607df 1163 rf24_datarate_e RF24::getDataRate( void )
gume 0:163155b607df 1164 {
gume 0:163155b607df 1165 rf24_datarate_e result ;
gume 0:163155b607df 1166 uint8_t dr = read_register(RF_SETUP) & (_BV(RF_DR_LOW) | _BV(RF_DR_HIGH));
gume 0:163155b607df 1167
gume 0:163155b607df 1168 // switch uses RAM (evil!)
gume 0:163155b607df 1169 // Order matters in our case below
gume 0:163155b607df 1170 if ( dr == _BV(RF_DR_LOW) ) {
gume 0:163155b607df 1171 // '10' = 250KBPS
gume 0:163155b607df 1172 result = RF24_250KBPS ;
gume 0:163155b607df 1173 } else if ( dr == _BV(RF_DR_HIGH) ) {
gume 0:163155b607df 1174 // '01' = 2MBPS
gume 0:163155b607df 1175 result = RF24_2MBPS ;
gume 0:163155b607df 1176 } else {
gume 0:163155b607df 1177 // '00' = 1MBPS
gume 0:163155b607df 1178 result = RF24_1MBPS ;
gume 0:163155b607df 1179 }
gume 0:163155b607df 1180 return result ;
gume 0:163155b607df 1181 }
gume 0:163155b607df 1182
gume 0:163155b607df 1183 /****************************************************************************/
gume 0:163155b607df 1184
gume 0:163155b607df 1185 void RF24::setCRCLength(rf24_crclength_e length)
gume 0:163155b607df 1186 {
gume 0:163155b607df 1187 uint8_t config = read_register(CONFIG) & ~( _BV(CRCO) | _BV(EN_CRC)) ;
gume 0:163155b607df 1188
gume 0:163155b607df 1189 // switch uses RAM (evil!)
gume 0:163155b607df 1190 if ( length == RF24_CRC_DISABLED ) {
gume 0:163155b607df 1191 // Do nothing, we turned it off above.
gume 0:163155b607df 1192 } else if ( length == RF24_CRC_8 ) {
gume 0:163155b607df 1193 config |= _BV(EN_CRC);
gume 0:163155b607df 1194 } else {
gume 0:163155b607df 1195 config |= _BV(EN_CRC);
gume 0:163155b607df 1196 config |= _BV( CRCO );
gume 0:163155b607df 1197 }
gume 0:163155b607df 1198 write_register( CONFIG, config ) ;
gume 0:163155b607df 1199 }
gume 0:163155b607df 1200
gume 0:163155b607df 1201 /****************************************************************************/
gume 0:163155b607df 1202
gume 0:163155b607df 1203 rf24_crclength_e RF24::getCRCLength(void)
gume 0:163155b607df 1204 {
gume 0:163155b607df 1205 rf24_crclength_e result = RF24_CRC_DISABLED;
gume 0:163155b607df 1206
gume 0:163155b607df 1207 uint8_t config = read_register(CONFIG) & ( _BV(CRCO) | _BV(EN_CRC)) ;
gume 0:163155b607df 1208 uint8_t AA = read_register(EN_AA);
gume 0:163155b607df 1209
gume 0:163155b607df 1210 if ( config & _BV(EN_CRC ) || AA) {
gume 0:163155b607df 1211 if ( config & _BV(CRCO) )
gume 0:163155b607df 1212 result = RF24_CRC_16;
gume 0:163155b607df 1213 else
gume 0:163155b607df 1214 result = RF24_CRC_8;
gume 0:163155b607df 1215 }
gume 0:163155b607df 1216
gume 0:163155b607df 1217 return result;
gume 0:163155b607df 1218 }
gume 0:163155b607df 1219
gume 0:163155b607df 1220 /****************************************************************************/
gume 0:163155b607df 1221
gume 0:163155b607df 1222 void RF24::disableCRC( void )
gume 0:163155b607df 1223 {
gume 0:163155b607df 1224 uint8_t disable = read_register(CONFIG) & ~_BV(EN_CRC) ;
gume 0:163155b607df 1225 write_register( CONFIG, disable ) ;
gume 0:163155b607df 1226 }
gume 0:163155b607df 1227
gume 0:163155b607df 1228 /****************************************************************************/
gume 0:163155b607df 1229 void RF24::setRetries(uint8_t delay, uint8_t count)
gume 0:163155b607df 1230 {
gume 0:163155b607df 1231 write_register(SETUP_RETR,(delay&0xf)<<ARD | (count&0xf)<<ARC);
gume 0:163155b607df 1232 }