void Radio::reUseTX() { // Clear max retry flag. write_register(STATUS, _BV(MAX_RT)); csnLow(); HalfDuplexSPI::byte(REUSE_TX_PL); csnHigh(); }
byte nRF24L01p::payLoadWidth(){ csnLow(); SPI.transfer(R_RX_PL_WID); byte _width=SPI.transfer(0x00); csnHigh(); return _width; }
byte nRF24L01p::readReg(byte _reg){ csnLow(); _status=SPI.transfer(_reg & REGISTERS); byte _byteRead=SPI.transfer(0x00); csnHigh(); return _byteRead; }
void nRF24L01p::writeReg(byte _reg, char* _data, byte _numBytes){ csnLow(); _status=SPI.transfer(W_REGISTER | (_reg & REGISTERS)); for(byte it=0; it<_numBytes; it++){ SPI.transfer(_data[it]); } csnHigh(); }
uint8_t Radio::get_status(void) { csnLow(); uint8_t status = HalfDuplexSPI::byte(NOP); csnHigh(); return status; }
uint8_t Radio::flush_tx(void) { csnLow(); uint8_t status = HalfDuplexSPI::byte(FLUSH_TX); csnHigh(); return status; }
uint8_t Radio::write_register(uint8_t reg, uint8_t value) { csnLow(); uint8_t status = HalfDuplexSPI::byte(W_REGISTER | (REGISTER_MASK & reg)); HalfDuplexSPI::byte(value); csnHigh(); return status; }
uint8_t Radio::read_register(uint8_t reg) { csnLow(); HalfDuplexSPI::byte(R_REGISTER | (REGISTER_MASK & reg)); uint8_t result = HalfDuplexSPI::byte(0xff); csnHigh(); return result; }
uint8_t Radio::write_register(uint8_t reg, const uint8_t *buf, uint8_t len) { csnLow(); uint8_t status = HalfDuplexSPI::byte(W_REGISTER | (REGISTER_MASK & reg)); while (len--) { HalfDuplexSPI::byte(*buf++); } csnHigh(); return status; }
nRF24L01p::nRF24L01p(const byte csn,const byte ce): _csn(csn),_ce(ce){ pinMode(_csn,OUTPUT); pinMode(_ce,OUTPUT); csnHigh(); ceLow(); _txIndex=0; _rxIndex=0; _prim_rx=false; _prim_tx=false; _init=false; }
uint8_t Radio::read_register(uint8_t reg, uint8_t *buf, uint8_t len) { csnLow(); uint8_t status = HalfDuplexSPI::byte(R_REGISTER | (REGISTER_MASK & reg)); while (len--) { *buf++ = HalfDuplexSPI::byte(0xff); } csnHigh(); return status; }
bool Radio::setup(void) { HalfDuplexSPI::setup(); csnHigh(); // Must allow the radio time to settle else configuration bits will not necessarily stick. // This is actually only required following power up but some settling time also appears to // be required after resets too. For full coverage, we'll always assume the worst. // Enabling 16b CRC is by far the most obvious case if the wrong timing is used - or skipped. // Technically we require 4.5ms + 14us as a worst case. We'll just call it 5ms for good measure. // WARNING: Delay is based on P-variant whereby non-P *may* require different timing. _delay_ms(5); // Reset CONFIG and enable 16-bit CRC. write_register(CONFIG, 0 | _BV(EN_CRC) | _BV(CRCO)); // Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier // WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet // sizes must never be used. See documentation for a more complete explanation. setRetries(5, 15); uint8_t setup = read_register(RF_SETUP); // Then set the data rate to the slowest (and most reliable) speed supported by all // hardware. setDataRate(DataRate::RATE_1MBPS); write_register(FEATURE, 0); write_register(DYNPD, 0); // Reset current status // Notice reset and flush is the last thing we do write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT)); setChannel(76); // Flush buffers flush_rx(); flush_tx(); //Power up by default when setup() is called. powerUp(); // 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 ) PTX should use only 22uA of power. write_register(CONFIG, (read_register(CONFIG)) & ~_BV(PRIM_RX)); // If setup is 0 or ff then there was no response from module. return setup != 0 && setup != 0xff; }
boolean nRF24L01p::send(boolean _modeSend){ if(_prim_tx==false){ _txIndex=32; return false; } if(_prim_rx==true){ ceLow(); primPTX(); } csnLow(); if(_modeSend==false || (_prim_rx && _prim_tx)){ SPI.transfer(W_TX_PAYLOAD); }else{ SPI.transfer(W_TX_PAYLOAD_NOACK); } for(int i=0;i<_txIndex;i++){ SPI.transfer(_txPayLoad[i]); } csnHigh(); cePulse(); unsigned long tmC1=micros(); while(1){ if(bitRead(getStatus(),5)){ //writeReg(STATUS,_status|(1<<6)); writeReg(STATUS,_status|(1<<5)); writeReg(STATUS,_status|(1<<4)); break; } if(bitRead(getStatus(),4)){ writeReg(STATUS,_status|(1<<4)); cePulse(); } unsigned long tmC2=micros(); if(tmC2-tmC1>100L){ //was 250000L - lowered to make the timeout wait much shorter //Serial.println("send(SLOW) returned false"); //Serial.println("connection lost "); return false; } } _txIndex=0; if(_prim_rx==true){ primPRX(); ceHigh(); } return true; }
boolean nRF24L01p::read(){ if(_prim_rx==false){ _rxIndex=32; return false; } _rxIndex=0; for(int it=0;it<32;it++){ _rxPayLoad[it]=0; } byte _plw=payLoadWidth(); csnLow(); SPI.transfer(R_RX_PAYLOAD); for(int it=0;it<_plw;it++){ _rxPayLoad[it]=SPI.transfer(0x00); } csnHigh(); writeReg(STATUS,1<<6); return true; }
uint8_t Radio::write_payload(const void *buf, uint8_t data_len, const uint8_t writeType) { const uint8_t *current = reinterpret_cast<const uint8_t *>(buf); data_len = data_len < PAYLOAD_SIZE ? data_len : PAYLOAD_SIZE; uint8_t blank_len = PAYLOAD_SIZE - data_len; csnLow(); uint8_t status = HalfDuplexSPI::byte(writeType); while (data_len--) { HalfDuplexSPI::byte(*current++); } while (blank_len--) { HalfDuplexSPI::byte(0); } csnHigh(); return status; }
uint8_t Radio::read_payload(void *buf, uint8_t data_len) { uint8_t *current = reinterpret_cast<uint8_t *>(buf); data_len = data_len > PAYLOAD_SIZE ? PAYLOAD_SIZE : data_len; uint8_t blank_len = PAYLOAD_SIZE - data_len; csnLow(); uint8_t status = HalfDuplexSPI::byte(R_RX_PAYLOAD); while (data_len--) { *current++ = HalfDuplexSPI::byte(0xFF); } while (blank_len--) { HalfDuplexSPI::byte(0xff); } csnHigh(); return status; }
void nRF24L01p::writeReg(byte _reg, byte _data){ csnLow(); _status=SPI.transfer(W_REGISTER | (_reg & REGISTERS)); SPI.transfer(_data); csnHigh(); }
void nRF24L01p::flushTX(){ csnLow(); SPI.transfer(FLUSH_TX); csnHigh(); }