From 48de4994494007a9d9faa832e8b7b4f98c407092 Mon Sep 17 00:00:00 2001 From: TMRh20 Date: Sat, 27 Sep 2014 01:24:24 -0600 Subject: [PATCH 1/2] Testing some changes/additions - Add NETWORK_POLL for finding responsive nodes - Add fragmented writes for AVR/Due etc. - Test support for address request types --- RF24Network.cpp | 134 +++++++++++++++++++++++++++++++++++++++++-- RF24Network.h | 39 +++++++------ RF24Network_config.h | 11 +++- 3 files changed, 160 insertions(+), 24 deletions(-) diff --git a/RF24Network.cpp b/RF24Network.cpp index 53737616..fbc74641 100644 --- a/RF24Network.cpp +++ b/RF24Network.cpp @@ -48,7 +48,8 @@ void RF24Network::begin(uint8_t _channel, uint16_t _node_address ) if ( ! radio.isValid() ){ return; } - + + radio.stopListening(); // Set up the radio the way we want it to look radio.setChannel(_channel); //radio.setDataRate(RF24_1MBPS); @@ -110,7 +111,7 @@ uint8_t RF24Network::update(void) radio.read( frame_buffer, sizeof(frame_buffer) ); // Read the beginning of the frame as the header - const RF24NetworkHeader& header = * reinterpret_cast(frame_buffer); + RF24NetworkHeader& header = * reinterpret_cast(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(frame_buffer + sizeof(RF24NetworkHeader));printf_P(PSTR("%lu: NET message %04x\n\r"),millis(),*i)); @@ -130,7 +131,27 @@ uint8_t RF24Network::update(void) returnVal = NETWORK_ACK; continue; } // Add it to the buffer of frames for us - + if(header.type == NETWORK_ADDR_RESPONSE ){ + uint16_t requester = frame_buffer[8];// | frame_buffer[9] << 8; + requester |= frame_buffer[9] << 8; + + if(requester != node_address){ + header.to_node = requester; + //header.from_node = node_address; + write(header.to_node,USER_TX_TO_PHYSICAL_ADDRESS); + //write(header.to_node,USER_TX_TO_PHYSICAL_ADDRESS); + //printf("fwd addr resp to 0%o , this node: 0%o\n", requester,node_address); + continue; + } + } + if(header.type == NETWORK_REQ_ADDRESS && node_address){ + //RF24NetworkHeader reqHeader = header; + header.from_node = node_address; + header.to_node = 0; + write(header.to_node,TX_NORMAL); + //printf("fwd addr req\n"); + continue; + } enqueue(); @@ -146,6 +167,17 @@ uint8_t RF24Network::update(void) #endif write(levelToAddress(multicast_level)<<3,4); } + + if(header.type == NETWORK_POLL ){ + header.to_node = header.from_node; + header.from_node = node_address; + delay(2); + write(header.to_node,USER_TX_TO_PHYSICAL_ADDRESS); + //write(header.to_node,USER_TX_TO_PHYSICAL_ADDRESS); + //Serial.println("send poll"); + continue; + } + enqueue(); lastMultiMessageID = header.id; } @@ -292,11 +324,103 @@ bool RF24Network::multicast(RF24NetworkHeader& header,const void* message, size_ /******************************************************************/ bool RF24Network::write(RF24NetworkHeader& header,const void* message, size_t len){ - return _write(header,message,len,070); + return write(header,message,len,070); } /******************************************************************/ bool RF24Network::write(RF24NetworkHeader& header,const void* message, size_t len, uint16_t writeDirect){ + +#if defined (DISABLE_FRAGMENTATION) return _write(header,message,len,writeDirect); +#else + bool txSuccess = true; + + //Check payload size + if (len > MAX_PAYLOAD_SIZE) { + IF_SERIAL_DEBUG(printf("%u: NET write message failed. Given 'len' is bigger than the MAX Payload size %i\n\r",millis(),MAX_PAYLOAD_SIZE);); + return false; + } + + //If the message payload is too big, whe cannot generate enough fragments + //and enumerate them + if (len > 255*max_frame_payload_size) { + txSuccess = false; + return txSuccess; + } + + //Normal Write (Un-Fragmented) + if (len <= max_frame_payload_size) { + txSuccess = _write(header,message,len,writeDirect); + //radio.startListening(); + return txSuccess; + } + + //Divide the message payload into chuncks of max_frame_payload_size + uint8_t fragment_id = 1 + ((len - 1) / max_frame_payload_size); //the number of fragments to send = ceil(len/max_frame_payload_size) + uint8_t msgCount = 0; + + IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG Total message fragments %i\n\r",millis(),fragment_id);); + + while (fragment_id > 0) { + + //Copy and fill out the header + RF24NetworkHeader fragmentHeader = header; + fragmentHeader.reserved = fragment_id; + + if (fragment_id == 1) { + fragmentHeader.type = NETWORK_LAST_FRAGMENT; //Set the last fragment flag to indicate the last fragment + fragmentHeader.reserved = header.type; //Workaroung/Hack: to transmit the user application defined header.type, save this variable in the header.fragment_id. + } else { + if (msgCount == 0) { + fragmentHeader.type = NETWORK_FIRST_FRAGMENT; + }else{ + fragmentHeader.type = NETWORK_MORE_FRAGMENTS; //Set the more fragments flag to indicate a fragmented frame + } + } + + size_t offset = msgCount*max_frame_payload_size; + size_t fragmentLen = min(len-offset,max_frame_payload_size); + + IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG try to transmit fragmented payload of size %i Bytes with fragmentID '%i'\n\r",millis(),fragmentLen,fragment_id);); + + //Try to send the payload chunk with the copied header + bool ok = _write(fragmentHeader,message+offset,fragmentLen,writeDirect); + + if(!ok){ delay(100); ok = _write(fragmentHeader,message+offset,fragmentLen,writeDirect); + if(!ok){ delay(150); ok = _write(fragmentHeader,message+offset,fragmentLen,writeDirect); + } + } + //if (!noListen) { + delayMicroseconds(50); + //} + + if (!ok) { + IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG message transmission with fragmentID '%i' failed. Abort.\n\r",millis(),fragment_id);); + txSuccess = false; + break; + } + + //Message was successful sent + IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG message transmission with fragmentID '%i' sucessfull.\n\r",millis(),fragment_id);); + + //Check and modify counters + fragment_id--; + msgCount++; + } + + //noListen = 0; + + // Now, continue listening + //radio.startListening(); + + int frag_delay = uint8_t(len/48); + delay( min(frag_delay,20)); + + //Return true if all the chunks where sent successfully + //else return false + IF_SERIAL_DEBUG(printf("%u: NET total message fragments sent %i. txSuccess ",millis(),msgCount); printf("%s\n\r", txSuccess ? "YES" : "NO");); + return txSuccess; + +#endif //Fragmentation enabled } /******************************************************************/ @@ -380,7 +504,7 @@ bool RF24Network::write(uint16_t to_node, uint8_t directTo) // Direct To: 0 = F dynLen=0; #if defined (SERIAL_DEBUG_ROUTING) - printf_P(PSTR("%lu MAC: Route OK to 0%o ACK sent to 0%o\n"),millis(),conversion.send_node,fromAddress); + printf_P(PSTR("%lu MAC: Route OK to 0%o ACK sent to 0%o\n"),millis(),to_node,header.to_node); #endif } diff --git a/RF24Network.h b/RF24Network.h index 47851a5a..d18f9e8f 100644 --- a/RF24Network.h +++ b/RF24Network.h @@ -27,12 +27,17 @@ * System types can also contain sub-types, included as information, TBD * */ - + +/* Header types range */ +#define MIN_USER_DEFINED_HEADER_TYPE 0 +#define MAX_USER_DEFINED_HEADER_TYPE 127 + /** System Discard Types */ #define NETWORK_ACK_REQUEST 128 #define NETWORK_ACK 129 /**System-Sub Types (0-255)*/ #define NETWORK_REQ_STREAM 11; +#define NETWORK_POLL 130 /** System retained types */ #define NETWORK_FIRST_FRAGMENT 148 @@ -49,6 +54,8 @@ #define USER_TX_TO_LOGICAL_ADDRESS 3 #define USER_TX_MULTICAST 4 +#define MAX_FRAME_SIZE 32 +#define MAX_PAYLOAD_SIZE 1500 class RF24; @@ -114,26 +121,26 @@ struct RF24NetworkHeader * * The frame put over the air consists of a header and a message payload */ -/** -@code + + struct RF24NetworkFrame { - RF24NetworkHeader header; /**< Header which is sent with each message / - size_t message_size; /**< The size in bytes of the payload length / - uint8_t message_buffer[MAX_PAYLOAD_SIZE]; /**< Vector to put the frame payload that will be sent/received over the air / - uint8_t total_fragments; /** Date: Sat, 27 Sep 2014 01:31:34 -0600 Subject: [PATCH 2/2] Testing some RPi changes/additions - Modify fragmented payload writing - Add network_poll and address request handling --- RPi/RF24Network/RF24Network.cpp | 119 ++++++++++++++++++++------- RPi/RF24Network/RF24Network.h | 3 +- RPi/RF24Network/RF24Network_config.h | 2 +- 3 files changed, 90 insertions(+), 34 deletions(-) diff --git a/RPi/RF24Network/RF24Network.cpp b/RPi/RF24Network/RF24Network.cpp index 10d8d626..4fa6ade3 100644 --- a/RPi/RF24Network/RF24Network.cpp +++ b/RPi/RF24Network/RF24Network.cpp @@ -33,7 +33,7 @@ uint32_t nFails = 0, nOK=0; /******************************************************************/ -RF24Network::RF24Network( RF24& _radio ): radio(_radio), frame_size(MAX_FRAME_SIZE), lastMultiMessageID(0), noListen(1), lastWriteTime(0) +RF24Network::RF24Network( RF24& _radio ): radio(_radio), frame_size(MAX_FRAME_SIZE) {} /******************************************************************/ @@ -48,7 +48,7 @@ void RF24Network::begin(uint8_t _channel, uint16_t _node_address ) { if ( ! radio.isValid() ) { return; } - + radio.stopListening(); // Set up the radio the way we want it to look radio.setChannel(_channel); radio.setDataRate(RF24_1MBPS); @@ -138,6 +138,28 @@ uint8_t RF24Network::update(void) { returnVal = NETWORK_ACK; continue; } + if(header.type == NETWORK_ADDR_RESPONSE ){ + uint16_t requester = frame_buffer[8];// | frame_buffer[9] << 8; + requester |= frame_buffer[9] << 8; + + if(requester != node_address){ + header.to_node = requester; + //header.from_node = node_address; + memcpy(frame_buffer,&header,sizeof(RF24NetworkHeader)); + write(header.to_node,USER_TX_TO_PHYSICAL_ADDRESS); + //printf("fwd addr resp to 0%o , this node: 0%o\n", requester,node_address); + continue; + } + } + if(header.type == NETWORK_REQ_ADDRESS && node_address){ + //RF24NetworkHeader reqHeader = header; + header.from_node = node_address; + header.to_node = 0; + memcpy(frame_buffer,&header,sizeof(RF24NetworkHeader)); + write(header.to_node,TX_NORMAL); + //printf("fwd addr req\n"); + continue; + } enqueue(frame); @@ -155,10 +177,18 @@ uint8_t RF24Network::update(void) { IF_SERIAL_DEBUG_ROUTING(printf_P(PSTR("RT: FWD multicast frame from 0%o to level %d\n"),header.from_node,multicast_level+1);); write(levelToAddress(multicast_level)<<3,4); } - + if(header.type == NETWORK_POLL ){ + header.to_node = header.from_node; + header.from_node = node_address; + memcpy(frame_buffer,&header,sizeof(RF24NetworkHeader)); + delay(2); + write(header.to_node,USER_TX_TO_PHYSICAL_ADDRESS); + //printf("send poll\n"); + continue; + } + lastMultiMessageID = header.id; enqueue(frame); - } else { //Duplicate received IF_SERIAL_DEBUG_ROUTING(printf_P(PSTR("RT: Drop duplicate multicast frame %u from 0%o\n"),header.id,header.from_node);); @@ -225,7 +255,7 @@ bool RF24Network::enqueue(RF24NetworkFrame frame) { result = true; - } else if (frame.header.type <= MAX_USER_DEFINED_HEADER_TYPE) { + } else{// if (frame.header.type <= MAX_USER_DEFINED_HEADER_TYPE) { //This is not a fragmented payload but a whole frame. IF_SERIAL_DEBUG(printf_P(PSTR("%u: NET Enqueue @%x "),millis(),frame_queue.size())); @@ -233,12 +263,12 @@ bool RF24Network::enqueue(RF24NetworkFrame frame) { frame_queue.push(frame); result = true; - } else { + }/* else { //Undefined/Unknown header.type received. Drop frame! IF_SERIAL_DEBUG_MINIMAL( printf("%u: FRG Received unknown or system header type %d with fragment id %d\n",millis(),frame.header.type, frame.header.fragment_id); ); //The frame is not explicitly dropped, but the given object is ignored. //FIXME: does this causes problems with memory management? - } + }*/ if (result) { IF_SERIAL_DEBUG(printf("ok\n\r")); @@ -253,6 +283,8 @@ bool RF24Network::enqueue(RF24NetworkFrame frame) { void RF24Network::appendFragmentToFrame(RF24NetworkFrame frame) { + + if(frameFragmentsCache.size() >= 7){ frameFragmentsCache.erase(frameFragmentsCache.begin()); } if (frameFragmentsCache.count(std::make_pair(frame.header.from_node,frame.header.id)) == 0 ) { // This is the first of many fragments. @@ -281,7 +313,7 @@ void RF24Network::appendFragmentToFrame(RF24NetworkFrame frame) { if (frame.header.fragment_id != f->header.fragment_id) { if (frame.header.fragment_id > f->header.fragment_id) { IF_SERIAL_DEBUG_MINIMAL(printf("%u: FRG Duplicate or out of sequence frame %d, expected %d. Cleared.\n",millis(),frame.header.fragment_id,f->header.fragment_id);); - frameFragmentsCache.erase( std::make_pair(frame.header.from_node,frame.header.id) ); + //frameFragmentsCache.erase( std::make_pair(frame.header.from_node,frame.header.id) ); } else { frameFragmentsCache.erase( std::make_pair(frame.header.from_node,frame.header.id) ); IF_SERIAL_DEBUG_MINIMAL(printf("%u: FRG Out of sequence frame %d, expected %d. Cleared.\n",millis(),frame.header.fragment_id,f->header.fragment_id);); @@ -371,7 +403,7 @@ bool RF24Network::multicast(RF24NetworkHeader& header,const void* message, size_ header.from_node = node_address; // Build the full frame to send - RF24NetworkFrame frame = RF24NetworkFrame(header,message,std::min(sizeof(message),len)); + //RF24NetworkFrame frame = RF24NetworkFrame(header,message,std::min(sizeof(message),len)); IF_SERIAL_DEBUG(printf_P(PSTR("%u: NET Sending %s\n\r"),millis(),header.toString())); if (len) { @@ -415,18 +447,18 @@ bool RF24Network::write(RF24NetworkHeader& header,const void* message, size_t le // --> We cann transmit the message. // First, stop listening so we can talk. - radio.stopListening(); + //radio.stopListening(); //Normal Write (Un-Fragmented) //The len of the payload if less or equal than the max_frame_payload_size, //therefore we send this payload in a single frame. Fragmentation not needed. if (len <= max_frame_payload_size) { txSuccess = _write(header,message,len,writeDirect); - radio.startListening(); + //radio.startListening(); return txSuccess; } - noListen = 1; + //noListen = 1; //Fragmented Write //The len payload is definitely bigger than the max_frame_payload_size, @@ -466,13 +498,18 @@ bool RF24Network::write(RF24NetworkHeader& header,const void* message, size_t le IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG try to transmit fragmented payload of size %i Bytes with fragmentID '%i'\n\r",millis(),fragmentLen,fragment_id);); + //uint8_t msg[32]; + //Try to send the payload chunk with the copied header - bool ok = _write(fragmentHeader,message+offset,fragmentLen,writeDirect); + bool ok = _write(fragmentHeader,((char *)message)+offset,fragmentLen,writeDirect); - if (!noListen) { - //Hack to allow the radio to be able to process the tx bytes + if(!ok){ delay(100); ok = _write(fragmentHeader,((char *)message)+offset,fragmentLen,writeDirect); + if(!ok){ delay(150); ok = _write(fragmentHeader,((char *)message)+offset,fragmentLen,writeDirect); + } + } + //if (!noListen) { delayMicroseconds(50); - } + //} if (!ok) { IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG message transmission with fragmentID '%i' failed. Abort.\n\r",millis(),fragment_id);); @@ -488,10 +525,10 @@ bool RF24Network::write(RF24NetworkHeader& header,const void* message, size_t le msgCount++; } - noListen = 0; + //noListen = 0; // Now, continue listening - radio.startListening(); + //radio.startListening(); int frag_delay = uint8_t(len/48); delay( std::min(frag_delay,20)); @@ -561,9 +598,9 @@ bool RF24Network::write(uint16_t to_node, uint8_t directTo) { return false; } - if (to_node != parent_node && !is_direct_child(to_node) ) { - noListen=0; - } + //if (to_node != parent_node && !is_direct_child(to_node) ) { + // noListen=0; + //} //Load info into our conversion structure, and get the converted address info conversion.send_node = to_node; conversion.send_pipe = directTo; @@ -582,11 +619,13 @@ bool RF24Network::write(uint16_t to_node, uint8_t directTo) { if ( directTo == 1 && ok && conversion.send_node == to_node && frame_buffer[6] != NETWORK_ACK ) { - RF24NetworkHeader& header = * reinterpret_cast(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; + //RF24NetworkHeader& header = * reinterpret_cast(frame_buffer); + frame_buffer[6] = NETWORK_ACK; // Set the payload type to NETWORK_ACK + //header.to_node = header.from_node; // Change the 'to' address to the 'from' address + frame_buffer[2] = frame_buffer[0]; + frame_buffer[3] = frame_buffer[1]; + + conversion.send_node = (frame_buffer[0] | frame_buffer[1] << 8);//header.from_node; conversion.send_pipe = TX_ROUTED; logicalToPhysicalAddress(&conversion); @@ -596,9 +635,9 @@ bool RF24Network::write(uint16_t to_node, uint8_t directTo) { IF_SERIAL_DEBUG_ROUTING(printf("RT Route OK to 0%o ACK sent to 0%o\n",to_node,header.to_node);); } - if (!noListen ) { + //if (!noListen ) { radio.startListening(); - } + //} if ( ok && (conversion.send_node != to_node) && (directTo==0 || directTo == 3 )) { @@ -611,7 +650,7 @@ bool RF24Network::write(uint16_t to_node, uint8_t directTo) { break; } } - if (!noListen) { radio.stopListening(); } + //if (!noListen) { radio.stopListening(); } } //Increment the number of correctly trasmitted frames or the number of fail transmissions @@ -682,9 +721,9 @@ bool RF24Network::write_to_pipe( uint16_t node, uint8_t pipe, bool multicast ) { uint64_t out_pipe = pipe_address( node, pipe ); - if (!noListen) { + //if (!noListen) { radio.stopListening(); - } + //} // Open the correct pipe for writing. radio.openWritingPipe(out_pipe); @@ -769,6 +808,24 @@ void RF24Network::setup_address(void) { /******************************************************************/ +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); +} + +/******************************************************************/ + 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 ) | 0B111; diff --git a/RPi/RF24Network/RF24Network.h b/RPi/RF24Network/RF24Network.h index e072cfd1..ab34988c 100644 --- a/RPi/RF24Network/RF24Network.h +++ b/RPi/RF24Network/RF24Network.h @@ -51,6 +51,7 @@ /* System Discard Types */ #define NETWORK_ACK_REQUEST 128 #define NETWORK_ACK 129 +#define NETWORK_POLL 130 /*System-Sub Types (0-255)*/ #define NETWORK_REQ_STREAM 11; @@ -376,12 +377,10 @@ uint16_t addressOfPipe( uint16_t node,uint8_t pipeNo ); std::queue frame_queue; std::map, RF24NetworkFrame> frameFragmentsCache; - 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 */ - uint16_t lastMultiMessageID; //FIXME bool noListen; //FIXME uint32_t lastWriteTime; //FIXME diff --git a/RPi/RF24Network/RF24Network_config.h b/RPi/RF24Network/RF24Network_config.h index a901bb66..1930a27f 100644 --- a/RPi/RF24Network/RF24Network_config.h +++ b/RPi/RF24Network/RF24Network_config.h @@ -13,7 +13,7 @@ /********** USER CONFIG **************/ -//#define RF24NetworkMulticast //Use multicast capabilities +#define RF24NetworkMulticast //Use multicast capabilities //#define SERIAL_DEBUG //Set for full debug #define SERIAL_DEBUG_MINIMAL //Enable minimal debugging //#define SERIAL_DEBUG_ROUTING