void nrf24l01p::rxMode() { setCeLow(); writeRegister(CONFIG, _BV(EN_CRC) | _BV(CRCO)); // Enable CRC (2bytes) delayMicroseconds(100); writeRegister(EN_AA, 0x00); // Disable auto acknowledgment writeRegister(EN_RXADDR, 0x01); // Enable first data pipe writeRegister(SETUP_AW, 0x03); // 5 bytes address writeRegister(SETUP_RETR, 0xFF); // 15 retransmit, 4000us pause writeRegister(RF_CH, 0x00); // channel 8 setBitrate(NRF24L01_BR_250K); setPower(mPower); writeRegister(STATUS, 0x70); // Clear status register writeRegister(RX_PW_P0, 0x0A); // RX payload of 10 bytes writeRegister(FIFO_STATUS, 0x00); // Nothing useful for write command delay(50); flushTx(); flushRx(); delayMicroseconds(100); writeRegister(CONFIG, _BV(EN_CRC) | _BV(CRCO) | _BV(PWR_UP) ); delayMicroseconds(100); writeRegister(CONFIG, _BV(EN_CRC) | _BV(CRCO) | _BV(PWR_UP) | _BV(PRIM_RX) ); delayMicroseconds(130); setCeHigh(); delayMicroseconds(100); }
void Nrf24l::send(uint8_t * value) // Sends a data package to the default address. Be sure to send the correct // amount of bytes as configured as payload on the receiver. { uint8_t status; status = getStatus(); while (PTX) { status = getStatus(); if((status & ((1 << TX_DS) | (1 << MAX_RT)))){ PTX = 0; break; } } // Wait until last paket is send ceLow(); powerUpTx(); // Set to transmitter mode , Power up flushTx(); nrfSpiWrite(W_TX_PAYLOAD, value, false, payload); // Write payload ceHi(); // Start transmission ceLow(); }
void Nrf24l::powerDown(){ ceLow(); configRegister(CONFIG, baseConfig); flushRx(); flushTx(); }
int nRF24L01::reset() { flushTx(); flushRx(); uint8_t status1 = strobe(NRF24L01_FF_NOP); uint8_t status2 = readReg(NRF24L01_07_STATUS); setTxRxMode(TXRX_OFF); #ifdef EMULATOR return 1; #endif return (status1 == status2 && (status1 & 0x0f) == 0x0e); }
void QRF24::startListening() { writeRegister(CONFIG, readRegister(CONFIG) | _BV(PWR_UP) | _BV(PRIM_RX)); writeRegister(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); // Restore the pipe0 adddress, if exists if (pipe0_reading_address) writeRegister(RX_ADDR_P0, reinterpret_cast<const quint8*>(&pipe0_reading_address), 5); // Flush buffers flushRx(); flushTx(); // Go! bcm2835_gpio_write(ce_pin, HIGH); // wait for the radio to come up (130us actually only needed) delayMicroseconds(130); }
void Radio_TxInit() { SPI_MasterInit(); DDRB|=(1<<CSN)|(1<<CE); PORTB|=(1<<IRQ)|(1<<CSN); delay_ms(5); //settling time specified in the data sheet unsigned char oneByte[1]={0x72}; unsigned char threeByte[3]={0x18, 0x04, 0x96}; writeRegister(0x00, oneByte, 1); //set config reg to power up into tx mode oneByte[0]=0x01; writeRegister(0x03, oneByte, 1); //set address length to 3 bytes writeRegister(0x10, threeByte, 3); //set address of transmit to random number, in this case my birthday oneByte[0]=76; writeRegister(0x05, oneByte, 1); //set to channel 76 oneByte[0]=0x00; writeRegister(0x01, oneByte, 1); //turn off Auto Acknowledge, one way communication okay if a few packets get dropped writeRegister(0x04, oneByte, 1); //turn off retransmit, not ideal for remote control oneByte[0]=0x01; writeRegister(0x1D, oneByte, 1); //enable W_TX_PAYLOAD_NOACK flushTx(); PORTB|=(1<<CE); }
void NRF::SE8R01::configure(Configuration* config) { NRF::SE8R01::Config configOff = { 0 }; configOff.b.maskDataReceived = true; configOff.b.maskDataSent = true; configOff.b.maskMaxRetrans = true; writeReg(Reg_Config, &configOff, sizeof(configOff)); flushTx(); Status status = flushRx(); writeReg(Reg_Status, &status, sizeof(status)); writeReg(Reg_FeatureCtl, &config->featureCtl, sizeof(config->featureCtl)); writeReg(Reg_AutoAckCtl, &config->autoAckCtl, sizeof(config->autoAckCtl)); writeReg(Reg_RxPipeEnable, &config->rxPipeEnable, sizeof(config->rxPipeEnable)); writeReg(Reg_AddressCtl, &config->addressCtl, sizeof(config->addressCtl)); writeReg(Reg_RetransCtl, &config->retransCtl, sizeof(config->retransCtl)); writeReg(Reg_RfChannel, &config->rfChannel, sizeof(config->rfChannel)); writeReg(Reg_RfSetup, &config->rfSetup, sizeof(config->rfSetup)); writeReg(Reg_DynLengthCtl, &config->dynLengthCtl, sizeof(config->dynLengthCtl)); writeReg(Reg_Tuning, &config->tuning, sizeof(config->tuning)); writeReg(Reg_GuardCtl, &config->guardCtl, sizeof(config->guardCtl)); writeReg(Reg_Config, &config->config, sizeof(config->config)); }
bool QRF24::write( const void* buf, quint8 len ) { bool result = false; // Begin the write startWrite(buf,len); // ------------ // At this point we could return from a non-blocking write, and then call // the rest after an interrupt // Instead, we are going to block here until we get TX_DS (transmission completed and ack'd) // or MAX_RT (maximum retries, transmission failed). Also, we'll timeout in case the radio // is flaky and we get neither. // IN the end, the send should be blocking. It comes back in 60ms worst case, or much faster // if I tighted up the retry logic. (Default settings will be 1500us. // Monitor the send quint8 observe_tx; quint8 status; uint32_t sent_at = millis(); const unsigned long timeout = 500; //ms to wait for timeout do { status = readRegister(OBSERVE_TX,&observe_tx,1); if (debug) printf("%02X", observe_tx); } while( ! ( status & ( _BV(TX_DS) | _BV(MAX_RT) ) ) && ( millis() - sent_at < timeout ) ); // The part above is what you could recreate with your own interrupt handler, // and then call this when you got an interrupt // ------------ // Call this when you get an interrupt // The status tells us three things // * The send was successful (TX_DS) // * The send failed, too many retries (MAX_RT) // * There is an ack packet waiting (RX_DR) bool tx_ok, tx_fail; whatHappened(tx_ok,tx_fail,ack_payload_available); //printf("%u%u%u\r\n",tx_ok,tx_fail,ack_payload_available); result = tx_ok; if (debug) printf(result?"...OK.":"...Failed"); // Handle the ack packet if ( ack_payload_available ) { ack_payload_length = getDynamicPayloadSize(); if (debug ) printf("[AckPacket]/%d", ack_payload_length); } // Yay, we are done. // Power down powerDown(); // Flush buffers (Is this a relic of past experimentation, and not needed anymore??) flushTx(); return result; }
void QRF24::stopListening() { bcm2835_gpio_write(ce_pin, LOW); flushTx(); flushRx(); }
bool QRF24::begin() { debug = true; // Init BCM2835 chipset for talking with us if (!bcm2835_init()) return false; // Initialise the CE pin of NRF24 (chip enable) bcm2835_gpio_fsel(ce_pin, BCM2835_GPIO_FSEL_OUTP); bcm2835_gpio_write(ce_pin, LOW); // used to drive custom I/O to trigger my logic analyser // bcm2835_gpio_fsel(GPIO_CTRL_PIN , BCM2835_GPIO_FSEL_OUTP); // start the SPI library: // Note the NRF24 wants mode 0, MSB first and default to 1 Mbps bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); bcm2835_spi_setDataMode(BCM2835_SPI_MODE0); // Set SPI bus Speed bcm2835_spi_setClockSpeed(spi_speed); // This initialize the SPI bus with // csn pin as chip select (custom or not) bcm2835_spi_begin(csn_pin); // wait 100ms delay(100); // 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( 5 ) ; // 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. //printf("write_register(%02X, %02X)\n", SETUP_RETR, (0b0100 << ARD) | (0b1111 << ARC)); writeRegister(SETUP_RETR,(0b0100 << ARD) | (0b1111 << ARC)); // Restore our default PA level setPALevel( RF24_PA_MAX ) ; // Determine if this is a p or non-p RF24 module and then // reset our data rate back to default value. This works // because a non-P variant won't allow the data rate to // be set to 250Kbps. if( setDataRate( RF24_250KBPS ) ) { p_variant = true ; } // Then set the data rate to the slowest (and most reliable) speed supported by all // hardware. setDataRate( RF24_1MBPS ) ; // Initialize CRC and request 2-byte (16bit) CRC setCRCLength( RF24_CRC_16 ) ; // Disable dynamic payloads, to match dynamic_payloads_enabled setting writeRegister(DYNPD,0); // Reset current status // Notice reset and flush is the last thing we do writeRegister(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); // Set up default configuration. Callers can always change it later. // This channel should be universally safe and not bleed over into adjacent // spectrum. setChannel(76); // Flush buffers flushRx(); flushTx(); return true; }