├── Enrf24.cpp ├── Enrf24.h ├── README.md ├── examples ├── AStelTXdemo │ └── AStelTXdemo.ino ├── Enrf24_ChannelScan │ └── Enrf24_ChannelScan.ino ├── Enrf24_RXdemo │ └── Enrf24_RXdemo.ino └── Enrf24_TXdemo │ └── Enrf24_TXdemo.ino ├── keywords.txt ├── library.json └── nRF24L01.h /Enrf24.cpp: -------------------------------------------------------------------------------- 1 | /* nRF24L01+ I/O for Energia 2 | * 3 | * Copyright (c) 2013 Eric Brundick 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include "Enrf24.h" 28 | 29 | /* Constructor */ 30 | Enrf24::Enrf24(uint8_t cePin, uint8_t csnPin, uint8_t irqPin) 31 | { 32 | _cePin = cePin; 33 | _csnPin = csnPin; 34 | _irqPin = irqPin; 35 | spibus = &SPI; 36 | 37 | rf_status = 0; 38 | rf_addr_width = 5; 39 | txbuf_len = 0; 40 | readpending = 0; 41 | } 42 | 43 | /* Initialization */ 44 | void Enrf24::begin(uint32_t datarate, uint8_t channel) 45 | { 46 | pinMode(_cePin, OUTPUT); 47 | digitalWrite(_cePin, LOW); 48 | pinMode(_csnPin, OUTPUT); 49 | digitalWrite(_csnPin, HIGH); 50 | pinMode(_irqPin, INPUT); 51 | //digitalWrite(_irqPin, LOW); // No pullups; the transceiver provides this! 52 | 53 | spibus->transfer(0); // Strawman transfer, fixes USCI issue on G2553 54 | 55 | // Is the transceiver present/alive? 56 | if (!_isAlive()) 57 | return; // Nothing more to do here... 58 | 59 | // Wait 100ms for module to initialize 60 | while ( millis() < 100 ) 61 | ; 62 | 63 | //Write to FEATURE Register and see if changes stick 64 | _writeReg(RF24_FEATURE, RF24_EN_DPL); 65 | 66 | if (_readReg(RF24_FEATURE) == 0x00) { 67 | //If changes do not stick, issue an activate command 68 | uint8_t _activate_data = 0x73; 69 | _issueCmdPayload(RF24_ACTIVATE, &_activate_data, 1); 70 | } 71 | 72 | // Init certain registers 73 | _writeReg(RF24_CONFIG, 0x00); // Deep power-down, everything disabled 74 | _writeReg(RF24_EN_AA, 0x03); 75 | _writeReg(RF24_EN_RXADDR, 0x03); 76 | _writeReg(RF24_RF_SETUP, 0x00); 77 | _writeReg(RF24_STATUS, ENRF24_IRQ_MASK); // Clear all IRQs 78 | _writeReg(RF24_DYNPD, 0x03); 79 | _writeReg(RF24_FEATURE, RF24_EN_DPL); // Dynamic payloads enabled by default 80 | 81 | // Set all parameters 82 | if (channel > 125) 83 | channel = 125; 84 | deepsleep(); 85 | _issueCmd(RF24_FLUSH_TX); 86 | _issueCmd(RF24_FLUSH_RX); 87 | readpending = 0; 88 | _irq_clear(ENRF24_IRQ_MASK); 89 | setChannel(channel); 90 | setSpeed(datarate); 91 | setTXpower(); 92 | setAutoAckParams(); 93 | setAddressLength(rf_addr_width); 94 | setCRC(true); // Default = CRC on, 8-bit 95 | } 96 | 97 | /* Formal shut-down/clearing of library state */ 98 | void Enrf24::end() 99 | { 100 | txbuf_len = 0; 101 | rf_status = 0; 102 | rf_addr_width = 5; 103 | 104 | if (!_isAlive()) 105 | return; 106 | deepsleep(); 107 | _issueCmd(RF24_FLUSH_TX); 108 | _issueCmd(RF24_FLUSH_RX); 109 | readpending = 0; 110 | _irq_clear(ENRF24_IRQ_MASK); 111 | digitalWrite(_cePin, LOW); 112 | digitalWrite(_csnPin, HIGH); 113 | } 114 | 115 | /* Basic SPI I/O */ 116 | uint8_t Enrf24::_readReg(uint8_t addr) 117 | { 118 | uint8_t result; 119 | 120 | digitalWrite(_csnPin, LOW); 121 | rf_status = spibus->transfer(RF24_R_REGISTER | addr); 122 | result = spibus->transfer(RF24_NOP); 123 | digitalWrite(_csnPin, HIGH); 124 | return result; 125 | } 126 | 127 | void Enrf24::_readRegMultiLSB(uint8_t addr, uint8_t *buf, size_t len) 128 | { 129 | uint8_t i; 130 | digitalWrite(_csnPin, LOW); 131 | rf_status = spibus->transfer(RF24_R_REGISTER | addr); 132 | for (i=0; itransfer(RF24_NOP); 134 | } 135 | digitalWrite(_csnPin, HIGH); 136 | } 137 | 138 | void Enrf24::_writeReg(uint8_t addr, uint8_t val) 139 | { 140 | digitalWrite(_csnPin, LOW); 141 | rf_status = spibus->transfer(RF24_W_REGISTER | addr); 142 | spibus->transfer(val); 143 | digitalWrite(_csnPin, HIGH); 144 | } 145 | 146 | void Enrf24::_writeRegMultiLSB(uint8_t addr, uint8_t *buf, size_t len) 147 | { 148 | size_t i; 149 | 150 | digitalWrite(_csnPin, LOW); 151 | rf_status = spibus->transfer(RF24_W_REGISTER | addr); 152 | for (i=0; itransfer(buf[len-i-1]); 154 | } 155 | digitalWrite(_csnPin, HIGH); 156 | } 157 | 158 | void Enrf24::_issueCmd(uint8_t cmd) 159 | { 160 | digitalWrite(_csnPin, LOW); 161 | rf_status = spibus->transfer(cmd); 162 | digitalWrite(_csnPin, HIGH); 163 | } 164 | 165 | void Enrf24::_issueCmdPayload(uint8_t cmd, uint8_t *buf, size_t len) 166 | { 167 | size_t i; 168 | 169 | digitalWrite(_csnPin, LOW); 170 | rf_status = spibus->transfer(cmd); 171 | for (i=0; itransfer(buf[i]); 173 | } 174 | digitalWrite(_csnPin, HIGH); 175 | } 176 | 177 | void Enrf24::_readCmdPayload(uint8_t cmd, uint8_t *buf, size_t len, size_t maxlen) 178 | { 179 | size_t i; 180 | 181 | digitalWrite(_csnPin, LOW); 182 | rf_status = spibus->transfer(cmd); 183 | for (i=0; itransfer(RF24_NOP); 186 | } else { 187 | spibus->transfer(RF24_NOP); // Beyond maxlen bytes, just discard the remaining data. 188 | } 189 | } 190 | digitalWrite(_csnPin, HIGH); 191 | } 192 | 193 | boolean Enrf24::_isAlive() 194 | { 195 | uint8_t aw; 196 | 197 | aw = _readReg(RF24_SETUP_AW); 198 | return ((aw & 0xFC) == 0x00 && (aw & 0x03) != 0x00); 199 | } 200 | 201 | uint8_t Enrf24::_irq_getreason() 202 | { 203 | lastirq = _readReg(RF24_STATUS) & ENRF24_IRQ_MASK; 204 | return lastirq; 205 | } 206 | 207 | // Get IRQ from last known rf_status update without querying module over SPI. 208 | uint8_t Enrf24::_irq_derivereason() 209 | { 210 | lastirq = rf_status & ENRF24_IRQ_MASK; 211 | return lastirq; 212 | } 213 | 214 | void Enrf24::_irq_clear(uint8_t irq) 215 | { 216 | _writeReg(RF24_STATUS, irq & ENRF24_IRQ_MASK); 217 | } 218 | 219 | #define ENRF24_CFGMASK_CRC(a) (a & (RF24_EN_CRC | RF24_CRCO)) 220 | 221 | void Enrf24::_readTXaddr(uint8_t *buf) 222 | { 223 | _readRegMultiLSB(RF24_TX_ADDR, buf, rf_addr_width); 224 | } 225 | 226 | void Enrf24::_writeRXaddrP0(uint8_t *buf) 227 | { 228 | _writeRegMultiLSB(RF24_RX_ADDR_P0, buf, rf_addr_width); 229 | } 230 | 231 | 232 | /* nRF24 I/O maintenance--called as a "hook" inside other I/O functions to give 233 | * the library a chance to take care of its buffers et al 234 | */ 235 | void Enrf24::_maintenanceHook() 236 | { 237 | uint8_t i; 238 | 239 | _irq_getreason(); 240 | 241 | if (lastirq & ENRF24_IRQ_TXFAILED) { 242 | lastTXfailed = true; 243 | _issueCmd(RF24_FLUSH_TX); 244 | _irq_clear(ENRF24_IRQ_TXFAILED); 245 | } 246 | 247 | if (lastirq & ENRF24_IRQ_TX) { 248 | lastTXfailed = false; 249 | _irq_clear(ENRF24_IRQ_TX); 250 | } 251 | 252 | if (lastirq & ENRF24_IRQ_RX) { 253 | if ( !(_readReg(RF24_FIFO_STATUS) & RF24_RX_FULL) ) { /* Don't feel it's necessary 254 | * to be notified of new 255 | * incoming packets if the RX 256 | * queue is full. 257 | */ 258 | _irq_clear(ENRF24_IRQ_RX); 259 | } 260 | 261 | /* Check if RX payload is 0-byte or >32byte (erroneous conditions) 262 | * Also check if data was received on pipe#0, which we are ignoring. 263 | * The reason for this is pipe#0 is needed for receiving AutoACK acknowledgements, 264 | * its address gets reset to the module's default and we do not care about data 265 | * coming in to that address... 266 | */ 267 | if ( (rf_status & 0x0E) != 0x0E ) { // Only check if there is an actual packet 268 | _readCmdPayload(RF24_R_RX_PL_WID, &i, 1, 1); 269 | if (i == 0 || i > 32 || ((rf_status & 0x0E) >> 1) == 0) { 270 | /* Zero-width RX payload is an error that happens a lot 271 | * with non-AutoAck, and must be cleared with FLUSH_RX. 272 | * Erroneous >32byte packets are a similar phenomenon. 273 | */ 274 | _issueCmd(RF24_FLUSH_RX); 275 | _irq_clear(ENRF24_IRQ_RX); 276 | readpending = 0; 277 | } else { 278 | readpending = 1; 279 | } 280 | } 281 | // Actual scavenging of RX queues is performed by user-directed use of read(). 282 | } 283 | } 284 | 285 | 286 | 287 | /* Public functions */ 288 | boolean Enrf24::available(boolean checkIrq) 289 | { 290 | if (checkIrq && digitalRead(_irqPin) == HIGH && readpending == 0) 291 | return false; 292 | _maintenanceHook(); 293 | if ( !(_readReg(RF24_FIFO_STATUS) & RF24_RX_EMPTY) ) { 294 | return true; 295 | } 296 | if (readpending) { 297 | return true; 298 | } 299 | return false; 300 | } 301 | 302 | size_t Enrf24::read(void *inbuf, uint8_t maxlen) 303 | { 304 | uint8_t *buf = (uint8_t *)inbuf; 305 | uint8_t plwidth; 306 | 307 | _maintenanceHook(); 308 | readpending = 0; 309 | if ((_readReg(RF24_FIFO_STATUS) & RF24_RX_EMPTY) || maxlen < 1) { 310 | return 0; 311 | } 312 | _readCmdPayload(RF24_R_RX_PL_WID, &plwidth, 1, 1); 313 | _readCmdPayload(RF24_R_RX_PAYLOAD, buf, plwidth, maxlen); 314 | buf[plwidth] = '\0'; // Zero-terminate in case this is a string. 315 | if (_irq_derivereason() & ENRF24_IRQ_RX) { 316 | _irq_clear(ENRF24_IRQ_RX); 317 | } 318 | 319 | return (size_t) plwidth; 320 | } 321 | 322 | // Perform TX of current ring-buffer contents 323 | void Enrf24::flush() 324 | { 325 | uint8_t reg, addrbuf[5]; 326 | boolean enaa=false, origrx=false; 327 | 328 | if (!txbuf_len) 329 | return; // Zero-length buffer? Nothing to send! 330 | 331 | reg = _readReg(RF24_FIFO_STATUS); 332 | if (reg & BIT5) { // RF24_TX_FULL #define is BIT0, which is not the correct bit for FIFO_STATUS. 333 | // Seen this before with a user whose CE pin was messed up. 334 | _issueCmd(RF24_FLUSH_TX); 335 | txbuf_len = 0; 336 | return; // Should never happen, but nonetheless a precaution to take. 337 | } 338 | 339 | _maintenanceHook(); 340 | 341 | if (reg & RF24_TX_REUSE) { 342 | // If somehow TX_REUSE is enabled, we need to flush the TX queue before loading our new payload. 343 | _issueCmd(RF24_FLUSH_TX); 344 | } 345 | 346 | if (_readReg(RF24_EN_AA) & 0x01 && (_readReg(RF24_RF_SETUP) & 0x28) != 0x20) { 347 | /* AutoACK enabled, must write TX addr to RX pipe#0 348 | * Note that 250Kbps doesn't support auto-ack, so we check RF24_RF_SETUP to verify that. 349 | */ 350 | enaa = true; 351 | _readTXaddr(addrbuf); 352 | _writeRXaddrP0(addrbuf); 353 | } 354 | 355 | reg = _readReg(RF24_CONFIG); 356 | if ( !(reg & RF24_PWR_UP) ) { 357 | //digitalWrite(_cePin, HIGH); // Workaround for SI24R1 knockoff chips 358 | _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP); 359 | delay(5); // 5ms delay required for nRF24 oscillator start-up 360 | //digitalWrite(_cePin, LOW); 361 | } 362 | if (reg & RF24_PRIM_RX) { 363 | origrx=true; 364 | digitalWrite(_cePin, LOW); 365 | _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP); 366 | } 367 | 368 | _issueCmdPayload(RF24_W_TX_PAYLOAD, txbuf, txbuf_len); 369 | digitalWrite(_cePin, HIGH); 370 | delayMicroseconds(100); 371 | digitalWrite(_cePin, LOW); 372 | 373 | txbuf_len = 0; // Reset TX ring buffer 374 | 375 | while (digitalRead(_irqPin) == HIGH) // Wait until IRQ fires 376 | ; 377 | // IRQ fired 378 | _maintenanceHook(); // Handle/clear IRQ 379 | 380 | // Purge Pipe#0 address (set to module's power-up default) 381 | if (enaa) { 382 | addrbuf[0] = 0xE7; addrbuf[1] = 0xE7; addrbuf[2] = 0xE7; addrbuf[3] = 0xE7; addrbuf[4] = 0xE7; 383 | _writeRXaddrP0(addrbuf); 384 | } 385 | 386 | // If we were in RX mode before writing, return back to RX mode. 387 | if (origrx) { 388 | enableRX(); 389 | } 390 | } 391 | 392 | void Enrf24::purge() 393 | { 394 | txbuf_len = 0; 395 | } 396 | 397 | size_t Enrf24::write(uint8_t c) 398 | { 399 | if (txbuf_len == 32) { // If we're trying to stuff an already-full buffer... 400 | flush(); // Blocking OTA TX 401 | } 402 | 403 | txbuf[txbuf_len] = c; 404 | txbuf_len++; 405 | 406 | return 1; 407 | } 408 | 409 | uint8_t Enrf24::radioState() 410 | { 411 | uint8_t reg; 412 | 413 | if (!_isAlive()) 414 | return ENRF24_STATE_NOTPRESENT; 415 | 416 | reg = _readReg(RF24_CONFIG); 417 | if ( !(reg & RF24_PWR_UP) ) 418 | return ENRF24_STATE_DEEPSLEEP; 419 | 420 | // At this point it's either Standby-I, II or PRX. 421 | if (reg & RF24_PRIM_RX) { 422 | if (digitalRead(_cePin)) 423 | return ENRF24_STATE_PRX; 424 | // PRIM_RX=1 but CE=0 is a form of idle state. 425 | return ENRF24_STATE_IDLE; 426 | } 427 | // Check if TX queue is empty, if so it's idle, if not it's PTX. 428 | if (_readReg(RF24_FIFO_STATUS) & RF24_TX_EMPTY) 429 | return ENRF24_STATE_IDLE; 430 | return ENRF24_STATE_PTX; 431 | } 432 | 433 | void Enrf24::deepsleep() 434 | { 435 | uint8_t reg; 436 | 437 | reg = _readReg(RF24_CONFIG); 438 | if (reg & (RF24_PWR_UP | RF24_PRIM_RX)) { 439 | _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg)); 440 | } 441 | digitalWrite(_cePin, LOW); 442 | } 443 | 444 | void Enrf24::enableRX() 445 | { 446 | uint8_t reg; 447 | 448 | reg = _readReg(RF24_CONFIG); 449 | _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP | RF24_PRIM_RX); 450 | digitalWrite(_cePin, HIGH); 451 | 452 | if ( !(reg & RF24_PWR_UP) ) { // Powering up from deep-sleep requires 5ms oscillator start delay 453 | delay(5); 454 | } 455 | } 456 | 457 | void Enrf24::disableRX() 458 | { 459 | uint8_t reg; 460 | 461 | digitalWrite(_cePin, LOW); 462 | 463 | reg = _readReg(RF24_CONFIG); 464 | if (reg & RF24_PWR_UP) { /* Keep us in standby-I if we're coming from RX mode, otherwise stay 465 | * in deep-sleep if we call this while already in PWR_UP=0 mode. 466 | */ 467 | _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg) | RF24_PWR_UP); 468 | } else { 469 | _writeReg(RF24_CONFIG, ENRF24_CFGMASK_IRQ | ENRF24_CFGMASK_CRC(reg)); 470 | } 471 | } 472 | 473 | void Enrf24::autoAck(boolean onoff) 474 | { 475 | uint8_t reg; 476 | 477 | reg = _readReg(RF24_EN_AA); 478 | if (onoff) { 479 | if ( !(reg & 0x01) || !(reg & 0x02) ) { 480 | _writeReg(RF24_EN_AA, 0x03); 481 | } 482 | } else { 483 | if (reg & 0x03) { 484 | _writeReg(RF24_EN_AA, 0x00); 485 | } 486 | } 487 | } 488 | 489 | void Enrf24::setChannel(uint8_t channel) 490 | { 491 | if (channel > 125) 492 | channel = 125; 493 | _writeReg(RF24_RF_CH, channel); 494 | } 495 | 496 | void Enrf24::setTXpower(int8_t dBm) 497 | { 498 | uint8_t reg, pwr; 499 | 500 | reg = _readReg(RF24_RF_SETUP) & 0xF8; // preserve RF speed settings 501 | pwr = 0x06; 502 | if (dBm >= 7) 503 | pwr = 0x07; 504 | if (dBm < 0) 505 | pwr = 0x04; 506 | if (dBm < -6) 507 | pwr = 0x02; 508 | if (dBm < -12) 509 | pwr = 0x00; 510 | _writeReg(RF24_RF_SETUP, reg | pwr); 511 | } 512 | 513 | void Enrf24::setSpeed(uint32_t rfspeed) 514 | { 515 | uint8_t reg, spd; 516 | 517 | reg = _readReg(RF24_RF_SETUP) & 0xD7; // preserve RF power settings 518 | spd = 0x01; 519 | if (rfspeed < 2000000) 520 | spd = 0x00; 521 | if (rfspeed < 1000000) 522 | spd = 0x04; 523 | _writeReg(RF24_RF_SETUP, reg | (spd << 3)); 524 | } 525 | 526 | void Enrf24::setCRC(boolean onoff, boolean crc16bit) 527 | { 528 | uint8_t reg, crcbits=0; 529 | 530 | reg = _readReg(RF24_CONFIG) & 0xF3; // preserve IRQ mask, PWR_UP/PRIM_RX settings 531 | if (onoff) 532 | crcbits |= RF24_EN_CRC; 533 | if (crc16bit) 534 | crcbits |= RF24_CRCO; 535 | _writeReg(RF24_CONFIG, reg | crcbits); 536 | } 537 | 538 | void Enrf24::setAutoAckParams(uint8_t autoretry_count, uint16_t autoretry_timeout) 539 | { 540 | uint8_t setup_retr=0; 541 | 542 | setup_retr = autoretry_count & 0x0F; 543 | autoretry_timeout -= 250; 544 | setup_retr |= ((autoretry_timeout / 250) & 0x0F) << 4; 545 | _writeReg(RF24_SETUP_RETR, setup_retr); 546 | } 547 | 548 | void Enrf24::setAddressLength(size_t len) 549 | { 550 | if (len < 3) 551 | len = 3; 552 | if (len > 5) 553 | len = 5; 554 | 555 | _writeReg(RF24_SETUP_AW, len-2); 556 | rf_addr_width = len; 557 | } 558 | 559 | void Enrf24::setRXaddress(const void *rxaddr) 560 | { 561 | _writeRegMultiLSB(RF24_RX_ADDR_P1, (uint8_t*)rxaddr, rf_addr_width); 562 | } 563 | 564 | void Enrf24::setTXaddress(const void *rxaddr) 565 | { 566 | _writeRegMultiLSB(RF24_TX_ADDR, (uint8_t*)rxaddr, rf_addr_width); 567 | } 568 | 569 | boolean Enrf24::rfSignalDetected() 570 | { 571 | uint8_t rpd; 572 | 573 | rpd = _readReg(RF24_RPD); 574 | return (boolean)rpd; 575 | } 576 | 577 | uint32_t Enrf24::getSpeed() 578 | { 579 | uint8_t reg = _readReg(RF24_RF_SETUP) & 0x28; 580 | 581 | switch (reg) { 582 | case 0x00: 583 | return 1000000UL; 584 | case 0x08: 585 | return 2000000UL; 586 | case 0x20: 587 | return 250000UL; 588 | } 589 | return 0UL; 590 | } 591 | 592 | int8_t Enrf24::getTXpower() 593 | { 594 | uint8_t reg = _readReg(RF24_RF_SETUP) & 0x07; 595 | 596 | if (reg & 0x01) 597 | return 7; // SI24R1-only +7dBm mode 598 | switch (reg) { 599 | case 0x02: 600 | return -12; 601 | case 0x04: 602 | return -6; 603 | case 0x06: 604 | return 0; 605 | } 606 | return -18; 607 | } 608 | 609 | boolean Enrf24::getAutoAck() 610 | { 611 | uint8_t reg = _readReg(RF24_EN_AA); 612 | 613 | if (reg) 614 | return true; 615 | return false; 616 | } 617 | 618 | void Enrf24::getRXaddress(void *buf) 619 | { 620 | _readRegMultiLSB(RF24_RX_ADDR_P1, (uint8_t*)buf, rf_addr_width); 621 | } 622 | 623 | void Enrf24::getTXaddress(void *buf) 624 | { 625 | _readRegMultiLSB(RF24_TX_ADDR, (uint8_t*)buf, rf_addr_width); 626 | } 627 | 628 | unsigned int Enrf24::getCRC() 629 | { 630 | uint8_t reg = _readReg(RF24_CONFIG) & 0x0C; 631 | 632 | switch (reg) { 633 | case 0x08: 634 | return 8; 635 | case 0x0C: 636 | return 16; 637 | } 638 | 639 | return 0; 640 | } 641 | -------------------------------------------------------------------------------- /Enrf24.h: -------------------------------------------------------------------------------- 1 | /* nRF24L01+ I/O for Energia 2 | * 3 | * Copyright (c) 2013 Eric Brundick 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, copy, 8 | * modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef _ENRF24_H 26 | #define _ENRF24_H 27 | 28 | #define ENRF24_LIBRARY_VERSION "1.9" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "nRF24L01.h" 35 | 36 | #if defined(TARGET_IS_SNOWFLAKE_RA0) || defined(TARGET_IS_SNOWFLAKE_RA1) || defined(TARGET_IS_BLIZZARD_RB1) 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #endif 43 | 44 | #ifndef BITF 45 | #define BIT0 (0x0001) 46 | #define BIT1 (0x0002) 47 | #define BIT2 (0x0004) 48 | #define BIT3 (0x0008) 49 | #define BIT4 (0x0010) 50 | #define BIT5 (0x0020) 51 | #define BIT6 (0x0040) 52 | #define BIT7 (0x0080) 53 | #define BIT8 (0x0100) 54 | #define BIT9 (0x0200) 55 | #define BITA (0x0400) 56 | #define BITB (0x0800) 57 | #define BITC (0x1000) 58 | #define BITD (0x2000) 59 | #define BITE (0x4000) 60 | #define BITF (0x8000) 61 | #endif 62 | 63 | /* Constants for speed, radio state */ 64 | #define ENRF24_STATE_NOTPRESENT 0 65 | #define ENRF24_STATE_DEEPSLEEP 1 66 | #define ENRF24_STATE_IDLE 2 67 | #define ENRF24_STATE_PTX 3 68 | #define ENRF24_STATE_PRX 4 69 | 70 | /* Internal IRQ handling */ 71 | #define ENRF24_IRQ_TX 0x20 72 | #define ENRF24_IRQ_RX 0x40 73 | #define ENRF24_IRQ_TXFAILED 0x10 74 | #define ENRF24_IRQ_MASK 0x70 75 | 76 | #define ENRF24_CFGMASK_IRQ 0 77 | 78 | 79 | 80 | /* Class definition--inherits from Print so we have .print() functions */ 81 | class Enrf24 : public Print { 82 | public: 83 | boolean lastTXfailed; 84 | 85 | Enrf24(uint8_t cePin, uint8_t csnPin, uint8_t irqPin); 86 | void begin(uint32_t datarate=1000000, uint8_t channel=0); // Specify bitrate & channel 87 | void end(); // Shut it off, clear the library's state 88 | void setSPI(SPIClass *spi_instance_ptr) { spibus = spi_instance_ptr; } // Change the SPI instance used 89 | 90 | // I/O 91 | boolean available(boolean checkIrq=false); // Check if incoming data is ready to be read 92 | size_t read(void *inbuf, uint8_t maxlen=32); /* Read contents of RX buffer up to 93 | * 'maxlen' bytes, return final length. 94 | * 'inbuf' should be maxlen+1 since a 95 | * null '\0' is tacked onto the end. 96 | */ 97 | virtual size_t write(uint8_t); // Single-byte write, implements TX ring-buffer & auto-send 98 | virtual size_t write(const void *buf, size_t len) { return write((const uint8_t *)buf, len); }; 99 | using Print::write; // Includes the multi-byte write for repeatedly hitting write(uint8_t) 100 | void flush(); // Force transmission of TX ring buffer contents 101 | void purge(); // Ignore TX ring buffer contents, return ring pointer to 0. 102 | 103 | // Power-state related stuff- 104 | uint8_t radioState(); // Evaluate current state of the transceiver (see ENRF24_STATE_* defines) 105 | void deepsleep(); // Enter POWERDOWN mode, ~0.9uA power consumption 106 | void enableRX(); // Enter PRX mode (~14mA) 107 | void disableRX(); /* Disable PRX mode (PRIM_RX bit in CONFIG register) 108 | * Note this won't necessarily push the transceiver into deep sleep, but rather 109 | * an idle standby mode where its internal oscillators are ready & running but 110 | * the RF transceiver PLL is disabled. ~26uA power consumption. 111 | */ 112 | 113 | // Custom tweaks to RF parameters, packet parameters 114 | void autoAck(boolean onoff=true); // Enable/disable auto-acknowledgements (enabled by default) 115 | void setChannel(uint8_t channel); 116 | void setTXpower(int8_t dBm=0); // Only a few values supported by this (0, -6, -12, -18 dBm) 117 | void setSpeed(uint32_t rfspeed); // Set 250000, 1000000, 2000000 speeds. 118 | void setCRC(boolean onoff, boolean crc16bit=false); /* Enable/disable CRC usage inside nRF24's 119 | * hardware packet engine, specify 8 or 120 | * 16-bit CRC. 121 | */ 122 | // Set AutoACK retry count, timeout params (0-15, 250-4000 respectively) 123 | void setAutoAckParams(uint8_t autoretry_count=15, uint16_t autoretry_timeout=2000); 124 | 125 | // Protocol addressing -- receive, transmit addresses 126 | void setAddressLength(size_t len); // Valid parameters = 3, 4 or 5. Defaults to 5. 127 | void setRXaddress(const void *rxaddr); // 3-5 byte RX address loaded into pipe#1 128 | void setTXaddress(const void *txaddr); // 3-5 byte TX address loaded into TXaddr register 129 | 130 | // Miscellaneous feature 131 | boolean rfSignalDetected(); /* Read RPD register to determine if transceiver has presently detected an RF signal 132 | * of -64dBm or greater. Only works in PRX (enableRX()) mode. 133 | */ 134 | 135 | // Query current parameters 136 | int getChannel(void) { return _readReg(RF24_RF_CH); }; 137 | uint32_t getSpeed(void); 138 | int8_t getTXpower(void); 139 | size_t getAddressLength(void) { return rf_addr_width; }; 140 | void getRXaddress(void *); 141 | void getTXaddress(void *); 142 | boolean getAutoAck(void); 143 | unsigned int getCRC(void); 144 | 145 | 146 | private: 147 | uint8_t rf_status; 148 | uint8_t rf_addr_width; 149 | uint8_t txbuf_len; 150 | uint8_t txbuf[32]; 151 | uint8_t lastirq, readpending; 152 | uint8_t _cePin, _csnPin, _irqPin; 153 | SPIClass *spibus; 154 | 155 | uint8_t _readReg(uint8_t addr); 156 | void _readRegMultiLSB(uint8_t addr, uint8_t *buf, size_t len); 157 | void _writeReg(uint8_t addr, uint8_t val); 158 | void _writeRegMultiLSB(uint8_t addr, uint8_t *buf, size_t len); 159 | void _issueCmd(uint8_t cmd); 160 | void _readCmdPayload(uint8_t addr, uint8_t *buf, size_t len, size_t maxlen); 161 | void _issueCmdPayload(uint8_t cmd, uint8_t *buf, size_t len); 162 | uint8_t _irq_getreason(); 163 | uint8_t _irq_derivereason(); // Get IRQ status from rf_status w/o querying module over SPI. 164 | void _irq_clear(uint8_t irq); 165 | boolean _isAlive(); 166 | void _readTXaddr(uint8_t *buf); 167 | void _writeRXaddrP0(uint8_t *buf); 168 | void _maintenanceHook(); // Handles IRQs and purges RX queue when erroneous contents exist. 169 | 170 | /* Private planning: 171 | Need to keep track of: 172 | RF status (since we get it after every SPI communication, might as well store it) 173 | RF channel (to refresh in order to reset PLOS_CNT) 174 | RF speed (to determine if autoAck makes any sense, since it doesn't @ 250Kbps) 175 | Address Length (to determine how many bytes to read out of set(RX|TX)address()) 176 | 32-byte TX ring buffer 177 | Ring buffer position 178 | */ 179 | }; 180 | 181 | #endif 182 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Enrf24 2 | ====== 3 | 4 | nRF24L01+ Transceiver Library for Energia, geared for simplicity. -------------------------------------------------------------------------------- /examples/AStelTXdemo/AStelTXdemo.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | Enrf24 radio(PE_1, PE_2, PE_3); // PE1 = CE, PE2 = CSN, PE3 = IRQ 7 | const uint8_t txaddr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x01 }; 8 | 9 | const char *str_on = "ON"; 10 | const char *str_off = "OFF"; 11 | 12 | void dump_radio_status_to_serialport(uint8_t); 13 | 14 | void setup() { 15 | Serial.begin(9600); 16 | 17 | SPI.setModule(3); 18 | SPI.begin(); 19 | SPI.setClockDivider(SPI_CLOCK_DIV8); 20 | SPI.setDataMode(SPI_MODE0); 21 | SPI.setBitOrder(MSBFIRST); 22 | 23 | radio.begin(); // Defaults 1Mbps, channel 0, max TX power 24 | dump_radio_status_to_serialport(radio.radioState()); 25 | 26 | radio.setTXaddress((void*)txaddr); 27 | } 28 | 29 | void loop() { 30 | Serial.print("Sending packet: "); 31 | Serial.println(str_on); 32 | radio.print(str_on); 33 | radio.flush(); // Force transmit (don't wait for any more data) 34 | dump_radio_status_to_serialport(radio.radioState()); // Should report IDLE 35 | delay(1000); 36 | 37 | Serial.print("Sending packet: "); 38 | Serial.println(str_off); 39 | radio.print(str_off); 40 | radio.flush(); // 41 | dump_radio_status_to_serialport(radio.radioState()); // Should report IDLE 42 | delay(1000); 43 | } 44 | 45 | void dump_radio_status_to_serialport(uint8_t status) 46 | { 47 | Serial.print("Enrf24 radio transceiver status: "); 48 | switch (status) { 49 | case ENRF24_STATE_NOTPRESENT: 50 | Serial.println("NO TRANSCEIVER PRESENT"); 51 | break; 52 | 53 | case ENRF24_STATE_DEEPSLEEP: 54 | Serial.println("DEEP SLEEP <1uA power consumption"); 55 | break; 56 | 57 | case ENRF24_STATE_IDLE: 58 | Serial.println("IDLE module powered up w/ oscillators running"); 59 | break; 60 | 61 | case ENRF24_STATE_PTX: 62 | Serial.println("Actively Transmitting"); 63 | break; 64 | 65 | case ENRF24_STATE_PRX: 66 | Serial.println("Receive Mode"); 67 | break; 68 | 69 | default: 70 | Serial.println("UNKNOWN STATUS CODE"); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /examples/Enrf24_ChannelScan/Enrf24_ChannelScan.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | Enrf24 radio(P2_0, P2_1, P2_2); // CE, CSN, IRQ pins 6 | 7 | void setup() 8 | { 9 | Serial.begin(9600); // Serial port used to display scan results 10 | SPI.begin(); 11 | SPI.setDataMode(SPI_MODE0); 12 | SPI.setBitOrder(MSBFIRST); 13 | 14 | radio.begin(); // Default 1Mbps, put 250000 or 2000000 to test those bitrates 15 | radio.enableRX(); // Wake up the transceiver 16 | } 17 | 18 | void loop() 19 | { 20 | int16_t i, j; 21 | uint8_t strength, chan=0, dumpbuf[33]; 22 | 23 | Serial.println("nRF24L01+ Channel Activity Scan"); 24 | Serial.println("-------------------------------"); 25 | 26 | // Sample channels 0 through 125. 27 | for (chan=0; chan < 126; chan++) { 28 | // Force RX off, change channel & force back on. 29 | radio.disableRX(); 30 | radio.setChannel(chan); 31 | radio.enableRX(); 32 | delay(1); // Strawman delay to make sure the RF engine is fully spun-up on the new channel 33 | 34 | /* Sample the RPD register (Receive Power Detect, >= -64dBm signal detected) 35 | * 256 times, once every 4 milliseconds, incrementing the 'strength' variable each 36 | * time it's detected. This will be used to produce a relative estimate of how 37 | * strong the ambient noise/crosstalk is on this channel. 38 | */ 39 | strength = 0; 40 | for (i=0; i<256; i++) { 41 | if (radio.rfSignalDetected()) 42 | strength++; 43 | delay(4); 44 | } 45 | 46 | /* Discover the highest bit set in our 'strength' variable; that will 47 | * be the size of the bargraph we'll show for this channel. 48 | */ 49 | j = 0; 50 | for (i=7; i >= 0; i--) { 51 | if (strength & (1 << i)) { 52 | j = i+1; 53 | break; 54 | } 55 | } 56 | 57 | /* Each channel represents a 1MHz bandwidth starting at 2400MHz, e.g. 58 | * channel 125 is 2525MHz, channel 64 is 2464MHz. 59 | */ 60 | Serial.print("Channel "); Serial.print(chan); 61 | Serial.print(" ("); Serial.print(2400+chan); Serial.print("MHz): "); 62 | for (i=0; i < j; i++) { 63 | Serial.print("*"); 64 | } 65 | Serial.println(" "); 66 | 67 | if (radio.available()) { /* Just in case some data got inadvertently received while 68 | * we were doing our scan, clear it out. 69 | */ 70 | radio.read(dumpbuf); 71 | } 72 | } // Loop to the next channel... 73 | 74 | Serial.println("Channel scan done; halting CPU. Hit RESET to do another scan."); 75 | Serial.flush(); 76 | radio.deepsleep(); 77 | while(1) ; // Permanently halt the CPU. Using while(1) is more portable e.g. to Stellaris LP. 78 | } 79 | 80 | -------------------------------------------------------------------------------- /examples/Enrf24_RXdemo/Enrf24_RXdemo.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | Enrf24 radio(P2_0, P2_1, P2_2); 7 | const uint8_t rxaddr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x01 }; 8 | 9 | const char *str_on = "ON"; 10 | const char *str_off = "OFF"; 11 | 12 | void dump_radio_status_to_serialport(uint8_t); 13 | 14 | void setup() { 15 | Serial.begin(9600); 16 | 17 | SPI.begin(); 18 | SPI.setDataMode(SPI_MODE0); 19 | SPI.setBitOrder(MSBFIRST); 20 | 21 | radio.begin(); // Defaults 1Mbps, channel 0, max TX power 22 | dump_radio_status_to_serialport(radio.radioState()); 23 | 24 | radio.setRXaddress((void*)rxaddr); 25 | 26 | pinMode(P1_0, OUTPUT); 27 | digitalWrite(P1_0, LOW); 28 | 29 | radio.enableRX(); // Start listening 30 | } 31 | 32 | void loop() { 33 | char inbuf[33]; 34 | 35 | dump_radio_status_to_serialport(radio.radioState()); // Should show Receive Mode 36 | 37 | while (!radio.available(true)) 38 | ; 39 | if (radio.read(inbuf)) { 40 | Serial.print("Received packet: "); 41 | Serial.println(inbuf); 42 | 43 | if (!strcmp(inbuf, str_on)) 44 | digitalWrite(P1_0, HIGH); 45 | if (!strcmp(inbuf, str_off)) 46 | digitalWrite(P1_0, LOW); 47 | } 48 | } 49 | 50 | void dump_radio_status_to_serialport(uint8_t status) 51 | { 52 | Serial.print("Enrf24 radio transceiver status: "); 53 | switch (status) { 54 | case ENRF24_STATE_NOTPRESENT: 55 | Serial.println("NO TRANSCEIVER PRESENT"); 56 | break; 57 | 58 | case ENRF24_STATE_DEEPSLEEP: 59 | Serial.println("DEEP SLEEP <1uA power consumption"); 60 | break; 61 | 62 | case ENRF24_STATE_IDLE: 63 | Serial.println("IDLE module powered up w/ oscillators running"); 64 | break; 65 | 66 | case ENRF24_STATE_PTX: 67 | Serial.println("Actively Transmitting"); 68 | break; 69 | 70 | case ENRF24_STATE_PRX: 71 | Serial.println("Receive Mode"); 72 | break; 73 | 74 | default: 75 | Serial.println("UNKNOWN STATUS CODE"); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /examples/Enrf24_TXdemo/Enrf24_TXdemo.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | Enrf24 radio(P2_0, P2_1, P2_2); // P2.0=CE, P2.1=CSN, P2.2=IRQ 7 | const uint8_t txaddr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x01 }; 8 | 9 | const char *str_on = "ON"; 10 | const char *str_off = "OFF"; 11 | 12 | void dump_radio_status_to_serialport(uint8_t); 13 | 14 | void setup() { 15 | Serial.begin(9600); 16 | 17 | SPI.begin(); 18 | SPI.setDataMode(SPI_MODE0); 19 | SPI.setBitOrder(MSBFIRST); 20 | 21 | radio.begin(); // Defaults 1Mbps, channel 0, max TX power 22 | dump_radio_status_to_serialport(radio.radioState()); 23 | 24 | radio.setTXaddress((void*)txaddr); 25 | } 26 | 27 | void loop() { 28 | Serial.print("Sending packet: "); 29 | Serial.println(str_on); 30 | radio.print(str_on); 31 | radio.flush(); // Force transmit (don't wait for any more data) 32 | dump_radio_status_to_serialport(radio.radioState()); // Should report IDLE 33 | delay(1000); 34 | 35 | Serial.print("Sending packet: "); 36 | Serial.println(str_off); 37 | radio.print(str_off); 38 | radio.flush(); // 39 | dump_radio_status_to_serialport(radio.radioState()); // Should report IDLE 40 | delay(1000); 41 | } 42 | 43 | void dump_radio_status_to_serialport(uint8_t status) 44 | { 45 | Serial.print("Enrf24 radio transceiver status: "); 46 | switch (status) { 47 | case ENRF24_STATE_NOTPRESENT: 48 | Serial.println("NO TRANSCEIVER PRESENT"); 49 | break; 50 | 51 | case ENRF24_STATE_DEEPSLEEP: 52 | Serial.println("DEEP SLEEP <1uA power consumption"); 53 | break; 54 | 55 | case ENRF24_STATE_IDLE: 56 | Serial.println("IDLE module powered up w/ oscillators running"); 57 | break; 58 | 59 | case ENRF24_STATE_PTX: 60 | Serial.println("Actively Transmitting"); 61 | break; 62 | 63 | case ENRF24_STATE_PRX: 64 | Serial.println("Receive Mode"); 65 | break; 66 | 67 | default: 68 | Serial.println("UNKNOWN STATUS CODE"); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | # Syntax coloring map for Enrf24 2 | 3 | # Datatypes (KEYWORD1) 4 | Enrf24 KEYWORD1 5 | 6 | # Methods and Functions (KEYWORD2) 7 | read KEYWORD2 8 | flush KEYWORD2 9 | purge KEYWORD2 10 | radioStatus KEYWORD2 11 | deepsleep KEYWORD2 12 | enableRX KEYWORD2 13 | disableRX KEYWORD2 14 | autoAck KEYWORD2 15 | setChannel KEYWORD2 16 | setTXpower KEYWORD2 17 | setSpeed KEYWORD2 18 | setCRC KEYWORD2 19 | setAutoAckParams KEYWORD2 20 | setAddressLength KEYWORD2 21 | setRXaddress KEYWORD2 22 | setTXaddress KEYWORD2 23 | rfSignalDetected KEYWORD2 24 | 25 | 26 | # Setup and loop functions (KEYWORD3) 27 | begin KEYWORD3 28 | end KEYWORD3 29 | available KEYWORD3 30 | 31 | # Constants (LITERAL1) 32 | ENRF24_STATE_NOTPRESENT LITERAL1 33 | ENRF24_STATE_DEEPSLEEP LITERAL1 34 | ENRF24_STATE_IDLE LITERAL1 35 | ENRF24_STATE_PTX LITERAL1 36 | ENRF24_STATE_PRX LITERAL1 37 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nRF24", 3 | "keywords": "rf, radio, wireless, spi", 4 | "description": "The nRF24L01 is a low-cost 2.4GHz ISM transceiver module. It supports a number of channel frequencies in the 2.4GHz band and a range of data rates.", 5 | "repository": 6 | { 7 | "type": "git", 8 | "url": "https://github.com/spirilis/Enrf24.git" 9 | }, 10 | "frameworks": "energia", 11 | "platforms": "timsp430" 12 | } 13 | -------------------------------------------------------------------------------- /nRF24L01.h: -------------------------------------------------------------------------------- 1 | /* nRF24L01.h 2 | * Register definitions for manipulating the Nordic Semiconductor 3 | * nRF24L01+ RF transceiver chipsets. 4 | * 5 | 6 | Copyright (c) 2007 Stefan Engelke 7 | Some parts copyright (c) 2012 Eric Brundick 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, copy, 13 | modify, merge, publish, distribute, sublicense, and/or sell copies 14 | of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be 18 | included in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27 | DEALINGS IN THE SOFTWARE. 28 | */ 29 | #ifndef _NRF24L01_H 30 | #define _NRF24L01_H 31 | 32 | /* Register Map */ 33 | #define RF24_CONFIG 0x00 34 | #define RF24_EN_AA 0x01 35 | #define RF24_EN_RXADDR 0x02 36 | #define RF24_SETUP_AW 0x03 37 | #define RF24_SETUP_RETR 0x04 38 | #define RF24_RF_CH 0x05 39 | #define RF24_RF_SETUP 0x06 40 | #define RF24_STATUS 0x07 41 | #define RF24_OBSERVE_TX 0x08 42 | #define RF24_CD 0x09 43 | #define RF24_RPD 0x09 44 | #define RF24_RX_ADDR_P0 0x0A 45 | #define RF24_RX_ADDR_P1 0x0B 46 | #define RF24_RX_ADDR_P2 0x0C 47 | #define RF24_RX_ADDR_P3 0x0D 48 | #define RF24_RX_ADDR_P4 0x0E 49 | #define RF24_RX_ADDR_P5 0x0F 50 | #define RF24_TX_ADDR 0x10 51 | #define RF24_RX_PW_P0 0x11 52 | #define RF24_RX_PW_P1 0x12 53 | #define RF24_RX_PW_P2 0x13 54 | #define RF24_RX_PW_P3 0x14 55 | #define RF24_RX_PW_P4 0x15 56 | #define RF24_RX_PW_P5 0x16 57 | #define RF24_FIFO_STATUS 0x17 58 | #define RF24_DYNPD 0x1C 59 | #define RF24_FEATURE 0x1D 60 | 61 | /* Register Bits */ 62 | #define RF24_MASK_RX_DR BIT6 63 | #define RF24_MASK_TX_DS BIT5 64 | #define RF24_MASK_MAX_RT BIT4 65 | #define RF24_EN_CRC BIT3 66 | #define RF24_CRCO BIT2 67 | #define RF24_PWR_UP BIT1 68 | #define RF24_PRIM_RX BIT0 69 | #define RF24_ENAA_P5 BIT5 70 | #define RF24_ENAA_P4 BIT4 71 | #define RF24_ENAA_P3 BIT3 72 | #define RF24_ENAA_P2 BIT2 73 | #define RF24_ENAA_P1 BIT1 74 | #define RF24_ENAA_P0 BIT0 75 | #define RF24_ERX_P5 BIT5 76 | #define RF24_ERX_P4 BIT4 77 | #define RF24_ERX_P3 BIT3 78 | #define RF24_ERX_P2 BIT2 79 | #define RF24_ERX_P1 BIT1 80 | #define RF24_ERX_P0 BIT0 81 | #define RF24_AW BIT0 82 | #define RF24_ARD BIT4 83 | #define RF24_ARC BIT0 84 | #define RF24_PLL_LOCK BIT4 85 | #define RF24_CONT_WAVE BIT7 86 | #define RF24_RF_DR BIT3 87 | #define RF24_RF_DR_LOW BIT5 88 | #define RF24_RF_DR_HIGH BIT3 89 | #define RF24_RF_PWR BIT1 90 | #define RF24_LNA_HCURR BIT0 91 | #define RF24_RX_DR BIT6 92 | #define RF24_TX_DS BIT5 93 | #define RF24_MAX_RT BIT4 94 | #define RF24_RX_P_NO BIT1 95 | #define RF24_TX_FULL BIT0 96 | #define RF24_PLOS_CNT BIT4 97 | #define RF24_ARC_CNT BIT0 98 | #define RF24_TX_REUSE BIT6 99 | #define RF24_FIFO_FULL BIT5 100 | #define RF24_TX_EMPTY BIT4 101 | #define RF24_RX_FULL BIT1 102 | #define RF24_RX_EMPTY BIT0 103 | #define RF24_EN_DPL BIT2 104 | #define RF24_EN_ACK_PAY BIT1 105 | #define RF24_EN_DYN_ACK BIT0 106 | 107 | /* Instructions */ 108 | #define RF24_R_REGISTER 0x00 109 | #define RF24_W_REGISTER 0x20 110 | #define RF24_REGISTER_MASK 0x1F 111 | #define RF24_R_RX_PAYLOAD 0x61 112 | #define RF24_W_TX_PAYLOAD 0xA0 113 | #define RF24_FLUSH_TX 0xE1 114 | #define RF24_FLUSH_RX 0xE2 115 | #define RF24_REUSE_TX_PL 0xE3 116 | #define RF24_R_RX_PL_WID 0x60 117 | #define RF24_W_ACK_PAYLOAD 0xA8 118 | #define RF24_W_TX_PAYLOAD_NOACK 0xB0 119 | #define RF24_NOP 0xFF 120 | #define RF24_ACTIVATE 0x50 121 | 122 | #endif 123 | --------------------------------------------------------------------------------