Merge branch 'master' into development
Conflicts: libraries/UIPEthernet/utility/uipethernet-conf.h
This commit is contained in:
@@ -19,15 +19,30 @@ void RF24::csn(bool mode)
|
||||
// divider of 4 is the minimum we want.
|
||||
// CLK:BUS 8Mhz:2Mhz, 16Mhz:4Mhz, or 20Mhz:5Mhz
|
||||
#ifdef ARDUINO
|
||||
#if !defined( __AVR_ATtiny85__ ) && !defined( __AVR_ATtiny84__) && !defined (__arm__)
|
||||
SPI.setBitOrder(MSBFIRST);
|
||||
SPI.setDataMode(SPI_MODE0);
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV2);
|
||||
#if ( !defined(RF24_TINY) && !defined (__arm__) && !defined (SOFTSPI)) || defined (CORE_TEENSY)
|
||||
_SPI.setBitOrder(MSBFIRST);
|
||||
_SPI.setDataMode(SPI_MODE0);
|
||||
_SPI.setClockDivider(SPI_CLOCK_DIV2);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __arm__
|
||||
digitalWrite(csn_pin,mode);
|
||||
|
||||
#if defined (RF24_TINY)
|
||||
if (ce_pin != csn_pin) {
|
||||
digitalWrite(csn_pin,mode);
|
||||
}
|
||||
else {
|
||||
if (mode == HIGH) {
|
||||
PORTB |= (1<<PINB2); // SCK->CSN HIGH
|
||||
delayMicroseconds(100); // allow csn to settle.
|
||||
}
|
||||
else {
|
||||
PORTB &= ~(1<<PINB2); // SCK->CSN LOW
|
||||
delayMicroseconds(11); // allow csn to settle
|
||||
}
|
||||
}
|
||||
#else if !defined (__arm__) || defined (CORE_TEENSY)
|
||||
digitalWrite(csn_pin,mode);
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -36,7 +51,8 @@ void RF24::csn(bool mode)
|
||||
|
||||
void RF24::ce(bool level)
|
||||
{
|
||||
digitalWrite(ce_pin,level);
|
||||
//Allow for 3-pin use on ATTiny
|
||||
if (ce_pin != csn_pin) digitalWrite(ce_pin,level);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -45,18 +61,18 @@ uint8_t RF24::read_register(uint8_t reg, uint8_t* buf, uint8_t len)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
#if defined (__arm__)
|
||||
status = SPI.transfer(csn_pin, R_REGISTER | ( REGISTER_MASK & reg ), SPI_CONTINUE );
|
||||
#if defined (__arm__) && !defined ( CORE_TEENSY )
|
||||
status = _SPI.transfer(csn_pin, R_REGISTER | ( REGISTER_MASK & reg ), SPI_CONTINUE );
|
||||
while ( len-- > 1 ){
|
||||
*buf++ = SPI.transfer(csn_pin,0xff, SPI_CONTINUE);
|
||||
*buf++ = _SPI.transfer(csn_pin,0xff, SPI_CONTINUE);
|
||||
}
|
||||
*buf++ = SPI.transfer(csn_pin,0xff);
|
||||
*buf++ = _SPI.transfer(csn_pin,0xff);
|
||||
|
||||
#else
|
||||
csn(LOW);
|
||||
status = SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) );
|
||||
status = _SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) );
|
||||
while ( len-- ){
|
||||
*buf++ = SPI.transfer(0xff);
|
||||
*buf++ = _SPI.transfer(0xff);
|
||||
}
|
||||
csn(HIGH);
|
||||
|
||||
@@ -70,13 +86,13 @@ uint8_t RF24::read_register(uint8_t reg, uint8_t* buf, uint8_t len)
|
||||
uint8_t RF24::read_register(uint8_t reg)
|
||||
{
|
||||
|
||||
#if defined (__arm__)
|
||||
SPI.transfer(csn_pin, R_REGISTER | ( REGISTER_MASK & reg ) , SPI_CONTINUE);
|
||||
uint8_t result = SPI.transfer(csn_pin,0xff);
|
||||
#if defined (__arm__) && !defined ( CORE_TEENSY )
|
||||
_SPI.transfer(csn_pin, R_REGISTER | ( REGISTER_MASK & reg ) , SPI_CONTINUE);
|
||||
uint8_t result = _SPI.transfer(csn_pin,0xff);
|
||||
#else
|
||||
csn(LOW);
|
||||
SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) );
|
||||
uint8_t result = SPI.transfer(0xff);
|
||||
_SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) );
|
||||
uint8_t result = _SPI.transfer(0xff);
|
||||
|
||||
csn(HIGH);
|
||||
#endif
|
||||
@@ -90,18 +106,18 @@ uint8_t RF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
#if defined (__arm__)
|
||||
status = SPI.transfer(csn_pin, W_REGISTER | ( REGISTER_MASK & reg ), SPI_CONTINUE );
|
||||
while ( len-- > 1){
|
||||
SPI.transfer(csn_pin,*buf++, SPI_CONTINUE);
|
||||
#if defined (__arm__) && !defined ( CORE_TEENSY )
|
||||
status = _SPI.transfer(csn_pin, W_REGISTER | ( REGISTER_MASK & reg ), SPI_CONTINUE );
|
||||
while ( --len){
|
||||
_SPI.transfer(csn_pin,*buf++, SPI_CONTINUE);
|
||||
}
|
||||
SPI.transfer(csn_pin,*buf++);
|
||||
_SPI.transfer(csn_pin,*buf++);
|
||||
#else
|
||||
|
||||
csn(LOW);
|
||||
status = SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) );
|
||||
status = _SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) );
|
||||
while ( len-- )
|
||||
SPI.transfer(*buf++);
|
||||
_SPI.transfer(*buf++);
|
||||
|
||||
csn(HIGH);
|
||||
|
||||
@@ -118,14 +134,14 @@ uint8_t RF24::write_register(uint8_t reg, uint8_t value)
|
||||
|
||||
IF_SERIAL_DEBUG(printf_P(PSTR("write_register(%02x,%02x)\r\n"),reg,value));
|
||||
|
||||
#if defined (__arm__)
|
||||
status = SPI.transfer(csn_pin, W_REGISTER | ( REGISTER_MASK & reg ), SPI_CONTINUE);
|
||||
SPI.transfer(csn_pin,value);
|
||||
#if defined (__arm__) && !defined ( CORE_TEENSY )
|
||||
status = _SPI.transfer(csn_pin, W_REGISTER | ( REGISTER_MASK & reg ), SPI_CONTINUE);
|
||||
_SPI.transfer(csn_pin,value);
|
||||
#else
|
||||
|
||||
csn(LOW);
|
||||
status = SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) );
|
||||
SPI.transfer(value);
|
||||
status = _SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) );
|
||||
_SPI.transfer(value);
|
||||
csn(HIGH);
|
||||
|
||||
#endif
|
||||
@@ -140,39 +156,39 @@ uint8_t RF24::write_payload(const void* buf, uint8_t data_len, const uint8_t wri
|
||||
uint8_t status;
|
||||
const uint8_t* current = reinterpret_cast<const uint8_t*>(buf);
|
||||
|
||||
if(data_len > payload_size) data_len = payload_size;
|
||||
uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
|
||||
|
||||
data_len = min(data_len, payload_size);
|
||||
uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
|
||||
|
||||
//printf("[Writing %u bytes %u blanks]",data_len,blank_len);
|
||||
|
||||
#if defined (__arm__)
|
||||
#if defined (__arm__) && !defined ( CORE_TEENSY )
|
||||
|
||||
status = SPI.transfer(csn_pin, writeType , SPI_CONTINUE);
|
||||
status = _SPI.transfer(csn_pin, writeType , SPI_CONTINUE);
|
||||
|
||||
if(blank_len){
|
||||
while ( data_len--){
|
||||
SPI.transfer(csn_pin,*current++, SPI_CONTINUE);
|
||||
_SPI.transfer(csn_pin,*current++, SPI_CONTINUE);
|
||||
}
|
||||
while ( --blank_len ){
|
||||
SPI.transfer(csn_pin,0, SPI_CONTINUE);
|
||||
_SPI.transfer(csn_pin,0, SPI_CONTINUE);
|
||||
}
|
||||
SPI.transfer(csn_pin,0);
|
||||
_SPI.transfer(csn_pin,0);
|
||||
}else{
|
||||
while( --data_len ){
|
||||
SPI.transfer(csn_pin,*current++, SPI_CONTINUE);
|
||||
_SPI.transfer(csn_pin,*current++, SPI_CONTINUE);
|
||||
}
|
||||
SPI.transfer(csn_pin,*current);
|
||||
_SPI.transfer(csn_pin,*current);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
csn(LOW);
|
||||
status = SPI.transfer( writeType );
|
||||
status = _SPI.transfer( writeType );
|
||||
while ( data_len-- ) {
|
||||
SPI.transfer(*current++);
|
||||
_SPI.transfer(*current++);
|
||||
}
|
||||
while ( blank_len-- ) {
|
||||
SPI.transfer(0);
|
||||
_SPI.transfer(0);
|
||||
}
|
||||
csn(HIGH);
|
||||
|
||||
@@ -190,39 +206,39 @@ uint8_t RF24::read_payload(void* buf, uint8_t data_len)
|
||||
|
||||
if(data_len > payload_size) data_len = payload_size;
|
||||
uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
|
||||
|
||||
|
||||
//printf("[Reading %u bytes %u blanks]",data_len,blank_len);
|
||||
|
||||
|
||||
#if defined (__arm__)
|
||||
#if defined (__arm__) && !defined ( CORE_TEENSY )
|
||||
|
||||
status = SPI.transfer(csn_pin, R_RX_PAYLOAD, SPI_CONTINUE );
|
||||
status = _SPI.transfer(csn_pin, R_RX_PAYLOAD, SPI_CONTINUE );
|
||||
|
||||
if( blank_len ){
|
||||
|
||||
while ( data_len-- ){
|
||||
*current++ = SPI.transfer(csn_pin,0xFF, SPI_CONTINUE);
|
||||
*current++ = _SPI.transfer(csn_pin,0xFF, SPI_CONTINUE);
|
||||
}
|
||||
|
||||
while ( --blank_len ){
|
||||
SPI.transfer(csn_pin,0xFF, SPI_CONTINUE);
|
||||
_SPI.transfer(csn_pin,0xFF, SPI_CONTINUE);
|
||||
}
|
||||
SPI.transfer(csn_pin,0xFF);
|
||||
_SPI.transfer(csn_pin,0xFF);
|
||||
}else{
|
||||
while ( --data_len ){
|
||||
*current++ = SPI.transfer(csn_pin,0xFF, SPI_CONTINUE);
|
||||
*current++ = _SPI.transfer(csn_pin,0xFF, SPI_CONTINUE);
|
||||
}
|
||||
*current = SPI.transfer(csn_pin,0xFF);
|
||||
*current = _SPI.transfer(csn_pin,0xFF);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
csn(LOW);
|
||||
status = SPI.transfer( R_RX_PAYLOAD );
|
||||
status = _SPI.transfer( R_RX_PAYLOAD );
|
||||
while ( data_len-- ) {
|
||||
*current++ = SPI.transfer(0xFF);
|
||||
*current++ = _SPI.transfer(0xFF);
|
||||
}
|
||||
while ( blank_len-- ) {
|
||||
SPI.transfer(0xff);
|
||||
_SPI.transfer(0xff);
|
||||
}
|
||||
csn(HIGH);
|
||||
|
||||
@@ -250,12 +266,12 @@ uint8_t RF24::flush_tx(void)
|
||||
uint8_t RF24::spiTrans(uint8_t cmd){
|
||||
|
||||
uint8_t status;
|
||||
#if defined (__arm__)
|
||||
status = SPI.transfer(csn_pin, cmd );
|
||||
#if defined (__arm__) && !defined ( CORE_TEENSY )
|
||||
status = _SPI.transfer(csn_pin, cmd );
|
||||
#else
|
||||
|
||||
csn(LOW);
|
||||
status = SPI.transfer( cmd );
|
||||
status = _SPI.transfer( cmd );
|
||||
csn(HIGH);
|
||||
#endif
|
||||
return status;
|
||||
@@ -271,7 +287,6 @@ uint8_t RF24::get_status(void)
|
||||
|
||||
/****************************************************************************/
|
||||
#if !defined (MINIMAL)
|
||||
|
||||
void RF24::print_status(uint8_t status)
|
||||
{
|
||||
printf_P(PSTR("STATUS\t\t = 0x%02x RX_DR=%x TX_DS=%x MAX_RT=%x RX_P_NO=%x TX_FULL=%x\r\n"),
|
||||
@@ -315,7 +330,7 @@ void RF24::print_address_register(const char* name, uint8_t reg, uint8_t qty)
|
||||
|
||||
while (qty--)
|
||||
{
|
||||
uint8_t buffer[5];
|
||||
uint8_t buffer[addr_width];
|
||||
read_register(reg++,buffer,sizeof buffer);
|
||||
|
||||
printf_P(PSTR(" 0x"));
|
||||
@@ -330,9 +345,8 @@ void RF24::print_address_register(const char* name, uint8_t reg, uint8_t qty)
|
||||
/****************************************************************************/
|
||||
|
||||
RF24::RF24(uint8_t _cepin, uint8_t _cspin):
|
||||
ce_pin(_cepin), csn_pin(_cspin), wide_band(false), p_variant(false),
|
||||
payload_size(32), dynamic_payloads_enabled(false),
|
||||
pipe0_reading_address(0)
|
||||
ce_pin(_cepin), csn_pin(_cspin), p_variant(false),
|
||||
payload_size(32), dynamic_payloads_enabled(false), addr_width(5)//,pipe0_reading_address(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -340,9 +354,6 @@ RF24::RF24(uint8_t _cepin, uint8_t _cspin):
|
||||
|
||||
void RF24::setChannel(uint8_t channel)
|
||||
{
|
||||
// TODO: This method could take advantage of the 'wide_band' calculation
|
||||
// done in setChannel() to require certain channel spacing.
|
||||
|
||||
const uint8_t max_channel = 127;
|
||||
write_register(RF_CH,min(channel,max_channel));
|
||||
}
|
||||
@@ -425,6 +436,7 @@ void RF24::printDetails(void)
|
||||
printf_P(PSTR("CRC Length\t = %S\r\n"),pgm_read_word(&rf24_crclength_e_str_P[getCRCLength()]));
|
||||
printf_P(PSTR("PA Power\t = %S\r\n"),pgm_read_word(&rf24_pa_dbm_e_str_P[getPALevel()]));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -433,18 +445,18 @@ void RF24::printDetails(void)
|
||||
void RF24::begin(void)
|
||||
{
|
||||
// Initialize pins
|
||||
pinMode(ce_pin,OUTPUT);
|
||||
if (ce_pin != csn_pin) pinMode(ce_pin,OUTPUT);
|
||||
|
||||
#if defined(__arm__)
|
||||
SPI.begin(csn_pin); // Using the extended SPI features of the DUE
|
||||
SPI.setClockDivider(csn_pin, 9); // Set the bus speed to 8.4mhz on Due
|
||||
SPI.setBitOrder(csn_pin,MSBFIRST); // Set the bit order and mode specific to this device
|
||||
SPI.setDataMode(csn_pin,SPI_MODE0);
|
||||
#if defined(__arm__) && ! defined( CORE_TEENSY )
|
||||
_SPI.begin(csn_pin); // Using the extended SPI features of the DUE
|
||||
_SPI.setClockDivider(csn_pin, 9); // Set the bus speed to 8.4mhz on Due
|
||||
_SPI.setBitOrder(csn_pin,MSBFIRST); // Set the bit order and mode specific to this device
|
||||
_SPI.setDataMode(csn_pin,SPI_MODE0);
|
||||
ce(LOW);
|
||||
//csn(HIGH);
|
||||
#else
|
||||
pinMode(csn_pin,OUTPUT);
|
||||
SPI.begin();
|
||||
if (ce_pin != csn_pin) pinMode(csn_pin,OUTPUT);
|
||||
_SPI.begin();
|
||||
ce(LOW);
|
||||
csn(HIGH);
|
||||
#endif
|
||||
@@ -503,39 +515,66 @@ void RF24::begin(void)
|
||||
// PTX should use only 22uA of power
|
||||
write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) );
|
||||
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void RF24::startListening(void)
|
||||
{
|
||||
#if !defined (RF24_TINY)
|
||||
powerUp();
|
||||
#endif
|
||||
write_register(CONFIG, read_register(CONFIG) | _BV(PRIM_RX));
|
||||
write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
|
||||
|
||||
// Restore the pipe0 adddress, if exists
|
||||
if (pipe0_reading_address){
|
||||
write_register(RX_ADDR_P0, reinterpret_cast<const uint8_t*>(&pipe0_reading_address), 5);
|
||||
if (pipe0_reading_address[0] > 0){
|
||||
write_register(RX_ADDR_P0, pipe0_reading_address, addr_width);
|
||||
}else{
|
||||
closeReadingPipe(0);
|
||||
}
|
||||
|
||||
// Flush buffers
|
||||
flush_rx();
|
||||
flush_tx();
|
||||
//flush_rx();
|
||||
if(read_register(FEATURE) & _BV(EN_ACK_PAY)){
|
||||
flush_tx();
|
||||
}
|
||||
|
||||
// Go!
|
||||
ce(HIGH);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
static const uint8_t child_pipe_enable[] PROGMEM =
|
||||
{
|
||||
ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5
|
||||
};
|
||||
|
||||
void RF24::stopListening(void)
|
||||
{
|
||||
|
||||
ce(LOW);
|
||||
flush_tx();
|
||||
flush_rx();
|
||||
#if defined(__arm__)
|
||||
delayMicroseconds(300);
|
||||
#endif
|
||||
delayMicroseconds(130);
|
||||
if(read_register(FEATURE) & _BV(EN_ACK_PAY)){
|
||||
flush_tx();
|
||||
}
|
||||
//flush_rx();
|
||||
write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) );
|
||||
|
||||
#if defined (RF24_TINY)
|
||||
// for 3 pins solution TX mode is only left with additonal powerDown/powerUp cycle
|
||||
if (ce_pin == csn_pin) {
|
||||
powerDown();
|
||||
powerUp();
|
||||
}
|
||||
#endif
|
||||
write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[0]))); // Enable RX on pipe0
|
||||
|
||||
delayMicroseconds(100);
|
||||
|
||||
}
|
||||
|
||||
@@ -566,18 +605,36 @@ void RF24::powerUp(void)
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
#if defined (FAILURE_HANDLING)
|
||||
void RF24::errNotify(){
|
||||
IF_SERIAL_DEBUG(printf_P(PSTR("HARDWARE FAIL\r\n")));
|
||||
failureDetected = 1;
|
||||
}
|
||||
#endif
|
||||
/******************************************************************/
|
||||
|
||||
//Similar to the previous write, clears the interrupt flags
|
||||
bool RF24::write( const void* buf, uint8_t len, const bool multicast )
|
||||
{
|
||||
//Start Writing
|
||||
startWrite(buf,len,multicast);
|
||||
startFastWrite(buf,len,multicast);
|
||||
|
||||
//Wait until complete or failed
|
||||
//ACK payloads that are handled improperly will cause this to hang
|
||||
//If autoAck is ON, a payload has to be written prior to reading a payload, else write after reading a payload
|
||||
while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) { }
|
||||
#if defined (FAILURE_HANDLING)
|
||||
uint32_t timer = millis();
|
||||
#endif
|
||||
|
||||
while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) {
|
||||
#if defined (FAILURE_HANDLING)
|
||||
if(millis() - timer > 75){
|
||||
errNotify();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ce(LOW);
|
||||
|
||||
uint8_t status = write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
|
||||
|
||||
@@ -611,6 +668,12 @@ bool RF24::writeBlocking( const void* buf, uint8_t len, uint32_t timeout )
|
||||
reUseTX(); //Set re-transmit and clear the MAX_RT interrupt flag
|
||||
if(millis() - timer > timeout){ return 0; } //If this payload has exceeded the user-defined timeout, exit and return 0
|
||||
}
|
||||
#if defined (FAILURE_HANDLING)
|
||||
if(millis() - timer > (timeout+75) ){
|
||||
errNotify();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -638,6 +701,10 @@ bool RF24::writeFast( const void* buf, uint8_t len, const bool multicast )
|
||||
//Return 0 so the user can control the retrys and set a timer or failure counter if required
|
||||
//The radio will auto-clear everything in the FIFO as long as CE remains high
|
||||
|
||||
#if defined (FAILURE_HANDLING)
|
||||
uint32_t timer = millis();
|
||||
#endif
|
||||
|
||||
while( ( get_status() & ( _BV(TX_FULL) ))) { //Blocking only if FIFO is full. This will loop and block until TX is successful or fail
|
||||
|
||||
if( get_status() & _BV(MAX_RT)){
|
||||
@@ -646,7 +713,12 @@ bool RF24::writeFast( const void* buf, uint8_t len, const bool multicast )
|
||||
return 0; //Return 0. The previous payload has been retransmitted
|
||||
//From the user perspective, if you get a 0, just keep trying to send the same payload
|
||||
}
|
||||
|
||||
#if defined (FAILURE_HANDLING)
|
||||
if(millis() - timer > 75 ){
|
||||
errNotify();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
//Start Writing
|
||||
startFastWrite(buf,len,multicast);
|
||||
@@ -673,6 +745,7 @@ void RF24::startFastWrite( const void* buf, uint8_t len, const bool multicast){
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
//Added the original startWrite back in so users can still use interrupts, ack payloads, etc
|
||||
//Allows the library to pass all tests
|
||||
@@ -681,16 +754,27 @@ void RF24::startWrite( const void* buf, uint8_t len, const bool multicast ){
|
||||
// Send the payload
|
||||
|
||||
//write_payload( buf, len );
|
||||
write_payload( buf, len, multicast?static_cast<uint8_t>(W_TX_PAYLOAD_NO_ACK):static_cast<uint8_t>(W_TX_PAYLOAD)) ;
|
||||
|
||||
write_payload( buf, len,multicast? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ;
|
||||
ce(HIGH);
|
||||
ce(LOW);
|
||||
#if defined(CORE_TEENSY) || !defined(ARDUINO)
|
||||
delayMicroseconds(10);
|
||||
#endif
|
||||
ce(LOW);
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool RF24::txStandBy(){
|
||||
/****************************************************************************/
|
||||
|
||||
bool RF24::rxFifoFull(){
|
||||
return read_register(FIFO_STATUS) & _BV(RX_FULL);
|
||||
}
|
||||
/****************************************************************************/
|
||||
|
||||
bool RF24::txStandBy(){
|
||||
#if defined (FAILURE_HANDLING)
|
||||
uint32_t timeout = millis();
|
||||
#endif
|
||||
while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){
|
||||
if( get_status() & _BV(MAX_RT)){
|
||||
write_register(STATUS,_BV(MAX_RT) );
|
||||
@@ -698,12 +782,20 @@ bool RF24::txStandBy(){
|
||||
flush_tx(); //Non blocking, flush the data
|
||||
return 0;
|
||||
}
|
||||
#if defined (FAILURE_HANDLING)
|
||||
if( millis() - timeout > 75){
|
||||
errNotify();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ce(LOW); //Set STANDBY-I mode
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
bool RF24::txStandBy(uint32_t timeout){
|
||||
|
||||
uint32_t start = millis();
|
||||
@@ -717,7 +809,15 @@ bool RF24::txStandBy(uint32_t timeout){
|
||||
ce(LOW); flush_tx(); return 0;
|
||||
}
|
||||
}
|
||||
#if defined (FAILURE_HANDLING)
|
||||
if( millis() - start > (timeout+75)){
|
||||
errNotify();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
ce(LOW); //Set STANDBY-I mode
|
||||
return 1;
|
||||
|
||||
@@ -735,18 +835,18 @@ uint8_t RF24::getDynamicPayloadSize(void)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
#if defined (__arm__)
|
||||
SPI.transfer(csn_pin, R_RX_PL_WID, SPI_CONTINUE );
|
||||
result = SPI.transfer(csn_pin,0xff);
|
||||
#if defined (__arm__) && ! defined( CORE_TEENSY )
|
||||
_SPI.transfer(csn_pin, R_RX_PL_WID, SPI_CONTINUE );
|
||||
result = _SPI.transfer(csn_pin,0xff);
|
||||
#else
|
||||
csn(LOW);
|
||||
SPI.transfer( R_RX_PL_WID );
|
||||
result = SPI.transfer(0xff);
|
||||
_SPI.transfer( R_RX_PL_WID );
|
||||
result = _SPI.transfer(0xff);
|
||||
csn(HIGH);
|
||||
|
||||
#endif
|
||||
|
||||
if(result > 32) { flush_rx(); return 0; }
|
||||
if(result > 32) { flush_rx(); delay(2); return 0; }
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -761,9 +861,12 @@ bool RF24::available(void)
|
||||
|
||||
bool RF24::available(uint8_t* pipe_num)
|
||||
{
|
||||
|
||||
//Check the FIFO buffer to see if data is waitng to be read
|
||||
|
||||
//Check the FIFO buffer to see if data is waiting to be read
|
||||
if(listeningStarted){
|
||||
while(micros() - lastAvailableCheck < 800 && listeningStarted){};
|
||||
lastAvailableCheck = micros();
|
||||
listeningStarted = 0;
|
||||
}
|
||||
if (!( read_register(FIFO_STATUS) & _BV(RX_EMPTY) )){
|
||||
|
||||
// If the caller wants the pipe number, include that
|
||||
@@ -774,8 +877,8 @@ bool RF24::available(uint8_t* pipe_num)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
@@ -813,8 +916,23 @@ void RF24::openWritingPipe(uint64_t value)
|
||||
// Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+)
|
||||
// expects it LSB first too, so we're good.
|
||||
|
||||
write_register(RX_ADDR_P0, reinterpret_cast<uint8_t*>(&value), 5);
|
||||
write_register(TX_ADDR, reinterpret_cast<uint8_t*>(&value), 5);
|
||||
write_register(RX_ADDR_P0, reinterpret_cast<uint8_t*>(&value), addr_width);
|
||||
write_register(TX_ADDR, reinterpret_cast<uint8_t*>(&value), addr_width);
|
||||
|
||||
|
||||
//const uint8_t max_payload_size = 32;
|
||||
//write_register(RX_PW_P0,min(payload_size,max_payload_size));
|
||||
write_register(RX_PW_P0,payload_size);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
void RF24::openWritingPipe(const uint8_t *address)
|
||||
{
|
||||
// Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+)
|
||||
// expects it LSB first too, so we're good.
|
||||
|
||||
write_register(RX_ADDR_P0,address, addr_width);
|
||||
write_register(TX_ADDR, address, addr_width);
|
||||
|
||||
//const uint8_t max_payload_size = 32;
|
||||
//write_register(RX_PW_P0,min(payload_size,max_payload_size));
|
||||
@@ -822,7 +940,6 @@ void RF24::openWritingPipe(uint64_t value)
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static const uint8_t child_pipe[] PROGMEM =
|
||||
{
|
||||
RX_ADDR_P0, RX_ADDR_P1, RX_ADDR_P2, RX_ADDR_P3, RX_ADDR_P4, RX_ADDR_P5
|
||||
@@ -831,24 +948,22 @@ static const uint8_t child_payload_size[] PROGMEM =
|
||||
{
|
||||
RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5
|
||||
};
|
||||
static const uint8_t child_pipe_enable[] PROGMEM =
|
||||
{
|
||||
ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5
|
||||
};
|
||||
|
||||
|
||||
void RF24::openReadingPipe(uint8_t child, uint64_t address)
|
||||
{
|
||||
// If this is pipe 0, cache the address. This is needed because
|
||||
// openWritingPipe() will overwrite the pipe 0 address, so
|
||||
// startListening() will have to restore it.
|
||||
if (child == 0)
|
||||
pipe0_reading_address = address;
|
||||
if (child == 0){
|
||||
memcpy(pipe0_reading_address,&address,addr_width);
|
||||
}
|
||||
|
||||
if (child <= 6)
|
||||
{
|
||||
// For pipes 2-5, only write the LSB
|
||||
if ( child < 2 )
|
||||
write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast<const uint8_t*>(&address), 5);
|
||||
write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast<const uint8_t*>(&address), addr_width);
|
||||
else
|
||||
write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast<const uint8_t*>(&address), 1);
|
||||
|
||||
@@ -861,6 +976,44 @@ void RF24::openReadingPipe(uint8_t child, uint64_t address)
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
void RF24::setAddressWidth(uint8_t a_width){
|
||||
|
||||
if(a_width -= 2){
|
||||
write_register(SETUP_AW,a_width%4);
|
||||
addr_width = (a_width%4) + 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void RF24::openReadingPipe(uint8_t child, const uint8_t *address)
|
||||
{
|
||||
// If this is pipe 0, cache the address. This is needed because
|
||||
// openWritingPipe() will overwrite the pipe 0 address, so
|
||||
// startListening() will have to restore it.
|
||||
if (child == 0){
|
||||
memcpy(pipe0_reading_address,address,addr_width);
|
||||
}
|
||||
if (child <= 6)
|
||||
{
|
||||
// For pipes 2-5, only write the LSB
|
||||
if ( child < 2 ){
|
||||
write_register(pgm_read_byte(&child_pipe[child]), address, addr_width);
|
||||
}else{
|
||||
write_register(pgm_read_byte(&child_pipe[child]), address, 1);
|
||||
}
|
||||
write_register(pgm_read_byte(&child_payload_size[child]),payload_size);
|
||||
|
||||
// Note it would be more efficient to set all of the bits for all open
|
||||
// pipes at once. However, I thought it would make the calling code
|
||||
// more simple to do it this way.
|
||||
write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child])));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void RF24::closeReadingPipe( uint8_t pipe )
|
||||
@@ -868,19 +1021,18 @@ void RF24::closeReadingPipe( uint8_t pipe )
|
||||
write_register(EN_RXADDR,read_register(EN_RXADDR) & ~_BV(pgm_read_byte(&child_pipe_enable[pipe])));
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void RF24::toggle_features(void)
|
||||
{
|
||||
|
||||
#if defined (__arm__)
|
||||
SPI.transfer(csn_pin, ACTIVATE, SPI_CONTINUE );
|
||||
SPI.transfer(csn_pin, 0x73 );
|
||||
#if defined (__arm__) && ! defined( CORE_TEENSY )
|
||||
_SPI.transfer(csn_pin, ACTIVATE, SPI_CONTINUE );
|
||||
_SPI.transfer(csn_pin, 0x73 );
|
||||
#else
|
||||
csn(LOW);
|
||||
SPI.transfer( ACTIVATE );
|
||||
SPI.transfer( 0x73 );
|
||||
_SPI.transfer( ACTIVATE );
|
||||
_SPI.transfer( 0x73 );
|
||||
csn(HIGH);
|
||||
#endif
|
||||
}
|
||||
@@ -924,6 +1076,7 @@ void RF24::enableAckPayload(void)
|
||||
//
|
||||
|
||||
write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P1) | _BV(DPL_P0));
|
||||
dynamic_payloads_enabled = true;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -948,19 +1101,19 @@ void RF24::writeAckPayload(uint8_t pipe, const void* buf, uint8_t len)
|
||||
|
||||
uint8_t data_len = min(len,32);
|
||||
|
||||
#if defined (__arm__)
|
||||
SPI.transfer(csn_pin, W_ACK_PAYLOAD | ( pipe & B111 ), SPI_CONTINUE);
|
||||
#if defined (__arm__) && ! defined( CORE_TEENSY )
|
||||
_SPI.transfer(csn_pin, W_ACK_PAYLOAD | ( pipe & B111 ), SPI_CONTINUE);
|
||||
while ( data_len-- > 1 ){
|
||||
SPI.transfer(csn_pin,*current++, SPI_CONTINUE);
|
||||
_SPI.transfer(csn_pin,*current++, SPI_CONTINUE);
|
||||
}
|
||||
SPI.transfer(csn_pin,*current++);
|
||||
_SPI.transfer(csn_pin,*current++);
|
||||
|
||||
#else
|
||||
csn(LOW);
|
||||
SPI.transfer(W_ACK_PAYLOAD | ( pipe & B111 ) );
|
||||
_SPI.transfer(W_ACK_PAYLOAD | ( pipe & B111 ) );
|
||||
|
||||
while ( data_len-- )
|
||||
SPI.transfer(*current++);
|
||||
_SPI.transfer(*current++);
|
||||
|
||||
csn(HIGH);
|
||||
|
||||
@@ -1032,7 +1185,7 @@ void RF24::setPALevel(uint8_t level)
|
||||
uint8_t setup = read_register(RF_SETUP) & 0b11111000;
|
||||
|
||||
if(level > 3){ // If invalid level, go to max PA
|
||||
level = RF24_PA_MAX << 1 + 1; // +1 to support the SI24R1 chip extra bit
|
||||
level = (RF24_PA_MAX << 1) + 1; // +1 to support the SI24R1 chip extra bit
|
||||
}else{
|
||||
level = (level << 1) + 1; // Else set level as requested
|
||||
}
|
||||
@@ -1057,13 +1210,11 @@ bool RF24::setDataRate(rf24_datarate_e speed)
|
||||
uint8_t setup = read_register(RF_SETUP) ;
|
||||
|
||||
// HIGH and LOW '00' is 1Mbs - our default
|
||||
wide_band = false ;
|
||||
setup &= ~(_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)) ;
|
||||
if( speed == RF24_250KBPS )
|
||||
{
|
||||
// Must set the RF_DR_LOW to 1; RF_DR_HIGH (used to be RF_DR) is already 0
|
||||
// Making it '10'.
|
||||
wide_band = false ;
|
||||
setup |= _BV( RF_DR_LOW ) ;
|
||||
}
|
||||
else
|
||||
@@ -1072,14 +1223,8 @@ bool RF24::setDataRate(rf24_datarate_e speed)
|
||||
// Making it '01'
|
||||
if ( speed == RF24_2MBPS )
|
||||
{
|
||||
wide_band = true ;
|
||||
setup |= _BV(RF_DR_HIGH);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1Mbs
|
||||
wide_band = false ;
|
||||
}
|
||||
}
|
||||
write_register(RF_SETUP,setup);
|
||||
|
||||
@@ -1088,10 +1233,6 @@ bool RF24::setDataRate(rf24_datarate_e speed)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
wide_band = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1151,9 +1292,11 @@ void RF24::setCRCLength(rf24_crclength_e length)
|
||||
rf24_crclength_e RF24::getCRCLength(void)
|
||||
{
|
||||
rf24_crclength_e result = RF24_CRC_DISABLED;
|
||||
|
||||
uint8_t config = read_register(CONFIG) & ( _BV(CRCO) | _BV(EN_CRC)) ;
|
||||
|
||||
if ( config & _BV(EN_CRC ) )
|
||||
uint8_t AA = read_register(EN_AA);
|
||||
|
||||
if ( config & _BV(EN_CRC ) || AA)
|
||||
{
|
||||
if ( config & _BV(CRCO) )
|
||||
result = RF24_CRC_16;
|
||||
@@ -1196,7 +1339,7 @@ void RF24::setRetries(uint8_t delay, uint8_t count)
|
||||
# define SS 3 // PA7
|
||||
#endif
|
||||
|
||||
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
#if defined(RF24_TINY)
|
||||
|
||||
void SPIClass::begin() {
|
||||
|
||||
|
||||
+183
-101
@@ -15,7 +15,10 @@
|
||||
#ifndef __RF24_H__
|
||||
#define __RF24_H__
|
||||
|
||||
|
||||
#include "RF24_config.h"
|
||||
#if defined SOFTSPI
|
||||
#include <DigitalIO.h>
|
||||
#endif
|
||||
/**
|
||||
* Power Amplifier level.
|
||||
*
|
||||
@@ -44,14 +47,22 @@ typedef enum { RF24_CRC_DISABLED = 0, RF24_CRC_8, RF24_CRC_16 } rf24_crclength_e
|
||||
class RF24
|
||||
{
|
||||
private:
|
||||
#ifdef SOFTSPI
|
||||
SoftSPI<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN, SPI_MODE> spi;
|
||||
#elif defined (SPI_UART)
|
||||
SPIUARTClass uspi;
|
||||
#endif
|
||||
|
||||
uint8_t ce_pin; /**< "Chip Enable" pin, activates the RX or TX role */
|
||||
uint8_t csn_pin; /**< SPI Chip select */
|
||||
bool wide_band; /* 2Mbs data rate in use? */
|
||||
uint8_t csn_pin; /**< SPI Chip select */
|
||||
bool p_variant; /* False for RF24L01 and true for RF24L01P */
|
||||
uint8_t payload_size; /**< Fixed size of payloads */
|
||||
bool dynamic_payloads_enabled; /**< Whether dynamic payloads are enabled. */
|
||||
uint64_t pipe0_reading_address; /**< Last address set on pipe 0 for reading. */
|
||||
|
||||
uint8_t pipe0_reading_address[5]; /**< Last address set on pipe 0 for reading. */
|
||||
uint8_t addr_width; /**< The address width to use - 3,4 or 5 bytes. */
|
||||
uint32_t lastAvailableCheck; /**< Limits the amount of time between reading data, only when switching between modes */
|
||||
boolean listeningStarted; /**< Var for delaying available() after start listening */
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@@ -76,9 +87,6 @@ public:
|
||||
* Begin operation of the chip
|
||||
*
|
||||
* Call this in setup(), before calling any other methods.
|
||||
*
|
||||
* @note Optimization: The radio is partially configured in PTX mode
|
||||
* when begin is called to make the transition to PTX mode simpler.
|
||||
*/
|
||||
void begin(void);
|
||||
|
||||
@@ -87,7 +95,7 @@ public:
|
||||
*
|
||||
* Be sure to call openReadingPipe() first. Do not call write() while
|
||||
* in this mode, without first calling stopListening(). Call
|
||||
* isAvailable() to check for incoming traffic, and read() to get it.
|
||||
* Available() to check for incoming traffic, and read() to get it.
|
||||
*/
|
||||
void startListening(void);
|
||||
|
||||
@@ -95,27 +103,12 @@ public:
|
||||
* Stop listening for incoming messages
|
||||
*
|
||||
* Do this before calling write().
|
||||
*
|
||||
* @note Optimization: The radio will be taken out of PRX mode as soon
|
||||
* as listening is stopped. Enables quicker and simpler engaging of
|
||||
* primary transmitter (PTX) mode.
|
||||
*/
|
||||
void stopListening(void);
|
||||
|
||||
/**
|
||||
* Test whether there are bytes available to be read
|
||||
*
|
||||
* @note Optimization: The available functino now checks the FIFO
|
||||
* buffers directly for data instead of relying of interrupt flags.
|
||||
*
|
||||
* @note Interrupt flags will not be cleared until a payload is
|
||||
* actually read from the FIFO
|
||||
*
|
||||
* @see txStandBy()
|
||||
* @see startWrite()
|
||||
* @see write()
|
||||
* @see writeFast()
|
||||
*
|
||||
* @return True if there is a payload available, false if none is
|
||||
*/
|
||||
bool available(void);
|
||||
@@ -128,9 +121,9 @@ public:
|
||||
* @note I specifically chose 'void*' as a data type to make it easier
|
||||
* for beginners to use. No casting needed.
|
||||
*
|
||||
* @note Optimization: No longer boolean. Use available to
|
||||
* determine if packets are available. Interrupt flags are now cleared
|
||||
* during reads instead of when calling available().
|
||||
* @note No longer boolean. Use available to determine if packets are
|
||||
* available. Interrupt flags are now cleared during reads instead of
|
||||
* when calling available().
|
||||
*
|
||||
* @param buf Pointer to a buffer where the data should be written
|
||||
* @param len Maximum number of bytes to read into the buffer
|
||||
@@ -139,15 +132,12 @@ public:
|
||||
void read( void* buf, uint8_t len );
|
||||
|
||||
/**
|
||||
* @note Optimization: Improved performance slightly
|
||||
* Write to the open writing pipe
|
||||
*
|
||||
* Be sure to call openWritingPipe() first to set the destination
|
||||
* of where to write to.
|
||||
*
|
||||
* This blocks until the message is successfully acknowledged by
|
||||
* the receiver or the timeout/retransmit maxima are reached. In
|
||||
* the current configuration, the max delay here is 60ms.
|
||||
* the current configuration, the max delay here is 60-70ms.
|
||||
*
|
||||
* The maximum size of data written is the fixed payload size, see
|
||||
* getPayloadSize(). However, you can write less, and the remainder
|
||||
@@ -162,24 +152,27 @@ public:
|
||||
bool write( const void* buf, uint8_t len );
|
||||
|
||||
/**
|
||||
* Open a pipe for writing
|
||||
* New: Open a pipe for writing via byte array. Old addressing format retained
|
||||
* for compatibility.
|
||||
*
|
||||
* Only one pipe can be open at once, but you can change the pipe
|
||||
* you'll listen to. Do not call this while actively listening.
|
||||
* Remember to stopListening() first.
|
||||
* Only one writing pipe can be open at once, but you can change the address
|
||||
* you'll write to. Call stopListening() first.
|
||||
*
|
||||
* Addresses are 40-bit hex values, e.g.:
|
||||
* Addresses are assigned via a byte array, default is 5 byte address length
|
||||
*
|
||||
* Usage is exactly the same as before, except for declaring the array
|
||||
*
|
||||
* @code
|
||||
* openWritingPipe(0xF0F0F0F0F0);
|
||||
* uint8_t addresses[][6] = {"1Node","2Node"};
|
||||
* openWritingPipe(addresses[0]);
|
||||
* @endcode
|
||||
* @see setAddressWidth
|
||||
*
|
||||
* @param address The 40-bit address of the pipe to open. This can be
|
||||
* any value whatsoever, as long as you are the only one writing to it
|
||||
* and only one other radio is listening to it. Coordinate these pipe
|
||||
* @param address The address of the pipe to open. Coordinate these pipe
|
||||
* addresses amongst nodes on the network.
|
||||
*/
|
||||
void openWritingPipe(uint64_t address);
|
||||
|
||||
void openWritingPipe(const uint8_t *address);
|
||||
|
||||
/**
|
||||
* Open a pipe for reading
|
||||
@@ -188,35 +181,27 @@ public:
|
||||
* reading pipes, and then call startListening().
|
||||
*
|
||||
* @see openWritingPipe
|
||||
* @see setAddressWidth
|
||||
*
|
||||
* @warning Pipes 1-5 should share the first 32 bits.
|
||||
* Only the least significant byte should be unique, e.g.
|
||||
* @warning Pipes 1-5 should share the same address, except the first byte.
|
||||
* Only the first byte in the array should be unique, e.g.
|
||||
* @code
|
||||
* openReadingPipe(1,0xF0F0F0F0AA);
|
||||
* openReadingPipe(2,0xF0F0F0F066);
|
||||
* uint8_t addresses[][6] = {"1Node","2Node"};
|
||||
* openReadingPipe(1,addresses[0]);
|
||||
* openReadingPipe(2,addresses[1]);
|
||||
* @endcode
|
||||
*
|
||||
* @warning Pipe 0 is also used by the writing pipe. So if you open
|
||||
* pipe 0 for reading, and then startListening(), it will overwrite the
|
||||
* writing pipe. Ergo, do an openWritingPipe() again before write().
|
||||
*
|
||||
* @todo Enforce the restriction that pipes 1-5 must share the top 32 bits
|
||||
*
|
||||
* @param number Which pipe# to open, 0-5.
|
||||
* @param address The 40-bit address of the pipe to open.
|
||||
* @param address The 24, 32 or 40 bit address of the pipe to open.
|
||||
*/
|
||||
void openReadingPipe(uint8_t number, uint64_t address);
|
||||
|
||||
void openReadingPipe(uint8_t number, const uint8_t *address);
|
||||
|
||||
|
||||
/**
|
||||
* Close a pipe after it has been previously opened.
|
||||
* Can be safely called without having previously opened a pipe.
|
||||
* @param pipe Which pipe # to close, 0-5.
|
||||
*/
|
||||
void closeReadingPipe( uint8_t pipe ) ;
|
||||
|
||||
/**@}*/
|
||||
/**@}*/
|
||||
/**
|
||||
* @name Advanced Operation
|
||||
*
|
||||
@@ -236,34 +221,41 @@ public:
|
||||
* FIFO buffers. This optimized version does not rely on interrupt
|
||||
* flags, but checks the actual FIFO buffers.
|
||||
*
|
||||
* @note Optimization: Interrupt flags are no longer cleared when available is called,
|
||||
* but will be reset only when the data is read from the FIFO buffers.
|
||||
*
|
||||
* @param[out] pipe_num Which pipe has the payload available
|
||||
* @return True if there is a payload available, false if none is
|
||||
*/
|
||||
bool available(uint8_t* pipe_num);
|
||||
|
||||
/**
|
||||
* Check if the radio needs to be read. Can be used to prevent data loss
|
||||
* @@return True if all three 32-byte radio buffers are full
|
||||
*/
|
||||
bool rxFifoFull();
|
||||
|
||||
/**
|
||||
* Enter low-power mode
|
||||
*
|
||||
* To return to normal power mode, either write() some data or
|
||||
* startListening, or powerUp().
|
||||
*
|
||||
* @note Optimization: The radio will never enter power down unless instructed
|
||||
* by the MCU via this command.
|
||||
* @note After calling startListening(), a basic radio will consume about 13.5mA
|
||||
* at max PA level.
|
||||
* During active transmission, the radio will consume about 11.5mA, but this will
|
||||
* be reduced to 26uA (.026mA) between sending.
|
||||
* In full powerDown mode, the radio will consume approximately 900nA (.0009mA)
|
||||
*/
|
||||
void powerDown(void);
|
||||
|
||||
/**
|
||||
* Leave low-power mode - making radio more responsive
|
||||
*
|
||||
* Leave low-power mode - required for normal radio operation after calling powerDown()
|
||||
*
|
||||
* To return to low power mode, call powerDown().
|
||||
* @note This will take up to 5ms for maximum compatibility
|
||||
*/
|
||||
void powerUp(void) ;
|
||||
|
||||
/**
|
||||
* Write for single NOACK writes. Disables acknowledgements/autoretries for a single write.
|
||||
* Write for single NOACK writes. Optionally disables acknowledgements/autoretries for a single write.
|
||||
*
|
||||
* @note enableDynamicAck() must be called to enable this feature
|
||||
*
|
||||
@@ -279,13 +271,12 @@ public:
|
||||
bool write( const void* buf, uint8_t len, const bool multicast );
|
||||
|
||||
/**
|
||||
* @note Optimization: New Command *
|
||||
* This will not block until the 3 FIFO buffers are filled with data.
|
||||
* Once the FIFOs are full, writeFast will simply wait for success or
|
||||
* timeout, and return 1 or 0 respectively. From a user perspective, just
|
||||
* keep trying to send the same data. The library will keep auto retrying
|
||||
* the current payload using the built in functionality.
|
||||
* @warning It is important to never keep the nRF24L01 in TX mode for more than 4ms at a time. If the auto
|
||||
* @warning It is important to never keep the nRF24L01 in TX mode and FIFO full for more than 4ms at a time. If the auto
|
||||
* retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO
|
||||
* to clear by issuing txStandBy() or ensure appropriate time between transmissions.
|
||||
*
|
||||
@@ -325,12 +316,11 @@ public:
|
||||
bool writeFast( const void* buf, uint8_t len, const bool multicast );
|
||||
|
||||
/**
|
||||
* @note Optimization: New Command
|
||||
* This function extends the auto-retry mechanism to any specified duration.
|
||||
* It will not block until the 3 FIFO buffers are filled with data.
|
||||
* If so the library will auto retry until a new payload is written
|
||||
* or the user specified timeout period is reached.
|
||||
* @warning It is important to never keep the nRF24L01 in TX mode for more than 4ms at a time. If the auto
|
||||
* @warning It is important to never keep the nRF24L01 in TX mode and FIFO full for more than 4ms at a time. If the auto
|
||||
* retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO
|
||||
* to clear by issuing txStandBy() or ensure appropriate time between transmissions.
|
||||
*
|
||||
@@ -355,7 +345,6 @@ public:
|
||||
bool writeBlocking( const void* buf, uint8_t len, uint32_t timeout );
|
||||
|
||||
/**
|
||||
* @note Optimization: New Command
|
||||
* This function should be called as soon as transmission is finished to
|
||||
* drop the radio back to STANDBY-I mode. If not issued, the radio will
|
||||
* remain in STANDBY-II mode which, per the data sheet, is not a recommended
|
||||
@@ -383,8 +372,6 @@ public:
|
||||
bool txStandBy();
|
||||
|
||||
/**
|
||||
* @note Optimization: New Command
|
||||
*
|
||||
* This function allows extended blocking and auto-retries per a user defined timeout
|
||||
* @code
|
||||
* Fully Blocking Example:
|
||||
@@ -408,8 +395,7 @@ public:
|
||||
* The next time a message is received on @p pipe, the data in @p buf will
|
||||
* be sent back in the acknowledgement.
|
||||
*
|
||||
* @warning According to the data sheet, only three of these can be pending
|
||||
* at any time as there are only 3 FIFO buffers.
|
||||
* @warning Only three of these can be pending at any time as there are only 3 FIFO buffers.
|
||||
*
|
||||
* @param pipe Which pipe# (typically 1-5) will get this response.
|
||||
* @param buf Pointer to data that is sent
|
||||
@@ -434,14 +420,10 @@ public:
|
||||
|
||||
/**
|
||||
* Determine if an ack payload was received in the most recent call to
|
||||
* write().
|
||||
* write(). The regular available() can also be used.
|
||||
*
|
||||
* Call read() to retrieve the ack payload.
|
||||
*
|
||||
* @note Optimization: Calling this function NO LONGER clears the interrupt
|
||||
* flag. The new functionality checks the RX FIFO buffer for an ACK payload
|
||||
* instead of relying on interrupt flags.Reading the payload will clear the flags.
|
||||
*
|
||||
* @return True if an ack payload is available.
|
||||
*/
|
||||
bool isAckPayloadAvailable(void);
|
||||
@@ -464,7 +446,7 @@ public:
|
||||
* @note Optimization: This function now leaves the CE pin high, so the radio
|
||||
* will remain in TX or STANDBY-II Mode until a txStandBy() command is issued.
|
||||
* This allows the chip to be used to its full potential in TX mode.
|
||||
* @warning It is important to never keep the nRF24L01 in TX mode for more than 4ms at a time. If the auto
|
||||
* @warning It is important to never keep the nRF24L01 in TX mode with FIFO full for more than 4ms at a time. If the auto
|
||||
* retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO
|
||||
* to clear by issuing txStandBy() or ensure appropriate time between transmissions.
|
||||
*
|
||||
@@ -490,10 +472,6 @@ public:
|
||||
* Just like write(), but it returns immediately. To find out what happened
|
||||
* to the send, catch the IRQ and then call whatHappened().
|
||||
*
|
||||
* @note Optimization: This function again behaves as it did previously for backwards-compatibility.
|
||||
* with user code. The library uses startFastWrite() internally.
|
||||
* This is mainly used for single-payload transactions.
|
||||
*
|
||||
* @see write()
|
||||
* @see writeFast()
|
||||
* @see startFastWrite()
|
||||
@@ -511,8 +489,6 @@ public:
|
||||
void startWrite( const void* buf, uint8_t len, const bool multicast );
|
||||
|
||||
/**
|
||||
* Optimization: New Command
|
||||
*
|
||||
* This function is mainly used internally to take advantage of the auto payload
|
||||
* re-use functionality of the chip, but can be beneficial to users as well.
|
||||
*
|
||||
@@ -584,7 +560,23 @@ public:
|
||||
* @param rx_ready Mask payload received interrupts
|
||||
*/
|
||||
void maskIRQ(bool tx_ok,bool tx_fail,bool rx_ready);
|
||||
|
||||
/**
|
||||
* Set the address width from 3 to 5 bytes (24, 32 or 40 bit)
|
||||
*
|
||||
* @param a_width The address width to use: 3,4 or 5
|
||||
*/
|
||||
|
||||
void setAddressWidth(uint8_t a_width);
|
||||
|
||||
|
||||
/**
|
||||
* Close a pipe after it has been previously opened.
|
||||
* Can be safely called without having previously opened a pipe.
|
||||
* @param pipe Which pipe # to close, 0-5.
|
||||
*/
|
||||
void closeReadingPipe( uint8_t pipe ) ;
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**@}*/
|
||||
@@ -642,7 +634,7 @@ public:
|
||||
* For dynamic payloads, this pulls the size of the payload off
|
||||
* the chip
|
||||
*
|
||||
* @note Optimization: Corrupt packets are now detected and flushed per the
|
||||
* @note Corrupt packets are now detected and flushed per the
|
||||
* manufacturer.
|
||||
*
|
||||
* @return Payload length of last-received dynamic payload
|
||||
@@ -655,7 +647,7 @@ public:
|
||||
* Ack payloads are a handy way to return data back to senders without
|
||||
* manually changing the radio modes on both units.
|
||||
*
|
||||
* @see examples/pingpair_pl/pingpair_pl.pde
|
||||
* @see examples/GettingStarted_CallResponse/GettingStarted_CallResponse.ino
|
||||
*/
|
||||
void enableAckPayload(void);
|
||||
|
||||
@@ -759,6 +751,73 @@ public:
|
||||
*
|
||||
*/
|
||||
void disableCRC( void ) ;
|
||||
|
||||
/**
|
||||
* Enable error detection by un-commenting #define FAILURE_HANDLING in RF24_config.h
|
||||
* If a failure has been detected, it usually indicates a hardware issue. By default the library
|
||||
* will cease operation when a failure is detected.
|
||||
* This should allow advanced users to detect and resolve intermittent hardware issues.
|
||||
*
|
||||
* In most cases, the radio must be re-enabled via radio.begin(); and the appropriate settings
|
||||
* applied after a failure occurs, if wanting to re-enable the device immediately.
|
||||
*
|
||||
* Usage: (Failure handling must be enabled per above)
|
||||
* @code
|
||||
* if(radio.failureDetected){
|
||||
* radio.begin(); // Attempt to re-configure the radio with defaults
|
||||
* radio.failureDetected = 0; // Reset the detection value
|
||||
* radio.openWritingPipe(addresses[1]); // Re-configure pipe addresses
|
||||
* radio.openReadingPipe(1,addresses[0]);
|
||||
* report_failure(); // Blink leds, send a message, etc. to indicate failure
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
//#if defined (FAILURE_HANDLING)
|
||||
bool failureDetected;
|
||||
//#endif
|
||||
|
||||
|
||||
/**@}*/
|
||||
/**
|
||||
* @name Deprecated
|
||||
*
|
||||
* Methods provided for backwards compabibility.
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
|
||||
/**
|
||||
* Open a pipe for reading
|
||||
* @note For compatibility with old code only, see new function
|
||||
*
|
||||
* @warning Pipes 1-5 should share the first 32 bits.
|
||||
* Only the least significant byte should be unique, e.g.
|
||||
* @code
|
||||
* openReadingPipe(1,0xF0F0F0F0AA);
|
||||
* openReadingPipe(2,0xF0F0F0F066);
|
||||
* @endcode
|
||||
*
|
||||
* @warning Pipe 0 is also used by the writing pipe. So if you open
|
||||
* pipe 0 for reading, and then startListening(), it will overwrite the
|
||||
* writing pipe. Ergo, do an openWritingPipe() again before write().
|
||||
*
|
||||
* @param number Which pipe# to open, 0-5.
|
||||
* @param address The 40-bit address of the pipe to open.
|
||||
*/
|
||||
void openReadingPipe(uint8_t number, uint64_t address);
|
||||
|
||||
/**
|
||||
* Open a pipe for writing
|
||||
* @note For compatibility with old code only, see new function
|
||||
* Addresses are 40-bit hex values, e.g.:
|
||||
*
|
||||
* @code
|
||||
* openWritingPipe(0xF0F0F0F0F0);
|
||||
* @endcode
|
||||
*
|
||||
* @param address The 40-bit address of the pipe to open.
|
||||
*/
|
||||
void openWritingPipe(uint64_t address);
|
||||
|
||||
private:
|
||||
|
||||
@@ -863,7 +922,8 @@ private:
|
||||
* @return Current value of status register
|
||||
*/
|
||||
uint8_t get_status(void);
|
||||
#if !defined (MINIMAL)
|
||||
|
||||
#if !defined (MINIMAL)
|
||||
/**
|
||||
* Decode and print the given status to stdout
|
||||
*
|
||||
@@ -921,6 +981,11 @@ private:
|
||||
*/
|
||||
|
||||
uint8_t spiTrans(uint8_t cmd);
|
||||
|
||||
#if defined (FAILURE_HANDLING)
|
||||
void errNotify(void);
|
||||
#endif
|
||||
|
||||
/**@}*/
|
||||
|
||||
};
|
||||
@@ -1014,6 +1079,18 @@ private:
|
||||
* ping/pong cycle, and the receiver sleeps between payloads. <br>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @example rf24ping85.ino
|
||||
* <b>New: Contributed by https://github.com/tong67</b><br>
|
||||
* This is an example of how to use the RF24 class to communicate with ATtiny85 and other node. <br>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @example timingSearch3pin.ino
|
||||
* <b>New: Contributed by https://github.com/tong67</b><br>
|
||||
* This is an example of how to determine the correct timing for ATtiny when using only 3-pins
|
||||
*/
|
||||
|
||||
/**
|
||||
* @example pingpair_dyn.ino
|
||||
*
|
||||
@@ -1071,7 +1148,7 @@ private:
|
||||
*
|
||||
* This library fork is designed to be...
|
||||
* @li More compliant with the manufacturer specified operation of the chip, while allowing advanced users
|
||||
* to work outside the reccommended operation.
|
||||
* to work outside the recommended operation.
|
||||
* @li Utilize the capabilities of the radio to their full potential via Arduino
|
||||
* @li More reliable, responsive and feature rich
|
||||
* @li Easy for beginners to use, with well documented examples and features
|
||||
@@ -1079,25 +1156,30 @@ private:
|
||||
*
|
||||
* @section News News
|
||||
*
|
||||
* <b>April 2014: Official Release: Still some work to do, but most benefits have been realized </b><br>
|
||||
* <b>Main changes: </b><br>
|
||||
* - The library has been tweaked to allow full use of the FIFO buffers for maximum transfer speeds
|
||||
* - Many issues and bugs have been resolved
|
||||
* - Changes to read() and available () functionality have increased reliability and response
|
||||
* - Extended timeout periods have been added to aid in noisy or otherwise unreliable environments
|
||||
* - Delays have been removed where possible to ensure maximum efficiency
|
||||
* - Full Due support with extended SPI functions
|
||||
* - ATTiny 24/44/84 25/45/85 now supported.
|
||||
* - ATTiny now supported.
|
||||
* - Raspberry Pi now supported
|
||||
* - More! See the links below and class documentation for more info.
|
||||
*
|
||||
* If issues are discovered with the documentation, please report them here: <a href="https://github.com/TMRh20/tmrh20.github.io/issues"> here</a>
|
||||
* If issues are discovered with the documentation, please report them <a href="https://github.com/TMRh20/tmrh20.github.io/issues"> here</a>
|
||||
* @section Useful Useful References
|
||||
*
|
||||
* Please refer to:
|
||||
*
|
||||
* @li <a href="http://tmrh20.github.io/">Documentation Main Page</a>
|
||||
* @li <a href="http://tmrh20.github.io/RF24/classRF24.html">RF24 Class Documentation</a>
|
||||
* @li <a href="http://tmrh20.blogspot.com/2014/03/high-speed-data-transfers-and-wireless.html">My Blog: RF24 Optimization Overview</a>
|
||||
* @li <a href="https://github.com/tmrh20/RF24/">Source Code</a>
|
||||
* @li <a href="https://github.com/tmrh20/RF24/archives/master">Downloads Page</a>
|
||||
* @li <a href="https://github.com/TMRh20/RF24/archive/master.zip">Download</a>
|
||||
* @li <a href="http://www.nordicsemi.com/files/Product/data_sheet/nRF24L01_Product_Specification_v2_0.pdf">Chip Datasheet</a>
|
||||
* @li <a href="http://tmrh20.github.io/RF24Network/">RF24Network: Easily create a home or long-range RF24 sensor network</a>
|
||||
* @li <a href="http://tmrh20.blogspot.com/2014/03/arduino-radiointercomwireless-audio.html">My Blog: RF24 Wireless Audio</a>
|
||||
* @li <a href="https://github.com/maniacbug/RF24">Original Library</a>
|
||||
*
|
||||
* This chip uses the SPI bus, plus two chip control pins. Remember that pin 10 must still remain an output, or
|
||||
@@ -1108,13 +1190,13 @@ private:
|
||||
* Most standard Arduino based boards are supported:
|
||||
* - ATMega 328 based boards (Uno, Nano, etc)
|
||||
* - Mega Boards (1280, 2560, etc)
|
||||
* - ARM based boards (Arduino Due) Note: Do not include printf.h or use printf begin. This functionality is already present. Must use one of the
|
||||
* hardware SS/CSN pins as extended SPI methods are used.
|
||||
* - Arduino Due: Must use one of the hardware SS/CSN pins as extended SPI methods are used.
|
||||
* Initial Due support taken from https://github.com/mcrosson/RF24/tree/due
|
||||
* - ATTiny board support added from https://github.com/jscrane/RF24
|
||||
* - ATTiny board support initially added from https://github.com/jscrane/RF24
|
||||
* Note: ATTiny support is built into the library. Do not include SPI.h. <br>
|
||||
* ATTiny 85: D0(pin 5): MISO, D1(pin6) MOSI, D2(pin7) SCK, D3(pin2):CSN/SS, D4(pin3): CE <br>
|
||||
* ATTiny 84: PA6:MISO, PA5:MOSI, PA4:SCK, PA7:CSN/SS, CE as desired <br>
|
||||
* See the included examples for more info on using ATTiny with RF24 <br>
|
||||
* See https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC for ATTiny patch
|
||||
* - Raspberry Pi Support: See the readme at https://github.com/TMRh20/RF24/tree/master/RPi/RF24
|
||||
*
|
||||
* @section More More Information
|
||||
*
|
||||
@@ -1122,7 +1204,7 @@ private:
|
||||
*
|
||||
* @li Project blog:
|
||||
* @li <a href="http://TMRh20.blogspot.com"> TMRh20.blogspot.com </a>
|
||||
* @li <a href="https://github.com/TMRh20"> RF24 Wireless Audio Library (Coming Soon) </a>
|
||||
* @li <a href="http://tmrh20.github.io/RF24Audio/"> RF24 Wireless Audio Library </a>
|
||||
* @li <a href="https://github.com/TMRh20/RF24Network"> Optimized RF24 Network Layer </a>
|
||||
* @li <a href="https://github.com/maniacbug/RF24"> ManiacBug on GitHub (Original Library Author)</a>
|
||||
*/
|
||||
|
||||
@@ -20,27 +20,65 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
//TMRh20:
|
||||
#define MINIMAL // saves 432 bytes!
|
||||
|
||||
/*** USER DEFINES: ***/
|
||||
//#define FAILURE_HANDLING
|
||||
//#define SERIAL_DEBUG
|
||||
#define MINIMAL
|
||||
//#define SPI_UART // Requires library from https://github.com/TMRh20/Sketches/tree/master/SPI_UART
|
||||
//#define SOFTSPI // Requires library from https://github.com/greiman/DigitalIO
|
||||
/**********************/
|
||||
|
||||
// Define _BV for non-Arduino platforms and for Arduino DUE
|
||||
#if defined (ARDUINO)
|
||||
#include <SPI.h>
|
||||
#if defined (ARDUINO) && !defined (__arm__)
|
||||
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
#define RF24_TINY
|
||||
#define _SPI SPI
|
||||
#else
|
||||
#if defined SPI_UART
|
||||
#include <SPI_UART.h>
|
||||
#define _SPI uspi
|
||||
#elif defined SOFTSPI
|
||||
// change these pins to your liking
|
||||
//
|
||||
const uint8_t SOFT_SPI_MISO_PIN = 16;
|
||||
const uint8_t SOFT_SPI_MOSI_PIN = 15;
|
||||
const uint8_t SOFT_SPI_SCK_PIN = 14;
|
||||
const uint8_t SPI_MODE = 0;
|
||||
#define _SPI spi
|
||||
|
||||
#else
|
||||
#include <SPI.h>
|
||||
#define _SPI SPI
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
extern HardwareSPI SPI;
|
||||
#define _BV(x) (1<<(x))
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#undef SERIAL_DEBUG
|
||||
#if defined(__arm__) || defined (CORE_TEENSY)
|
||||
#include <SPI.h>
|
||||
#endif
|
||||
|
||||
#if !defined(CORE_TEENSY)
|
||||
#define _BV(x) (1<<(x))
|
||||
#if !defined(__arm__)
|
||||
extern HardwareSPI SPI;
|
||||
#endif
|
||||
#else
|
||||
#define printf Serial.printf
|
||||
#endif
|
||||
|
||||
#define _SPI SPI
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
#define IF_SERIAL_DEBUG(x) ({x;})
|
||||
#else
|
||||
#define IF_SERIAL_DEBUG(x)
|
||||
#if defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny85__)
|
||||
#if defined(RF24_TINY)
|
||||
#define printf_P(...)
|
||||
#endif
|
||||
#endif
|
||||
@@ -48,7 +86,7 @@
|
||||
// Avoid spurious warnings
|
||||
// Arduino DUE is arm and uses traditional PROGMEM constructs
|
||||
#if 1
|
||||
#if ! defined( NATIVE ) && defined( ARDUINO ) && ! defined(__arm__)
|
||||
#if ! defined( NATIVE ) && defined( ARDUINO ) && ! defined(__arm__) && ! defined( CORE_TEENSY3 )
|
||||
#undef PROGMEM
|
||||
#define PROGMEM __attribute__(( section(".progmem.data") ))
|
||||
#undef PSTR
|
||||
@@ -68,20 +106,25 @@
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined ( CORE_TEENSY )
|
||||
typedef uint16_t prog_uint16_t;
|
||||
#define PSTR(x) (x)
|
||||
#define printf_P printf
|
||||
#define strlen_P strlen
|
||||
#define PROGMEM
|
||||
#define pgm_read_word(p) (*(p))
|
||||
#endif
|
||||
|
||||
#define PRIPSTR "%s"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// ATTiny support code is from https://github.com/jscrane/RF24
|
||||
|
||||
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
#if defined(RF24_TINY)
|
||||
#include <stdio.h>
|
||||
#include <Arduino.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
Reference in New Issue
Block a user