Add new scene controller with touch display example.
Upgraded RF24 to latest version which supports SoftSPI. Added DigitalIO and UTFT libraries to support the new example. Fix problem reported in RelayWithButtonActuator example.
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