Merge branch 'master' into development

Conflicts:
	libraries/UIPEthernet/utility/uipethernet-conf.h
This commit is contained in:
Henrik Ekblad
2014-10-22 00:15:56 +02:00
227 changed files with 27983 additions and 261 deletions
+282 -139
View File
@@ -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
View File
@@ -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>
*/
+58 -15
View File
@@ -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>