Maniacbug RF24 on Nucleo STM32

Dependents:   NRF24_master_slave NRF24_master_slave

Committer:
olympux
Date:
Mon Feb 09 00:01:47 2015 +0000
Revision:
5:aaff7f374e2b
Parent:
4:baf3b07be1a7
clean code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
olympux 0:707771bf6708 1 /*
olympux 0:707771bf6708 2 Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
olympux 0:707771bf6708 3
olympux 0:707771bf6708 4 This program is free software; you can redistribute it and/or
olympux 0:707771bf6708 5 modify it under the terms of the GNU General Public License
olympux 0:707771bf6708 6 version 2 as published by the Free Software Foundation.
olympux 0:707771bf6708 7 */
olympux 0:707771bf6708 8
olympux 0:707771bf6708 9 #include "nRF24L01.h"
olympux 0:707771bf6708 10 #include "RF24_config.h"
olympux 0:707771bf6708 11 #include "RF24.h"
olympux 0:707771bf6708 12
olympux 3:af425ff47d9f 13 #if 0
olympux 3:af425ff47d9f 14 //Enable debug
olympux 3:af425ff47d9f 15 #include <cstdio>
olympux 3:af425ff47d9f 16 #define DBG(x, ...) std::printf("[RF24 : DBG]"x, ##__VA_ARGS__);
olympux 3:af425ff47d9f 17 #define WARN(x, ...) std::printf("[RF24 : WARN]"x, ##__VA_ARGS__);
olympux 3:af425ff47d9f 18 #define ERR(x, ...) std::printf("[RF24 : ERR]"x, ##__VA_ARGS__);
olympux 3:af425ff47d9f 19 #else
olympux 3:af425ff47d9f 20 //Disable debug
olympux 3:af425ff47d9f 21 #define DBG(x, ...)
olympux 3:af425ff47d9f 22 #define WARN(x, ...)
olympux 3:af425ff47d9f 23 #define ERR(x, ...)
olympux 3:af425ff47d9f 24 #endif
olympux 0:707771bf6708 25
olympux 1:8fc901e8846f 26 /**
olympux 1:8fc901e8846f 27 * Timer for RF24 network
olympux 1:8fc901e8846f 28 */
olympux 1:8fc901e8846f 29 Timer RF24Timer;
olympux 1:8fc901e8846f 30
olympux 1:8fc901e8846f 31
olympux 0:707771bf6708 32 /********************** mbed functions ************************************************/
olympux 0:707771bf6708 33 void digitalWrite(DigitalOut pin, int val)
olympux 0:707771bf6708 34 {
olympux 0:707771bf6708 35 pin = val;
olympux 0:707771bf6708 36 }
olympux 1:8fc901e8846f 37
olympux 0:707771bf6708 38 size_t min(size_t a, size_t b)
olympux 0:707771bf6708 39 {
olympux 0:707771bf6708 40 if(a < b)
olympux 0:707771bf6708 41 return a;
olympux 0:707771bf6708 42 else
olympux 0:707771bf6708 43 return b;
olympux 0:707771bf6708 44 }
olympux 0:707771bf6708 45
olympux 0:707771bf6708 46
olympux 0:707771bf6708 47 /****************************************************************************/
olympux 0:707771bf6708 48
olympux 0:707771bf6708 49 void RF24::csn(int mode)
olympux 0:707771bf6708 50 {
olympux 1:8fc901e8846f 51 digitalWrite(csn_pin,mode);
olympux 0:707771bf6708 52 }
olympux 0:707771bf6708 53
olympux 0:707771bf6708 54 /****************************************************************************/
olympux 0:707771bf6708 55
olympux 0:707771bf6708 56 void RF24::ce(int level)
olympux 0:707771bf6708 57 {
olympux 1:8fc901e8846f 58 digitalWrite(ce_pin,level);
olympux 0:707771bf6708 59 }
olympux 0:707771bf6708 60
olympux 0:707771bf6708 61 /****************************************************************************/
olympux 0:707771bf6708 62
olympux 0:707771bf6708 63 uint8_t RF24::read_register(uint8_t reg, uint8_t* buf, uint8_t len)
olympux 0:707771bf6708 64 {
olympux 1:8fc901e8846f 65 uint8_t status;
olympux 0:707771bf6708 66
olympux 1:8fc901e8846f 67 csn(LOW);
olympux 1:8fc901e8846f 68 status = spi.write( R_REGISTER | ( REGISTER_MASK & reg ) );
olympux 1:8fc901e8846f 69 while ( len-- )
olympux 1:8fc901e8846f 70 *buf++ = spi.write(0xff);
olympux 0:707771bf6708 71
olympux 1:8fc901e8846f 72 csn(HIGH);
olympux 0:707771bf6708 73
olympux 1:8fc901e8846f 74 return status;
olympux 0:707771bf6708 75 }
olympux 0:707771bf6708 76
olympux 0:707771bf6708 77 /****************************************************************************/
olympux 0:707771bf6708 78
olympux 0:707771bf6708 79 uint8_t RF24::read_register(uint8_t reg)
olympux 0:707771bf6708 80 {
olympux 1:8fc901e8846f 81 csn(LOW);
olympux 1:8fc901e8846f 82 spi.write( R_REGISTER | ( REGISTER_MASK & reg ) );
olympux 1:8fc901e8846f 83 uint8_t result = spi.write(0xff);
olympux 0:707771bf6708 84
olympux 1:8fc901e8846f 85 csn(HIGH);
olympux 1:8fc901e8846f 86 return result;
olympux 0:707771bf6708 87 }
olympux 0:707771bf6708 88
olympux 0:707771bf6708 89 /****************************************************************************/
olympux 0:707771bf6708 90
olympux 0:707771bf6708 91 uint8_t RF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len)
olympux 0:707771bf6708 92 {
olympux 1:8fc901e8846f 93 uint8_t status;
olympux 0:707771bf6708 94
olympux 1:8fc901e8846f 95 csn(LOW);
olympux 1:8fc901e8846f 96 status = spi.write( W_REGISTER | ( REGISTER_MASK & reg ) );
olympux 1:8fc901e8846f 97 while ( len-- )
olympux 1:8fc901e8846f 98 spi.write(*buf++);
olympux 0:707771bf6708 99
olympux 1:8fc901e8846f 100 csn(HIGH);
olympux 0:707771bf6708 101
olympux 1:8fc901e8846f 102 return status;
olympux 0:707771bf6708 103 }
olympux 0:707771bf6708 104
olympux 0:707771bf6708 105 /****************************************************************************/
olympux 0:707771bf6708 106
olympux 0:707771bf6708 107 uint8_t RF24::write_register(uint8_t reg, uint8_t value)
olympux 0:707771bf6708 108 {
olympux 1:8fc901e8846f 109 uint8_t status;
olympux 0:707771bf6708 110
olympux 1:8fc901e8846f 111 DBG("write_register(%02x,%02x)\r\n",reg,value);
olympux 0:707771bf6708 112
olympux 1:8fc901e8846f 113 csn(LOW);
olympux 1:8fc901e8846f 114 status = spi.write( W_REGISTER | ( REGISTER_MASK & reg ) );
olympux 1:8fc901e8846f 115 spi.write(value);
olympux 1:8fc901e8846f 116 csn(HIGH);
olympux 0:707771bf6708 117
olympux 1:8fc901e8846f 118 return status;
olympux 0:707771bf6708 119 }
olympux 0:707771bf6708 120
olympux 0:707771bf6708 121 /****************************************************************************/
olympux 0:707771bf6708 122
olympux 0:707771bf6708 123 uint8_t RF24::write_payload(const void* buf, uint8_t len)
olympux 0:707771bf6708 124 {
olympux 1:8fc901e8846f 125 uint8_t status;
olympux 1:8fc901e8846f 126
olympux 1:8fc901e8846f 127 const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);
olympux 0:707771bf6708 128
olympux 1:8fc901e8846f 129 uint8_t data_len = min(len,payload_size);
olympux 1:8fc901e8846f 130 uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
olympux 1:8fc901e8846f 131
olympux 1:8fc901e8846f 132 //printf("[Writing %u bytes %u blanks]",data_len,blank_len);
olympux 0:707771bf6708 133
olympux 1:8fc901e8846f 134 csn(LOW);
olympux 1:8fc901e8846f 135 status = spi.write( W_TX_PAYLOAD );
olympux 1:8fc901e8846f 136 while ( data_len-- )
olympux 1:8fc901e8846f 137 spi.write(*current++);
olympux 1:8fc901e8846f 138 while ( blank_len-- )
olympux 1:8fc901e8846f 139 spi.write(0);
olympux 1:8fc901e8846f 140 csn(HIGH);
olympux 0:707771bf6708 141
olympux 1:8fc901e8846f 142 return status;
olympux 0:707771bf6708 143 }
olympux 0:707771bf6708 144
olympux 0:707771bf6708 145 /****************************************************************************/
olympux 0:707771bf6708 146
olympux 0:707771bf6708 147 uint8_t RF24::read_payload(void* buf, uint8_t len)
olympux 0:707771bf6708 148 {
olympux 1:8fc901e8846f 149 uint8_t status;
olympux 1:8fc901e8846f 150 uint8_t* current = reinterpret_cast<uint8_t*>(buf);
olympux 1:8fc901e8846f 151
olympux 1:8fc901e8846f 152 uint8_t data_len = min(len,payload_size);
olympux 1:8fc901e8846f 153 uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
olympux 1:8fc901e8846f 154
olympux 1:8fc901e8846f 155 //printf("[Reading %u bytes %u blanks]",data_len,blank_len);
olympux 0:707771bf6708 156
olympux 1:8fc901e8846f 157 csn(LOW);
olympux 1:8fc901e8846f 158 status = spi.write( R_RX_PAYLOAD );
olympux 1:8fc901e8846f 159 while ( data_len-- )
olympux 1:8fc901e8846f 160 *current++ = spi.write(0xff);
olympux 1:8fc901e8846f 161 while ( blank_len-- )
olympux 1:8fc901e8846f 162 spi.write(0xff);
olympux 1:8fc901e8846f 163 csn(HIGH);
olympux 0:707771bf6708 164
olympux 1:8fc901e8846f 165 return status;
olympux 0:707771bf6708 166 }
olympux 0:707771bf6708 167
olympux 0:707771bf6708 168 /****************************************************************************/
olympux 0:707771bf6708 169
olympux 0:707771bf6708 170 uint8_t RF24::flush_rx(void)
olympux 0:707771bf6708 171 {
olympux 1:8fc901e8846f 172 uint8_t status;
olympux 0:707771bf6708 173
olympux 1:8fc901e8846f 174 csn(LOW);
olympux 1:8fc901e8846f 175 status = spi.write( FLUSH_RX );
olympux 1:8fc901e8846f 176 csn(HIGH);
olympux 0:707771bf6708 177
olympux 1:8fc901e8846f 178 return status;
olympux 0:707771bf6708 179 }
olympux 0:707771bf6708 180
olympux 0:707771bf6708 181 /****************************************************************************/
olympux 0:707771bf6708 182
olympux 0:707771bf6708 183 uint8_t RF24::flush_tx(void)
olympux 0:707771bf6708 184 {
olympux 1:8fc901e8846f 185 uint8_t status;
olympux 0:707771bf6708 186
olympux 1:8fc901e8846f 187 csn(LOW);
olympux 1:8fc901e8846f 188 status = spi.write( FLUSH_TX );
olympux 1:8fc901e8846f 189 csn(HIGH);
olympux 0:707771bf6708 190
olympux 1:8fc901e8846f 191 return status;
olympux 0:707771bf6708 192 }
olympux 0:707771bf6708 193
olympux 0:707771bf6708 194 /****************************************************************************/
olympux 0:707771bf6708 195
olympux 0:707771bf6708 196 uint8_t RF24::get_status(void)
olympux 0:707771bf6708 197 {
olympux 1:8fc901e8846f 198 uint8_t status;
olympux 0:707771bf6708 199
olympux 1:8fc901e8846f 200 csn(LOW);
olympux 1:8fc901e8846f 201 status = spi.write( NOP );
olympux 1:8fc901e8846f 202 csn(HIGH);
olympux 0:707771bf6708 203
olympux 1:8fc901e8846f 204 return status;
olympux 0:707771bf6708 205 }
olympux 0:707771bf6708 206
olympux 0:707771bf6708 207 /****************************************************************************/
olympux 0:707771bf6708 208
olympux 0:707771bf6708 209 void RF24::print_status(uint8_t status)
olympux 0:707771bf6708 210 {
olympux 1:8fc901e8846f 211 DBG("STATUS\t\t = 0x%02x RX_DR=%x TX_DS=%x MAX_RT=%x RX_P_NO=%x TX_FULL=%x\r\n",
olympux 1:8fc901e8846f 212 status,
olympux 1:8fc901e8846f 213 (status & _BV(RX_DR))?1:0,
olympux 1:8fc901e8846f 214 (status & _BV(TX_DS))?1:0,
olympux 1:8fc901e8846f 215 (status & _BV(MAX_RT))?1:0,
olympux 1:8fc901e8846f 216 ((status >> RX_P_NO) & 7),
olympux 1:8fc901e8846f 217 (status & _BV(TX_FULL))?1:0
olympux 1:8fc901e8846f 218 );
olympux 0:707771bf6708 219 }
olympux 0:707771bf6708 220
olympux 0:707771bf6708 221 /****************************************************************************/
olympux 0:707771bf6708 222
olympux 0:707771bf6708 223 void RF24::print_observe_tx(uint8_t value)
olympux 0:707771bf6708 224 {
olympux 1:8fc901e8846f 225 DBG("OBSERVE_TX=%02x: POLS_CNT=%x ARC_CNT=%x\r\n",
olympux 1:8fc901e8846f 226 value,
olympux 1:8fc901e8846f 227 (value >> PLOS_CNT) & 15,
olympux 1:8fc901e8846f 228 (value >> ARC_CNT) & 15
olympux 1:8fc901e8846f 229 );
olympux 0:707771bf6708 230 }
olympux 0:707771bf6708 231
olympux 0:707771bf6708 232 /****************************************************************************/
olympux 0:707771bf6708 233
olympux 0:707771bf6708 234 void RF24::print_byte_register(const char* name, uint8_t reg, uint8_t qty)
olympux 0:707771bf6708 235 {
olympux 1:8fc901e8846f 236 char extra_tab = strlen(name) < 8 ? '\t' : 0;
olympux 1:8fc901e8846f 237 DBG("%s\t%c =",name,extra_tab);
olympux 1:8fc901e8846f 238 while (qty--)
olympux 1:8fc901e8846f 239 DBG(" 0x%02x",read_register(reg++));
olympux 1:8fc901e8846f 240 DBG("\r\n");
olympux 0:707771bf6708 241 }
olympux 0:707771bf6708 242
olympux 0:707771bf6708 243 /****************************************************************************/
olympux 0:707771bf6708 244
olympux 0:707771bf6708 245 void RF24::print_address_register(const char* name, uint8_t reg, uint8_t qty)
olympux 0:707771bf6708 246 {
olympux 1:8fc901e8846f 247 char extra_tab = strlen(name) < 8 ? '\t' : 0;
olympux 1:8fc901e8846f 248 DBG("%s\t%c =",name,extra_tab);
olympux 0:707771bf6708 249
olympux 1:8fc901e8846f 250 while (qty--) {
olympux 1:8fc901e8846f 251 uint8_t buffer[5];
olympux 1:8fc901e8846f 252 read_register(reg++,buffer,sizeof buffer);
olympux 0:707771bf6708 253
olympux 1:8fc901e8846f 254 DBG(" 0x");
olympux 1:8fc901e8846f 255 uint8_t* bufptr = buffer + sizeof buffer;
olympux 1:8fc901e8846f 256 while( --bufptr >= buffer )
olympux 1:8fc901e8846f 257 DBG("%02x",*bufptr);
olympux 1:8fc901e8846f 258 }
olympux 0:707771bf6708 259
olympux 1:8fc901e8846f 260 DBG("\r\n");
olympux 0:707771bf6708 261 }
olympux 0:707771bf6708 262
olympux 0:707771bf6708 263 /****************************************************************************/
olympux 0:707771bf6708 264
olympux 0:707771bf6708 265 RF24::RF24(PinName mosi, PinName miso, PinName sck, PinName _cepin, PinName _csnpin):
olympux 1:8fc901e8846f 266 ce_pin(_cepin), csn_pin(_csnpin), wide_band(true), p_variant(false),
olympux 1:8fc901e8846f 267 payload_size(32), ack_payload_available(false), dynamic_payloads_enabled(false),
olympux 1:8fc901e8846f 268 pipe0_reading_address(0), spi(mosi, miso, sck)
olympux 0:707771bf6708 269 {
olympux 0:707771bf6708 270 spi.frequency(10000000/5); // 2Mbit, 1/5th the maximum transfer rate for the spi bus
olympux 0:707771bf6708 271 spi.format(8,0);
olympux 0:707771bf6708 272 }
olympux 0:707771bf6708 273
olympux 0:707771bf6708 274 /****************************************************************************/
olympux 0:707771bf6708 275
olympux 0:707771bf6708 276 void RF24::setChannel(uint8_t channel)
olympux 0:707771bf6708 277 {
olympux 1:8fc901e8846f 278 // TODO: This method could take advantage of the 'wide_band' calculation
olympux 1:8fc901e8846f 279 // done in setChannel() to require certain channel spacing.
olympux 0:707771bf6708 280
olympux 1:8fc901e8846f 281 const uint8_t max_channel = 127;
olympux 1:8fc901e8846f 282 write_register(RF_CH,min(channel,max_channel));
olympux 0:707771bf6708 283 }
olympux 0:707771bf6708 284
olympux 0:707771bf6708 285 /****************************************************************************/
olympux 0:707771bf6708 286
olympux 0:707771bf6708 287 void RF24::setPayloadSize(uint8_t size)
olympux 0:707771bf6708 288 {
olympux 1:8fc901e8846f 289 const uint8_t max_payload_size = 32;
olympux 1:8fc901e8846f 290 payload_size = min(size,max_payload_size);
olympux 0:707771bf6708 291 }
olympux 0:707771bf6708 292
olympux 0:707771bf6708 293 /****************************************************************************/
olympux 0:707771bf6708 294
olympux 0:707771bf6708 295 uint8_t RF24::getPayloadSize(void)
olympux 0:707771bf6708 296 {
olympux 1:8fc901e8846f 297 return payload_size;
olympux 0:707771bf6708 298 }
olympux 0:707771bf6708 299
olympux 0:707771bf6708 300 /****************************************************************************/
olympux 0:707771bf6708 301
olympux 0:707771bf6708 302 static const char rf24_datarate_e_str_0[] = "1MBPS";
olympux 0:707771bf6708 303 static const char rf24_datarate_e_str_1[] = "2MBPS";
olympux 0:707771bf6708 304 static const char rf24_datarate_e_str_2[] = "250KBPS";
olympux 0:707771bf6708 305 static const char * const rf24_datarate_e_str_P[] = {
olympux 1:8fc901e8846f 306 rf24_datarate_e_str_0,
olympux 1:8fc901e8846f 307 rf24_datarate_e_str_1,
olympux 1:8fc901e8846f 308 rf24_datarate_e_str_2,
olympux 0:707771bf6708 309 };
olympux 0:707771bf6708 310 static const char rf24_model_e_str_0[] = "nRF24L01";
olympux 0:707771bf6708 311 static const char rf24_model_e_str_1[] = "nRF24L01+";
olympux 0:707771bf6708 312 static const char * const rf24_model_e_str_P[] = {
olympux 1:8fc901e8846f 313 rf24_model_e_str_0,
olympux 1:8fc901e8846f 314 rf24_model_e_str_1,
olympux 0:707771bf6708 315 };
olympux 0:707771bf6708 316 static const char rf24_crclength_e_str_0[] = "Disabled";
olympux 0:707771bf6708 317 static const char rf24_crclength_e_str_1[] = "8 bits";
olympux 0:707771bf6708 318 static const char rf24_crclength_e_str_2[] = "16 bits" ;
olympux 0:707771bf6708 319 static const char * const rf24_crclength_e_str_P[] = {
olympux 1:8fc901e8846f 320 rf24_crclength_e_str_0,
olympux 1:8fc901e8846f 321 rf24_crclength_e_str_1,
olympux 1:8fc901e8846f 322 rf24_crclength_e_str_2,
olympux 0:707771bf6708 323 };
olympux 0:707771bf6708 324 static const char rf24_pa_dbm_e_str_0[] = "PA_MIN";
olympux 0:707771bf6708 325 static const char rf24_pa_dbm_e_str_1[] = "PA_LOW";
olympux 0:707771bf6708 326 static const char rf24_pa_dbm_e_str_2[] = "LA_MED";
olympux 0:707771bf6708 327 static const char rf24_pa_dbm_e_str_3[] = "PA_HIGH";
olympux 1:8fc901e8846f 328 static const char * const rf24_pa_dbm_e_str_P[] = {
olympux 1:8fc901e8846f 329 rf24_pa_dbm_e_str_0,
olympux 1:8fc901e8846f 330 rf24_pa_dbm_e_str_1,
olympux 1:8fc901e8846f 331 rf24_pa_dbm_e_str_2,
olympux 1:8fc901e8846f 332 rf24_pa_dbm_e_str_3,
olympux 0:707771bf6708 333 };
olympux 0:707771bf6708 334
olympux 0:707771bf6708 335 void RF24::printDetails(void)
olympux 0:707771bf6708 336 {
olympux 1:8fc901e8846f 337 print_status(get_status());
olympux 0:707771bf6708 338
olympux 1:8fc901e8846f 339 print_address_register("RX_ADDR_P0-1",RX_ADDR_P0,2);
olympux 1:8fc901e8846f 340 print_byte_register("RX_ADDR_P2-5",RX_ADDR_P2,4);
olympux 1:8fc901e8846f 341 print_address_register("TX_ADDR",TX_ADDR);
olympux 0:707771bf6708 342
olympux 1:8fc901e8846f 343 print_byte_register("RX_PW_P0-6",RX_PW_P0,6);
olympux 1:8fc901e8846f 344 print_byte_register("EN_AA",EN_AA);
olympux 1:8fc901e8846f 345 print_byte_register("EN_RXADDR",EN_RXADDR);
olympux 1:8fc901e8846f 346 print_byte_register("RF_CH",RF_CH);
olympux 1:8fc901e8846f 347 print_byte_register("RF_SETUP",RF_SETUP);
olympux 1:8fc901e8846f 348 print_byte_register("CONFIG",CONFIG);
olympux 1:8fc901e8846f 349 print_byte_register("DYNPD/FEATURE",DYNPD,2);
olympux 0:707771bf6708 350
olympux 1:8fc901e8846f 351 DBG("Data Rate\t = %s\r\n",rf24_datarate_e_str_P[getDataRate()]);
olympux 1:8fc901e8846f 352 DBG("Model\t\t = %s\r\n",rf24_model_e_str_P[isPVariant()]);
olympux 1:8fc901e8846f 353 DBG("CRC Length\t = %s\r\n",rf24_crclength_e_str_P[getCRCLength()]);
olympux 1:8fc901e8846f 354 DBG("PA Power\t = %s\r\n",rf24_pa_dbm_e_str_P[getPALevel()]);
olympux 0:707771bf6708 355 }
olympux 0:707771bf6708 356
olympux 0:707771bf6708 357 /****************************************************************************/
olympux 0:707771bf6708 358
olympux 0:707771bf6708 359 void RF24::begin(void)
olympux 0:707771bf6708 360 {
olympux 1:8fc901e8846f 361 RF24Timer.start();
olympux 0:707771bf6708 362
olympux 1:8fc901e8846f 363 ce(LOW);
olympux 1:8fc901e8846f 364 csn(HIGH);
olympux 0:707771bf6708 365
olympux 1:8fc901e8846f 366 // Must allow the radio time to settle else configuration bits will not necessarily stick.
olympux 1:8fc901e8846f 367 // This is actually only required following power up but some settling time also appears to
olympux 1:8fc901e8846f 368 // be required after resets too. For full coverage, we'll always assume the worst.
olympux 1:8fc901e8846f 369 // Enabling 16b CRC is by far the most obvious case if the wrong timing is used - or skipped.
olympux 1:8fc901e8846f 370 // Technically we require 4.5ms + 14us as a worst case. We'll just call it 5ms for good measure.
olympux 1:8fc901e8846f 371 // WARNING: Delay is based on P-variant whereby non-P *may* require different timing.
olympux 1:8fc901e8846f 372 wait_ms( 5 ) ;
olympux 0:707771bf6708 373
olympux 1:8fc901e8846f 374 // Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier
olympux 1:8fc901e8846f 375 // WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet
olympux 1:8fc901e8846f 376 // sizes must never be used. See documentation for a more complete explanation.
olympux 1:8fc901e8846f 377 write_register(SETUP_RETR,(4 << ARD) | (15 << ARC));
olympux 0:707771bf6708 378
olympux 1:8fc901e8846f 379 // Restore our default PA level
olympux 1:8fc901e8846f 380 setPALevel( RF24_PA_MAX ) ;
olympux 0:707771bf6708 381
olympux 1:8fc901e8846f 382 // Determine if this is a p or non-p RF24 module and then
olympux 1:8fc901e8846f 383 // reset our data rate back to default value. This works
olympux 1:8fc901e8846f 384 // because a non-P variant won't allow the data rate to
olympux 1:8fc901e8846f 385 // be set to 250Kbps.
olympux 1:8fc901e8846f 386 if( setDataRate( RF24_250KBPS ) ) {
olympux 1:8fc901e8846f 387 p_variant = true ;
olympux 1:8fc901e8846f 388 }
olympux 1:8fc901e8846f 389
olympux 1:8fc901e8846f 390 // Then set the data rate to the slowest (and most reliable) speed supported by all
olympux 1:8fc901e8846f 391 // hardware.
olympux 1:8fc901e8846f 392 setDataRate( RF24_1MBPS ) ;
olympux 1:8fc901e8846f 393
olympux 1:8fc901e8846f 394 // Initialize CRC and request 2-byte (16bit) CRC
olympux 1:8fc901e8846f 395 setCRCLength( RF24_CRC_16 ) ;
olympux 0:707771bf6708 396
olympux 1:8fc901e8846f 397 // Disable dynamic payloads, to match dynamic_payloads_enabled setting
olympux 1:8fc901e8846f 398 write_register(DYNPD,0);
olympux 1:8fc901e8846f 399
olympux 1:8fc901e8846f 400 // Reset current status
olympux 1:8fc901e8846f 401 // Notice reset and flush is the last thing we do
olympux 1:8fc901e8846f 402 write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
olympux 0:707771bf6708 403
olympux 1:8fc901e8846f 404 // Set up default configuration. Callers can always change it later.
olympux 1:8fc901e8846f 405 // This channel should be universally safe and not bleed over into adjacent
olympux 1:8fc901e8846f 406 // spectrum.
olympux 1:8fc901e8846f 407 setChannel(76);
olympux 0:707771bf6708 408
olympux 1:8fc901e8846f 409 // Flush buffers
olympux 1:8fc901e8846f 410 flush_rx();
olympux 1:8fc901e8846f 411 flush_tx();
olympux 0:707771bf6708 412 }
olympux 0:707771bf6708 413
olympux 0:707771bf6708 414 /****************************************************************************/
olympux 0:707771bf6708 415
olympux 0:707771bf6708 416 void RF24::startListening(void)
olympux 0:707771bf6708 417 {
olympux 1:8fc901e8846f 418 write_register(CONFIG, read_register(CONFIG) | _BV(PWR_UP) | _BV(PRIM_RX));
olympux 1:8fc901e8846f 419 write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
olympux 0:707771bf6708 420
olympux 1:8fc901e8846f 421 // Restore the pipe0 adddress, if exists
olympux 1:8fc901e8846f 422 if (pipe0_reading_address)
olympux 1:8fc901e8846f 423 write_register(RX_ADDR_P0, reinterpret_cast<const uint8_t*>(&pipe0_reading_address), 5);
olympux 0:707771bf6708 424
olympux 1:8fc901e8846f 425 // Flush buffers
olympux 1:8fc901e8846f 426 flush_rx();
olympux 1:8fc901e8846f 427 flush_tx();
olympux 0:707771bf6708 428
olympux 1:8fc901e8846f 429 // Go!
olympux 1:8fc901e8846f 430 ce(HIGH);
olympux 0:707771bf6708 431
olympux 1:8fc901e8846f 432 // wait for the radio to come up (130us actually only needed)
olympux 1:8fc901e8846f 433 wait_us(130);
olympux 0:707771bf6708 434 }
olympux 0:707771bf6708 435
olympux 0:707771bf6708 436 /****************************************************************************/
olympux 0:707771bf6708 437
olympux 0:707771bf6708 438 void RF24::stopListening(void)
olympux 0:707771bf6708 439 {
olympux 1:8fc901e8846f 440 ce(LOW);
olympux 1:8fc901e8846f 441 flush_tx();
olympux 1:8fc901e8846f 442 flush_rx();
olympux 0:707771bf6708 443 }
olympux 0:707771bf6708 444
olympux 0:707771bf6708 445 /****************************************************************************/
olympux 0:707771bf6708 446
olympux 0:707771bf6708 447 void RF24::powerDown(void)
olympux 0:707771bf6708 448 {
olympux 1:8fc901e8846f 449 write_register(CONFIG,read_register(CONFIG) & ~_BV(PWR_UP));
olympux 0:707771bf6708 450 }
olympux 0:707771bf6708 451
olympux 0:707771bf6708 452 /****************************************************************************/
olympux 0:707771bf6708 453
olympux 0:707771bf6708 454 void RF24::powerUp(void)
olympux 0:707771bf6708 455 {
olympux 1:8fc901e8846f 456 write_register(CONFIG,read_register(CONFIG) | _BV(PWR_UP));
olympux 0:707771bf6708 457 }
olympux 0:707771bf6708 458
olympux 0:707771bf6708 459 /******************************************************************/
olympux 0:707771bf6708 460
olympux 0:707771bf6708 461 bool RF24::write( const void* buf, uint8_t len )
olympux 0:707771bf6708 462 {
olympux 1:8fc901e8846f 463 bool result = false;
olympux 0:707771bf6708 464
olympux 1:8fc901e8846f 465 // Begin the write
olympux 1:8fc901e8846f 466 startWrite(buf,len);
olympux 0:707771bf6708 467
olympux 1:8fc901e8846f 468 // ------------
olympux 1:8fc901e8846f 469 // At this point we could return from a non-blocking write, and then call
olympux 1:8fc901e8846f 470 // the rest after an interrupt
olympux 0:707771bf6708 471
olympux 1:8fc901e8846f 472 // Instead, we are going to block here until we get TX_DS (transmission completed and ack'd)
olympux 1:8fc901e8846f 473 // or MAX_RT (maximum retries, transmission failed). Also, we'll timeout in case the radio
olympux 1:8fc901e8846f 474 // is flaky and we get neither.
olympux 0:707771bf6708 475
olympux 1:8fc901e8846f 476 // IN the end, the send should be blocking. It comes back in 60ms worst case, or much faster
olympux 1:8fc901e8846f 477 // if I tighted up the retry logic. (Default settings will be 1500us.
olympux 1:8fc901e8846f 478 // Monitor the send
olympux 1:8fc901e8846f 479 uint8_t observe_tx;
olympux 1:8fc901e8846f 480 uint8_t status;
olympux 1:8fc901e8846f 481 uint32_t sent_at = RF24Timer.read_ms();
olympux 1:8fc901e8846f 482 const uint32_t timeout = 500; //ms to wait for timeout
olympux 1:8fc901e8846f 483 do {
olympux 1:8fc901e8846f 484 status = read_register(OBSERVE_TX,&observe_tx,1);
olympux 2:2ccc2e2a42d8 485 DBG("%x\r\n",observe_tx);
olympux 1:8fc901e8846f 486 } while( ! ( status & ( _BV(TX_DS) | _BV(MAX_RT) ) ) && ( RF24Timer.read_ms() - sent_at < timeout ) );
olympux 0:707771bf6708 487
olympux 1:8fc901e8846f 488 // The part above is what you could recreate with your own interrupt handler,
olympux 1:8fc901e8846f 489 // and then call this when you got an interrupt
olympux 1:8fc901e8846f 490 // ------------
olympux 0:707771bf6708 491
olympux 1:8fc901e8846f 492 // Call this when you get an interrupt
olympux 1:8fc901e8846f 493 // The status tells us three things
olympux 1:8fc901e8846f 494 // * The send was successful (TX_DS)
olympux 1:8fc901e8846f 495 // * The send failed, too many retries (MAX_RT)
olympux 1:8fc901e8846f 496 // * There is an ack packet waiting (RX_DR)
olympux 1:8fc901e8846f 497 bool tx_ok, tx_fail;
olympux 1:8fc901e8846f 498 whatHappened(tx_ok,tx_fail,ack_payload_available);
olympux 0:707771bf6708 499
olympux 1:8fc901e8846f 500 //printf("%u%u%u\r\n",tx_ok,tx_fail,ack_payload_available);
olympux 1:8fc901e8846f 501
olympux 1:8fc901e8846f 502 result = tx_ok;
olympux 1:8fc901e8846f 503 if (result == true) {
olympux 2:2ccc2e2a42d8 504 DBG("OK\r\n");
olympux 1:8fc901e8846f 505 } else {
olympux 2:2ccc2e2a42d8 506 DBG("Failed\r\n");
olympux 1:8fc901e8846f 507 }
olympux 0:707771bf6708 508
olympux 1:8fc901e8846f 509 // Handle the ack packet
olympux 1:8fc901e8846f 510 if ( ack_payload_available ) {
olympux 1:8fc901e8846f 511 ack_payload_length = getDynamicPayloadSize();
olympux 1:8fc901e8846f 512 DBG("[AckPacket]/");
olympux 2:2ccc2e2a42d8 513 DBG("ack_payload_length = %d\r\n",ack_payload_length);
olympux 1:8fc901e8846f 514 }
olympux 0:707771bf6708 515
olympux 1:8fc901e8846f 516 // Yay, we are done.
olympux 0:707771bf6708 517
olympux 1:8fc901e8846f 518 // Power down
olympux 1:8fc901e8846f 519 powerDown();
olympux 0:707771bf6708 520
olympux 1:8fc901e8846f 521 // Flush buffers (Is this a relic of past experimentation, and not needed anymore??)
olympux 1:8fc901e8846f 522 flush_tx();
olympux 0:707771bf6708 523
olympux 1:8fc901e8846f 524 return result;
olympux 0:707771bf6708 525 }
olympux 0:707771bf6708 526 /****************************************************************************/
olympux 0:707771bf6708 527
olympux 0:707771bf6708 528 void RF24::startWrite( const void* buf, uint8_t len )
olympux 0:707771bf6708 529 {
olympux 1:8fc901e8846f 530 // Transmitter power-up
olympux 1:8fc901e8846f 531 write_register(CONFIG, ( read_register(CONFIG) | _BV(PWR_UP) ) & ~_BV(PRIM_RX) );
olympux 1:8fc901e8846f 532 wait_us(150);
olympux 0:707771bf6708 533
olympux 1:8fc901e8846f 534 // Send the payload
olympux 1:8fc901e8846f 535 write_payload( buf, len );
olympux 0:707771bf6708 536
olympux 1:8fc901e8846f 537 // Allons!
olympux 1:8fc901e8846f 538 ce(HIGH);
olympux 1:8fc901e8846f 539 wait_us(15);
olympux 1:8fc901e8846f 540 ce(LOW);
olympux 0:707771bf6708 541 }
olympux 0:707771bf6708 542
olympux 0:707771bf6708 543 /****************************************************************************/
olympux 0:707771bf6708 544
olympux 0:707771bf6708 545 uint8_t RF24::getDynamicPayloadSize(void)
olympux 0:707771bf6708 546 {
olympux 1:8fc901e8846f 547 uint8_t result = 0;
olympux 0:707771bf6708 548
olympux 1:8fc901e8846f 549 csn(LOW);
olympux 1:8fc901e8846f 550 spi.write( R_RX_PL_WID );
olympux 1:8fc901e8846f 551 result = spi.write(0xff);
olympux 1:8fc901e8846f 552 csn(HIGH);
olympux 0:707771bf6708 553
olympux 1:8fc901e8846f 554 return result;
olympux 0:707771bf6708 555 }
olympux 0:707771bf6708 556
olympux 0:707771bf6708 557 /****************************************************************************/
olympux 0:707771bf6708 558
olympux 0:707771bf6708 559 bool RF24::available(void)
olympux 0:707771bf6708 560 {
olympux 1:8fc901e8846f 561 return available(NULL);
olympux 0:707771bf6708 562 }
olympux 0:707771bf6708 563
olympux 0:707771bf6708 564 /****************************************************************************/
olympux 0:707771bf6708 565
olympux 0:707771bf6708 566 bool RF24::available(uint8_t* pipe_num)
olympux 0:707771bf6708 567 {
olympux 5:aaff7f374e2b 568 // tmrh20's code
olympux 4:baf3b07be1a7 569 if (!( read_register(FIFO_STATUS) & _BV(RX_EMPTY) )) {
olympux 4:baf3b07be1a7 570
olympux 4:baf3b07be1a7 571 // If the caller wants the pipe number, include that
olympux 4:baf3b07be1a7 572 if ( pipe_num ) {
olympux 4:baf3b07be1a7 573 uint8_t status = get_status();
olympux 4:baf3b07be1a7 574 *pipe_num = ( status >> RX_P_NO ) & 7;
olympux 4:baf3b07be1a7 575 }
olympux 4:baf3b07be1a7 576 return 1;
olympux 4:baf3b07be1a7 577 }
olympux 4:baf3b07be1a7 578
olympux 4:baf3b07be1a7 579 return 0;
olympux 4:baf3b07be1a7 580
olympux 5:aaff7f374e2b 581 /*
olympux 5:aaff7f374e2b 582 // Maniacbug's code
olympux 1:8fc901e8846f 583 uint8_t status = get_status();
olympux 0:707771bf6708 584
olympux 1:8fc901e8846f 585 // Too noisy, enable if you really want lots o data!!
olympux 1:8fc901e8846f 586 //IF_SERIAL_DEBUG(print_status(status));
olympux 0:707771bf6708 587
olympux 1:8fc901e8846f 588 bool result = ( status & _BV(RX_DR) );
olympux 0:707771bf6708 589
olympux 1:8fc901e8846f 590 if (result) {
olympux 1:8fc901e8846f 591 // If the caller wants the pipe number, include that
olympux 1:8fc901e8846f 592 if ( pipe_num )
olympux 1:8fc901e8846f 593 *pipe_num = ( status >> RX_P_NO ) & 7;
olympux 0:707771bf6708 594
olympux 1:8fc901e8846f 595 // Clear the status bit
olympux 0:707771bf6708 596
olympux 1:8fc901e8846f 597 // ??? Should this REALLY be cleared now? Or wait until we
olympux 1:8fc901e8846f 598 // actually READ the payload?
olympux 0:707771bf6708 599
olympux 1:8fc901e8846f 600 write_register(STATUS,_BV(RX_DR) );
olympux 0:707771bf6708 601
olympux 1:8fc901e8846f 602 // Handle ack payload receipt
olympux 1:8fc901e8846f 603 if ( status & _BV(TX_DS) ) {
olympux 1:8fc901e8846f 604 write_register(STATUS,_BV(TX_DS));
olympux 1:8fc901e8846f 605 }
olympux 0:707771bf6708 606 }
olympux 0:707771bf6708 607
olympux 1:8fc901e8846f 608 return result;
olympux 4:baf3b07be1a7 609 */
olympux 0:707771bf6708 610 }
olympux 0:707771bf6708 611
olympux 0:707771bf6708 612 /****************************************************************************/
olympux 0:707771bf6708 613
olympux 0:707771bf6708 614 bool RF24::read( void* buf, uint8_t len )
olympux 0:707771bf6708 615 {
olympux 1:8fc901e8846f 616 // Fetch the payload
olympux 1:8fc901e8846f 617 read_payload( buf, len );
olympux 0:707771bf6708 618
olympux 1:8fc901e8846f 619 // was this the last of the data available?
olympux 1:8fc901e8846f 620 return read_register(FIFO_STATUS) & _BV(RX_EMPTY);
olympux 0:707771bf6708 621 }
olympux 0:707771bf6708 622
olympux 0:707771bf6708 623 /****************************************************************************/
olympux 0:707771bf6708 624
olympux 0:707771bf6708 625 void RF24::whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready)
olympux 0:707771bf6708 626 {
olympux 1:8fc901e8846f 627 // Read the status & reset the status in one easy call
olympux 1:8fc901e8846f 628 // Or is that such a good idea?
olympux 1:8fc901e8846f 629 uint8_t status = write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
olympux 0:707771bf6708 630
olympux 1:8fc901e8846f 631 // Report to the user what happened
olympux 1:8fc901e8846f 632 tx_ok = status & _BV(TX_DS);
olympux 1:8fc901e8846f 633 tx_fail = status & _BV(MAX_RT);
olympux 1:8fc901e8846f 634 rx_ready = status & _BV(RX_DR);
olympux 0:707771bf6708 635 }
olympux 0:707771bf6708 636
olympux 0:707771bf6708 637 /****************************************************************************/
olympux 0:707771bf6708 638
olympux 0:707771bf6708 639 void RF24::openWritingPipe(uint64_t value)
olympux 0:707771bf6708 640 {
olympux 1:8fc901e8846f 641 // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+)
olympux 1:8fc901e8846f 642 // expects it LSB first too, so we're good.
olympux 0:707771bf6708 643
olympux 1:8fc901e8846f 644 write_register(RX_ADDR_P0, reinterpret_cast<uint8_t*>(&value), 5);
olympux 1:8fc901e8846f 645 write_register(TX_ADDR, reinterpret_cast<uint8_t*>(&value), 5);
olympux 0:707771bf6708 646
olympux 1:8fc901e8846f 647 const uint8_t max_payload_size = 32;
olympux 1:8fc901e8846f 648 write_register(RX_PW_P0,min(payload_size,max_payload_size));
olympux 0:707771bf6708 649 }
olympux 0:707771bf6708 650
olympux 0:707771bf6708 651 /****************************************************************************/
olympux 0:707771bf6708 652
olympux 1:8fc901e8846f 653 static const uint8_t child_pipe[] = {
olympux 1:8fc901e8846f 654 RX_ADDR_P0, RX_ADDR_P1, RX_ADDR_P2, RX_ADDR_P3, RX_ADDR_P4, RX_ADDR_P5
olympux 0:707771bf6708 655 };
olympux 1:8fc901e8846f 656 static const uint8_t child_payload_size[] = {
olympux 1:8fc901e8846f 657 RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5
olympux 0:707771bf6708 658 };
olympux 1:8fc901e8846f 659 static const uint8_t child_pipe_enable[] = {
olympux 1:8fc901e8846f 660 ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5
olympux 0:707771bf6708 661 };
olympux 0:707771bf6708 662
olympux 0:707771bf6708 663 void RF24::openReadingPipe(uint8_t child, uint64_t address)
olympux 0:707771bf6708 664 {
olympux 2:2ccc2e2a42d8 665 DBG("Opening reading pipe\r\n");
olympux 1:8fc901e8846f 666 // If this is pipe 0, cache the address. This is needed because
olympux 1:8fc901e8846f 667 // openWritingPipe() will overwrite the pipe 0 address, so
olympux 1:8fc901e8846f 668 // startListening() will have to restore it.
olympux 1:8fc901e8846f 669 if (child == 0)
olympux 1:8fc901e8846f 670 pipe0_reading_address = address;
olympux 0:707771bf6708 671
olympux 1:8fc901e8846f 672 if (child <= 6) {
olympux 1:8fc901e8846f 673 // For pipes 2-5, only write the LSB
olympux 1:8fc901e8846f 674 if ( child < 2 )
olympux 1:8fc901e8846f 675 write_register(child_pipe[child], reinterpret_cast<const uint8_t*>(&address), 5);
olympux 1:8fc901e8846f 676 else
olympux 1:8fc901e8846f 677 write_register(child_pipe[child], reinterpret_cast<const uint8_t*>(&address), 1);
olympux 0:707771bf6708 678
olympux 1:8fc901e8846f 679 write_register(child_payload_size[child],payload_size);
olympux 0:707771bf6708 680
olympux 1:8fc901e8846f 681 // Note it would be more efficient to set all of the bits for all open
olympux 1:8fc901e8846f 682 // pipes at once. However, I thought it would make the calling code
olympux 1:8fc901e8846f 683 // more simple to do it this way.
olympux 1:8fc901e8846f 684 write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(child_pipe_enable[child]));
olympux 1:8fc901e8846f 685 }
olympux 0:707771bf6708 686 }
olympux 0:707771bf6708 687
olympux 0:707771bf6708 688 /****************************************************************************/
olympux 0:707771bf6708 689
olympux 0:707771bf6708 690 void RF24::toggle_features(void)
olympux 0:707771bf6708 691 {
olympux 1:8fc901e8846f 692 csn(LOW);
olympux 1:8fc901e8846f 693 spi.write( ACTIVATE );
olympux 1:8fc901e8846f 694 spi.write( 0x73 );
olympux 1:8fc901e8846f 695 csn(HIGH);
olympux 0:707771bf6708 696 }
olympux 0:707771bf6708 697
olympux 0:707771bf6708 698 /****************************************************************************/
olympux 0:707771bf6708 699
olympux 0:707771bf6708 700 void RF24::enableDynamicPayloads(void)
olympux 0:707771bf6708 701 {
olympux 1:8fc901e8846f 702 // Enable dynamic payload throughout the system
olympux 0:707771bf6708 703 write_register(FEATURE,read_register(FEATURE) | _BV(EN_DPL) );
olympux 0:707771bf6708 704
olympux 1:8fc901e8846f 705 // If it didn't work, the features are not enabled
olympux 1:8fc901e8846f 706 if ( ! read_register(FEATURE) ) {
olympux 1:8fc901e8846f 707 // So enable them and try again
olympux 1:8fc901e8846f 708 toggle_features();
olympux 1:8fc901e8846f 709 write_register(FEATURE,read_register(FEATURE) | _BV(EN_DPL) );
olympux 1:8fc901e8846f 710 }
olympux 0:707771bf6708 711
olympux 1:8fc901e8846f 712 DBG("FEATURE=%i\r\n",read_register(FEATURE));
olympux 0:707771bf6708 713
olympux 1:8fc901e8846f 714 // Enable dynamic payload on all pipes
olympux 1:8fc901e8846f 715 //
olympux 1:8fc901e8846f 716 // Not sure the use case of only having dynamic payload on certain
olympux 1:8fc901e8846f 717 // pipes, so the library does not support it.
olympux 1:8fc901e8846f 718 write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P5) | _BV(DPL_P4) | _BV(DPL_P3) | _BV(DPL_P2) | _BV(DPL_P1) | _BV(DPL_P0));
olympux 1:8fc901e8846f 719
olympux 1:8fc901e8846f 720 dynamic_payloads_enabled = true;
olympux 0:707771bf6708 721 }
olympux 0:707771bf6708 722
olympux 0:707771bf6708 723 /****************************************************************************/
olympux 0:707771bf6708 724
olympux 0:707771bf6708 725 void RF24::enableAckPayload(void)
olympux 0:707771bf6708 726 {
olympux 1:8fc901e8846f 727 //
olympux 1:8fc901e8846f 728 // enable ack payload and dynamic payload features
olympux 1:8fc901e8846f 729 //
olympux 0:707771bf6708 730
olympux 1:8fc901e8846f 731 write_register(FEATURE,read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL) );
olympux 0:707771bf6708 732
olympux 1:8fc901e8846f 733 // If it didn't work, the features are not enabled
olympux 1:8fc901e8846f 734 if ( ! read_register(FEATURE) ) {
olympux 1:8fc901e8846f 735 // So enable them and try again
olympux 1:8fc901e8846f 736 toggle_features();
olympux 1:8fc901e8846f 737 write_register(FEATURE,read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL) );
olympux 1:8fc901e8846f 738 }
olympux 0:707771bf6708 739
olympux 1:8fc901e8846f 740 DBG("FEATURE=%i\r\n",read_register(FEATURE));
olympux 0:707771bf6708 741
olympux 1:8fc901e8846f 742 //
olympux 1:8fc901e8846f 743 // Enable dynamic payload on pipes 0 & 1
olympux 1:8fc901e8846f 744 //
olympux 0:707771bf6708 745
olympux 1:8fc901e8846f 746 write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P1) | _BV(DPL_P0));
olympux 0:707771bf6708 747 }
olympux 0:707771bf6708 748
olympux 0:707771bf6708 749 /****************************************************************************/
olympux 0:707771bf6708 750
olympux 0:707771bf6708 751 void RF24::writeAckPayload(uint8_t pipe, const void* buf, uint8_t len)
olympux 0:707771bf6708 752 {
olympux 1:8fc901e8846f 753 const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);
olympux 0:707771bf6708 754
olympux 1:8fc901e8846f 755 csn(LOW);
olympux 1:8fc901e8846f 756 spi.write( W_ACK_PAYLOAD | ( pipe & 7 ) );
olympux 1:8fc901e8846f 757 const uint8_t max_payload_size = 32;
olympux 1:8fc901e8846f 758 uint8_t data_len = min(len,max_payload_size);
olympux 1:8fc901e8846f 759 while ( data_len-- )
olympux 1:8fc901e8846f 760 spi.write(*current++);
olympux 0:707771bf6708 761
olympux 1:8fc901e8846f 762 csn(HIGH);
olympux 0:707771bf6708 763 }
olympux 0:707771bf6708 764
olympux 0:707771bf6708 765 /****************************************************************************/
olympux 0:707771bf6708 766
olympux 0:707771bf6708 767 bool RF24::isAckPayloadAvailable(void)
olympux 0:707771bf6708 768 {
olympux 1:8fc901e8846f 769 bool result = ack_payload_available;
olympux 1:8fc901e8846f 770 ack_payload_available = false;
olympux 1:8fc901e8846f 771 return result;
olympux 0:707771bf6708 772 }
olympux 0:707771bf6708 773
olympux 0:707771bf6708 774 /****************************************************************************/
olympux 0:707771bf6708 775
olympux 0:707771bf6708 776 bool RF24::isPVariant(void)
olympux 0:707771bf6708 777 {
olympux 1:8fc901e8846f 778 return p_variant ;
olympux 0:707771bf6708 779 }
olympux 0:707771bf6708 780
olympux 0:707771bf6708 781 /****************************************************************************/
olympux 0:707771bf6708 782
olympux 0:707771bf6708 783 void RF24::setAutoAck(bool enable)
olympux 0:707771bf6708 784 {
olympux 1:8fc901e8846f 785 if ( enable )
olympux 1:8fc901e8846f 786 write_register(EN_AA, 63);
olympux 1:8fc901e8846f 787 else
olympux 1:8fc901e8846f 788 write_register(EN_AA, 0);
olympux 0:707771bf6708 789 }
olympux 0:707771bf6708 790
olympux 0:707771bf6708 791 /****************************************************************************/
olympux 0:707771bf6708 792
olympux 0:707771bf6708 793 void RF24::setAutoAck( uint8_t pipe, bool enable )
olympux 0:707771bf6708 794 {
olympux 1:8fc901e8846f 795 if ( pipe <= 6 ) {
olympux 1:8fc901e8846f 796 uint8_t en_aa = read_register( EN_AA ) ;
olympux 1:8fc901e8846f 797 if( enable ) {
olympux 1:8fc901e8846f 798 en_aa |= _BV(pipe) ;
olympux 1:8fc901e8846f 799 } else {
olympux 1:8fc901e8846f 800 en_aa &= ~_BV(pipe) ;
olympux 1:8fc901e8846f 801 }
olympux 1:8fc901e8846f 802 write_register( EN_AA, en_aa ) ;
olympux 0:707771bf6708 803 }
olympux 0:707771bf6708 804 }
olympux 0:707771bf6708 805
olympux 0:707771bf6708 806 /****************************************************************************/
olympux 0:707771bf6708 807
olympux 0:707771bf6708 808 bool RF24::testCarrier(void)
olympux 0:707771bf6708 809 {
olympux 1:8fc901e8846f 810 return ( read_register(CD) & 1 );
olympux 0:707771bf6708 811 }
olympux 0:707771bf6708 812
olympux 0:707771bf6708 813 /****************************************************************************/
olympux 0:707771bf6708 814
olympux 0:707771bf6708 815 bool RF24::testRPD(void)
olympux 0:707771bf6708 816 {
olympux 1:8fc901e8846f 817 return ( read_register(RPD) & 1 ) ;
olympux 0:707771bf6708 818 }
olympux 0:707771bf6708 819
olympux 0:707771bf6708 820 /****************************************************************************/
olympux 0:707771bf6708 821
olympux 0:707771bf6708 822 void RF24::setPALevel(rf24_pa_dbm_e level)
olympux 0:707771bf6708 823 {
olympux 1:8fc901e8846f 824 uint8_t setup = read_register(RF_SETUP) ;
olympux 1:8fc901e8846f 825 setup &= ~(_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH)) ;
olympux 0:707771bf6708 826
olympux 1:8fc901e8846f 827 // switch uses RAM (evil!)
olympux 1:8fc901e8846f 828 if ( level == RF24_PA_MAX ) {
olympux 1:8fc901e8846f 829 setup |= (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH)) ;
olympux 1:8fc901e8846f 830 } else if ( level == RF24_PA_HIGH ) {
olympux 1:8fc901e8846f 831 setup |= _BV(RF_PWR_HIGH) ;
olympux 1:8fc901e8846f 832 } else if ( level == RF24_PA_LOW ) {
olympux 1:8fc901e8846f 833 setup |= _BV(RF_PWR_LOW);
olympux 1:8fc901e8846f 834 } else if ( level == RF24_PA_MIN ) {
olympux 1:8fc901e8846f 835 // nothing
olympux 1:8fc901e8846f 836 } else if ( level == RF24_PA_ERROR ) {
olympux 1:8fc901e8846f 837 // On error, go to maximum PA
olympux 1:8fc901e8846f 838 setup |= (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH)) ;
olympux 1:8fc901e8846f 839 }
olympux 0:707771bf6708 840
olympux 1:8fc901e8846f 841 write_register( RF_SETUP, setup ) ;
olympux 0:707771bf6708 842 }
olympux 0:707771bf6708 843
olympux 0:707771bf6708 844 /****************************************************************************/
olympux 0:707771bf6708 845
olympux 0:707771bf6708 846 rf24_pa_dbm_e RF24::getPALevel(void)
olympux 0:707771bf6708 847 {
olympux 1:8fc901e8846f 848 rf24_pa_dbm_e result = RF24_PA_ERROR ;
olympux 1:8fc901e8846f 849 uint8_t power = read_register(RF_SETUP) & (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH)) ;
olympux 0:707771bf6708 850
olympux 1:8fc901e8846f 851 // switch uses RAM (evil!)
olympux 1:8fc901e8846f 852 if ( power == (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH)) ) {
olympux 1:8fc901e8846f 853 result = RF24_PA_MAX ;
olympux 1:8fc901e8846f 854 } else if ( power == _BV(RF_PWR_HIGH) ) {
olympux 1:8fc901e8846f 855 result = RF24_PA_HIGH ;
olympux 1:8fc901e8846f 856 } else if ( power == _BV(RF_PWR_LOW) ) {
olympux 1:8fc901e8846f 857 result = RF24_PA_LOW ;
olympux 1:8fc901e8846f 858 } else {
olympux 1:8fc901e8846f 859 result = RF24_PA_MIN ;
olympux 1:8fc901e8846f 860 }
olympux 0:707771bf6708 861
olympux 1:8fc901e8846f 862 return result ;
olympux 0:707771bf6708 863 }
olympux 0:707771bf6708 864
olympux 0:707771bf6708 865 /****************************************************************************/
olympux 0:707771bf6708 866
olympux 0:707771bf6708 867 bool RF24::setDataRate(rf24_datarate_e speed)
olympux 0:707771bf6708 868 {
olympux 1:8fc901e8846f 869 bool result = false;
olympux 1:8fc901e8846f 870 uint8_t setup = read_register(RF_SETUP) ;
olympux 0:707771bf6708 871
olympux 1:8fc901e8846f 872 // HIGH and LOW '00' is 1Mbs - our default
olympux 0:707771bf6708 873 wide_band = false ;
olympux 1:8fc901e8846f 874 setup &= ~(_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)) ;
olympux 1:8fc901e8846f 875 if( speed == RF24_250KBPS ) {
olympux 1:8fc901e8846f 876 // Must set the RF_DR_LOW to 1; RF_DR_HIGH (used to be RF_DR) is already 0
olympux 1:8fc901e8846f 877 // Making it '10'.
olympux 1:8fc901e8846f 878 wide_band = false ;
olympux 1:8fc901e8846f 879 setup |= _BV( RF_DR_LOW ) ;
olympux 1:8fc901e8846f 880 } else {
olympux 1:8fc901e8846f 881 // Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1
olympux 1:8fc901e8846f 882 // Making it '01'
olympux 1:8fc901e8846f 883 if ( speed == RF24_2MBPS ) {
olympux 1:8fc901e8846f 884 wide_band = true ;
olympux 1:8fc901e8846f 885 setup |= _BV(RF_DR_HIGH);
olympux 1:8fc901e8846f 886 } else {
olympux 1:8fc901e8846f 887 // 1Mbs
olympux 1:8fc901e8846f 888 wide_band = false ;
olympux 1:8fc901e8846f 889 }
olympux 0:707771bf6708 890 }
olympux 1:8fc901e8846f 891 write_register(RF_SETUP,setup);
olympux 0:707771bf6708 892
olympux 1:8fc901e8846f 893 // Verify our result
olympux 1:8fc901e8846f 894 if ( read_register(RF_SETUP) == setup ) {
olympux 1:8fc901e8846f 895 result = true;
olympux 1:8fc901e8846f 896 } else {
olympux 1:8fc901e8846f 897 wide_band = false;
olympux 1:8fc901e8846f 898 }
olympux 0:707771bf6708 899
olympux 1:8fc901e8846f 900 return result;
olympux 0:707771bf6708 901 }
olympux 0:707771bf6708 902
olympux 0:707771bf6708 903 /****************************************************************************/
olympux 0:707771bf6708 904
olympux 0:707771bf6708 905 rf24_datarate_e RF24::getDataRate( void )
olympux 0:707771bf6708 906 {
olympux 1:8fc901e8846f 907 rf24_datarate_e result ;
olympux 1:8fc901e8846f 908 uint8_t dr = read_register(RF_SETUP) & (_BV(RF_DR_LOW) | _BV(RF_DR_HIGH));
olympux 1:8fc901e8846f 909
olympux 1:8fc901e8846f 910 // switch uses RAM (evil!)
olympux 1:8fc901e8846f 911 // Order matters in our case below
olympux 1:8fc901e8846f 912 if ( dr == _BV(RF_DR_LOW) ) {
olympux 1:8fc901e8846f 913 // '10' = 250KBPS
olympux 1:8fc901e8846f 914 result = RF24_250KBPS ;
olympux 1:8fc901e8846f 915 } else if ( dr == _BV(RF_DR_HIGH) ) {
olympux 1:8fc901e8846f 916 // '01' = 2MBPS
olympux 1:8fc901e8846f 917 result = RF24_2MBPS ;
olympux 1:8fc901e8846f 918 } else {
olympux 1:8fc901e8846f 919 // '00' = 1MBPS
olympux 1:8fc901e8846f 920 result = RF24_1MBPS ;
olympux 1:8fc901e8846f 921 }
olympux 1:8fc901e8846f 922 return result ;
olympux 0:707771bf6708 923 }
olympux 0:707771bf6708 924
olympux 0:707771bf6708 925 /****************************************************************************/
olympux 0:707771bf6708 926
olympux 0:707771bf6708 927 void RF24::setCRCLength(rf24_crclength_e length)
olympux 0:707771bf6708 928 {
olympux 1:8fc901e8846f 929 uint8_t config = read_register(CONFIG) & ~( _BV(CRCO) | _BV(EN_CRC)) ;
olympux 1:8fc901e8846f 930
olympux 1:8fc901e8846f 931 // switch uses RAM (evil!)
olympux 1:8fc901e8846f 932 if ( length == RF24_CRC_DISABLED ) {
olympux 1:8fc901e8846f 933 // Do nothing, we turned it off above.
olympux 1:8fc901e8846f 934 } else if ( length == RF24_CRC_8 ) {
olympux 1:8fc901e8846f 935 config |= _BV(EN_CRC);
olympux 1:8fc901e8846f 936 } else {
olympux 1:8fc901e8846f 937 config |= _BV(EN_CRC);
olympux 1:8fc901e8846f 938 config |= _BV( CRCO );
olympux 1:8fc901e8846f 939 }
olympux 1:8fc901e8846f 940 write_register( CONFIG, config ) ;
olympux 0:707771bf6708 941 }
olympux 0:707771bf6708 942
olympux 0:707771bf6708 943 /****************************************************************************/
olympux 0:707771bf6708 944
olympux 0:707771bf6708 945 rf24_crclength_e RF24::getCRCLength(void)
olympux 0:707771bf6708 946 {
olympux 1:8fc901e8846f 947 rf24_crclength_e result = RF24_CRC_DISABLED;
olympux 1:8fc901e8846f 948 uint8_t config = read_register(CONFIG) & ( _BV(CRCO) | _BV(EN_CRC)) ;
olympux 0:707771bf6708 949
olympux 1:8fc901e8846f 950 if ( config & _BV(EN_CRC ) ) {
olympux 1:8fc901e8846f 951 if ( config & _BV(CRCO) )
olympux 1:8fc901e8846f 952 result = RF24_CRC_16;
olympux 1:8fc901e8846f 953 else
olympux 1:8fc901e8846f 954 result = RF24_CRC_8;
olympux 1:8fc901e8846f 955 }
olympux 0:707771bf6708 956
olympux 1:8fc901e8846f 957 return result;
olympux 0:707771bf6708 958 }
olympux 0:707771bf6708 959
olympux 0:707771bf6708 960 /****************************************************************************/
olympux 0:707771bf6708 961
olympux 0:707771bf6708 962 void RF24::disableCRC( void )
olympux 0:707771bf6708 963 {
olympux 1:8fc901e8846f 964 uint8_t disable = read_register(CONFIG) & ~_BV(EN_CRC) ;
olympux 1:8fc901e8846f 965 write_register( CONFIG, disable ) ;
olympux 0:707771bf6708 966 }
olympux 0:707771bf6708 967
olympux 0:707771bf6708 968 /****************************************************************************/
olympux 0:707771bf6708 969 void RF24::setRetries(uint8_t delay, uint8_t count)
olympux 0:707771bf6708 970 {
olympux 1:8fc901e8846f 971 write_register(SETUP_RETR,(delay&0xf)<<ARD | (count&0xf)<<ARC);
olympux 0:707771bf6708 972 }
olympux 0:707771bf6708 973
olympux 0:707771bf6708 974 // vim:ai:cin:sts=2 sw=2 ft=cpp