Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: xtoff3 CYS_Receiver
Fork of RF24Network by
Revision 4:75c5aa56411f, committed 2016-04-21
- Comitter:
- akashvibhute
- Date:
- Thu Apr 21 03:43:13 2016 +0000
- Parent:
- 3:dfc8da7ac18c
- Child:
- 5:b1110d26a900
- Commit message:
- Library re-ported with all the latest and greatest stuff from Manicbug; Synced with TMRh20's RF24 library on Apr/18/2015 from https://github.com/TMRh20
Changed in this revision
--- a/RF24Network.cpp Thu Nov 05 05:54:47 2015 +0000
+++ b/RF24Network.cpp Thu Apr 21 03:43:13 2016 +0000
@@ -5,18 +5,24 @@
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
-
+
/*
-* Mbed support added by Akash Vibhute <akash.roboticist@gmail.com>
-* Porting completed on Nov/05/2015
-*
-* Updated with TMRh20's RF24 library on Nov/04/2015 from https://github.com/TMRh20
-*
-*/
+ * Mbed support added by Akash Vibhute <akash.roboticist@gmail.com>
+ * Porting completed on Nov/05/2015
+ *
+ * Updated 1: Synced with TMRh20's RF24 library on Nov/04/2015 from https://github.com/TMRh20
+ * Updated 2: Synced with TMRh20's RF24 library on Apr/18/2015 from https://github.com/TMRh20
+ *
+ */
+
+#include "RF24Network_config.h"
+#include "RF24.h"
+#include "RF24Network.h"
-#include "RF24Network_config.h"
-#include <RF24.h>
-#include "RF24Network.h"
+#if defined (ENABLE_SLEEP_MODE)
+ volatile byte sleep_cycles_remaining;
+ volatile bool wasInterrupted;
+#endif
uint16_t RF24NetworkHeader::next_id = 1;
#if defined ENABLE_NETWORK_STATS
@@ -31,79 +37,80 @@
/******************************************************************/
#if !defined (DUAL_HEAD_RADIO)
-RF24Network::RF24Network( RF24& _radio ): radio(_radio), next_frame(frame_queue)
+RF24Network::RF24Network( RF24& _radio ): radio(_radio), next_frame(frame_queue)
{
-#if !defined ( DISABLE_FRAGMENTATION )
- frag_queue.message_buffer=&frag_queue_message_buffer[0];
- frag_ptr = &frag_queue;
-#endif
+ #if !defined ( DISABLE_FRAGMENTATION )
+ frag_queue.message_buffer=&frag_queue_message_buffer[0];
+ frag_ptr = &frag_queue;
+ #endif
+ txTime=0; networkFlags=0; returnSysMsgs=0; multicastRelay=0;
}
#else
RF24Network::RF24Network( RF24& _radio, RF24& _radio1 ): radio(_radio), radio1(_radio1), next_frame(frame_queue)
{
-#if !defined ( DISABLE_FRAGMENTATION )
- frag_queue.message_buffer=&frag_queue_message_buffer[0];
- frag_ptr = &frag_queue;
-#endif
+ #if !defined ( DISABLE_FRAGMENTATION )
+ frag_queue.message_buffer=&frag_queue_message_buffer[0];
+ frag_ptr = &frag_queue;
+ #endif
+ txTime=0; networkFlags=0; returnSysMsgs=0; multicastRelay=0;
}
#endif
/******************************************************************/
void RF24Network::begin(uint8_t _channel, uint16_t _node_address )
{
- rf24netTimer.start();
- if (! is_valid_address(_node_address) )
- return;
+ mainTimer.start();
+ if (! is_valid_address(_node_address) )
+ return;
- node_address = _node_address;
+ node_address = _node_address;
- if ( ! radio.isValid() ) {
- return;
- }
+ if ( ! radio.isValid() ){
+ return;
+ }
- // Set up the radio the way we want it to look
- if(_channel != USE_CURRENT_CHANNEL) {
- radio.setChannel(_channel);
- }
- //radio.enableDynamicAck();
- radio.setAutoAck(0,0);
-
-#if defined (ENABLE_DYNAMIC_PAYLOADS)
- radio.enableDynamicPayloads();
-#endif
-
- // Use different retry periods to reduce data collisions
- uint8_t retryVar = (((node_address % 6)+1) *2) + 3;
- radio.setRetries(retryVar, 5);
- txTimeout = 25;
- routeTimeout = txTimeout*9; // Adjust for max delay per node
+ // Set up the radio the way we want it to look
+ if(_channel != USE_CURRENT_CHANNEL){
+ radio.setChannel(_channel);
+ }
+ //radio.enableDynamicAck();
+ radio.setAutoAck(0,0);
+
+ #if defined (ENABLE_DYNAMIC_PAYLOADS)
+ radio.enableDynamicPayloads();
+ #endif
+
+ // Use different retry periods to reduce data collisions
+ uint8_t retryVar = (((node_address % 6)+1) *2) + 3;
+ radio.setRetries(retryVar, 5); // max about 85ms per attempt
+ txTimeout = 25;
+ routeTimeout = txTimeout*3; // Adjust for max delay per node within a single chain
#if defined (DUAL_HEAD_RADIO)
- radio1.setChannel(_channel);
- radio1.enableDynamicAck();
- radio1.enableDynamicPayloads();
+ radio1.setChannel(_channel);
+ radio1.enableDynamicAck();
+ radio1.enableDynamicPayloads();
#endif
- // Setup our address helper cache
- setup_address();
+ // Setup our address helper cache
+ setup_address();
- // Open up all listening pipes
- uint8_t i = 6;
- while (i--) {
- radio.openReadingPipe(i,pipe_address(_node_address,i));
- }
- radio.startListening();
+ // Open up all listening pipes
+ uint8_t i = 6;
+ while (i--){
+ radio.openReadingPipe(i,pipe_address(_node_address,i));
+ }
+ radio.startListening();
}
/******************************************************************/
#if defined ENABLE_NETWORK_STATS
-void RF24Network::failures(uint32_t *_fails, uint32_t *_ok)
-{
- *_fails = nFails;
- *_ok = nOK;
+void RF24Network::failures(uint32_t *_fails, uint32_t *_ok){
+ *_fails = nFails;
+ *_ok = nOK;
}
#endif
@@ -111,289 +118,286 @@
uint8_t RF24Network::update(void)
{
- // if there is data ready
- uint8_t pipe_num;
- uint8_t returnVal = 0;
-
- // If bypass is enabled, continue although incoming user data may be dropped
- // Allows system payloads to be read while user cache is full
- // Incoming Hold prevents data from being read from the radio, preventing incoming payloads from being acked
-
-
- if(!(networkFlags & FLAG_BYPASS_HOLDS)) {
- if( (networkFlags & FLAG_HOLD_INCOMING) || (next_frame-frame_queue) + 34 > MAIN_BUFFER_SIZE ) {
- if(!available()) {
- networkFlags &= ~FLAG_HOLD_INCOMING;
- } else {
- return 0;
- }
- }
+ // if there is data ready
+ uint8_t pipe_num;
+ uint8_t returnVal = 0;
+
+ // If bypass is enabled, continue although incoming user data may be dropped
+ // Allows system payloads to be read while user cache is full
+ // Incoming Hold prevents data from being read from the radio, preventing incoming payloads from being acked
+
+ if(!(networkFlags & FLAG_BYPASS_HOLDS)){
+ if( (networkFlags & FLAG_HOLD_INCOMING) || (next_frame-frame_queue) + 34 > MAIN_BUFFER_SIZE ){
+ if(!available()){
+ networkFlags &= ~FLAG_HOLD_INCOMING;
+ }else{
+ return 0;
+ }
}
-
-
- while ( radio.isValid() && radio.available(&pipe_num) ) {
+ }
+
+
+
+ while ( radio.isValid() && radio.available(&pipe_num) ){
-#if defined (ENABLE_DYNAMIC_PAYLOADS)
- if( (frame_size = radio.getDynamicPayloadSize() ) < sizeof(RF24NetworkHeader)) {
- wait_ms(10);
- continue;
- }
-#else
- frame_size=32;
-#endif
- // Dump the payloads until we've gotten everything
- // Fetch the payload, and see if this was the last one.
- radio.read( frame_buffer, frame_size );
-
- // Read the beginning of the frame as the header
- RF24NetworkHeader *header = (RF24NetworkHeader*)(&frame_buffer);
-
- IF_SERIAL_DEBUG(printf_P(PSTR("%lu: MAC Received on %u %s\n\r"),millis(),pipe_num,header->toString()));
- IF_SERIAL_DEBUG(const uint16_t* i = reinterpret_cast<const uint16_t*>(frame_buffer + sizeof(RF24NetworkHeader)); printf_P(PSTR("%lu: NET message %04x\n\r"),millis(),*i));
-
+ #if defined (ENABLE_DYNAMIC_PAYLOADS)
+ if( (frame_size = radio.getDynamicPayloadSize() ) < sizeof(RF24NetworkHeader)){
+ wait_ms(10);
+ continue;
+ }
+ #else
+ frame_size=32;
+ #endif
+ // Dump the payloads until we've gotten everything
+ // Fetch the payload, and see if this was the last one.
+ radio.read( frame_buffer, frame_size );
+
+ // Read the beginning of the frame as the header
+ RF24NetworkHeader *header = (RF24NetworkHeader*)(&frame_buffer);
+
+ IF_SERIAL_DEBUG(printf_P(PSTR("%lu: MAC Received on %u %s\n\r"),millis(),pipe_num,header->toString()));
+ IF_SERIAL_DEBUG(const uint16_t* i = reinterpret_cast<const uint16_t*>(frame_buffer + sizeof(RF24NetworkHeader));printf_P(PSTR("%lu: NET message %04x\n\r"),millis(),*i));
- // Throw it away if it's not a valid address
- if ( !is_valid_address(header->to_node) ) {
- continue;
- }
-
- uint8_t returnVal = header->type;
-
- // Is this for us?
- if ( header->to_node == node_address ) {
+
+ // Throw it away if it's not a valid address
+ if ( !is_valid_address(header->to_node) ){
+ continue;
+ }
+
+ uint8_t returnVal = header->type;
- if(header->type == NETWORK_PING) {
- continue;
- }
- if(header->type == NETWORK_ADDR_RESPONSE ) {
- uint16_t requester = frame_buffer[8];
- requester |= frame_buffer[9] << 8;
- if(requester != node_address) {
- header->to_node = requester;
- write(header->to_node,USER_TX_TO_PHYSICAL_ADDRESS);
- wait_ms(10);
+ // Is this for us?
+ if ( header->to_node == node_address ){
+
+ if(header->type == NETWORK_PING){
+ continue;
+ }
+ if(header->type == NETWORK_ADDR_RESPONSE ){
+ uint16_t requester = 04444;
+ if(requester != node_address){
+ header->to_node = requester;
+ write(header->to_node,USER_TX_TO_PHYSICAL_ADDRESS);
+ wait_ms(10);
write(header->to_node,USER_TX_TO_PHYSICAL_ADDRESS);
- //printf("Fwd add response to 0%o\n",requester);
- continue;
- }
- }
- if(header->type == NETWORK_REQ_ADDRESS && node_address) {
- //printf("Fwd add req to 0\n");
- header->from_node = node_address;
- header->to_node = 0;
- write(header->to_node,TX_NORMAL);
- continue;
- }
+ //printf("Fwd add response to 0%o\n",requester);
+ continue;
+ }
+ }
+ if(header->type == NETWORK_REQ_ADDRESS && node_address){
+ //printf("Fwd add req to 0\n");
+ header->from_node = node_address;
+ header->to_node = 0;
+ write(header->to_node,TX_NORMAL);
+ continue;
+ }
+
+ if( (returnSysMsgs && header->type > 127) || header->type == NETWORK_ACK ){
+ IF_SERIAL_DEBUG_ROUTING( printf_P(PSTR("%lu MAC: System payload rcvd %d\n"),millis(),returnVal); );
+ //if( (header->type < 148 || header->type > 150) && header->type != NETWORK_MORE_FRAGMENTS_NACK && header->type != EXTERNAL_DATA_TYPE && header->type!= NETWORK_LAST_FRAGMENT){
+ if( header->type != NETWORK_FIRST_FRAGMENT && header->type != NETWORK_MORE_FRAGMENTS && header->type != NETWORK_MORE_FRAGMENTS_NACK && header->type != EXTERNAL_DATA_TYPE && header->type!= NETWORK_LAST_FRAGMENT){
+ return returnVal;
+ }
+ }
- if( (returnSysMsgs && header->type > 127) || header->type == NETWORK_ACK ) {
- //IF_SERIAL_DEBUG_ROUTING( printf_P(PSTR("%lu MAC: System payload rcvd %d\n"),millis(),returnVal); );
- //if( (header->type < 148 || header->type > 150) && header->type != NETWORK_MORE_FRAGMENTS_NACK && header->type != EXTERNAL_DATA_TYPE && header->type!= NETWORK_LAST_FRAGMENT){
- if( header->type != NETWORK_FIRST_FRAGMENT && header->type != NETWORK_MORE_FRAGMENTS && header->type != NETWORK_MORE_FRAGMENTS_NACK && header->type != EXTERNAL_DATA_TYPE && header->type!= NETWORK_LAST_FRAGMENT) {
- return returnVal;
- }
- }
+ if( enqueue(header) == 2 ){ //External data received
+ #if defined (SERIAL_DEBUG_MINIMAL)
+ printf("ret ext\n");
+ #endif
+ return EXTERNAL_DATA_TYPE;
+ }
+ }else{
- if( enqueue(header) == 2 ) { //External data received
-#if defined (SERIAL_DEBUG_MINIMAL)
- printf("ret ext\n");
-#endif
- return EXTERNAL_DATA_TYPE;
- }
- } else {
-
-#if defined (RF24NetworkMulticast)
+ #if defined (RF24NetworkMulticast)
- if( header->to_node == 0100) {
-
-
- if(header->type == NETWORK_POLL ) {
- //Serial.println("Send poll");
- header->to_node = header->from_node;
- header->from_node = node_address;
- //delay((node_address%5)*3);
- write(header->to_node,USER_TX_TO_PHYSICAL_ADDRESS);
- continue;
- }
- uint8_t val = enqueue(header);
+ if( header->to_node == 0100){
+
- if(multicastRelay) {
- //IF_SERIAL_DEBUG_ROUTING( printf_P(PSTR("%u MAC: FWD multicast frame from 0%o to level %u\n"),millis(),header->from_node,multicast_level+1); );
- write(levelToAddress(multicast_level)<<3,4);
- }
- if( val == 2 ) { //External data received
- //Serial.println("ret ext multicast");
- return EXTERNAL_DATA_TYPE;
- }
+ if(header->type == NETWORK_POLL ){
+ if( !(networkFlags & FLAG_NO_POLL) && node_address != 04444 ){
+ header->to_node = header->from_node;
+ header->from_node = node_address;
+ wait_ms(parent_pipe);
+ write(header->to_node,USER_TX_TO_PHYSICAL_ADDRESS);
+ }
+ continue;
+ }
+ uint8_t val = enqueue(header);
+
+ if(multicastRelay){
+ IF_SERIAL_DEBUG_ROUTING( printf_P(PSTR("%u MAC: FWD multicast frame from 0%o to level %u\n"),millis(),header->from_node,multicast_level+1); );
+ write(levelToAddress(multicast_level)<<3,4);
+ }
+ if( val == 2 ){ //External data received
+ //Serial.println("ret ext multicast");
+ return EXTERNAL_DATA_TYPE;
+ }
- } else {
- write(header->to_node,1); //Send it on, indicate it is a routed payload
- }
-#else
- write(header->to_node,1); //Send it on, indicate it is a routed payload
-#endif
- }
-
- }
- return returnVal;
+ }else{
+ write(header->to_node,1); //Send it on, indicate it is a routed payload
+ }
+ #else
+ write(header->to_node,1); //Send it on, indicate it is a routed payload
+ #endif
+ }
+
+ }
+ return returnVal;
}
/******************************************************************/
uint8_t RF24Network::enqueue(RF24NetworkHeader* header)
{
- bool result = false;
- uint8_t message_size = frame_size - sizeof(RF24NetworkHeader);
-
- IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Enqueue @%x "),millis(),next_frame-frame_queue));
-
-#if !defined ( DISABLE_FRAGMENTATION )
+ bool result = false;
+ uint16_t message_size = frame_size - sizeof(RF24NetworkHeader);
+
+ IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Enqueue @%x "),mainTimer.read_ms(),next_frame-frame_queue));
+
+#if !defined ( DISABLE_FRAGMENTATION )
- bool isFragment = header->type == NETWORK_FIRST_FRAGMENT || header->type == NETWORK_MORE_FRAGMENTS || header->type == NETWORK_LAST_FRAGMENT || header->type == NETWORK_MORE_FRAGMENTS_NACK ;
+ bool isFragment = header->type == NETWORK_FIRST_FRAGMENT || header->type == NETWORK_MORE_FRAGMENTS || header->type == NETWORK_LAST_FRAGMENT || header->type == NETWORK_MORE_FRAGMENTS_NACK ;
- if(isFragment) {
+ if(isFragment){
- if(header->type == NETWORK_FIRST_FRAGMENT) {
- // Drop frames exceeding max size and duplicates (MAX_PAYLOAD_SIZE needs to be divisible by 24)
- if(header->reserved > (MAX_PAYLOAD_SIZE / max_frame_payload_size) ) {
+ if(header->type == NETWORK_FIRST_FRAGMENT){
+ // Drop frames exceeding max size and duplicates (MAX_PAYLOAD_SIZE needs to be divisible by 24)
+ if(header->reserved > (MAX_PAYLOAD_SIZE / max_frame_payload_size) ){
-#if defined (SERIAL_DEBUG_FRAGMENTATION) || defined (SERIAL_DEBUG_MINIMAL)
- printf_P(PSTR("Frag frame with %d frags exceeds MAX_PAYLOAD_SIZE or out of sequence\n"),header->reserved);
-#endif
- frag_queue.header.reserved = 0;
- return false;
- } else if(frag_queue.header.id == header->id && frag_queue.header.from_node == header->from_node) {
- return true;
- }
-
- if( (header->reserved * 24) > (MAX_PAYLOAD_SIZE - (next_frame-frame_queue)) ) {
- networkFlags |= FLAG_HOLD_INCOMING;
- radio.stopListening();
- }
-
- memcpy(&frag_queue,&frame_buffer,8);
- memcpy(frag_queue.message_buffer,frame_buffer+sizeof(RF24NetworkHeader),message_size);
-
+ #if defined (SERIAL_DEBUG_FRAGMENTATION) || defined (SERIAL_DEBUG_MINIMAL)
+ printf_P(PSTR("Frag frame with %d frags exceeds MAX_PAYLOAD_SIZE or out of sequence\n"),header->reserved);
+ #endif
+ frag_queue.header.reserved = 0;
+ return false;
+ }else
+ if(frag_queue.header.id == header->id && frag_queue.header.from_node == header->from_node){
+ return true;
+ }
+
+ if( (header->reserved * 24) > (MAX_PAYLOAD_SIZE - (next_frame-frame_queue)) ){
+ networkFlags |= FLAG_HOLD_INCOMING;
+ radio.stopListening();
+ }
+
+ memcpy(&frag_queue,&frame_buffer,8);
+ memcpy(frag_queue.message_buffer,frame_buffer+sizeof(RF24NetworkHeader),message_size);
+
//IF_SERIAL_DEBUG_FRAGMENTATION( Serial.print(F("queue first, total frags ")); Serial.println(header->reserved); );
- //Store the total size of the stored frame in message_size
- frag_queue.message_size = message_size;
- --frag_queue.header.reserved;
-
- IF_SERIAL_DEBUG_FRAGMENTATION_L2( for(int i=0; i<frag_queue.message_size; i++) {
- Serial.println(frag_queue.message_buffer[i],HEX);
- } );
-
- return true;
-
- } else // NETWORK_MORE_FRAGMENTS
- if(header->type == NETWORK_LAST_FRAGMENT || header->type == NETWORK_MORE_FRAGMENTS || header->type == NETWORK_MORE_FRAGMENTS_NACK) {
+ //Store the total size of the stored frame in message_size
+ frag_queue.message_size = message_size;
+ --frag_queue.header.reserved;
+
+IF_SERIAL_DEBUG_FRAGMENTATION_L2( for(int i=0; i<frag_queue.message_size;i++){ Serial.println(frag_queue.message_buffer[i],HEX); } );
+
+ return true;
- if(frag_queue.message_size + message_size > MAX_PAYLOAD_SIZE) {
-#if defined (SERIAL_DEBUG_FRAGMENTATION) || defined (SERIAL_DEBUG_MINIMAL)
- Serial.print(F("Drop frag "));
- Serial.print(header->reserved);
- Serial.println(F(" Size exceeds max"));
-#endif
- frag_queue.header.reserved=0;
- return false;
- }
- if( frag_queue.header.reserved == 0 || (header->type != NETWORK_LAST_FRAGMENT && header->reserved != frag_queue.header.reserved ) || frag_queue.header.id != header->id ) {
-#if defined (SERIAL_DEBUG_FRAGMENTATION) || defined (SERIAL_DEBUG_MINIMAL)
- Serial.print(F("Drop frag "));
- Serial.print(header->reserved);
- //Serial.print(F(" header id ")); Serial.print(header->id);
- Serial.println(F(" Out of order "));
-#endif
- return false;
- }
-
- memcpy(frag_queue.message_buffer+frag_queue.message_size,frame_buffer+sizeof(RF24NetworkHeader),message_size);
- frag_queue.message_size += message_size;
-
- if(header->type != NETWORK_LAST_FRAGMENT) {
- --frag_queue.header.reserved;
- return true;
- }
- frag_queue.header.reserved = 0;
- frag_queue.header.type = header->reserved;
+ }else // NETWORK_MORE_FRAGMENTS
+ if(header->type == NETWORK_LAST_FRAGMENT || header->type == NETWORK_MORE_FRAGMENTS || header->type == NETWORK_MORE_FRAGMENTS_NACK){
+
+ if(frag_queue.message_size + message_size > MAX_PAYLOAD_SIZE){
+ #if defined (SERIAL_DEBUG_FRAGMENTATION) || defined (SERIAL_DEBUG_MINIMAL)
+ Serial.print(F("Drop frag ")); Serial.print(header->reserved);
+ Serial.println(F(" Size exceeds max"));
+ #endif
+ frag_queue.header.reserved=0;
+ return false;
+ }
+ if( frag_queue.header.reserved == 0 || (header->type != NETWORK_LAST_FRAGMENT && header->reserved != frag_queue.header.reserved ) || frag_queue.header.id != header->id ){
+ #if defined (SERIAL_DEBUG_FRAGMENTATION) || defined (SERIAL_DEBUG_MINIMAL)
+ Serial.print(F("Drop frag ")); Serial.print(header->reserved);
+ //Serial.print(F(" header id ")); Serial.print(header->id);
+ Serial.println(F(" Out of order "));
+ #endif
+ return false;
+ }
+
+ memcpy(frag_queue.message_buffer+frag_queue.message_size,frame_buffer+sizeof(RF24NetworkHeader),message_size);
+ frag_queue.message_size += message_size;
+
+ if(header->type != NETWORK_LAST_FRAGMENT){
+ --frag_queue.header.reserved;
+ return true;
+ }
+ frag_queue.header.reserved = 0;
+ frag_queue.header.type = header->reserved;
+
+IF_SERIAL_DEBUG_FRAGMENTATION( printf_P(PSTR("fq 3: %d\n"),frag_queue.message_size); );
+IF_SERIAL_DEBUG_FRAGMENTATION_L2(for(int i=0; i< frag_queue.message_size;i++){ Serial.println(frag_queue.message_buffer[i],HEX); } );
+
+ //Frame assembly complete, copy to main buffer if OK
+ if(frag_queue.header.type == EXTERNAL_DATA_TYPE){
+ return 2;
+ }
+ #if defined (DISABLE_USER_PAYLOADS)
+ return 0;
+ #endif
+
+ if(MAX_PAYLOAD_SIZE - (next_frame-frame_queue) >= frag_queue.message_size){
+ memcpy(next_frame,&frag_queue,10);
+ memcpy(next_frame+10,frag_queue.message_buffer,frag_queue.message_size);
+ next_frame += (10+frag_queue.message_size);
+ #if !defined(ARDUINO_ARCH_AVR)
+ if(uint8_t padding = (frag_queue.message_size+10)%4){
+ next_frame += 4 - padding;
+ }
+ #endif
+ IF_SERIAL_DEBUG_FRAGMENTATION( printf_P(PSTR("enq size %d\n"),frag_queue.message_size); );
+ return true;
+ }else{
+ radio.stopListening();
+ networkFlags |= FLAG_HOLD_INCOMING;
+ }
+ IF_SERIAL_DEBUG_FRAGMENTATION( printf_P(PSTR("Drop frag payload, queue full\n")); );
+ return false;
+ }//If more or last fragments
- IF_SERIAL_DEBUG_FRAGMENTATION( printf(PSTR("fq 3: %d\n"),frag_queue.message_size); );
- IF_SERIAL_DEBUG_FRAGMENTATION_L2(for(int i=0; i< frag_queue.message_size; i++) {
- Serial.println(frag_queue.message_buffer[i],HEX);
- } );
-
- //Frame assembly complete, copy to main buffer if OK
- if(frag_queue.header.type == EXTERNAL_DATA_TYPE) {
- return 2;
- }
-#if defined (DISABLE_USER_PAYLOADS)
- return 0;
-#endif
+ }else //else is not a fragment
+ #endif // End fragmentation enabled
- if(MAX_PAYLOAD_SIZE - (next_frame-frame_queue) >= frag_queue.message_size) {
- memcpy(next_frame,&frag_queue,10);
- memcpy(next_frame+10,frag_queue.message_buffer,frag_queue.message_size);
- next_frame += (10+frag_queue.message_size);
- IF_SERIAL_DEBUG_FRAGMENTATION( printf(PSTR("enq size %d\n"),frag_queue.message_size); );
- return true;
- } else {
- radio.stopListening();
- networkFlags |= FLAG_HOLD_INCOMING;
- }
- IF_SERIAL_DEBUG_FRAGMENTATION( printf(PSTR("Drop frag payload, queue full\n")); );
- return false;
- }//If more or last fragments
-
- } else //else is not a fragment
-#endif // End fragmentation enabled
-
- // Copy the current frame into the frame queue
+ // Copy the current frame into the frame queue
#if !defined( DISABLE_FRAGMENTATION )
- if(header->type == EXTERNAL_DATA_TYPE) {
- memcpy(&frag_queue,&frame_buffer,8);
- frag_queue.message_buffer = frame_buffer+sizeof(RF24NetworkHeader);
- frag_queue.message_size = message_size;
- return 2;
- }
-#endif
+ if(header->type == EXTERNAL_DATA_TYPE){
+ memcpy(&frag_queue,&frame_buffer,8);
+ frag_queue.message_buffer = frame_buffer+sizeof(RF24NetworkHeader);
+ frag_queue.message_size = message_size;
+ return 2;
+ }
+#endif
#if defined (DISABLE_USER_PAYLOADS)
- return 0;
-}
+ return 0;
+ }
#else
- if(message_size + (next_frame-frame_queue) <= MAIN_BUFFER_SIZE)
- {
- memcpy(next_frame,&frame_buffer,8);
- RF24NetworkFrame *f = (RF24NetworkFrame*)next_frame;
- f->message_size = message_size;
- memcpy(next_frame+10,frame_buffer+sizeof(RF24NetworkHeader),message_size);
-
- IF_SERIAL_DEBUG_FRAGMENTATION( for(int i=0; i<message_size; i++) {
- Serial.print(next_frame[i],HEX);
- Serial.print(" : ");
- }
- Serial.println(""); );
-
- next_frame += (message_size + 10);
- IF_SERIAL_DEBUG_FRAGMENTATION( Serial.print("Enq "); Serial.println(next_frame-frame_queue); );//printf_P(PSTR("enq %d\n"),next_frame-frame_queue); );
-
- result = true;
- } else
- {
- result = false;
- IF_SERIAL_DEBUG(printf_P(PSTR("NET **Drop Payload** Buffer Full")));
+ if(message_size + (next_frame-frame_queue) <= MAIN_BUFFER_SIZE){
+ memcpy(next_frame,&frame_buffer,8);
+ memcpy(next_frame+8,&message_size,2);
+ memcpy(next_frame+10,frame_buffer+8,message_size);
+
+ //IF_SERIAL_DEBUG_FRAGMENTATION( for(int i=0; i<message_size;i++){ Serial.print(next_frame[i],HEX); Serial.print(" : "); } Serial.println(""); );
+
+ next_frame += (message_size + 10);
+ #if !defined(ARDUINO_ARCH_AVR)
+ if(uint8_t padding = (message_size+10)%4){
+ next_frame += 4 - padding;
}
- return result;
+ #endif
+ //IF_SERIAL_DEBUG_FRAGMENTATION( Serial.print("Enq "); Serial.println(next_frame-frame_queue); );//printf_P(PSTR("enq %d\n"),next_frame-frame_queue); );
+
+ result = true;
+ }else{
+ result = false;
+ IF_SERIAL_DEBUG(printf_P(PSTR("NET **Drop Payload** Buffer Full")));
+ }
+ return result;
}
-#endif //USER_PAYLOADS_ENABLED
-
+#endif
/******************************************************************/
bool RF24Network::available(void)
{
- // Are there frames on the queue for us?
- return (next_frame > frame_queue);
+ // Are there frames on the queue for us?
+ return (next_frame > frame_queue);
}
@@ -401,540 +405,548 @@
uint16_t RF24Network::parent() const
{
- if ( node_address == 0 )
- return -1;
- else
- return parent_node;
+ if ( node_address == 0 )
+ return -1;
+ else
+ return parent_node;
}
/******************************************************************/
/*uint8_t RF24Network::peekData(){
-
- return frame_queue[0];
+
+ return frame_queue[0];
}*/
uint16_t RF24Network::peek(RF24NetworkHeader& header)
{
- if ( available() ) {
- RF24NetworkFrame *frame = (RF24NetworkFrame*)(frame_queue);
- memcpy(&header,&frame->header,sizeof(RF24NetworkHeader));
- return frame->message_size;
+ if ( available() )
+ {
- }
- return 0;
+ RF24NetworkFrame *frame = (RF24NetworkFrame*)(frame_queue);
+ memcpy(&header,&frame->header,sizeof(RF24NetworkHeader));
+ uint16_t msg_size;
+ memcpy(&msg_size,frame+8,2);
+ return msg_size;
+ }
+ return 0;
}
/******************************************************************/
uint16_t RF24Network::read(RF24NetworkHeader& header,void* message, uint16_t maxlen)
{
- uint16_t bufsize = 0;
-
- if ( available() ) {
+ uint16_t bufsize = 0;
- memcpy(&header,frame_queue,8);
- RF24NetworkFrame *f = (RF24NetworkFrame*)frame_queue;
- bufsize = f->message_size;
+
+ if ( available() )
+ {
+
+ memcpy(&header,frame_queue,8);
+ memcpy(&bufsize,frame_queue+8,2);
- if (maxlen > 0) {
- maxlen = min(maxlen,bufsize);
- memcpy(message,frame_queue+10,maxlen);
- IF_SERIAL_DEBUG(printf("%lu: NET message size %d\n",millis(),bufsize););
+ if (maxlen > 0)
+ {
+ maxlen = rf24_min(maxlen,bufsize);
+ memcpy(message,frame_queue+10,maxlen);
+ IF_SERIAL_DEBUG(printf("%lu: NET message size %d\n",millis(),bufsize););
- IF_SERIAL_DEBUG( uint16_t len = maxlen; printf_P(PSTR("%lu: NET r message "),millis()); const uint8_t* charPtr = reinterpret_cast<const uint8_t*>(message); while(len--) {
- printf("%02x ",charPtr[len]);
- }
- printf_P(PSTR("\n\r") ) );
+
+ IF_SERIAL_DEBUG( uint16_t len = maxlen; printf_P(PSTR("%lu: NET r message "),millis());const uint8_t* charPtr = reinterpret_cast<const uint8_t*>(message);while(len--){ printf("%02x ",charPtr[len]);} printf_P(PSTR("\n\r") ) );
+
+ }
+ memmove(frame_queue,frame_queue+bufsize+10,sizeof(frame_queue)- bufsize);
+ next_frame-=bufsize+10;
+
+ if(uint8_t padding = (bufsize+10)%4){
+ next_frame -= 4 - padding;
+ }
+
+ //IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Received %s\n\r"),millis(),header.toString()));
+ }
- }
- memmove(frame_queue,frame_queue+bufsize+10,sizeof(frame_queue)- bufsize);
- next_frame-=bufsize+10;
-
- //IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Received %s\n\r"),millis(),header.toString()));
- }
-
- return bufsize;
+ return bufsize;
}
#if defined RF24NetworkMulticast
/******************************************************************/
-bool RF24Network::multicast(RF24NetworkHeader& header,const void* message, uint16_t len, uint8_t level)
-{
- // Fill out the header
- header.to_node = 0100;
- header.from_node = node_address;
- return write(header, message, len, levelToAddress(level));
+bool RF24Network::multicast(RF24NetworkHeader& header,const void* message, uint16_t len, uint8_t level){
+ // Fill out the header
+ header.to_node = 0100;
+ header.from_node = node_address;
+ return write(header, message, len, levelToAddress(level));
}
#endif
/******************************************************************/
-bool RF24Network::write(RF24NetworkHeader& header,const void* message, uint16_t len)
-{
- return write(header,message,len,070);
+bool RF24Network::write(RF24NetworkHeader& header,const void* message, uint16_t len){
+ return write(header,message,len,070);
}
/******************************************************************/
-bool RF24Network::write(RF24NetworkHeader& header,const void* message, uint16_t len, uint16_t writeDirect)
-{
-
+bool RF24Network::write(RF24NetworkHeader& header,const void* message, uint16_t len, uint16_t writeDirect){
+
//Allows time for requests (RF24Mesh) to get through between failed writes on busy nodes
- while(rf24netTimer.read_ms()-txTime < 25) {
- if(update() > 127) {
- break;
- }
- }
- wait_us(200);
+ while(mainTimer.read_ms()-txTime < 25){ if(update() > 127){break;} }
+ wait_us(200);
#if defined (DISABLE_FRAGMENTATION)
frame_size = rf24_min(len+sizeof(RF24NetworkHeader),MAX_FRAME_SIZE);
- return _write(header,message,rf24_min(len,max_frame_payload_size),writeDirect);
-#else
- if(len <= max_frame_payload_size) {
- //Normal Write (Un-Fragmented)
- frame_size = len + sizeof(RF24NetworkHeader);
- if(_write(header,message,len,writeDirect)) {
- return 1;
- }
- txTime = rf24netTimer.read_ms();
- return 0;
+ return _write(header,message,rf24_min(len,max_frame_payload_size),writeDirect);
+#else
+ if(len <= max_frame_payload_size){
+ //Normal Write (Un-Fragmented)
+ frame_size = len + sizeof(RF24NetworkHeader);
+ if(_write(header,message,len,writeDirect)){
+ return 1;
}
- //Check payload size
- if (len > MAX_PAYLOAD_SIZE) {
- IF_SERIAL_DEBUG(printf("%u: NET write message failed. Given 'len' %d is bigger than the MAX Payload size %i\n\r",millis(),len,MAX_PAYLOAD_SIZE););
- return false;
- }
+ txTime = mainTimer.read_ms();
+ return 0;
+ }
+ //Check payload size
+ if (len > MAX_PAYLOAD_SIZE) {
+ IF_SERIAL_DEBUG(printf("%u: NET write message failed. Given 'len' %d is bigger than the MAX Payload size %i\n\r",millis(),len,MAX_PAYLOAD_SIZE););
+ return false;
+ }
+
+ //Divide the message payload into chunks of max_frame_payload_size
+ uint8_t fragment_id = (len % max_frame_payload_size != 0) + ((len ) / max_frame_payload_size); //the number of fragments to send = ceil(len/max_frame_payload_size)
+
+ uint8_t msgCount = 0;
- //Divide the message payload into chunks of max_frame_payload_size
- uint8_t fragment_id = (len % max_frame_payload_size != 0) + ((len ) / max_frame_payload_size); //the number of fragments to send = ceil(len/max_frame_payload_size)
+ //IF_SERIAL_DEBUG_FRAGMENTATION(printf("%lu: FRG Total message fragments %d\n\r",millis(),fragment_id););
+
+ if(header.to_node != 0100){
+ networkFlags |= FLAG_FAST_FRAG;
+ #if !defined (DUAL_HEAD_RADIO)
+ radio.stopListening();
+ #endif
+ }
+
+ uint8_t retriesPerFrag = 0;
+ uint8_t type = header.type;
+ bool ok = 0;
+
+ while (fragment_id > 0) {
+
+ //Copy and fill out the header
+ //RF24NetworkHeader fragmentHeader = header;
+ header.reserved = fragment_id;
- uint8_t msgCount = 0;
-
- IF_SERIAL_DEBUG_FRAGMENTATION(printf("%lu: FRG Total message fragments %d\n\r",millis(),fragment_id););
+ if (fragment_id == 1) {
+ header.type = NETWORK_LAST_FRAGMENT; //Set the last fragment flag to indicate the last fragment
+ header.reserved = type; //The reserved field is used to transmit the header type
+ } else {
+ if (msgCount == 0) {
+ header.type = NETWORK_FIRST_FRAGMENT;
+ }else{
+ header.type = NETWORK_MORE_FRAGMENTS; //Set the more fragments flag to indicate a fragmented frame
+ }
+ }
+
+ uint16_t offset = msgCount*max_frame_payload_size;
+ uint16_t fragmentLen = rf24_min((uint16_t)(len-offset),max_frame_payload_size);
- if(header.to_node != 0100) {
- networkFlags |= FLAG_FAST_FRAG;
-#if !defined (DUAL_HEAD_RADIO)
- radio.stopListening();
-#endif
+ //Try to send the payload chunk with the copied header
+ frame_size = sizeof(RF24NetworkHeader)+fragmentLen;
+ ok = _write(header,((char *)message)+offset,fragmentLen,writeDirect);
+
+ if (!ok) {
+ wait_ms(2);
+ ++retriesPerFrag;
+
+ }else{
+ retriesPerFrag = 0;
+ fragment_id--;
+ msgCount++;
+ }
+
+ //if(writeDirect != 070){ delay(2); } //Delay 2ms between sending multicast payloads
+
+ if (!ok && retriesPerFrag >= 3) {
+ //IF_SERIAL_DEBUG_FRAGMENTATION(printf("%lu: FRG TX with fragmentID '%d' failed after %d fragments. Abort.\n\r",millis(),fragment_id,msgCount););
+ break;
}
- uint8_t retriesPerFrag = 0;
- uint8_t type = header.type;
-
- while (fragment_id > 0) {
-
- //Copy and fill out the header
- //RF24NetworkHeader fragmentHeader = header;
- header.reserved = fragment_id;
-
- if (fragment_id == 1) {
- header.type = NETWORK_LAST_FRAGMENT; //Set the last fragment flag to indicate the last fragment
- header.reserved = type; //The reserved field is used to transmit the header type
- } else {
- if (msgCount == 0) {
- header.type = NETWORK_FIRST_FRAGMENT;
- } else {
- header.type = NETWORK_MORE_FRAGMENTS; //Set the more fragments flag to indicate a fragmented frame
- }
- }
-
- uint16_t offset = msgCount*max_frame_payload_size;
- uint16_t fragmentLen = rf24_min((uint16_t)(len-offset),max_frame_payload_size);
-
- //Try to send the payload chunk with the copied header
- frame_size = sizeof(RF24NetworkHeader)+fragmentLen;
- bool ok = _write(header,((char *)message)+offset,fragmentLen,writeDirect);
-
- if (!ok) {
- wait_ms(2);
- ++retriesPerFrag;
+
+ //Message was successful sent
+ #if defined SERIAL_DEBUG_FRAGMENTATION_L2
+ printf("%lu: FRG message transmission with fragmentID '%d' sucessfull.\n\r",mainTimer.read_ms(),fragment_id);
+ #endif
- } else {
- retriesPerFrag = 0;
- fragment_id--;
- msgCount++;
- }
-
- if(writeDirect != 070) {
- wait_ms(2); //Delay 2ms between sending multicast payloads
- }
-
- if (!ok && retriesPerFrag >= 3) {
- IF_SERIAL_DEBUG_FRAGMENTATION(printf("%lu: FRG TX with fragmentID '%d' failed after %d fragments. Abort.\n\r",millis(),fragment_id,msgCount););
- break;
- }
-
- //Message was successful sent
-#if defined SERIAL_DEBUG_FRAGMENTATION_L2
- printf("%lu: FRG message transmission with fragmentID '%d' sucessfull.\n\r",millis(),fragment_id);
-#endif
+ }
+ header.type = type;
+ #if !defined (DUAL_HEAD_RADIO)
+ if(networkFlags & FLAG_FAST_FRAG){
+ ok = radio.txStandBy(txTimeout);
+ radio.startListening();
+ radio.setAutoAck(0,0);
+ }
+ networkFlags &= ~FLAG_FAST_FRAG;
+
+ if(!ok){
+ return false;
+ }
+ #endif
+ //int frag_delay = uint8_t(len/48);
+ //delay( rf24_min(len/48,20));
- }
-
-#if !defined (DUAL_HEAD_RADIO)
- if(networkFlags & FLAG_FAST_FRAG) {
- radio.startListening();
- }
-#endif
- networkFlags &= ~FLAG_FAST_FRAG
- //int frag_delay = uint8_t(len/48);
- //delay( rf24_min(len/48,20));
-
- //Return true if all the chunks where sent successfully
-
- IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG total message fragments sent %i. \n",millis(),msgCount); );
- if(fragment_id > 0) {
- txTime = rf24netTimer.read_ms();
- return false;
- }
- return true;
-
+ //Return true if all the chunks where sent successfully
+
+ IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG total message fragments sent %i. \n",mainTimer.read_ms(),msgCount); );
+ if(fragment_id > 0){
+ txTime = mainTimer.read_ms();
+ return false;
+ }
+ return true;
+
#endif //Fragmentation enabled
}
/******************************************************************/
bool RF24Network::_write(RF24NetworkHeader& header,const void* message, uint16_t len, uint16_t writeDirect)
{
- // Fill out the header
- header.from_node = node_address;
-
- // Build the full frame to send
- memcpy(frame_buffer,&header,sizeof(RF24NetworkHeader));
-
- IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Sending %s\n\r"),millis(),header.toString()));
+ // Fill out the header
+ header.from_node = node_address;
+
+ // Build the full frame to send
+ memcpy(frame_buffer,&header,sizeof(RF24NetworkHeader));
+
+ IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Sending %s\n\r"),mainTimer.read_ms(),header.toString()));
- if (len) {
-
- memcpy(frame_buffer + sizeof(RF24NetworkHeader),message,len);
-
- IF_SERIAL_DEBUG(uint16_t tmpLen = len; printf_P(PSTR("%lu: NET message "),millis()); const uint8_t* charPtr = reinterpret_cast<const uint8_t*>(message); while(tmpLen--) {
- printf("%02x ",charPtr[tmpLen]);
- }
- printf_P(PSTR("\n\r") ) );
-
- }
+ if (len){
+ memcpy(frame_buffer + sizeof(RF24NetworkHeader),message,len);
+
+ IF_SERIAL_DEBUG(uint16_t tmpLen = len;printf_P(PSTR("%lu: NET message "),mainTimer.read_ms());const uint8_t* charPtr = reinterpret_cast<const uint8_t*>(message);while(tmpLen--){ printf("%02x ",charPtr[tmpLen]);} printf_P(PSTR("\n\r") ) );
+ }
- // If the user is trying to send it to himself
- /*if ( header.to_node == node_address ){
- #if defined (RF24_LINUX)
- RF24NetworkFrame frame = RF24NetworkFrame(header,message,rf24_min(MAX_FRAME_SIZE-sizeof(RF24NetworkHeader),len));
- #else
- RF24NetworkFrame frame(header,len);
- #endif
- // Just queue it in the received queue
- return enqueue(frame);
- }*/
- // Otherwise send it out over the air
-
-
- if(writeDirect != 070) {
- uint8_t sendType = USER_TX_TO_LOGICAL_ADDRESS; // Payload is multicast to the first node, and routed normally to the next
-
- if(header.to_node == 0100) {
- sendType = USER_TX_MULTICAST;
- }
- if(header.to_node == writeDirect) {
- sendType = USER_TX_TO_PHYSICAL_ADDRESS; // Payload is multicast to the first node, which is the recipient
- }
- return write(writeDirect,sendType);
- }
- return write(header.to_node,TX_NORMAL);
-
+ // If the user is trying to send it to himself
+ /*if ( header.to_node == node_address ){
+ #if defined (RF24_LINUX)
+ RF24NetworkFrame frame = RF24NetworkFrame(header,message,rf24_min(MAX_FRAME_SIZE-sizeof(RF24NetworkHeader),len));
+ #else
+ RF24NetworkFrame frame(header,len);
+ #endif
+ // Just queue it in the received queue
+ return enqueue(frame);
+ }*/
+ // Otherwise send it out over the air
+
+
+ if(writeDirect != 070){
+ uint8_t sendType = USER_TX_TO_LOGICAL_ADDRESS; // Payload is multicast to the first node, and routed normally to the next
+
+ if(header.to_node == 0100){
+ sendType = USER_TX_MULTICAST;
+ }
+ if(header.to_node == writeDirect){
+ sendType = USER_TX_TO_PHYSICAL_ADDRESS; // Payload is multicast to the first node, which is the recipient
+ }
+ return write(writeDirect,sendType);
+ }
+ return write(header.to_node,TX_NORMAL);
+
}
/******************************************************************/
bool RF24Network::write(uint16_t to_node, uint8_t directTo) // Direct To: 0 = First Payload, standard routing, 1=routed payload, 2=directRoute to host, 3=directRoute to Route
{
- bool ok = false;
- bool isAckType = false;
- if(frame_buffer[6] > 64 && frame_buffer[6] < 192 ) {
- isAckType=true;
- }
+ bool ok = false;
+ bool isAckType = false;
+ if(frame_buffer[6] > 64 && frame_buffer[6] < 192 ){ isAckType=true; }
+
+ /*if( ( (frame_buffer[7] % 2) && frame_buffer[6] == NETWORK_MORE_FRAGMENTS) ){
+ isAckType = 0;
+ }*/
+
+ // Throw it away if it's not a valid address
+ if ( !is_valid_address(to_node) )
+ return false;
+
+ //Load info into our conversion structure, and get the converted address info
+ logicalToPhysicalStruct conversion = { to_node,directTo,0};
+ logicalToPhysicalAddress(&conversion);
+
- /*if( ( (frame_buffer[7] % 2) && frame_buffer[6] == NETWORK_MORE_FRAGMENTS) ){
- isAckType = 0;
- }*/
+ IF_SERIAL_DEBUG(printf_P(PSTR("%lu: MAC Sending to 0%o via 0%o on pipe %x\n\r"),mainTimer.read_ms(),to_node,conversion.send_node,conversion.send_pipe));
- // Throw it away if it's not a valid address
- if ( !is_valid_address(to_node) )
- return false;
+ /**Write it*/
+ ok=write_to_pipe(conversion.send_node, conversion.send_pipe, conversion.multicast);
+
+
+ if(!ok){
- //Load info into our conversion structure, and get the converted address info
- logicalToPhysicalStruct conversion = { to_node,directTo,0};
- logicalToPhysicalAddress(&conversion);
-
-
- IF_SERIAL_DEBUG(printf_P(PSTR("%lu: MAC Sending to 0%o via 0%o on pipe %x\n\r"),millis(),to_node,conversion.send_node,conversion.send_pipe));
+ IF_SERIAL_DEBUG_ROUTING( printf_P(PSTR("%lu: MAC Send fail to 0%o via 0%o on pipe %x\n\r"),mainTimer.read_ms(),to_node,conversion.send_node,conversion.send_pipe););
+ }
+
+
+ if( directTo == TX_ROUTED && ok && conversion.send_node == to_node && isAckType){
+
+ RF24NetworkHeader* header = (RF24NetworkHeader*)&frame_buffer;
+ header->type = NETWORK_ACK; // Set the payload type to NETWORK_ACK
+ header->to_node = header->from_node; // Change the 'to' address to the 'from' address
- /**Write it*/
- ok=write_to_pipe(conversion.send_node, conversion.send_pipe, conversion.multicast);
-
+ conversion.send_node = header->from_node;
+ conversion.send_pipe = TX_ROUTED;
+ conversion.multicast = 0;
+ logicalToPhysicalAddress(&conversion);
+
+ //Write the data using the resulting physical address
+ frame_size = sizeof(RF24NetworkHeader);
+ write_to_pipe(conversion.send_node, conversion.send_pipe, conversion.multicast);
+
+ //dynLen=0;
- if(!ok) {
- IF_SERIAL_DEBUG_ROUTING( printf_P(PSTR("%lu: MAC Send fail to 0%o via 0%o on pipe %x\n\r"),millis(),to_node,conversion.send_node,conversion.send_pipe););
- }
+ IF_SERIAL_DEBUG_ROUTING( printf_P(PSTR("%lu MAC: Route OK to 0%o ACK sent to 0%o\n"),mainTimer.read_ms(),to_node,header->from_node); );
+
+ }
+
- if( directTo == TX_ROUTED && ok && conversion.send_node == to_node && isAckType) {
-
- RF24NetworkHeader* header = (RF24NetworkHeader*)&frame_buffer;
- header->type = NETWORK_ACK; // Set the payload type to NETWORK_ACK
- header->to_node = header->from_node; // Change the 'to' address to the 'from' address
-
- conversion.send_node = header->from_node;
- conversion.send_pipe = TX_ROUTED;
- conversion.multicast = 0;
- logicalToPhysicalAddress(&conversion);
+ if( ok && conversion.send_node != to_node && (directTo==0 || directTo==3) && isAckType){
+ #if !defined (DUAL_HEAD_RADIO)
+ // Now, continue listening
+ if(networkFlags & FLAG_FAST_FRAG){
+ radio.txStandBy(txTimeout);
+ networkFlags &= ~FLAG_FAST_FRAG;
+ radio.setAutoAck(0,0);
+ }
+ radio.startListening();
+ #endif
+ uint32_t reply_time = mainTimer.read_ms();
- //Write the data using the resulting physical address
- frame_size = sizeof(RF24NetworkHeader);
- write_to_pipe(conversion.send_node, conversion.send_pipe, conversion.multicast);
-
- //dynLen=0;
-
- IF_SERIAL_DEBUG_ROUTING( printf_P(PSTR("%lu MAC: Route OK to 0%o ACK sent to 0%o\n"),millis(),to_node,header->from_node); );
-
- }
-
+ while( update() != NETWORK_ACK){
- if( ok && conversion.send_node != to_node && (directTo==0 || directTo==3) && isAckType) {
-#if !defined (DUAL_HEAD_RADIO)
- // Now, continue listening
- if(networkFlags & FLAG_FAST_FRAG) {
- radio.txStandBy(txTimeout);
- networkFlags &= ~FLAG_FAST_FRAG;
- }
- radio.startListening();
-#endif
- uint32_t reply_time = rf24netTimer.read_ms();
+ if(mainTimer.read_ms() - reply_time > routeTimeout){
+
+ IF_SERIAL_DEBUG_ROUTING( printf_P(PSTR("%lu: MAC Network ACK fail from 0%o via 0%o on pipe %x\n\r"),mainTimer.read_ms(),to_node,conversion.send_node,conversion.send_pipe); );
- while( update() != NETWORK_ACK) {
- wait_us(900);
- if(rf24netTimer.read_ms() - reply_time > routeTimeout) {
-
- IF_SERIAL_DEBUG_ROUTING( printf_P(PSTR("%lu: MAC Network ACK fail from 0%o via 0%o on pipe %x\n\r"),millis(),to_node,conversion.send_node,conversion.send_pipe); );
-
- ok=false;
- break;
- }
- }
+ ok=false;
+ break;
+ }
+ }
}
- if( !(networkFlags & FLAG_FAST_FRAG) ) {
-#if !defined (DUAL_HEAD_RADIO)
- // Now, continue listening
- radio.startListening();
-#endif
- }
+ if( !(networkFlags & FLAG_FAST_FRAG) ){
+ #if !defined (DUAL_HEAD_RADIO)
+ // Now, continue listening
+ radio.startListening();
+ #endif
+ }
#if defined ENABLE_NETWORK_STATS
- if(ok == true) {
- ++nOK;
- } else {
- ++nFails;
- }
+ if(ok == true){
+ ++nOK;
+ }else{ ++nFails;
+ }
#endif
- return ok;
+ return ok;
}
/******************************************************************/
-// Provided the to_node and directTo option, it will return the resulting node and pipe
-bool RF24Network::logicalToPhysicalAddress(logicalToPhysicalStruct *conversionInfo)
-{
+ // Provided the to_node and directTo option, it will return the resulting node and pipe
+bool RF24Network::logicalToPhysicalAddress(logicalToPhysicalStruct *conversionInfo){
- //Create pointers so this makes sense.. kind of
- //We take in the to_node(logical) now, at the end of the function, output the send_node(physical) address, etc.
- //back to the original memory address that held the logical information.
- uint16_t *to_node = &conversionInfo->send_node;
- uint8_t *directTo = &conversionInfo->send_pipe;
- bool *multicast = &conversionInfo->multicast;
-
- // Where do we send this? By default, to our parent
- uint16_t pre_conversion_send_node = parent_node;
-
- // On which pipe
- uint8_t pre_conversion_send_pipe = parent_pipe %5;
+ //Create pointers so this makes sense.. kind of
+ //We take in the to_node(logical) now, at the end of the function, output the send_node(physical) address, etc.
+ //back to the original memory address that held the logical information.
+ uint16_t *to_node = &conversionInfo->send_node;
+ uint8_t *directTo = &conversionInfo->send_pipe;
+ bool *multicast = &conversionInfo->multicast;
+
+ // Where do we send this? By default, to our parent
+ uint16_t pre_conversion_send_node = parent_node;
- if(*directTo > TX_ROUTED ) {
- pre_conversion_send_node = *to_node;
- *multicast = 1;
- //if(*directTo == USER_TX_MULTICAST || *directTo == USER_TX_TO_PHYSICAL_ADDRESS){
- pre_conversion_send_pipe=0;
- //}
- }
- // If the node is a direct child,
- else if ( is_direct_child(*to_node) ) {
- // Send directly
- pre_conversion_send_node = *to_node;
- // To its listening pipe
- pre_conversion_send_pipe = 5;
- }
- // If the node is a child of a child
- // talk on our child's listening pipe,
- // and let the direct child relay it.
- else if ( is_descendant(*to_node) ) {
- pre_conversion_send_node = direct_child_route_to(*to_node);
- pre_conversion_send_pipe = 5;
- }
-
- *to_node = pre_conversion_send_node;
- *directTo = pre_conversion_send_pipe;
-
- return 1;
-
+ // On which pipe
+ uint8_t pre_conversion_send_pipe = parent_pipe;
+
+ if(*directTo > TX_ROUTED ){
+ pre_conversion_send_node = *to_node;
+ *multicast = 1;
+ //if(*directTo == USER_TX_MULTICAST || *directTo == USER_TX_TO_PHYSICAL_ADDRESS){
+ pre_conversion_send_pipe=0;
+ //}
+ }
+ // If the node is a direct child,
+ else
+ if ( is_direct_child(*to_node) )
+ {
+ // Send directly
+ pre_conversion_send_node = *to_node;
+ // To its listening pipe
+ pre_conversion_send_pipe = 5;
+ }
+ // If the node is a child of a child
+ // talk on our child's listening pipe,
+ // and let the direct child relay it.
+ else if ( is_descendant(*to_node) )
+ {
+ pre_conversion_send_node = direct_child_route_to(*to_node);
+ pre_conversion_send_pipe = 5;
+ }
+
+ *to_node = pre_conversion_send_node;
+ *directTo = pre_conversion_send_pipe;
+
+ return 1;
+
}
/********************************************************/
+
bool RF24Network::write_to_pipe( uint16_t node, uint8_t pipe, bool multicast )
{
- bool ok = false;
- uint64_t out_pipe = pipe_address( node, pipe );
-
-#if !defined (DUAL_HEAD_RADIO)
- // Open the correct pipe for writing.
- // First, stop listening so we can talk
-
- if(!(networkFlags & FLAG_FAST_FRAG)) {
- radio.stopListening();
- }
+ bool ok = false;
+ uint64_t out_pipe = pipe_address( node, pipe );
+
+ #if !defined (DUAL_HEAD_RADIO)
+ // Open the correct pipe for writing.
+ // First, stop listening so we can talk
- if(multicast) {
- radio.setAutoAck(0,0);
- } else {
- radio.setAutoAck(0,1);
- }
+ if(!(networkFlags & FLAG_FAST_FRAG)){
+ radio.stopListening();
+ }
+
+ if(multicast){ radio.setAutoAck(0,0);}else{radio.setAutoAck(0,1);}
+
+ radio.openWritingPipe(out_pipe);
- radio.openWritingPipe(out_pipe);
- radio.writeFast(frame_buffer, frame_size,multicast);
+ ok = radio.writeFast(frame_buffer, frame_size,multicast);
+
+ if(!(networkFlags & FLAG_FAST_FRAG)){
ok = radio.txStandBy(txTimeout);
-
radio.setAutoAck(0,0);
-
+ }
+
#else
- radio1.openWritingPipe(out_pipe);
- radio1.writeFast(frame_buffer, frame_size);
- ok = radio1.txStandBy(txTimeout,multicast);
+ radio1.openWritingPipe(out_pipe);
+ radio1.writeFast(frame_buffer, frame_size);
+ ok = radio1.txStandBy(txTimeout,multicast);
#endif
- IF_SERIAL_DEBUG(printf_P(PSTR("%lu: MAC Sent on %lx %S\n\r"),rf24netTimer.read_ms(),(uint32_t)out_pipe,ok?PSTR("ok"):PSTR("failed")));
-
- return ok;
+/* #if defined (__arm__) || defined (RF24_LINUX)
+ IF_SERIAL_DEBUG(printf_P(PSTR("%u: MAC Sent on %x %s\n\r"),millis(),(uint32_t)out_pipe,ok?PSTR("ok"):PSTR("failed")));
+ #else
+ IF_SERIAL_DEBUG(printf_P(PSTR("%lu: MAC Sent on %lx %S\n\r"),millis(),(uint32_t)out_pipe,ok?PSTR("ok"):PSTR("failed")));
+ #endif
+*/
+ return ok;
}
/******************************************************************/
const char* RF24NetworkHeader::toString(void) const
{
- static char buffer[45];
- //snprintf_P(buffer,sizeof(buffer),PSTR("id %04x from 0%o to 0%o type %c"),id,from_node,to_node,type);
- sprintf(buffer,PSTR("id %u from 0%o to 0%o type %d"),id,from_node,to_node,type);
- return buffer;
+ static char buffer[45];
+ //snprintf_P(buffer,sizeof(buffer),PSTR("id %04x from 0%o to 0%o type %c"),id,from_node,to_node,type);
+ //sprintf_P(buffer,PSTR("id %u from 0%o to 0%o type %d"),id,from_node,to_node,type);
+ return buffer;
}
/******************************************************************/
bool RF24Network::is_direct_child( uint16_t node )
{
- bool result = false;
+ bool result = false;
- // A direct child of ours has the same low numbers as us, and only
- // one higher number.
- //
- // e.g. node 0234 is a direct child of 034, and node 01234 is a
- // descendant but not a direct child
+ // A direct child of ours has the same low numbers as us, and only
+ // one higher number.
+ //
+ // e.g. node 0234 is a direct child of 034, and node 01234 is a
+ // descendant but not a direct child
- // First, is it even a descendant?
- if ( is_descendant(node) ) {
- // Does it only have ONE more level than us?
- uint16_t child_node_mask = ( ~ node_mask ) << 3;
- result = ( node & child_node_mask ) == 0 ;
- }
- return result;
+ // First, is it even a descendant?
+ if ( is_descendant(node) )
+ {
+ // Does it only have ONE more level than us?
+ uint16_t child_node_mask = ( ~ node_mask ) << 3;
+ result = ( node & child_node_mask ) == 0 ;
+ }
+ return result;
}
/******************************************************************/
bool RF24Network::is_descendant( uint16_t node )
{
- return ( node & node_mask ) == node_address;
+ return ( node & node_mask ) == node_address;
}
/******************************************************************/
void RF24Network::setup_address(void)
{
- // First, establish the node_mask
- uint16_t node_mask_check = 0xFFFF;
-#if defined (RF24NetworkMulticast)
- uint8_t count = 0;
-#endif
-
- while ( node_address & node_mask_check ) {
- node_mask_check <<= 3;
-#if defined (RF24NetworkMulticast)
- count++;
- }
- multicast_level = count;
-#else
- }
-#endif
-
- node_mask = ~ node_mask_check;
+ // First, establish the node_mask
+ uint16_t node_mask_check = 0xFFFF;
+ #if defined (RF24NetworkMulticast)
+ uint8_t count = 0;
+ #endif
+
+ while ( node_address & node_mask_check ){
+ node_mask_check <<= 3;
+ #if defined (RF24NetworkMulticast)
+ count++;
+ }
+ multicast_level = count;
+ #else
+ }
+ #endif
+
+ node_mask = ~ node_mask_check;
- // parent mask is the next level down
- uint16_t parent_mask = node_mask >> 3;
+ // parent mask is the next level down
+ uint16_t parent_mask = node_mask >> 3;
- // parent node is the part IN the mask
- parent_node = node_address & parent_mask;
+ // parent node is the part IN the mask
+ parent_node = node_address & parent_mask;
- // parent pipe is the part OUT of the mask
- uint16_t i = node_address;
- uint16_t m = parent_mask;
- while (m)
- {
- i >>= 3;
- m >>= 3;
- }
- parent_pipe = i;
+ // parent pipe is the part OUT of the mask
+ uint16_t i = node_address;
+ uint16_t m = parent_mask;
+ while (m)
+ {
+ i >>= 3;
+ m >>= 3;
+ }
+ parent_pipe = i;
- IF_SERIAL_DEBUG( printf_P(PSTR("setup_address node=0%o mask=0%o parent=0%o pipe=0%o\n\r"),node_address,node_mask,parent_node,parent_pipe););
+ IF_SERIAL_DEBUG_MINIMAL( printf_P(PSTR("setup_address node=0%o mask=0%o parent=0%o pipe=0%o\n\r"),node_address,node_mask,parent_node,parent_pipe););
}
/******************************************************************/
uint16_t RF24Network::addressOfPipe( uint16_t node, uint8_t pipeNo )
{
- //Say this node is 013 (1011), mask is 077 or (00111111)
- //Say we want to use pipe 3 (11)
- //6 bits in node mask, so shift pipeNo 6 times left and | into address
- uint16_t m = node_mask >> 3;
- uint8_t i=0;
-
- while (m) { //While there are bits left in the node mask
- m>>=1; //Shift to the right
- i++; //Count the # of increments
- }
- return node | (pipeNo << i);
+ //Say this node is 013 (1011), mask is 077 or (00111111)
+ //Say we want to use pipe 3 (11)
+ //6 bits in node mask, so shift pipeNo 6 times left and | into address
+ uint16_t m = node_mask >> 3;
+ uint8_t i=0;
+
+ while (m){ //While there are bits left in the node mask
+ m>>=1; //Shift to the right
+ i++; //Count the # of increments
+ }
+ return node | (pipeNo << i);
}
/******************************************************************/
uint16_t RF24Network::direct_child_route_to( uint16_t node )
{
- // Presumes that this is in fact a child!!
- uint16_t child_mask = ( node_mask << 3 ) | 7;
- return node & child_mask;
-
+ // Presumes that this is in fact a child!!
+ uint16_t child_mask = ( node_mask << 3 ) | 0B111;
+ return node & child_mask;
+
}
/******************************************************************/
/*
uint8_t RF24Network::pipe_to_descendant( uint16_t node )
{
- uint16_t i = node;
+ uint16_t i = node;
uint16_t m = node_mask;
while (m)
@@ -950,138 +962,91 @@
bool RF24Network::is_valid_address( uint16_t node )
{
- bool result = true;
+ bool result = true;
- while(node) {
- uint8_t digit = node & 7;
-#if !defined (RF24NetworkMulticast)
- if (digit < 1 || digit > 5)
-#else
- if (digit < 0 || digit > 5) //Allow our out of range multicast address
-#endif
- {
- result = false;
- IF_SERIAL_DEBUG_MINIMAL(printf_P(PSTR("*** WARNING *** Invalid address 0%o\n\r"),node););
- break;
- }
- node >>= 3;
+ while(node)
+ {
+ uint8_t digit = node & 0B111;
+ #if !defined (RF24NetworkMulticast)
+ if (digit < 1 || digit > 5)
+ #else
+ if (digit < 0 || digit > 5) //Allow our out of range multicast address
+ #endif
+ {
+ result = false;
+ IF_SERIAL_DEBUG_MINIMAL(printf_P(PSTR("*** WARNING *** Invalid address 0%o\n\r"),node););
+ break;
}
+ node >>= 3;
+ }
- return result;
+ return result;
}
/******************************************************************/
#if defined (RF24NetworkMulticast)
-void RF24Network::multicastLevel(uint8_t level)
-{
- multicast_level = level;
- //radio.stopListening();
- radio.openReadingPipe(0,pipe_address(levelToAddress(level),0));
- //radio.startListening();
-}
-
-uint16_t levelToAddress(uint8_t level)
-{
-
- uint16_t levelAddr = 1;
- if(level) {
- levelAddr = levelAddr << ((level-1) * 3);
- } else {
- return 0;
- }
- return levelAddr;
-}
+void RF24Network::multicastLevel(uint8_t level){
+ multicast_level = level;
+ //radio.stopListening();
+ radio.openReadingPipe(0,pipe_address(levelToAddress(level),0));
+ //radio.startListening();
+ }
+
+uint16_t levelToAddress(uint8_t level){
+
+ uint16_t levelAddr = 1;
+ if(level){
+ levelAddr = levelAddr << ((level-1) * 3);
+ }else{
+ return 0;
+ }
+ return levelAddr;
+}
#endif
/******************************************************************/
uint64_t pipe_address( uint16_t node, uint8_t pipe )
{
-
- static uint8_t address_translation[] = { 0xc3,0x3c,0x33,0xce,0x3e,0xe3,0xec };
- uint64_t result = 0xCCCCCCCCCCLL;
- uint8_t* out = reinterpret_cast<uint8_t*>(&result);
-
- // Translate the address to use our optimally chosen radio address bytes
- uint8_t count = 1;
- uint16_t dec = node;
-
- while(dec) {
-#if defined (RF24NetworkMulticast)
- if(pipe != 0 || !node)
-#endif
- out[count]=address_translation[(dec % 8)]; // Convert our decimal values to octal, translate them to address bytes, and set our address
+
+ static uint8_t address_translation[] = { 0xc3,0x3c,0x33,0xce,0x3e,0xe3,0xec };
+ uint64_t result = 0xCCCCCCCCCCLL;
+ uint8_t* out = reinterpret_cast<uint8_t*>(&result);
+
+ // Translate the address to use our optimally chosen radio address bytes
+ uint8_t count = 1; uint16_t dec = node;
- dec /= 8;
- count++;
- }
+ while(dec){
+ #if defined (RF24NetworkMulticast)
+ if(pipe != 0 || !node)
+ #endif
+ out[count]=address_translation[(dec % 8)]; // Convert our decimal values to octal, translate them to address bytes, and set our address
+
+ dec /= 8;
+ count++;
+ }
+
+ #if defined (RF24NetworkMulticast)
+ if(pipe != 0 || !node)
+ #endif
+ out[0] = address_translation[pipe];
+ #if defined (RF24NetworkMulticast)
+ else
+ out[1] = address_translation[count-1];
+ #endif
-#if defined (RF24NetworkMulticast)
- if(pipe != 0 || !node)
-#endif
- out[0] = address_translation[pipe];
-#if defined (RF24NetworkMulticast)
- else
- out[1] = address_translation[count-1];
-#endif
+
+
+ IF_SERIAL_DEBUG(uint32_t* top = reinterpret_cast<uint32_t*>(out+1);printf_P(PSTR("%lu: NET Pipe %i on node 0%o has address %lx%x\n\r"),mainTimer.read_ms(),pipe,node,*top,*out));
- IF_SERIAL_DEBUG(uint32_t* top = reinterpret_cast<uint32_t*>(out+1); printf_P(PSTR("%lu: NET Pipe %i on node 0%o has address %lx%x\n\r"),millis(),pipe,node,*top,*out));
-
- return result;
+
+ return result;
}
/************************ Sleep Mode ******************************************/
-#if defined ENABLE_SLEEP_MODE
-void wakeUp()
-{
- wasInterrupted=true;
- sleep_cycles_remaining = 0;
-}
-
-ISR(WDT_vect)
-{
- --sleep_cycles_remaining;
-}
-
-
-bool RF24Network::sleepNode( unsigned int cycles, int interruptPin )
-{
+/**/
- sleep_cycles_remaining = cycles;
- set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
- sleep_enable();
- //if(interruptPin != 255){
- // wasInterrupted = false; //Reset Flag
- // attachInterrupt(interruptPin,wakeUp, LOW);
- //}
-
- WDTCSR |= _BV(WDIE);
-
- while(sleep_cycles_remaining) {
- sleep_mode(); // System sleeps here
- } // The WDT_vect interrupt wakes the MCU from here
- sleep_disable(); // System continues execution here when watchdog timed out
- //detachInterrupt(interruptPin);
-
- WDTCSR &= ~_BV(WDIE);
-
- return !wasInterrupted;
-}
-
-void RF24Network::setup_watchdog(uint8_t prescalar)
-{
-
- uint8_t wdtcsr = prescalar & 7;
- if ( prescalar & 8 )
- wdtcsr |= _BV(WDP3);
- MCUSR &= ~_BV(WDRF); // Clear the WD System Reset Flag
-
- WDTCSR = _BV(WDCE) | _BV(WDE); // Write the WD Change enable bit to enable changing the prescaler and enable system reset
- WDTCSR = _BV(WDCE) | wdtcsr | _BV(WDIE); // Write the prescalar bits (how long to sleep, enable the interrupt to wake the MCU
-}
-
-#endif
--- a/RF24Network.h Thu Nov 05 05:54:47 2015 +0000
+++ b/RF24Network.h Thu Apr 21 03:43:13 2016 +0000
@@ -5,15 +5,16 @@
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
-
+
/*
-* Mbed support added by Akash Vibhute <akash.roboticist@gmail.com>
-* Porting completed on Nov/05/2015
-*
-* Updated with TMRh20's RF24 library on Nov/04/2015 from https://github.com/TMRh20
-*
-*/
-
+ * Mbed support added by Akash Vibhute <akash.roboticist@gmail.com>
+ * Porting completed on Nov/05/2015
+ *
+ * Updated 1: Synced with TMRh20's RF24 library on Nov/04/2015 from https://github.com/TMRh20
+ * Updated 2: Synced with TMRh20's RF24 library on Apr/18/2015 from https://github.com/TMRh20
+ *
+ */
+
#ifndef __RF24NETWORK_H__
#define __RF24NETWORK_H__
@@ -22,25 +23,34 @@
*
* Class declaration for RF24Network
*/
-#define min(a,b) (a<b?a:b)
+
+ #include "mbed.h"
#include <stddef.h>
#include <stdint.h>
+//#include <stdio.h>
+//#include <string.h>
#include "RF24Network_config.h"
+
+
+/**
+
+ */
+
/* Header types range */
#define MIN_USER_DEFINED_HEADER_TYPE 0
#define MAX_USER_DEFINED_HEADER_TYPE 127
-/**
+/**
*/
-
+
// ACK Response Types
/**
* **Reserved network message types**
*
* The network will determine whether to automatically acknowledge payloads based on their general type <br>
- *
+ *
* **User types** (1-127) 1-64 will NOT be acknowledged <br>
* **System types** (128-255) 192 through 255 will NOT be acknowledged<br>
*
@@ -53,37 +63,37 @@
/**
* A NETWORK_ADDR_RESPONSE type is utilized to manually route custom messages containing a single RF24Network address
-*
+*
* Used by RF24Mesh
-*
+*
* If a node receives a message of this type that is directly addressed to it, it will read the included message, and forward the payload
* on to the proper recipient. <br>
* This allows nodes to forward multicast messages to the master node, receive a response, and forward it back to the requester.
*/
-#define NETWORK_ADDR_RESPONSE 128
+#define NETWORK_ADDR_RESPONSE 128
//#define NETWORK_ADDR_CONFIRM 129
/**
-* Messages of type NETWORK_PING will be dropped automatically by the recipient. A NETWORK_ACK or automatic radio-ack will indicate to the sender whether the
+* Messages of type NETWORK_PING will be dropped automatically by the recipient. A NETWORK_ACK or automatic radio-ack will indicate to the sender whether the
* payload was successful. The time it takes to successfully send a NETWORK_PING is the round-trip-time.
*/
#define NETWORK_PING 130
/**
- * External data types are used to define messages that will be passed to an external data system. This allows RF24Network to route and pass any type of data, such
+ * External data types are used to define messages that will be passed to an external data system. This allows RF24Network to route and pass any type of data, such
* as TCP/IP frames, while still being able to utilize standard RF24Network messages etc.
*
* **Linux**
- * Linux devices (defined RF24_LINUX) will buffer all data types in the user cache.
+ * Linux devices (defined RF24_LINUX) will buffer all data types in the user cache.
*
* **Arduino/AVR/Etc:** Data transmitted with the type set to EXTERNAL_DATA_TYPE will not be loaded into the user cache. <br>
* External systems can extract external data using the following process, while internal data types are cached in the user buffer, and accessed using network.read() :
* @code
* uint8_t return_type = network.update();
* if(return_type == EXTERNAL_DATA_TYPE){
- * uint16_t size = network.frag_ptr->message_size;
+ * uint16_t size = network.frag_ptr->message_size;
* memcpy(&myDataBuffer,network.frag_ptr->message_buffer,network.frag_ptr->message_size);
- * }
+ * }
* @endcode
*/
#define EXTERNAL_DATA_TYPE 131
@@ -102,7 +112,7 @@
* Messages of this type indicate the last fragment in a sequence of message fragments.
* Messages of this type do not receive a NETWORK_ACK
*/
-#define NETWORK_LAST_FRAGMENT 150
+#define NETWORK_LAST_FRAGMENT 150
//#define NETWORK_LAST_FRAGMENT 201
// NO ACK Response Types
@@ -112,9 +122,9 @@
* Messages of this type are used internally, to signal the sender that a transmission has been completed.
* RF24Network does not directly have a built-in transport layer protocol, so message delivery is not 100% guaranteed.<br>
* Messages can be lost via corrupted dynamic payloads, or a NETWORK_ACK can fail, while the message was actually successful.
- *
+ *
* NETWORK_ACK messages can be utilized as a traffic/flow control mechanism, since transmitting nodes will be forced to wait until
- * the payload is transmitted across the network and acknowledged, before sending additional data.
+ * the payload is transmitted across the network and acknowledged, before sending additional data.
*
* In the event that the transmitting device will be waiting for a direct response, manually sent by the recipient, a NETWORK_ACK is not required. <br>
* User messages utilizing a 'type' with a decimal value of 64 or less will not be acknowledged across the network via NETWORK_ACK messages.
@@ -127,7 +137,7 @@
* Messages of this type are used with multi-casting , to find active/available nodes.
* Any node receiving a NETWORK_POLL sent to a multicast address will respond directly to the sender with a blank message, indicating the
* address of the available node via the header.
- */
+ */
#define NETWORK_POLL 194
/**
@@ -143,6 +153,7 @@
#define NETWORK_MORE_FRAGMENTS_NACK 200
+
/** Internal defines for handling written payloads */
#define TX_NORMAL 0
#define TX_ROUTED 1
@@ -157,17 +168,19 @@
/** Internal defines for handling internal payloads - prevents reading additional data from the radio
* when buffers are full */
-#define FLAG_HOLD_INCOMING 1
-/** FLAG_BYPASS_HOLDS is mainly for use with RF24Mesh as follows:
- * a: Ensure no data in radio buffers, else exit
- * b: Address is changed to multicast address for renewal
- * c: Holds Cleared (bypass flag is set)
- * d: Address renewal takes place and is set
- * e: Holds Enabled (bypass flag off)
- */
-#define FLAG_BYPASS_HOLDS 2
-
-#define FLAG_FAST_FRAG 4
+ #define FLAG_HOLD_INCOMING 1
+ /** FLAG_BYPASS_HOLDS is mainly for use with RF24Mesh as follows:
+ * a: Ensure no data in radio buffers, else exit
+ * b: Address is changed to multicast address for renewal
+ * c: Holds Cleared (bypass flag is set)
+ * d: Address renewal takes place and is set
+ * e: Holds Enabled (bypass flag off)
+ */
+ #define FLAG_BYPASS_HOLDS 2
+
+ #define FLAG_FAST_FRAG 4
+
+ #define FLAG_NO_POLL 8
class RF24;
@@ -178,68 +191,69 @@
*
* Headers are addressed to the appropriate node, and the network forwards them on to their final destination.
*/
-struct RF24NetworkHeader {
- uint16_t from_node; /**< Logical address where the message was generated */
- uint16_t to_node; /**< Logical address where the message is going */
- uint16_t id; /**< Sequential message ID, incremented every time a new frame is constructed */
- /**
- * Message Types:
- * User message types 1 through 64 will NOT be acknowledged by the network, while message types 65 through 127 will receive a network ACK.
- * System message types 192 through 255 will NOT be acknowledged by the network. Message types 128 through 192 will receive a network ACK. <br>
- * <br><br>
- */
- unsigned char type; /**< <b>Type of the packet. </b> 0-127 are user-defined types, 128-255 are reserved for system */
+struct RF24NetworkHeader
+{
+ uint16_t from_node; /**< Logical address where the message was generated */
+ uint16_t to_node; /**< Logical address where the message is going */
+ uint16_t id; /**< Sequential message ID, incremented every time a new frame is constructed */
+ /**
+ * Message Types:
+ * User message types 1 through 64 will NOT be acknowledged by the network, while message types 65 through 127 will receive a network ACK.
+ * System message types 192 through 255 will NOT be acknowledged by the network. Message types 128 through 192 will receive a network ACK. <br>
+ * <br><br>
+ */
+ unsigned char type; /**< <b>Type of the packet. </b> 0-127 are user-defined types, 128-255 are reserved for system */
+
+ /**
+ * During fragmentation, it carries the fragment_id, and on the last fragment
+ * it carries the header_type.<br>
+ */
+ unsigned char reserved; /**< *Reserved for system use* */
- /**
- * During fragmentation, it carries the fragment_id, and on the last fragment
- * it carries the header_type.<br>
- */
- unsigned char reserved; /**< *Reserved for system use* */
-
- static uint16_t next_id; /**< The message ID of the next message to be sent (unused)*/
+ static uint16_t next_id; /**< The message ID of the next message to be sent (unused)*/
- /**
- * Default constructor
- *
+ /**
+ * Default constructor
+ *
- * Simply constructs a blank header
- */
- RF24NetworkHeader() {}
+ * Simply constructs a blank header
+ */
+ RF24NetworkHeader() {}
- /**
- * Send constructor
- *
- * @note Now supports automatic fragmentation for very long messages, which can be sent as usual if fragmentation is enabled.
- *
- * Fragmentation is enabled by default for all devices except ATTiny <br>
- * Configure fragmentation and max payload size in RF24Network_config.h
- *
- * Use this constructor to create a header and then send a message
- *
- * @code
- * uint16_t recipient_address = 011;
- *
- * RF24NetworkHeader header(recipient_address,'t');
- *
- * network.write(header,&message,sizeof(message));
- * @endcode
- *
- * @param _to The Octal format, logical node address where the message is going
- * @param _type The type of message which follows. Only 0-127 are allowed for
- * user messages. Types 1-64 will not receive a network acknowledgement.
- */
+ /**
+ * Send constructor
+ *
+ * @note Now supports automatic fragmentation for very long messages, which can be sent as usual if fragmentation is enabled.
+ *
+ * Fragmentation is enabled by default for all devices except ATTiny <br>
+ * Configure fragmentation and max payload size in RF24Network_config.h
+ *
+ * Use this constructor to create a header and then send a message
+ *
+ * @code
+ * uint16_t recipient_address = 011;
+ *
+ * RF24NetworkHeader header(recipient_address,'t');
+ *
+ * network.write(header,&message,sizeof(message));
+ * @endcode
+ *
+ * @param _to The Octal format, logical node address where the message is going
+ * @param _type The type of message which follows. Only 0-127 are allowed for
+ * user messages. Types 1-64 will not receive a network acknowledgement.
+ */
- RF24NetworkHeader(uint16_t _to, unsigned char _type = 0): to_node(_to), id(next_id++), type(_type) {}
- /**
- * Create debugging string
- *
- * Useful for debugging. Dumps all members into a single string, using
- * internal static memory. This memory will get overridden next time
- * you call the method.
- *
- * @return String representation of this object
- */
- const char* toString(void) const;
+ RF24NetworkHeader(uint16_t _to, unsigned char _type = 0): to_node(_to), id(next_id++), type(_type) {}
+ /**
+ * Create debugging string
+ *
+ * Useful for debugging. Dumps all members into a single string, using
+ * internal static memory. This memory will get overridden next time
+ * you call the method.
+ *
+ * @return String representation of this object
+ */
+ const char* toString(void) const;
};
@@ -248,71 +262,76 @@
*
* The actual frame put over the air consists of a header (8-bytes) and a message payload (Up to 24-bytes)<br>
* When data is received, it is stored using the RF24NetworkFrame structure, which includes:
- * 1. The header
- * 2. The size of the included message
+ * 1. The header
+ * 2. The size of the included message
* 3. The 'message' or data being received
- *
+ *
*
*/
-struct RF24NetworkFrame {
- RF24NetworkHeader header; /**< Header which is sent with each message */
- uint16_t message_size; /**< The size in bytes of the payload length */
- /**
- * On Arduino, the message buffer is just a pointer, and can be pointed to any memory location.
- * On Linux the message buffer is a standard byte array, equal in size to the defined MAX_PAYLOAD_SIZE
- */
-
- uint8_t *message_buffer; //< Pointer to the buffer storing the actual message
-
- /**
- * Default constructor
- *
- * Simply constructs a blank frame. Frames are generally used internally. See RF24NetworkHeader.
- */
- //RF24NetworkFrame() {}
+ struct RF24NetworkFrame
+{
+ RF24NetworkHeader header; /**< Header which is sent with each message */
+ uint16_t message_size; /**< The size in bytes of the payload length */
+
+ /**
+ * On Arduino, the message buffer is just a pointer, and can be pointed to any memory location.
+ * On Linux the message buffer is a standard byte array, equal in size to the defined MAX_PAYLOAD_SIZE
+ */
+
+
+
+ uint8_t *message_buffer; //< Pointer to the buffer storing the actual message
- RF24NetworkFrame() {}
- /**
- * Constructor - create a network frame with data
- * Frames are constructed and handled differently on Arduino/AVR and Linux devices (defined RF24_LINUX)
- *
- * <br>
- * **Linux:**
- * @param _header The RF24Network header to be stored in the frame
- * @param _message The 'message' or data.
- * @param _len The size of the 'message' or data.
- *
- * <br>
- * **Arduino/AVR/Etc.**
- * @see RF24Network.frag_ptr
- * @param _header The RF24Network header to be stored in the frame
- * @param _message_size The size of the 'message' or data
- *
- *
- * Frames are used internally and by external systems. See RF24NetworkHeader.
- */
+ /**
+ * Default constructor
+ *
+ * Simply constructs a blank frame. Frames are generally used internally. See RF24NetworkHeader.
+ */
+ //RF24NetworkFrame() {}
+
+ RF24NetworkFrame() {}
+ /**
+ * Constructor - create a network frame with data
+ * Frames are constructed and handled differently on Arduino/AVR and Linux devices (defined RF24_LINUX)
+ *
+ * <br>
+ * **Linux:**
+ * @param _header The RF24Network header to be stored in the frame
+ * @param _message The 'message' or data.
+ * @param _len The size of the 'message' or data.
+ *
+ * <br>
+ * **Arduino/AVR/Etc.**
+ * @see RF24Network.frag_ptr
+ * @param _header The RF24Network header to be stored in the frame
+ * @param _message_size The size of the 'message' or data
+ *
+ *
+ * Frames are used internally and by external systems. See RF24NetworkHeader.
+ */
+
+ RF24NetworkFrame(RF24NetworkHeader &_header, uint16_t _message_size):
+ header(_header), message_size(_message_size){
+ }
- RF24NetworkFrame(RF24NetworkHeader &_header, uint16_t _message_size):
- header(_header), message_size(_message_size) {
- }
- /**
- * Create debugging string
- *
- * Useful for debugging. Dumps all members into a single string, using
- * internal static memory. This memory will get overridden next time
- * you call the method.
- *
- * @return String representation of this object
- */
- const char* toString(void) const;
+ /**
+ * Create debugging string
+ *
+ * Useful for debugging. Dumps all members into a single string, using
+ * internal static memory. This memory will get overridden next time
+ * you call the method.
+ *
+ * @return String representation of this object
+ */
+ const char* toString(void) const;
};
-
+
/**
* 2014-2015 - Optimized Network Layer for RF24 Radios
@@ -323,485 +342,490 @@
class RF24Network
{
-private:
- Timer rf24netTimer;
- /**@}*/
- /**
- * @name Primary Interface
- *
- * These are the main methods you need to operate the network
- */
- /**@{*/
+
+ /**@}*/
+ /**
+ * @name Primary Interface
+ *
+ * These are the main methods you need to operate the network
+ */
+ /**@{*/
+
public:
- /**
- * Construct the network
- *
- * @param _radio The underlying radio driver instance
- *
- */
+ /**
+ * Construct the network
+ *
+ * @param _radio The underlying radio driver instance
+ *
+ */
- RF24Network( RF24& _radio );
+ RF24Network( RF24& _radio );
- /**
- * Bring up the network using the current radio frequency/channel.
- * Calling begin brings up the network, and configures the address, which designates the location of the node within RF24Network topology.
- * @note Node addresses are specified in Octal format, see <a href=Addressing.html>RF24Network Addressing</a> for more information.
- * @warning Be sure to 'begin' the radio first.
- *
- * **Example 1:** Begin on current radio channel with address 0 (master node)
- * @code
- * network.begin(00);
- * @endcode
- * **Example 2:** Begin with address 01 (child of master)
- * @code
- * network.begin(01);
- * @endcode
- * **Example 3:** Begin with address 011 (child of 01, grandchild of master)
- * @code
- * network.begin(011);
- * @endcode
- *
- * @see begin(uint8_t _channel, uint16_t _node_address )
- * @param _node_address The logical address of this node
- *
- */
+ /**
+ * Bring up the network using the current radio frequency/channel.
+ * Calling begin brings up the network, and configures the address, which designates the location of the node within RF24Network topology.
+ * @note Node addresses are specified in Octal format, see <a href=Addressing.html>RF24Network Addressing</a> for more information.
+ * @warning Be sure to 'begin' the radio first.
+ *
+ * **Example 1:** Begin on current radio channel with address 0 (master node)
+ * @code
+ * network.begin(00);
+ * @endcode
+ * **Example 2:** Begin with address 01 (child of master)
+ * @code
+ * network.begin(01);
+ * @endcode
+ * **Example 3:** Begin with address 011 (child of 01, grandchild of master)
+ * @code
+ * network.begin(011);
+ * @endcode
+ *
+ * @see begin(uint8_t _channel, uint16_t _node_address )
+ * @param _node_address The logical address of this node
+ *
+ */
+
+ inline void begin(uint16_t _node_address){
+ begin(USE_CURRENT_CHANNEL,_node_address);
+ }
- inline void begin(uint16_t _node_address) {
- begin(USE_CURRENT_CHANNEL,_node_address);
- }
+ /**
+ * Main layer loop
+ *
+ * This function must be called regularly to keep the layer going. This is where payloads are
+ * re-routed, received, and all the action happens.
+ *
+ * @see
+ *
+ * @return Returns the type of the last received payload.
+ */
+ uint8_t update(void);
+
+ /**
+ * Test whether there is a message available for this node
+ *
+ * @return Whether there is a message available for this node
+ */
+ bool available(void);
+
+ /**
+ * Read the next available header
+ *
+ * Reads the next available header without advancing to the next
+ * incoming message. Useful for doing a switch on the message type
+ *
+ * If there is no message available, the header is not touched
+ *
+ * @param[out] header The header (envelope) of the next message
+ */
+ uint16_t peek(RF24NetworkHeader& header);
- /**
- * Main layer loop
- *
- * This function must be called regularly to keep the layer going. This is where payloads are
- * re-routed, received, and all the action happens.
- *
- * @see
- *
- * @return Returns the type of the last received payload.
- */
- uint8_t update(void);
+ /**
+ * Read a message
+ *
+ * @code
+ * while ( network.available() ) {
+ * RF24NetworkHeader header;
+ * uint32_t time;
+ * network.peek(header);
+ * if(header.type == 'T'){
+ * network.read(header,&time,sizeof(time));
+ * Serial.print("Got time: ");
+ * Serial.println(time);
+ * }
+ * }
+ * @endcode
+ * @param[out] header The header (envelope) of this message
+ * @param[out] message Pointer to memory where the message should be placed
+ * @param maxlen The largest message size which can be held in @p message
+ * @return The total number of bytes copied into @p message
+ */
+ uint16_t read(RF24NetworkHeader& header, void* message, uint16_t maxlen);
- /**
- * Test whether there is a message available for this node
- *
- * @return Whether there is a message available for this node
- */
- bool available(void);
+ /**
+ * Send a message
+ *
+ * @note RF24Network now supports fragmentation for very long messages, send as normal. Fragmentation
+ * may need to be enabled or configured by editing the RF24Network_config.h file. Default max payload size is 120 bytes.
+ *
+ * @code
+ * uint32_t time = millis();
+ * uint16_t to = 00; // Send to master
+ * RF24NetworkHeader header(to, 'T'); // Send header type 'T'
+ * network.write(header,&time,sizeof(time));
+ * @endcode
+ * @param[in,out] header The header (envelope) of this message. The critical
+ * thing to fill in is the @p to_node field so we know where to send the
+ * message. It is then updated with the details of the actual header sent.
+ * @param message Pointer to memory where the message is located
+ * @param len The size of the message
+ * @return Whether the message was successfully received
+ */
+ bool write(RF24NetworkHeader& header,const void* message, uint16_t len);
- /**
- * Read the next available header
- *
- * Reads the next available header without advancing to the next
- * incoming message. Useful for doing a switch on the message type
- *
- * If there is no message available, the header is not touched
- *
- * @param[out] header The header (envelope) of the next message
- */
- uint16_t peek(RF24NetworkHeader& header);
+ /**@}*/
+ /**
+ * @name Advanced Configuration
+ *
+ * For advanced configuration of the network
+ */
+ /**@{*/
+
- /**
- * Read a message
- *
- * @code
- * while ( network.available() ) {
- * RF24NetworkHeader header;
- * uint32_t time;
- * network.peek(header);
- * if(header.type == 'T'){
- * network.read(header,&time,sizeof(time));
- * Serial.print("Got time: ");
- * Serial.println(time);
- * }
- * }
- * @endcode
- * @param[out] header The header (envelope) of this message
- * @param[out] message Pointer to memory where the message should be placed
- * @param maxlen The largest message size which can be held in @p message
- * @return The total number of bytes copied into @p message
- */
- uint16_t read(RF24NetworkHeader& header, void* message, uint16_t maxlen);
+ /**
+ * Construct the network in dual head mode using two radio modules.
+ * @note Not working on RPi. Radios will share MISO, MOSI and SCK pins, but require separate CE,CS pins.
+ * @code
+ * RF24 radio(7,8);
+ * RF24 radio1(4,5);
+ * RF24Network(radio.radio1);
+ * @endcode
+ * @param _radio The underlying radio driver instance
+ * @param _radio1 The second underlying radio driver instance
+ */
+
+ RF24Network( RF24& _radio, RF24& _radio1);
+
+ /**
+ * By default, multicast addresses are divided into levels.
+ *
+ * Nodes 1-5 share a multicast address, nodes n1-n5 share a multicast address, and nodes n11-n55 share a multicast address.<br>
+ *
+ * This option is used to override the defaults, and create custom multicast groups that all share a single
+ * address. <br>
+ * The level should be specified in decimal format 1-6 <br>
+ * @see multicastRelay
+ * @param level Levels 1 to 6 are available. All nodes at the same level will receive the same
+ * messages if in range. Messages will be routed in order of level, low to high by default, with the
+ * master node (00) at multicast Level 0
+ */
+
+ void multicastLevel(uint8_t level);
+
+ /**
+ * Enabling this will allow this node to automatically forward received multicast frames to the next highest
+ * multicast level. Duplicate frames are filtered out, so multiple forwarding nodes at the same level should
+ * not interfere. Forwarded payloads will also be received.
+ * @see multicastLevel
+ */
+
+ bool multicastRelay;
+
+ /**
+ * Set up the watchdog timer for sleep mode using the number 0 through 10 to represent the following time periods:<br>
+ * wdt_16ms = 0, wdt_32ms, wdt_64ms, wdt_128ms, wdt_250ms, wdt_500ms, wdt_1s, wdt_2s, wdt_4s, wdt_8s
+ * @code
+ * setup_watchdog(7); // Sets the WDT to trigger every second
+ * @endcode
+ * @param prescalar The WDT prescaler to define how often the node will wake up. When defining sleep mode cycles, this time period is 1 cycle.
+ */
+ void setup_watchdog(uint8_t prescalar);
/**
- * Send a message
- *
- * @note RF24Network now supports fragmentation for very long messages, send as normal. Fragmentation
- * may need to be enabled or configured by editing the RF24Network_config.h file. Default max payload size is 120 bytes.
- *
- * @code
- * uint32_t time = millis();
- * uint16_t to = 00; // Send to master
- * RF24NetworkHeader header(to, 'T'); // Send header type 'T'
- * network.write(header,&time,sizeof(time));
- * @endcode
- * @param[in,out] header The header (envelope) of this message. The critical
- * thing to fill in is the @p to_node field so we know where to send the
- * message. It is then updated with the details of the actual header sent.
- * @param message Pointer to memory where the message is located
- * @param len The size of the message
- * @return Whether the message was successfully received
- */
- bool write(RF24NetworkHeader& header,const void* message, uint16_t len);
-
- /**@}*/
- /**
- * @name Advanced Configuration
- *
- * For advanced configuration of the network
- */
- /**@{*/
-
+ * @note: This value is automatically assigned based on the node address
+ * to reduce errors and increase throughput of the network.
+ *
+ * Sets the timeout period for individual payloads in milliseconds at staggered intervals.
+ * Payloads will be retried automatically until success or timeout
+ * Set to 0 to use the normal auto retry period defined by radio.setRetries()
+ *
+ */
- /**
- * Construct the network in dual head mode using two radio modules.
- * @note Not working on RPi. Radios will share MISO, MOSI and SCK pins, but require separate CE,CS pins.
- * @code
- * RF24 radio(7,8);
- * RF24 radio1(4,5);
- * RF24Network(radio.radio1);
- * @endcode
- * @param _radio The underlying radio driver instance
- * @param _radio1 The second underlying radio driver instance
- */
-
- RF24Network( RF24& _radio, RF24& _radio1);
-
- /**
- * By default, multicast addresses are divided into levels.
- *
- * Nodes 1-5 share a multicast address, nodes n1-n5 share a multicast address, and nodes n11-n55 share a multicast address.<br>
- *
- * This option is used to override the defaults, and create custom multicast groups that all share a single
- * address. <br>
- * The level should be specified in decimal format 1-6 <br>
- * @see multicastRelay
- * @param level Levels 1 to 6 are available. All nodes at the same level will receive the same
- * messages if in range. Messages will be routed in order of level, low to high by default, with the
- * master node (00) at multicast Level 0
- */
-
- void multicastLevel(uint8_t level);
-
- /**
- * Enabling this will allow this node to automatically forward received multicast frames to the next highest
- * multicast level. Duplicate frames are filtered out, so multiple forwarding nodes at the same level should
- * not interfere. Forwarded payloads will also be received.
- * @see multicastLevel
- */
-
- bool multicastRelay;
+ uint32_t txTimeout; /**< Network timeout value */
+
+ /**
+ * This only affects payloads that are routed by one or more nodes.
+ * This specifies how long to wait for an ack from across the network.
+ * Radios sending directly to their parent or children nodes do not
+ * utilize this value.
+ */
+
+ uint16_t routeTimeout; /**< Timeout for routed payloads */
+
+
+ /**@}*/
+ /**
+ * @name Advanced Operation
+ *
+ * For advanced operation of the network
+ */
+ /**@{*/
- /**
- * Set up the watchdog timer for sleep mode using the number 0 through 10 to represent the following time periods:<br>
- * wdt_16ms = 0, wdt_32ms, wdt_64ms, wdt_128ms, wdt_250ms, wdt_500ms, wdt_1s, wdt_2s, wdt_4s, wdt_8s
- * @code
- * setup_watchdog(7); // Sets the WDT to trigger every second
- * @endcode
- * @param prescalar The WDT prescaler to define how often the node will wake up. When defining sleep mode cycles, this time period is 1 cycle.
- */
- void setup_watchdog(uint8_t prescalar);
-
- /**
- * @note: This value is automatically assigned based on the node address
- * to reduce errors and increase throughput of the network.
- *
- * Sets the timeout period for individual payloads in milliseconds at staggered intervals.
- * Payloads will be retried automatically until success or timeout
- * Set to 0 to use the normal auto retry period defined by radio.setRetries()
- *
- */
-
- uint32_t txTimeout; /**< Network timeout value */
-
- /**
- * This only affects payloads that are routed by one or more nodes.
- * This specifies how long to wait for an ack from across the network.
- * Radios sending directly to their parent or children nodes do not
- * utilize this value.
- */
-
- uint16_t routeTimeout; /**< Timeout for routed payloads */
-
+ /**
+ * Return the number of failures and successes for all transmitted payloads, routed or sent directly
+ * @note This needs to be enabled via #define ENABLE_NETWORK_STATS in RF24Network_config.h
+ *
+ * @code
+ * bool fails, success;
+ * network.failures(&fails,&success);
+ * @endcode
+ *
+ */
+ void failures(uint32_t *_fails, uint32_t *_ok);
+
+ #if defined (RF24NetworkMulticast)
+
+ /**
+ * Send a multicast message to multiple nodes at once
+ * Allows messages to be rapidly broadcast through the network
+ *
+ * Multicasting is arranged in levels, with all nodes on the same level listening to the same address
+ * Levels are assigned by network level ie: nodes 01-05: Level 1, nodes 011-055: Level 2
+ * @see multicastLevel
+ * @see multicastRelay
+ * @param message Pointer to memory where the message is located
+ * @param len The size of the message
+ * @param level Multicast level to broadcast to
+ * @return Whether the message was successfully sent
+ */
+
+ bool multicast(RF24NetworkHeader& header,const void* message, uint16_t len, uint8_t level);
+
+
+ #endif
+
+ /**
+ * Writes a direct (unicast) payload. This allows routing or sending messages outside of the usual routing paths.
+ * The same as write, but a physical address is specified as the last option.
+ * The payload will be written to the physical address, and routed as necessary by the recipient
+ */
+ bool write(RF24NetworkHeader& header,const void* message, uint16_t len, uint16_t writeDirect);
- /**@}*/
- /**
- * @name Advanced Operation
- *
- * For advanced operation of the network
- */
- /**@{*/
-
- /**
- * Return the number of failures and successes for all transmitted payloads, routed or sent directly
- * @note This needs to be enabled via #define ENABLE_NETWORK_STATS in RF24Network_config.h
- *
- * @code
- * bool fails, success;
- * network.failures(&fails,&success);
- * @endcode
- *
- */
- void failures(uint32_t *_fails, uint32_t *_ok);
-
-#if defined (RF24NetworkMulticast)
-
- /**
- * Send a multicast message to multiple nodes at once
- * Allows messages to be rapidly broadcast through the network
- *
- * Multicasting is arranged in levels, with all nodes on the same level listening to the same address
- * Levels are assigned by network level ie: nodes 01-05: Level 1, nodes 011-055: Level 2
- * @see multicastLevel
- * @see multicastRelay
- * @param message Pointer to memory where the message is located
- * @param len The size of the message
- * @param level Multicast level to broadcast to
- * @return Whether the message was successfully sent
- */
-
- bool multicast(RF24NetworkHeader& header,const void* message, uint16_t len, uint8_t level);
+ /**
+ * Sleep this node - For AVR devices only
+ * @note NEW - Nodes can now be slept while the radio is not actively transmitting. This must be manually enabled by uncommenting
+ * the #define ENABLE_SLEEP_MODE in RF24Network_config.h
+ * @note Setting the interruptPin to 255 will disable interrupt wake-ups
+ * @note The watchdog timer should be configured in setup() if using sleep mode.
+ * This function will sleep the node, with the radio still active in receive mode.
+ *
+ * The node can be awoken in two ways, both of which can be enabled simultaneously:
+ * 1. An interrupt - usually triggered by the radio receiving a payload. Must use pin 2 (interrupt 0) or 3 (interrupt 1) on Uno, Nano, etc.
+ * 2. The watchdog timer waking the MCU after a designated period of time, can also be used instead of delays to control transmission intervals.
+ * @code
+ * if(!network.available()){ network.sleepNode(1,0); } //Sleeps the node for 1 second or a payload is received
+ *
+ * Other options:
+ * network.sleepNode(0,0); // Sleep this node for the designated time period, or a payload is received.
+ * network.sleepNode(1,255); // Sleep this node for 1 cycle. Do not wake up until then, even if a payload is received ( no interrupt )
+ * @endcode
+ * @see setup_watchdog()
+ * @param cycles: The node will sleep in cycles of 1s. Using 2 will sleep 2 WDT cycles, 3 sleeps 3WDT cycles...
+ * @param interruptPin: The interrupt number to use (0,1) for pins two and three on Uno,Nano. More available on Mega etc.
+ * @return True if sleepNode completed normally, after the specified number of cycles. False if sleep was interrupted
+ */
+ bool sleepNode( unsigned int cycles, int interruptPin );
-#endif
-
- /**
- * Writes a direct (unicast) payload. This allows routing or sending messages outside of the usual routing paths.
- * The same as write, but a physical address is specified as the last option.
- * The payload will be written to the physical address, and routed as necessary by the recipient
- */
- bool write(RF24NetworkHeader& header,const void* message, uint16_t len, uint16_t writeDirect);
-
- /**
- * Sleep this node - For AVR devices only
- * @note NEW - Nodes can now be slept while the radio is not actively transmitting. This must be manually enabled by uncommenting
- * the #define ENABLE_SLEEP_MODE in RF24Network_config.h
- * @note Setting the interruptPin to 255 will disable interrupt wake-ups
- * @note The watchdog timer should be configured in setup() if using sleep mode.
- * This function will sleep the node, with the radio still active in receive mode.
- *
- * The node can be awoken in two ways, both of which can be enabled simultaneously:
- * 1. An interrupt - usually triggered by the radio receiving a payload. Must use pin 2 (interrupt 0) or 3 (interrupt 1) on Uno, Nano, etc.
- * 2. The watchdog timer waking the MCU after a designated period of time, can also be used instead of delays to control transmission intervals.
- * @code
- * if(!network.available()){ network.sleepNode(1,0); } //Sleeps the node for 1 second or a payload is received
- *
- * Other options:
- * network.sleepNode(0,0); // Sleep this node for the designated time period, or a payload is received.
- * network.sleepNode(1,255); // Sleep this node for 1 cycle. Do not wake up until then, even if a payload is received ( no interrupt )
- * @endcode
- * @see setup_watchdog()
- * @param cycles: The node will sleep in cycles of 1s. Using 2 will sleep 2 WDT cycles, 3 sleeps 3WDT cycles...
- * @param interruptPin: The interrupt number to use (0,1) for pins two and three on Uno,Nano. More available on Mega etc.
- * @return True if sleepNode completed normally, after the specified number of cycles. False if sleep was interrupted
- */
- bool sleepNode( unsigned int cycles, int interruptPin );
-
-
- /**
- * This node's parent address
- *
- * @return This node's parent address, or -1 if this is the base
- */
- uint16_t parent() const;
-
- /**
- * Provided a node address and a pipe number, will return the RF24Network address of that child pipe for that node
- */
- uint16_t addressOfPipe( uint16_t node,uint8_t pipeNo );
-
- /**
- * @note Addresses are specified in octal: 011, 034
- * @return True if a supplied address is valid
- */
- bool is_valid_address( uint16_t node );
+ /**
+ * This node's parent address
+ *
+ * @return This node's parent address, or -1 if this is the base
+ */
+ uint16_t parent() const;
+
+ /**
+ * Provided a node address and a pipe number, will return the RF24Network address of that child pipe for that node
+ */
+ uint16_t addressOfPipe( uint16_t node,uint8_t pipeNo );
+
+ /**
+ * @note Addresses are specified in octal: 011, 034
+ * @return True if a supplied address is valid
+ */
+ bool is_valid_address( uint16_t node );
- /**@}*/
- /**
- * @name Deprecated
- *
- * Maintained for backwards compatibility
- */
- /**@{*/
+ /**@}*/
+ /**
+ * @name Deprecated
+ *
+ * Maintained for backwards compatibility
+ */
+ /**@{*/
+
+ /**
+ * Bring up the network on a specific radio frequency/channel.
+ * @note Use radio.setChannel() to configure the radio channel
+ *
+ * **Example 1:** Begin on channel 90 with address 0 (master node)
+ * @code
+ * network.begin(90,0);
+ * @endcode
+ * **Example 2:** Begin on channel 90 with address 01 (child of master)
+ * @code
+ * network.begin(90,01);
+ * @endcode
+ * **Example 3:** Begin on channel 90 with address 011 (child of 01, grandchild of master)
+ * @code
+ * network.begin(90,011);
+ * @endcode
+ *
+ * @param _channel The RF channel to operate on
+ * @param _node_address The logical address of this node
+ *
+ */
+ void begin(uint8_t _channel, uint16_t _node_address );
+
+ /**@}*/
+ /**
+ * @name External Applications/Systems
+ *
+ * Interface for External Applications and Systems ( RF24Mesh, RF24Ethernet )
+ */
+ /**@{*/
+
+ /** The raw system frame buffer of received data. */
+
+ uint8_t frame_buffer[MAX_FRAME_SIZE];
- /**
- * Bring up the network on a specific radio frequency/channel.
- * @note Use radio.setChannel() to configure the radio channel
- *
- * **Example 1:** Begin on channel 90 with address 0 (master node)
- * @code
- * network.begin(90,0);
- * @endcode
- * **Example 2:** Begin on channel 90 with address 01 (child of master)
- * @code
- * network.begin(90,01);
- * @endcode
- * **Example 3:** Begin on channel 90 with address 011 (child of 01, grandchild of master)
- * @code
- * network.begin(90,011);
- * @endcode
- *
- * @param _channel The RF channel to operate on
- * @param _node_address The logical address of this node
- *
- */
- void begin(uint8_t _channel, uint16_t _node_address );
-
- /**@}*/
- /**
- * @name External Applications/Systems
- *
- * Interface for External Applications and Systems ( RF24Mesh, RF24Ethernet )
- */
- /**@{*/
-
- /** The raw system frame buffer of received data. */
-
- uint8_t frame_buffer[MAX_FRAME_SIZE];
-
- /**
- * **Linux** <br>
- * Data with a header type of EXTERNAL_DATA_TYPE will be loaded into a separate queue.
- * The data can be accessed as follows:
- * @code
- * RF24NetworkFrame f;
- * while(network.external_queue.size() > 0){
- * f = network.external_queue.front();
- * uint16_t dataSize = f.message_size;
- * //read the frame message buffer
- * memcpy(&myBuffer,&f.message_buffer,dataSize);
- * network.external_queue.pop();
- * }
- * @endcode
- */
-
+ /**
+ * **Linux** <br>
+ * Data with a header type of EXTERNAL_DATA_TYPE will be loaded into a separate queue.
+ * The data can be accessed as follows:
+ * @code
+ * RF24NetworkFrame f;
+ * while(network.external_queue.size() > 0){
+ * f = network.external_queue.front();
+ * uint16_t dataSize = f.message_size;
+ * //read the frame message buffer
+ * memcpy(&myBuffer,&f.message_buffer,dataSize);
+ * network.external_queue.pop();
+ * }
+ * @endcode
+ */
+
+
+
+
+ #if !defined ( DISABLE_FRAGMENTATION )
+ /**
+ * **ARDUINO** <br>
+ * The frag_ptr is only used with Arduino (not RPi/Linux) and is mainly used for external data systems like RF24Ethernet. When
+ * an EXTERNAL_DATA payload type is received, and returned from network.update(), the frag_ptr will always point to the starting
+ * memory location of the received frame. <br>This is used by external data systems (RF24Ethernet) to immediately copy the received
+ * data to a buffer, without using the user-cache.
+ *
+ * @see RF24NetworkFrame
+ *
+ * @code
+ * uint8_t return_type = network.update();
+ * if(return_type == EXTERNAL_DATA_TYPE){
+ * uint16_t size = network.frag_ptr->message_size;
+ * memcpy(&myDataBuffer,network.frag_ptr->message_buffer,network.frag_ptr->message_size);
+ * }
+ * @endcode
+ * Linux devices (defined as RF24_LINUX) currently cache all payload types, and do not utilize frag_ptr.
+ */
+ RF24NetworkFrame* frag_ptr;
+ #endif
-#if !defined ( DISABLE_FRAGMENTATION )
- /**
- * **ARDUINO** <br>
- * The frag_ptr is only used with Arduino (not RPi/Linux) and is mainly used for external data systems like RF24Ethernet. When
- * an EXTERNAL_DATA payload type is received, and returned from network.update(), the frag_ptr will always point to the starting
- * memory location of the received frame. <br>This is used by external data systems (RF24Ethernet) to immediately copy the received
- * data to a buffer, without using the user-cache.
- *
- * @see RF24NetworkFrame
- *
- * @code
- * uint8_t return_type = network.update();
- * if(return_type == EXTERNAL_DATA_TYPE){
- * uint16_t size = network.frag_ptr->message_size;
- * memcpy(&myDataBuffer,network.frag_ptr->message_buffer,network.frag_ptr->message_size);
- * }
- * @endcode
- * Linux devices (defined as RF24_LINUX) currently cache all payload types, and do not utilize frag_ptr.
- */
- RF24NetworkFrame* frag_ptr;
-#endif
+ /**
+ * Variable to determine whether update() will return after the radio buffers have been emptied (DEFAULT), or
+ * whether to return immediately when (most) system types are received.
+ *
+ * As an example, this is used with RF24Mesh to catch and handle system messages without loading them into the user cache.
+ *
+ * The following reserved/system message types are handled automatically, and not returned.
+ *
+ * | System Message Types <br> (Not Returned) |
+ * |-----------------------|
+ * | NETWORK_ADDR_RESPONSE |
+ * | NETWORK_ACK |
+ * | NETWORK_PING |
+ * | NETWORK_POLL <br>(With multicast enabled) |
+ * | NETWORK_REQ_ADDRESS |
+ *
+ */
+ bool returnSysMsgs;
- /**
- * Variable to determine whether update() will return after the radio buffers have been emptied (DEFAULT), or
- * whether to return immediately when (most) system types are received.
- *
- * As an example, this is used with RF24Mesh to catch and handle system messages without loading them into the user cache.
- *
- * The following reserved/system message types are handled automatically, and not returned.
- *
- * | System Message Types <br> (Not Returned) |
- * |-----------------------|
- * | NETWORK_ADDR_RESPONSE |
- * | NETWORK_ACK |
- * | NETWORK_PING |
- * | NETWORK_POLL <br>(With multicast enabled) |
- * | NETWORK_REQ_ADDRESS |
- *
- */
- bool returnSysMsgs;
+ /**
+ * Network Flags allow control of data flow
+ *
+ * Incoming Blocking: If the network user-cache is full, lets radio cache fill up. Radio ACKs are not sent when radio internal cache is full.<br>
+ * This behaviour may seem to result in more failed sends, but the payloads would have otherwise been dropped due to the cache being full.<br>
+ *
+ * | FLAGS | Value | Description |
+ * |-------|-------|-------------|
+ * |FLAG_HOLD_INCOMING| 1(bit_1) | INTERNAL: Set automatically when a fragmented payload will exceed the available cache |
+ * |FLAG_BYPASS_HOLDS| 2(bit_2) | EXTERNAL: Can be used to prevent holds from blocking. Note: Holds are disabled & re-enabled by RF24Mesh when renewing addresses. This will cause data loss if incoming data exceeds the available cache space|
+ * |FLAG_FAST_FRAG| 4(bit_3) | INTERNAL: Replaces the fastFragTransfer variable, and allows for faster transfers between directly connected nodes. |
+ * |FLAG_NO_POLL| 8(bit_4) | EXTERNAL/USER: Disables NETWORK_POLL responses on a node-by-node basis. |
+ *
+ */
+ uint8_t networkFlags;
+
+ private:
- /**
- * Network Flags allow control of data flow
- *
- * Incoming Blocking: If the network user-cache is full, lets radio cache fill up. Radio ACKs are not sent when radio internal cache is full.<br>
- * This behaviour may seem to result in more failed sends, but the payloads would have otherwise been dropped due to the cache being full.<br>
- *
- * | FLAGS | Value | Description |
- * |-------|-------|-------------|
- * |FLAG_HOLD_INCOMING| 1(bit_1) | INTERNAL: Set automatically when a fragmented payload will exceed the available cache |
- * |FLAG_BYPASS_HOLDS| 2(bit_2) | EXTERNAL: Can be used to prevent holds from blocking. Note: Holds are disabled & re-enabled by RF24Mesh when renewing addresses. This will cause data loss if incoming data exceeds the available cache space|
- * |FLAG_FAST_FRAG| 4(bit_3) | INTERNAL: Replaces the fastFragTransfer variable, and allows for faster transfers between directly connected nodes. |
- *
- */
- uint8_t networkFlags;
-
-private:
-
- uint32_t txTime;
+ uint32_t txTime;
+ Timer mainTimer;
+
+ bool write(uint16_t, uint8_t directTo);
+ bool write_to_pipe( uint16_t node, uint8_t pipe, bool multicast );
+ uint8_t enqueue(RF24NetworkHeader *header);
- bool write(uint16_t, uint8_t directTo);
- bool write_to_pipe( uint16_t node, uint8_t pipe, bool multicast );
- uint8_t enqueue(RF24NetworkHeader *header);
-
- bool is_direct_child( uint16_t node );
- bool is_descendant( uint16_t node );
-
- uint16_t direct_child_route_to( uint16_t node );
- //uint8_t pipe_to_descendant( uint16_t node );
- void setup_address(void);
- bool _write(RF24NetworkHeader& header,const void* message, uint16_t len, uint16_t writeDirect);
-
- struct logicalToPhysicalStruct {
- uint16_t send_node;
- uint8_t send_pipe;
- bool multicast;
- };
-
- bool logicalToPhysicalAddress(logicalToPhysicalStruct *conversionInfo);
-
-
- RF24& radio; /**< Underlying radio driver, provides link/physical layers */
+ bool is_direct_child( uint16_t node );
+ bool is_descendant( uint16_t node );
+
+ uint16_t direct_child_route_to( uint16_t node );
+ //uint8_t pipe_to_descendant( uint16_t node );
+ void setup_address(void);
+ bool _write(RF24NetworkHeader& header,const void* message, uint16_t len, uint16_t writeDirect);
+
+ struct logicalToPhysicalStruct{
+ uint16_t send_node;
+ uint8_t send_pipe;
+ bool multicast;
+ };
+
+ bool logicalToPhysicalAddress(logicalToPhysicalStruct *conversionInfo);
+
+
+ RF24& radio; /**< Underlying radio driver, provides link/physical layers */
#if defined (DUAL_HEAD_RADIO)
- RF24& radio1;
+ RF24& radio1;
#endif
-#if defined (RF24NetworkMulticast)
- uint8_t multicast_level;
+#if defined (RF24NetworkMulticast)
+ uint8_t multicast_level;
#endif
- uint16_t node_address; /**< Logical node address of this unit, 1 .. UINT_MAX */
- //const static int frame_size = 32; /**< How large is each frame over the air */
- uint8_t frame_size;
- const static unsigned int max_frame_payload_size = MAX_FRAME_SIZE-sizeof(RF24NetworkHeader);
-
-
-#if !defined (NUM_USER_PAYLOADS)
-#define NUM_USER_PAYLOADS 5
-#endif
-
-#if defined (DISABLE_USER_PAYLOADS)
- uint8_t frame_queue[1]; /**< Space for a small set of frames that need to be delivered to the app layer */
-#else
- uint8_t frame_queue[MAIN_BUFFER_SIZE]; /**< Space for a small set of frames that need to be delivered to the app layer */
-#endif
-
- uint8_t* next_frame; /**< Pointer into the @p frame_queue where we should place the next received frame */
+ uint16_t node_address; /**< Logical node address of this unit, 1 .. UINT_MAX */
+ //const static int frame_size = 32; /**< How large is each frame over the air */
+ uint8_t frame_size;
+ const static unsigned int max_frame_payload_size = MAX_FRAME_SIZE-sizeof(RF24NetworkHeader);
-#if !defined ( DISABLE_FRAGMENTATION )
- RF24NetworkFrame frag_queue;
- uint8_t frag_queue_message_buffer[MAX_PAYLOAD_SIZE]; //frame size + 1
-#endif
-
- //uint8_t frag_queue[MAX_PAYLOAD_SIZE + 11];
- //RF24NetworkFrame frag_queue;
+
+ #if !defined (NUM_USER_PAYLOADS)
+ #define NUM_USER_PAYLOADS 5
+ #endif
+
+ #if defined (DISABLE_USER_PAYLOADS)
+ uint8_t frame_queue[1]; /**< Space for a small set of frames that need to be delivered to the app layer */
+ #else
+ uint8_t frame_queue[MAIN_BUFFER_SIZE]; /**< Space for a small set of frames that need to be delivered to the app layer */
+ #endif
+
+ uint8_t* next_frame; /**< Pointer into the @p frame_queue where we should place the next received frame */
+
+ #if !defined ( DISABLE_FRAGMENTATION )
+ RF24NetworkFrame frag_queue;
+ uint8_t frag_queue_message_buffer[MAX_PAYLOAD_SIZE]; //frame size + 1
+ #endif
- uint16_t parent_node; /**< Our parent's node address */
- uint8_t parent_pipe; /**< The pipe our parent uses to listen to us */
- uint16_t node_mask; /**< The bits which contain signfificant node address information */
-
-#if defined ENABLE_NETWORK_STATS
- static uint32_t nFails;
- static uint32_t nOK;
-#endif
-
+
+ //uint8_t frag_queue[MAX_PAYLOAD_SIZE + 11];
+ //RF24NetworkFrame frag_queue;
+
+ uint16_t parent_node; /**< Our parent's node address */
+ uint8_t parent_pipe; /**< The pipe our parent uses to listen to us */
+ uint16_t node_mask; /**< The bits which contain signfificant node address information */
+
+ #if defined ENABLE_NETWORK_STATS
+ static uint32_t nFails;
+ static uint32_t nOK;
+ #endif
+
public:
-
+
};
@@ -869,7 +893,7 @@
* @section Purpose Purpose/Goal
*
* Original: Create an alternative to ZigBee radios for Arduino communication.
- *
+ *
* New: Enhance the current functionality for maximum efficiency, reliability, and speed
*
* Xbees are excellent little radios, backed up by a mature and robust standard
@@ -884,10 +908,10 @@
*
* @section Features Features
*
- * <b>Whats new? </b><br>
+ * <b>Whats new? </b><br>
* @li New: (Dec 8) Merge of RPi and Arduino code. Finally moving closer to a stable release. Report issues at https://github.com/TMRh20/RF24Network/issues
* @li New functionality: (Dec 8) Support for fragmented multicast payloads on both RPi and Arduino
- * @li New functionality: (Nov 24) Fragmentation & reassembly supported on both RPi and Arduino
+ * @li New functionality: (Nov 24) Fragmentation & reassembly supported on both RPi and Arduino
* @li Note: structure of network frames is changed, these are only used by external applications like RF24Ethernet and RF24toTUN, and for fragmentation
* @li New functionality: User message types 1 through 64 will not receive a network ack
*
@@ -917,7 +941,7 @@
* @li <a href="https://github.com/TMRh20/RF24Network/archive/Development.zip">Download Current Development Package</a>
* @li <a href="examples.html">Examples Page</a>. Start with <a href="helloworld_rx_8ino-example.html">helloworld_rx</a> and <a href="helloworld_tx_8ino-example.html">helloworld_tx</a>.
*
- * <b> Additional Information & Add-ons </b>
+ * <b> Additional Information & Add-ons </b>
* @li <a href="https://github.com/TMRh20/RF24Mesh">RF24Mesh: Dynamic Mesh Layer for RF24Network Dev</a>
* @li <a href="https://github.com/TMRh20/RF24Ethernet">RF24Ethernet: TCP/IP over RF24Network</a>
* @li <a href="http://tmrh20.blogspot.com/2014/03/high-speed-data-transfers-and-wireless.html">My Blog: RF24 Optimization Overview</a>
@@ -989,25 +1013,25 @@
*
* @section Overview Overview
* The nrf24 radio modules typically use a 40-bit address format, requiring 5-bytes of storage space per address, and allowing a wide
- * array of addresses to be utilized. In addition, the radios are limited to direct communication with 6 other nodes while using the
- * Enhanced-Shock-Burst (ESB) functionality of the radios.
+ * array of addresses to be utilized. In addition, the radios are limited to direct communication with 6 other nodes while using the
+ * Enhanced-Shock-Burst (ESB) functionality of the radios.
*
* RF24Network uses a simple method of data compression to store the addresses using only 2 bytes, in a format designed to represent the
* network topology in an intuitive way.
* See the <a href="Tuning.html"> Topology and Overview</a> page for more info regarding topology.
*
* @section Octal_Binary Decimal, Octal and Binary formats
- *
+ *
* Say we want to designate a logical address to a node, using a tree topology as defined by the manufacturer.
- * In the simplest format, we could assign the first node the address of 1, the second 2 and so on.
+ * In the simplest format, we could assign the first node the address of 1, the second 2 and so on.
* Since a single node can only connect to 6 other nodes (1 parent and 5 children) subnets need to be created if using more than 6 nodes.<br>
* In this case the children of node 1 could simply be designated as 11,21,31,41, and 51<br>
- * Children of node 2 could be designated as 12,22,32,42, and 52
- *
+ * Children of node 2 could be designated as 12,22,32,42, and 52
+ *
* The above example is exactly how RF24Network manages the addresses, but they are represented in Octal format.
- *
- * <b>Decimal, Octal and Binary</b>
- * <table>
+ *
+ * <b>Decimal, Octal and Binary</b>
+ * <table>
* <tr bgcolor="#a3b4d7" >
* <td> Decimal </td> <td> Binary </td><td> Decimal </td> <td> Binary </td><td> Decimal </td> <td> Binary </td>
* </tr><tr>
@@ -1019,15 +1043,15 @@
* </tr>
* </table>
*
- *
- * Since the numbers 0-7 can be represented in exactly three bits, each digit is represented by exactly 3 bits when viewed in octal format.
- * This allows a very simple method of managing addresses via masking and bit shifting.
- *
+ *
+ * Since the numbers 0-7 can be represented in exactly three bits, each digit is represented by exactly 3 bits when viewed in octal format.
+ * This allows a very simple method of managing addresses via masking and bit shifting.
+ *
* @section DisplayAddresses Displaying Addresses
*
* When using Arduino devices, octal addresses can be printed in the following manner:
* @code
- * uint16_t address = 0111;
+ * uint16_t address = 0111;
* Serial.println(address,OCT);
* @endcode
*
@@ -1038,7 +1062,7 @@
* @endcode
*
* See http://www.cplusplus.com/doc/hex/ for more information<br>
- * See the <a href="Tuning.html"> Topology and Overview</a> page for more info regarding topology.
+ * See the <a href="Tuning.html"> Topology and Overview</a> page for more info regarding topology.
*
* @page AdvancedConfig Advanced Configuration
*
@@ -1063,12 +1087,12 @@
* @section General Understanding Radio Communication and Topology
* When a transmission takes place from one radio module to another, the receiving radio will communicate
* back to the sender with an acknowledgement (ACK) packet, to indicate success. If the sender does not
- * receive an ACK, the radio automatically engages in a series of timed retries, at set intervals. The
- * radios use techniques like addressing and numbering of payloads to manage this, but it is all done
+ * receive an ACK, the radio automatically engages in a series of timed retries, at set intervals. The
+ * radios use techniques like addressing and numbering of payloads to manage this, but it is all done
* automatically by the nrf chip, out of sight from the user.
*
* When working over a radio network, some of these automated techniques can actually hinder data transmission to a degree.
- * Retrying failed payloads over and over on a radio network can hinder communication for nearby nodes, or
+ * Retrying failed payloads over and over on a radio network can hinder communication for nearby nodes, or
* reduce throughput and errors on routing nodes.
*
* Radios in this network are linked by <b>addresses</b> assigned to <b>pipes</b>. Each radio can listen
@@ -1083,16 +1107,16 @@
* subnet below it, with up to 4 additional child nodes. The numbering scheme can also be related to IP addresses,
* for purposes of understanding the topology via subnetting. Nodes can have 5 children if multicast is disabled.
*
- * Expressing RF24Network addresses in IP format:
+ * Expressing RF24Network addresses in IP format:
*
- * As an example, we could designate the master node in theory, as Address 10.10.10.10 <br>
- * The children nodes of the master would be 10.10.10.1, 10.10.10.2, 10.10.10.3, 10.10.10.4 and 10.10.10.5 <br>
- * The children nodes of 10.10.10.1 would be 10.10.1.1, 10.10.2.1, 10.10.3.1, 10.10.4.1 and 10.10.5.1 <br>
- *
+ * As an example, we could designate the master node in theory, as Address 10.10.10.10 <br>
+ * The children nodes of the master would be 10.10.10.1, 10.10.10.2, 10.10.10.3, 10.10.10.4 and 10.10.10.5 <br>
+ * The children nodes of 10.10.10.1 would be 10.10.1.1, 10.10.2.1, 10.10.3.1, 10.10.4.1 and 10.10.5.1 <br>
+ *
* In RF24Network, the master is just 00 <br>
* Children of master are 01,02,03,04,05 <br>
* Children of 01 are 011,021,031,041,051 <br>
- *
+ *
* @section Network Routing
*
* Routing of traffic is handled invisibly to the user, by the network layer. If the network addresses are
@@ -1114,8 +1138,8 @@
*
* Old Functionality: Node 00 sends to node 011 using auto-ack. Node 00 first sends to 01, 01 acknowledges.
* Node 01 forwards the payload to 011 using auto-ack. If the payload fails between 01 and 011, node 00 has
- * no way of knowing.
- *
+ * no way of knowing.
+ *
* @note When retrying failed payloads that have been routed, there is a chance of duplicate payloads if the network-ack
* is not successful. In this case, it is left up to the user to manage retries and filtering of duplicate payloads.
*
@@ -1123,7 +1147,7 @@
* an acknowledgement is not required, so a user defined type of 0-64 should be used, to prevent the network from
* responding with an acknowledgement. If not requesting a response, and wanting to know if the payload was successful
* or not, users can utilize header types 65-127.
- *
+ *
* @section TuningOverview Tuning Overview
* The RF24 radio modules are generally only capable of either sending or receiving data at any given
* time, but have built-in auto-retry mechanisms to prevent the loss of data. These values are adjusted
@@ -1179,13 +1203,13 @@
*
* a: Master node configured with extended timeouts of .5 seconds, and increased retry delay:
* @code
- * radio.setRetries(11,15);
- * network.txTimeout = 500;
- * @endcode
+ * radio.setRetries(11,15);
+ * network.txTimeout = 500;
+ * @endcode
* b: Second leaf node configured with a similar timeout period and retry delay:
* @code
- * radio.setRetries(8,15);
- * network.txTimeout = 553;
+ * radio.setRetries(8,15);
+ * network.txTimeout = 553;
* @endcode
* c: First and third leaf nodes configured with default timeout periods or slightly increased timout periods.
*
@@ -1202,9 +1226,9 @@
* 4. Setup the radio and network like so:
*
* @code
- * RF24 radio(7,8); // Using CE (7) and CS (8) for first radio
- * RF24 radio1(4,5); // Using CE (4) and CS (5) for second radio
- * RF24Network network(radio,radio1); // Set up the network using both radios
+ * RF24 radio(7,8); // Using CE (7) and CS (8) for first radio
+ * RF24 radio1(4,5); // Using CE (4) and CS (5) for second radio
+ * RF24Network network(radio,radio1); // Set up the network using both radios
*
* Then in setup(), call radio.begin(); and radio1.begin(); before network.begin();
* @endcode
@@ -1250,10 +1274,12 @@
* @li Base node. The top of the tree node with no parents, only children. Typically this node
* will bridge to another kind of network like Ethernet. ZigBee calls it a Co-ordinator node.
*
- *
+ *
*
*
*/
#endif // __RF24NETWORK_H__
+
+
--- a/RF24Network_config.h Thu Nov 05 05:54:47 2015 +0000
+++ b/RF24Network_config.h Thu Apr 21 03:43:13 2016 +0000
@@ -7,98 +7,91 @@
version 2 as published by the Free Software Foundation.
*/
- /*
+/*
* Mbed support added by Akash Vibhute <akash.roboticist@gmail.com>
* Porting completed on Nov/05/2015
*
- * Updated with TMRh20's RF24 library on Nov/04/2015 from https://github.com/TMRh20
+ * Updated 1: Synced with TMRh20's RF24 library on Nov/04/2015 from https://github.com/TMRh20
+ * Updated 2: Synced with TMRh20's RF24 library on Apr/18/2015 from https://github.com/TMRh20
*
*/
-
+
#ifndef __RF24NETWORK_CONFIG_H__
#define __RF24NETWORK_CONFIG_H__
-#include "mbed.h"
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#define _BV(x) (1<<(x))
+ /********** USER CONFIG **************/
+
+ //#define DUAL_HEAD_RADIO
+ //#define ENABLE_SLEEP_MODE //AVR only
+ #define RF24NetworkMulticast
+
+ /** \def
+ * Saves memory by disabling fragmentation
+ */
+ //#define DISABLE_FRAGMENTATION
+
+ /** System defines */
+
+ /** The size of the main buffer. This is the user-cache, where incoming data is stored.
+ * Data is stored using Frames: Header (8-bytes) + Frame_Size (2-bytes) + Data (?-bytes)
+ *
+ * @note The MAX_PAYLOAD_SIZE is (MAIN_BUFFER_SIZE - 10), and the result must be divisible by 24.
+ */
+ #define MAIN_BUFFER_SIZE 144 + 10
+
+ /** Maximum size of fragmented network frames and fragmentation cache. This MUST BE divisible by 24.
+ * @note: Must be a multiple of 24.
+ * @note: If used with RF24Ethernet, this value is used to set the buffer sizes.
+ */
+ #define MAX_PAYLOAD_SIZE MAIN_BUFFER_SIZE-10
+
+ /** Disable user payloads. Saves memory when used with RF24Ethernet or software that uses external data.*/
+ //#define DISABLE_USER_PAYLOADS
+
+ /** Enable tracking of success and failures for all transmissions, routed and user initiated */
+ //#define ENABLE_NETWORK_STATS
+
+ /** Enable dynamic payloads - If using different types of NRF24L01 modules, some may be incompatible when using this feature **/
+ #define ENABLE_DYNAMIC_PAYLOADS
-#include <stddef.h>
+ /** Debug Options */
+ //#define SERIAL_DEBUG
+ //#define SERIAL_DEBUG_MINIMAL
+ //#define SERIAL_DEBUG_ROUTING
+ //#define SERIAL_DEBUG_FRAGMENTATION
+ //#define SERIAL_DEBUG_FRAGMENTATION_L2
+ /*************************************/
+
+#endif //RF24_NETWORK_CONFIG_H
+
+#include <RF24_config.h>
+
+#define sprintf_P sprintf
+
+ #if defined (SERIAL_DEBUG_MINIMAL)
+ #define IF_SERIAL_DEBUG_MINIMAL(x) ({x;})
+ #else
+ #define IF_SERIAL_DEBUG_MINIMAL(x)
+ #endif
+
+ #if defined (SERIAL_DEBUG_FRAGMENTATION)
+ #define IF_SERIAL_DEBUG_FRAGMENTATION(x) ({x;})
+ #else
+ #define IF_SERIAL_DEBUG_FRAGMENTATION(x)
+ #endif
+
+ #if defined (SERIAL_DEBUG_FRAGMENTATION_L2)
+ #define IF_SERIAL_DEBUG_FRAGMENTATION_L2(x) ({x;})
+ #else
+ #define IF_SERIAL_DEBUG_FRAGMENTATION_L2(x)
+ #endif
+
+ #if defined (SERIAL_DEBUG_ROUTING)
+ #define IF_SERIAL_DEBUG_ROUTING(x) ({x;})
+ #else
+ #define IF_SERIAL_DEBUG_ROUTING(x)
+ #endif
-//#define DUAL_HEAD_RADIO
-//#define ENABLE_SLEEP_MODE //AVR only
-#define RF24NetworkMulticast
-
-/** \def
- * Saves memory by disabling fragmentation
- */
-//#define DISABLE_FRAGMENTATION
-
-/** System defines */
-
-/** The size of the main buffer. This is the user-cache, where incoming data is stored.
- * Data is stored using Frames: Header (8-bytes) + Frame_Size (2-bytes) + Data (?-bytes)
- *
- * @note The MAX_PAYLOAD_SIZE is (MAIN_BUFFER_SIZE - 10), and the result must be divisible by 24.
- */
-#define MAIN_BUFFER_SIZE 144 + 10
-
-/** Maximum size of fragmented network frames and fragmentation cache. This MUST BE divisible by 24.
-* @note: Must be a multiple of 24.
-* @note: If used with RF24Ethernet, this value is used to set the buffer sizes.
-*/
-#define MAX_PAYLOAD_SIZE MAIN_BUFFER_SIZE-10
-
-/** Disable user payloads. Saves memory when used with RF24Ethernet or software that uses external data.*/
-//#define DISABLE_USER_PAYLOADS
-
-/** Enable tracking of success and failures for all transmissions, routed and user initiated */
-//#define ENABLE_NETWORK_STATS
-
-/** Enable dynamic payloads - If using different types of NRF24L01 modules, some may be incompatible when using this feature **/
-#define ENABLE_DYNAMIC_PAYLOADS
-
-/** Debug Options */
-//#define SERIAL_DEBUG
-//#define SERIAL_DEBUG_MINIMAL
-//#define SERIAL_DEBUG_ROUTING
-//#define SERIAL_DEBUG_FRAGMENTATION
-//#define SERIAL_DEBUG_FRAGMENTATION_L2
-/*************************************/
-#ifndef rf24_max
-#define rf24_max(a,b) (a>b?a:b)
-#endif
-#ifndef rf24_min
-#define rf24_min(a,b) (a<b?a:b)
-#endif
-
-
-#if defined (SERIAL_DEBUG_MINIMAL)
-#define IF_SERIAL_DEBUG_MINIMAL(x) ({x;})
-#else
-#define IF_SERIAL_DEBUG_MINIMAL(x)
-#endif
-
-#if defined (SERIAL_DEBUG_FRAGMENTATION)
-#define IF_SERIAL_DEBUG_FRAGMENTATION(x) ({x;})
-#else
-#define IF_SERIAL_DEBUG_FRAGMENTATION(x)
-#endif
-
-#if defined (SERIAL_DEBUG_FRAGMENTATION_L2)
-#define IF_SERIAL_DEBUG_FRAGMENTATION_L2(x) ({x;})
-#else
-#define IF_SERIAL_DEBUG_FRAGMENTATION_L2(x)
-#endif
-
-#if defined (SERIAL_DEBUG_ROUTING)
-#define IF_SERIAL_DEBUG_ROUTING(x) ({x;})
-#else
-#define IF_SERIAL_DEBUG_ROUTING(x)
-#endif
-#endif // RF24_NETWORK_CONFIG_H
-
--- a/Sync.cpp Thu Nov 05 05:54:47 2015 +0000
+++ b/Sync.cpp Thu Apr 21 03:43:13 2016 +0000
@@ -5,7 +5,16 @@
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
-
+
+/*
+ * Mbed support added by Akash Vibhute <akash.roboticist@gmail.com>
+ * Porting completed on Nov/05/2015
+ *
+ * Updated 1: Synced with TMRh20's RF24 library on Nov/04/2015 from https://github.com/TMRh20
+ * Updated 2: Synced with TMRh20's RF24 library on Apr/18/2015 from https://github.com/TMRh20
+ *
+ */
+
// STL headers
// C headers
#include <stdlib.h>
@@ -65,6 +74,7 @@
{
case 'S':
//IF_SERIAL_DEBUG(printf_P(PSTR("%lu: SYN Received sync message\n\r"),millis()));
+ IF_SERIAL_DEBUG(printf_P(PSTR("SYN Received sync message\n\r")));
network.read(header,&message,sizeof(message));
// Parse the message and update the vars
@@ -79,6 +89,7 @@
uint8_t val = *mptr++;
//IF_SERIAL_DEBUG(printf_P(PSTR("%lu: SYN Updated position %u to value %u\n\r"),millis(),pos,val));
+ IF_SERIAL_DEBUG(printf_P(PSTR("%SYN Updated position %u to value %u\n\r"),pos,val));
app_data[pos] = val;
internal_data[pos] = val;
@@ -91,3 +102,5 @@
}
}
// vim:cin:ai:sts=2 sw=2 ft=cpp
+
+
--- a/Sync.h Thu Nov 05 05:54:47 2015 +0000 +++ b/Sync.h Thu Apr 21 03:43:13 2016 +0000 @@ -5,7 +5,16 @@ modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. */ - + +/* + * Mbed support added by Akash Vibhute <akash.roboticist@gmail.com> + * Porting completed on Nov/05/2015 + * + * Updated 1: Synced with TMRh20's RF24 library on Nov/04/2015 from https://github.com/TMRh20 + * Updated 2: Synced with TMRh20's RF24 library on Apr/18/2015 from https://github.com/TMRh20 + * + */ + #ifndef __SYNC_H__ #define __SYNC_H__ @@ -83,3 +92,5 @@ #endif // __SYNC_H__ // vim:cin:ai:sts=2 sw=2 ft=cpp + +
