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.
RF24Network.cpp
00001 /* 00002 Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com> 00003 00004 This program is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU General Public License 00006 version 2 as published by the Free Software Foundation. 00007 */ 00008 00009 /* 00010 * Mbed support added by Akash Vibhute <akash.roboticist@gmail.com> 00011 * Porting completed on Nov/05/2015 00012 * 00013 * Updated with TMRh20's RF24 library on Nov/04/2015 from https://github.com/TMRh20 00014 * 00015 */ 00016 00017 #include "RF24Network_config.h" 00018 #include <RF24.h> 00019 #include "RF24Network.h" 00020 00021 uint16_t RF24NetworkHeader::next_id = 1; 00022 #if defined ENABLE_NETWORK_STATS 00023 uint32_t RF24Network::nFails = 0; 00024 uint32_t RF24Network::nOK = 0; 00025 #endif 00026 uint64_t pipe_address( uint16_t node, uint8_t pipe ); 00027 #if defined (RF24NetworkMulticast) 00028 uint16_t levelToAddress( uint8_t level ); 00029 #endif 00030 bool is_valid_address( uint16_t node ); 00031 00032 /******************************************************************/ 00033 #if !defined (DUAL_HEAD_RADIO) 00034 RF24Network::RF24Network( RF24& _radio ): radio(_radio), next_frame(frame_queue) 00035 { 00036 #if !defined ( DISABLE_FRAGMENTATION ) 00037 frag_queue.message_buffer=&frag_queue_message_buffer[0]; 00038 frag_ptr = &frag_queue; 00039 #endif 00040 } 00041 #else 00042 RF24Network::RF24Network( RF24& _radio, RF24& _radio1 ): radio(_radio), radio1(_radio1), next_frame(frame_queue) 00043 { 00044 #if !defined ( DISABLE_FRAGMENTATION ) 00045 frag_queue.message_buffer=&frag_queue_message_buffer[0]; 00046 frag_ptr = &frag_queue; 00047 #endif 00048 } 00049 #endif 00050 /******************************************************************/ 00051 00052 void RF24Network::begin(uint8_t _channel, uint16_t _node_address ) 00053 { 00054 rf24netTimer.start(); 00055 if (! is_valid_address (_node_address) ) 00056 return; 00057 00058 node_address = _node_address; 00059 00060 if ( ! radio.isValid() ) { 00061 return; 00062 } 00063 00064 // Set up the radio the way we want it to look 00065 if(_channel != USE_CURRENT_CHANNEL) { 00066 radio.setChannel(_channel); 00067 } 00068 //radio.enableDynamicAck(); 00069 radio.setAutoAck(0,0); 00070 00071 #if defined (ENABLE_DYNAMIC_PAYLOADS) 00072 radio.enableDynamicPayloads(); 00073 #endif 00074 00075 // Use different retry periods to reduce data collisions 00076 uint8_t retryVar = (((node_address % 6)+1) *2) + 3; 00077 radio.setRetries(retryVar, 5); 00078 txTimeout = 25; 00079 routeTimeout = txTimeout*9; // Adjust for max delay per node 00080 00081 00082 #if defined (DUAL_HEAD_RADIO) 00083 radio1.setChannel(_channel); 00084 radio1.enableDynamicAck(); 00085 radio1.enableDynamicPayloads(); 00086 #endif 00087 00088 // Setup our address helper cache 00089 setup_address(); 00090 00091 // Open up all listening pipes 00092 uint8_t i = 6; 00093 while (i--) { 00094 radio.openReadingPipe(i,pipe_address(_node_address,i)); 00095 } 00096 radio.startListening(); 00097 00098 } 00099 00100 /******************************************************************/ 00101 00102 #if defined ENABLE_NETWORK_STATS 00103 void RF24Network::failures(uint32_t *_fails, uint32_t *_ok) 00104 { 00105 *_fails = nFails; 00106 *_ok = nOK; 00107 } 00108 #endif 00109 00110 /******************************************************************/ 00111 00112 uint8_t RF24Network::update(void) 00113 { 00114 // if there is data ready 00115 uint8_t pipe_num; 00116 uint8_t returnVal = 0; 00117 00118 // If bypass is enabled, continue although incoming user data may be dropped 00119 // Allows system payloads to be read while user cache is full 00120 // Incoming Hold prevents data from being read from the radio, preventing incoming payloads from being acked 00121 00122 00123 if(!(networkFlags & FLAG_BYPASS_HOLDS)) { 00124 if( (networkFlags & FLAG_HOLD_INCOMING) || (next_frame-frame_queue) + 34 > MAIN_BUFFER_SIZE ) { 00125 if(!available()) { 00126 networkFlags &= ~FLAG_HOLD_INCOMING; 00127 } else { 00128 return 0; 00129 } 00130 } 00131 } 00132 00133 00134 while ( radio.isValid() && radio.available(&pipe_num) ) { 00135 00136 #if defined (ENABLE_DYNAMIC_PAYLOADS) 00137 if( (frame_size = radio.getDynamicPayloadSize() ) < sizeof(RF24NetworkHeader)) { 00138 wait_ms(10); 00139 continue; 00140 } 00141 #else 00142 frame_size=32; 00143 #endif 00144 // Dump the payloads until we've gotten everything 00145 // Fetch the payload, and see if this was the last one. 00146 radio.read( frame_buffer, frame_size ); 00147 00148 // Read the beginning of the frame as the header 00149 RF24NetworkHeader *header = (RF24NetworkHeader*)(&frame_buffer); 00150 00151 IF_SERIAL_DEBUG(printf_P(PSTR("%lu: MAC Received on %u %s\n\r"),millis(),pipe_num,header->toString())); 00152 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)); 00153 00154 00155 // Throw it away if it's not a valid address 00156 if ( !is_valid_address (header->to_node) ) { 00157 continue; 00158 } 00159 00160 uint8_t returnVal = header->type; 00161 00162 // Is this for us? 00163 if ( header->to_node == node_address ) { 00164 00165 if(header->type == NETWORK_PING) { 00166 continue; 00167 } 00168 if(header->type == NETWORK_ADDR_RESPONSE ) { 00169 uint16_t requester = frame_buffer[8]; 00170 requester |= frame_buffer[9] << 8; 00171 if(requester != node_address) { 00172 header->to_node = requester; 00173 write(header->to_node,USER_TX_TO_PHYSICAL_ADDRESS); 00174 wait_ms(10); 00175 write(header->to_node,USER_TX_TO_PHYSICAL_ADDRESS); 00176 //printf("Fwd add response to 0%o\n",requester); 00177 continue; 00178 } 00179 } 00180 if(header->type == NETWORK_REQ_ADDRESS && node_address) { 00181 //printf("Fwd add req to 0\n"); 00182 header->from_node = node_address; 00183 header->to_node = 0; 00184 write(header->to_node,TX_NORMAL); 00185 continue; 00186 } 00187 00188 if( (returnSysMsgs && header->type > 127) || header->type == NETWORK_ACK ) { 00189 //IF_SERIAL_DEBUG_ROUTING( printf_P(PSTR("%lu MAC: System payload rcvd %d\n"),millis(),returnVal); ); 00190 //if( (header->type < 148 || header->type > 150) && header->type != NETWORK_MORE_FRAGMENTS_NACK && header->type != EXTERNAL_DATA_TYPE && header->type!= NETWORK_LAST_FRAGMENT){ 00191 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) { 00192 return returnVal; 00193 } 00194 } 00195 00196 if( enqueue(header) == 2 ) { //External data received 00197 #if defined (SERIAL_DEBUG_MINIMAL) 00198 printf("ret ext\n"); 00199 #endif 00200 return EXTERNAL_DATA_TYPE; 00201 } 00202 } else { 00203 00204 #if defined (RF24NetworkMulticast) 00205 00206 if( header->to_node == 0100) { 00207 00208 00209 if(header->type == NETWORK_POLL ) { 00210 //Serial.println("Send poll"); 00211 header->to_node = header->from_node; 00212 header->from_node = node_address; 00213 //delay((node_address%5)*3); 00214 write(header->to_node,USER_TX_TO_PHYSICAL_ADDRESS); 00215 continue; 00216 } 00217 uint8_t val = enqueue(header); 00218 00219 if(multicastRelay) { 00220 //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); ); 00221 write(levelToAddress(multicast_level)<<3,4); 00222 } 00223 if( val == 2 ) { //External data received 00224 //Serial.println("ret ext multicast"); 00225 return EXTERNAL_DATA_TYPE; 00226 } 00227 00228 } else { 00229 write(header->to_node,1); //Send it on, indicate it is a routed payload 00230 } 00231 #else 00232 write(header->to_node,1); //Send it on, indicate it is a routed payload 00233 #endif 00234 } 00235 00236 } 00237 return returnVal; 00238 } 00239 00240 /******************************************************************/ 00241 00242 uint8_t RF24Network::enqueue(RF24NetworkHeader* header) 00243 { 00244 bool result = false; 00245 uint8_t message_size = frame_size - sizeof(RF24NetworkHeader); 00246 00247 IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Enqueue @%x "),millis(),next_frame-frame_queue)); 00248 00249 #if !defined ( DISABLE_FRAGMENTATION ) 00250 00251 bool isFragment = header->type == NETWORK_FIRST_FRAGMENT || header->type == NETWORK_MORE_FRAGMENTS || header->type == NETWORK_LAST_FRAGMENT || header->type == NETWORK_MORE_FRAGMENTS_NACK ; 00252 00253 if(isFragment) { 00254 00255 if(header->type == NETWORK_FIRST_FRAGMENT) { 00256 // Drop frames exceeding max size and duplicates (MAX_PAYLOAD_SIZE needs to be divisible by 24) 00257 if(header->reserved > (MAX_PAYLOAD_SIZE / max_frame_payload_size) ) { 00258 00259 #if defined (SERIAL_DEBUG_FRAGMENTATION) || defined (SERIAL_DEBUG_MINIMAL) 00260 printf_P(PSTR("Frag frame with %d frags exceeds MAX_PAYLOAD_SIZE or out of sequence\n"),header->reserved); 00261 #endif 00262 frag_queue.header.reserved = 0; 00263 return false; 00264 } else if(frag_queue.header.id == header->id && frag_queue.header.from_node == header->from_node) { 00265 return true; 00266 } 00267 00268 if( (header->reserved * 24) > (MAX_PAYLOAD_SIZE - (next_frame-frame_queue)) ) { 00269 networkFlags |= FLAG_HOLD_INCOMING; 00270 radio.stopListening(); 00271 } 00272 00273 memcpy(&frag_queue,&frame_buffer,8); 00274 memcpy(frag_queue.message_buffer,frame_buffer+sizeof(RF24NetworkHeader),message_size); 00275 00276 //IF_SERIAL_DEBUG_FRAGMENTATION( Serial.print(F("queue first, total frags ")); Serial.println(header->reserved); ); 00277 //Store the total size of the stored frame in message_size 00278 frag_queue.message_size = message_size; 00279 --frag_queue.header.reserved; 00280 00281 IF_SERIAL_DEBUG_FRAGMENTATION_L2( for(int i=0; i<frag_queue.message_size; i++) { 00282 Serial.println(frag_queue.message_buffer[i],HEX); 00283 } ); 00284 00285 return true; 00286 00287 } else // NETWORK_MORE_FRAGMENTS 00288 if(header->type == NETWORK_LAST_FRAGMENT || header->type == NETWORK_MORE_FRAGMENTS || header->type == NETWORK_MORE_FRAGMENTS_NACK) { 00289 00290 if(frag_queue.message_size + message_size > MAX_PAYLOAD_SIZE) { 00291 #if defined (SERIAL_DEBUG_FRAGMENTATION) || defined (SERIAL_DEBUG_MINIMAL) 00292 Serial.print(F("Drop frag ")); 00293 Serial.print(header->reserved); 00294 Serial.println(F(" Size exceeds max")); 00295 #endif 00296 frag_queue.header.reserved=0; 00297 return false; 00298 } 00299 if( frag_queue.header.reserved == 0 || (header->type != NETWORK_LAST_FRAGMENT && header->reserved != frag_queue.header.reserved ) || frag_queue.header.id != header->id ) { 00300 #if defined (SERIAL_DEBUG_FRAGMENTATION) || defined (SERIAL_DEBUG_MINIMAL) 00301 Serial.print(F("Drop frag ")); 00302 Serial.print(header->reserved); 00303 //Serial.print(F(" header id ")); Serial.print(header->id); 00304 Serial.println(F(" Out of order ")); 00305 #endif 00306 return false; 00307 } 00308 00309 memcpy(frag_queue.message_buffer+frag_queue.message_size,frame_buffer+sizeof(RF24NetworkHeader),message_size); 00310 frag_queue.message_size += message_size; 00311 00312 if(header->type != NETWORK_LAST_FRAGMENT) { 00313 --frag_queue.header.reserved; 00314 return true; 00315 } 00316 frag_queue.header.reserved = 0; 00317 frag_queue.header.type = header->reserved; 00318 00319 IF_SERIAL_DEBUG_FRAGMENTATION( printf(PSTR("fq 3: %d\n"),frag_queue.message_size); ); 00320 IF_SERIAL_DEBUG_FRAGMENTATION_L2(for(int i=0; i< frag_queue.message_size; i++) { 00321 Serial.println(frag_queue.message_buffer[i],HEX); 00322 } ); 00323 00324 //Frame assembly complete, copy to main buffer if OK 00325 if(frag_queue.header.type == EXTERNAL_DATA_TYPE) { 00326 return 2; 00327 } 00328 #if defined (DISABLE_USER_PAYLOADS) 00329 return 0; 00330 #endif 00331 00332 if(MAX_PAYLOAD_SIZE - (next_frame-frame_queue) >= frag_queue.message_size) { 00333 memcpy(next_frame,&frag_queue,10); 00334 memcpy(next_frame+10,frag_queue.message_buffer,frag_queue.message_size); 00335 next_frame += (10+frag_queue.message_size); 00336 IF_SERIAL_DEBUG_FRAGMENTATION( printf(PSTR("enq size %d\n"),frag_queue.message_size); ); 00337 return true; 00338 } else { 00339 radio.stopListening(); 00340 networkFlags |= FLAG_HOLD_INCOMING; 00341 } 00342 IF_SERIAL_DEBUG_FRAGMENTATION( printf(PSTR("Drop frag payload, queue full\n")); ); 00343 return false; 00344 }//If more or last fragments 00345 00346 } else //else is not a fragment 00347 #endif // End fragmentation enabled 00348 00349 // Copy the current frame into the frame queue 00350 00351 #if !defined( DISABLE_FRAGMENTATION ) 00352 00353 if(header->type == EXTERNAL_DATA_TYPE) { 00354 memcpy(&frag_queue,&frame_buffer,8); 00355 frag_queue.message_buffer = frame_buffer+sizeof(RF24NetworkHeader); 00356 frag_queue.message_size = message_size; 00357 return 2; 00358 } 00359 #endif 00360 #if defined (DISABLE_USER_PAYLOADS) 00361 return 0; 00362 } 00363 #else 00364 if(message_size + (next_frame-frame_queue) <= MAIN_BUFFER_SIZE) 00365 { 00366 memcpy(next_frame,&frame_buffer,8); 00367 RF24NetworkFrame *f = (RF24NetworkFrame*)next_frame; 00368 f->message_size = message_size; 00369 memcpy(next_frame+10,frame_buffer+sizeof(RF24NetworkHeader),message_size); 00370 00371 IF_SERIAL_DEBUG_FRAGMENTATION( for(int i=0; i<message_size; i++) { 00372 Serial.print(next_frame[i],HEX); 00373 Serial.print(" : "); 00374 } 00375 Serial.println(""); ); 00376 00377 next_frame += (message_size + 10); 00378 IF_SERIAL_DEBUG_FRAGMENTATION( Serial.print("Enq "); Serial.println(next_frame-frame_queue); );//printf_P(PSTR("enq %d\n"),next_frame-frame_queue); ); 00379 00380 result = true; 00381 } else 00382 { 00383 result = false; 00384 IF_SERIAL_DEBUG(printf_P(PSTR("NET **Drop Payload** Buffer Full"))); 00385 } 00386 return result; 00387 } 00388 #endif //USER_PAYLOADS_ENABLED 00389 00390 00391 /******************************************************************/ 00392 00393 bool RF24Network::available(void) 00394 { 00395 // Are there frames on the queue for us? 00396 return (next_frame > frame_queue); 00397 00398 } 00399 00400 /******************************************************************/ 00401 00402 int16_t RF24Network::parent() const 00403 { 00404 if ( node_address == 0 ) 00405 return -1; 00406 else 00407 return parent_node; 00408 } 00409 00410 /******************************************************************/ 00411 /*uint8_t RF24Network::peekData(){ 00412 00413 return frame_queue[0]; 00414 }*/ 00415 00416 uint16_t RF24Network::peek(RF24NetworkHeader& header) 00417 { 00418 if ( available() ) { 00419 RF24NetworkFrame *frame = (RF24NetworkFrame*)(frame_queue); 00420 memcpy(&header,&frame->header,sizeof(RF24NetworkHeader)); 00421 return frame->message_size; 00422 00423 } 00424 return 0; 00425 } 00426 00427 /******************************************************************/ 00428 00429 uint16_t RF24Network::read(RF24NetworkHeader& header,void* message, uint16_t maxlen) 00430 { 00431 uint16_t bufsize = 0; 00432 00433 if ( available() ) { 00434 00435 memcpy(&header,frame_queue,8); 00436 RF24NetworkFrame *f = (RF24NetworkFrame*)frame_queue; 00437 bufsize = f->message_size; 00438 00439 if (maxlen > 0) { 00440 maxlen = min(maxlen,bufsize); 00441 memcpy(message,frame_queue+10,maxlen); 00442 IF_SERIAL_DEBUG(printf("%lu: NET message size %d\n",millis(),bufsize);); 00443 00444 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--) { 00445 printf("%02x ",charPtr[len]); 00446 } 00447 printf_P(PSTR("\n\r") ) ); 00448 00449 } 00450 memmove(frame_queue,frame_queue+bufsize+10,sizeof(frame_queue)- bufsize); 00451 next_frame-=bufsize+10; 00452 00453 //IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Received %s\n\r"),millis(),header.toString())); 00454 } 00455 00456 return bufsize; 00457 } 00458 00459 00460 #if defined RF24NetworkMulticast 00461 /******************************************************************/ 00462 bool RF24Network::multicast(RF24NetworkHeader& header,const void* message, uint16_t len, uint8_t level) 00463 { 00464 // Fill out the header 00465 header.to_node = 0100; 00466 header.from_node = node_address; 00467 return write(header, message, len, levelToAddress(level)); 00468 } 00469 #endif 00470 00471 /******************************************************************/ 00472 bool RF24Network::write(RF24NetworkHeader& header,const void* message, uint16_t len) 00473 { 00474 return write(header,message,len,070); 00475 } 00476 /******************************************************************/ 00477 bool RF24Network::write(RF24NetworkHeader& header,const void* message, uint16_t len, uint16_t writeDirect) 00478 { 00479 00480 //Allows time for requests (RF24Mesh) to get through between failed writes on busy nodes 00481 while(rf24netTimer.read_ms()-txTime < 25) { 00482 if(update() > 127) { 00483 break; 00484 } 00485 } 00486 wait_us(200); 00487 00488 #if defined (DISABLE_FRAGMENTATION) 00489 frame_size = rf24_min(len+sizeof(RF24NetworkHeader),MAX_FRAME_SIZE); 00490 return _write(header,message,rf24_min(len,max_frame_payload_size),writeDirect); 00491 #else 00492 if(len <= max_frame_payload_size) { 00493 //Normal Write (Un-Fragmented) 00494 frame_size = len + sizeof(RF24NetworkHeader); 00495 if(_write(header,message,len,writeDirect)) { 00496 return 1; 00497 } 00498 txTime = rf24netTimer.read_ms(); 00499 return 0; 00500 } 00501 //Check payload size 00502 if (len > MAX_PAYLOAD_SIZE) { 00503 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);); 00504 return false; 00505 } 00506 00507 //Divide the message payload into chunks of max_frame_payload_size 00508 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) 00509 00510 uint8_t msgCount = 0; 00511 00512 IF_SERIAL_DEBUG_FRAGMENTATION(printf("%lu: FRG Total message fragments %d\n\r",millis(),fragment_id);); 00513 00514 if(header.to_node != 0100) { 00515 networkFlags |= FLAG_FAST_FRAG; 00516 #if !defined (DUAL_HEAD_RADIO) 00517 radio.stopListening(); 00518 #endif 00519 } 00520 00521 uint8_t retriesPerFrag = 0; 00522 uint8_t type = header.type; 00523 00524 while (fragment_id > 0) { 00525 00526 //Copy and fill out the header 00527 //RF24NetworkHeader fragmentHeader = header; 00528 header.reserved = fragment_id; 00529 00530 if (fragment_id == 1) { 00531 header.type = NETWORK_LAST_FRAGMENT; //Set the last fragment flag to indicate the last fragment 00532 header.reserved = type; //The reserved field is used to transmit the header type 00533 } else { 00534 if (msgCount == 0) { 00535 header.type = NETWORK_FIRST_FRAGMENT; 00536 } else { 00537 header.type = NETWORK_MORE_FRAGMENTS; //Set the more fragments flag to indicate a fragmented frame 00538 } 00539 } 00540 00541 uint16_t offset = msgCount*max_frame_payload_size; 00542 uint16_t fragmentLen = rf24_min((uint16_t)(len-offset),max_frame_payload_size); 00543 00544 //Try to send the payload chunk with the copied header 00545 frame_size = sizeof(RF24NetworkHeader)+fragmentLen; 00546 bool ok = _write(header,((char *)message)+offset,fragmentLen,writeDirect); 00547 00548 if (!ok) { 00549 wait_ms(2); 00550 ++retriesPerFrag; 00551 00552 } else { 00553 retriesPerFrag = 0; 00554 fragment_id--; 00555 msgCount++; 00556 } 00557 00558 if(writeDirect != 070) { 00559 wait_ms(2); //Delay 2ms between sending multicast payloads 00560 } 00561 00562 if (!ok && retriesPerFrag >= 3) { 00563 IF_SERIAL_DEBUG_FRAGMENTATION(printf("%lu: FRG TX with fragmentID '%d' failed after %d fragments. Abort.\n\r",millis(),fragment_id,msgCount);); 00564 break; 00565 } 00566 00567 //Message was successful sent 00568 #if defined SERIAL_DEBUG_FRAGMENTATION_L2 00569 printf("%lu: FRG message transmission with fragmentID '%d' sucessfull.\n\r",millis(),fragment_id); 00570 #endif 00571 00572 } 00573 00574 #if !defined (DUAL_HEAD_RADIO) 00575 if(networkFlags & FLAG_FAST_FRAG) { 00576 radio.startListening(); 00577 } 00578 #endif 00579 networkFlags &= ~FLAG_FAST_FRAG 00580 //int frag_delay = uint8_t(len/48); 00581 //delay( rf24_min(len/48,20)); 00582 00583 //Return true if all the chunks where sent successfully 00584 00585 IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG total message fragments sent %i. \n",millis(),msgCount); ); 00586 if(fragment_id > 0) { 00587 txTime = rf24netTimer.read_ms(); 00588 return false; 00589 } 00590 return true; 00591 00592 #endif //Fragmentation enabled 00593 } 00594 /******************************************************************/ 00595 00596 bool RF24Network::_write(RF24NetworkHeader& header,const void* message, uint16_t len, uint16_t writeDirect) 00597 { 00598 // Fill out the header 00599 header.from_node = node_address; 00600 00601 // Build the full frame to send 00602 memcpy(frame_buffer,&header,sizeof(RF24NetworkHeader)); 00603 00604 IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Sending %s\n\r"),millis(),header.toString())); 00605 00606 if (len) { 00607 00608 memcpy(frame_buffer + sizeof(RF24NetworkHeader),message,len); 00609 00610 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--) { 00611 printf("%02x ",charPtr[tmpLen]); 00612 } 00613 printf_P(PSTR("\n\r") ) ); 00614 00615 } 00616 00617 // If the user is trying to send it to himself 00618 /*if ( header.to_node == node_address ){ 00619 #if defined (RF24_LINUX) 00620 RF24NetworkFrame frame = RF24NetworkFrame(header,message,rf24_min(MAX_FRAME_SIZE-sizeof(RF24NetworkHeader),len)); 00621 #else 00622 RF24NetworkFrame frame(header,len); 00623 #endif 00624 // Just queue it in the received queue 00625 return enqueue(frame); 00626 }*/ 00627 // Otherwise send it out over the air 00628 00629 00630 if(writeDirect != 070) { 00631 uint8_t sendType = USER_TX_TO_LOGICAL_ADDRESS; // Payload is multicast to the first node, and routed normally to the next 00632 00633 if(header.to_node == 0100) { 00634 sendType = USER_TX_MULTICAST; 00635 } 00636 if(header.to_node == writeDirect) { 00637 sendType = USER_TX_TO_PHYSICAL_ADDRESS; // Payload is multicast to the first node, which is the recipient 00638 } 00639 return write(writeDirect,sendType); 00640 } 00641 return write(header.to_node,TX_NORMAL); 00642 00643 } 00644 00645 /******************************************************************/ 00646 00647 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 00648 { 00649 bool ok = false; 00650 bool isAckType = false; 00651 if(frame_buffer[6] > 64 && frame_buffer[6] < 192 ) { 00652 isAckType=true; 00653 } 00654 00655 /*if( ( (frame_buffer[7] % 2) && frame_buffer[6] == NETWORK_MORE_FRAGMENTS) ){ 00656 isAckType = 0; 00657 }*/ 00658 00659 // Throw it away if it's not a valid address 00660 if ( !is_valid_address (to_node) ) 00661 return false; 00662 00663 //Load info into our conversion structure, and get the converted address info 00664 logicalToPhysicalStruct conversion = { to_node,directTo,0}; 00665 logicalToPhysicalAddress(&conversion); 00666 00667 00668 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)); 00669 00670 /**Write it*/ 00671 ok=write_to_pipe(conversion.send_node, conversion.send_pipe, conversion.multicast); 00672 00673 00674 if(!ok) { 00675 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);); 00676 } 00677 00678 00679 if( directTo == TX_ROUTED && ok && conversion.send_node == to_node && isAckType) { 00680 00681 RF24NetworkHeader* header = (RF24NetworkHeader*)&frame_buffer; 00682 header->type = NETWORK_ACK; // Set the payload type to NETWORK_ACK 00683 header->to_node = header->from_node; // Change the 'to' address to the 'from' address 00684 00685 conversion.send_node = header->from_node; 00686 conversion.send_pipe = TX_ROUTED; 00687 conversion.multicast = 0; 00688 logicalToPhysicalAddress(&conversion); 00689 00690 //Write the data using the resulting physical address 00691 frame_size = sizeof(RF24NetworkHeader); 00692 write_to_pipe(conversion.send_node, conversion.send_pipe, conversion.multicast); 00693 00694 //dynLen=0; 00695 00696 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); ); 00697 00698 } 00699 00700 00701 if( ok && conversion.send_node != to_node && (directTo==0 || directTo==3) && isAckType) { 00702 #if !defined (DUAL_HEAD_RADIO) 00703 // Now, continue listening 00704 if(networkFlags & FLAG_FAST_FRAG) { 00705 radio.txStandBy(txTimeout); 00706 networkFlags &= ~FLAG_FAST_FRAG; 00707 } 00708 radio.startListening(); 00709 #endif 00710 uint32_t reply_time = rf24netTimer.read_ms(); 00711 00712 while( update() != NETWORK_ACK) { 00713 wait_us(900); 00714 if(rf24netTimer.read_ms() - reply_time > routeTimeout) { 00715 00716 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); ); 00717 00718 ok=false; 00719 break; 00720 } 00721 } 00722 } 00723 if( !(networkFlags & FLAG_FAST_FRAG) ) { 00724 #if !defined (DUAL_HEAD_RADIO) 00725 // Now, continue listening 00726 radio.startListening(); 00727 #endif 00728 } 00729 00730 #if defined ENABLE_NETWORK_STATS 00731 if(ok == true) { 00732 ++nOK; 00733 } else { 00734 ++nFails; 00735 } 00736 #endif 00737 return ok; 00738 } 00739 00740 /******************************************************************/ 00741 00742 // Provided the to_node and directTo option, it will return the resulting node and pipe 00743 bool RF24Network::logicalToPhysicalAddress(logicalToPhysicalStruct *conversionInfo) 00744 { 00745 00746 //Create pointers so this makes sense.. kind of 00747 //We take in the to_node(logical) now, at the end of the function, output the send_node(physical) address, etc. 00748 //back to the original memory address that held the logical information. 00749 uint16_t *to_node = &conversionInfo->send_node; 00750 uint8_t *directTo = &conversionInfo->send_pipe; 00751 bool *multicast = &conversionInfo->multicast; 00752 00753 // Where do we send this? By default, to our parent 00754 uint16_t pre_conversion_send_node = parent_node; 00755 00756 // On which pipe 00757 uint8_t pre_conversion_send_pipe = parent_pipe %5; 00758 00759 if(*directTo > TX_ROUTED ) { 00760 pre_conversion_send_node = *to_node; 00761 *multicast = 1; 00762 //if(*directTo == USER_TX_MULTICAST || *directTo == USER_TX_TO_PHYSICAL_ADDRESS){ 00763 pre_conversion_send_pipe=0; 00764 //} 00765 } 00766 // If the node is a direct child, 00767 else if ( is_direct_child(*to_node) ) { 00768 // Send directly 00769 pre_conversion_send_node = *to_node; 00770 // To its listening pipe 00771 pre_conversion_send_pipe = 5; 00772 } 00773 // If the node is a child of a child 00774 // talk on our child's listening pipe, 00775 // and let the direct child relay it. 00776 else if ( is_descendant(*to_node) ) { 00777 pre_conversion_send_node = direct_child_route_to(*to_node); 00778 pre_conversion_send_pipe = 5; 00779 } 00780 00781 *to_node = pre_conversion_send_node; 00782 *directTo = pre_conversion_send_pipe; 00783 00784 return 1; 00785 00786 } 00787 00788 /********************************************************/ 00789 00790 bool RF24Network::write_to_pipe( uint16_t node, uint8_t pipe, bool multicast ) 00791 { 00792 bool ok = false; 00793 uint64_t out_pipe = pipe_address( node, pipe ); 00794 00795 #if !defined (DUAL_HEAD_RADIO) 00796 // Open the correct pipe for writing. 00797 // First, stop listening so we can talk 00798 00799 if(!(networkFlags & FLAG_FAST_FRAG)) { 00800 radio.stopListening(); 00801 } 00802 00803 if(multicast) { 00804 radio.setAutoAck(0,0); 00805 } else { 00806 radio.setAutoAck(0,1); 00807 } 00808 00809 radio.openWritingPipe(out_pipe); 00810 radio.writeFast(frame_buffer, frame_size,multicast); 00811 ok = radio.txStandBy(txTimeout); 00812 00813 radio.setAutoAck(0,0); 00814 00815 #else 00816 radio1.openWritingPipe(out_pipe); 00817 radio1.writeFast(frame_buffer, frame_size); 00818 ok = radio1.txStandBy(txTimeout,multicast); 00819 00820 #endif 00821 00822 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"))); 00823 00824 return ok; 00825 } 00826 00827 /******************************************************************/ 00828 00829 const char* RF24NetworkHeader::toString(void) const 00830 { 00831 static char buffer[45]; 00832 //snprintf_P(buffer,sizeof(buffer),PSTR("id %04x from 0%o to 0%o type %c"),id,from_node,to_node,type); 00833 sprintf(buffer,PSTR("id %u from 0%o to 0%o type %d"),id,from_node,to_node,type); 00834 return buffer; 00835 } 00836 00837 /******************************************************************/ 00838 00839 bool RF24Network::is_direct_child( uint16_t node ) 00840 { 00841 bool result = false; 00842 00843 // A direct child of ours has the same low numbers as us, and only 00844 // one higher number. 00845 // 00846 // e.g. node 0234 is a direct child of 034, and node 01234 is a 00847 // descendant but not a direct child 00848 00849 // First, is it even a descendant? 00850 if ( is_descendant(node) ) { 00851 // Does it only have ONE more level than us? 00852 uint16_t child_node_mask = ( ~ node_mask ) << 3; 00853 result = ( node & child_node_mask ) == 0 ; 00854 } 00855 return result; 00856 } 00857 00858 /******************************************************************/ 00859 00860 bool RF24Network::is_descendant( uint16_t node ) 00861 { 00862 return ( node & node_mask ) == node_address; 00863 } 00864 00865 /******************************************************************/ 00866 00867 void RF24Network::setup_address(void) 00868 { 00869 // First, establish the node_mask 00870 uint16_t node_mask_check = 0xFFFF; 00871 #if defined (RF24NetworkMulticast) 00872 uint8_t count = 0; 00873 #endif 00874 00875 while ( node_address & node_mask_check ) { 00876 node_mask_check <<= 3; 00877 #if defined (RF24NetworkMulticast) 00878 count++; 00879 } 00880 multicast_level = count; 00881 #else 00882 } 00883 #endif 00884 00885 node_mask = ~ node_mask_check; 00886 00887 // parent mask is the next level down 00888 uint16_t parent_mask = node_mask >> 3; 00889 00890 // parent node is the part IN the mask 00891 parent_node = node_address & parent_mask; 00892 00893 // parent pipe is the part OUT of the mask 00894 uint16_t i = node_address; 00895 uint16_t m = parent_mask; 00896 while (m) 00897 { 00898 i >>= 3; 00899 m >>= 3; 00900 } 00901 parent_pipe = i; 00902 00903 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);); 00904 00905 } 00906 00907 /******************************************************************/ 00908 uint16_t RF24Network::addressOfPipe( uint16_t node, uint8_t pipeNo ) 00909 { 00910 //Say this node is 013 (1011), mask is 077 or (00111111) 00911 //Say we want to use pipe 3 (11) 00912 //6 bits in node mask, so shift pipeNo 6 times left and | into address 00913 uint16_t m = node_mask >> 3; 00914 uint8_t i=0; 00915 00916 while (m) { //While there are bits left in the node mask 00917 m>>=1; //Shift to the right 00918 i++; //Count the # of increments 00919 } 00920 return node | (pipeNo << i); 00921 } 00922 00923 /******************************************************************/ 00924 00925 uint16_t RF24Network::direct_child_route_to( uint16_t node ) 00926 { 00927 // Presumes that this is in fact a child!! 00928 uint16_t child_mask = ( node_mask << 3 ) | 7; 00929 return node & child_mask; 00930 00931 } 00932 00933 /******************************************************************/ 00934 /* 00935 uint8_t RF24Network::pipe_to_descendant( uint16_t node ) 00936 { 00937 uint16_t i = node; 00938 uint16_t m = node_mask; 00939 00940 while (m) 00941 { 00942 i >>= 3; 00943 m >>= 3; 00944 } 00945 00946 return i & 0B111; 00947 }*/ 00948 00949 /******************************************************************/ 00950 00951 bool RF24Network::is_valid_address ( uint16_t node ) 00952 { 00953 bool result = true; 00954 00955 while(node) { 00956 int8_t digit = node & 7; 00957 #if !defined (RF24NetworkMulticast) 00958 if (digit < 1 || digit > 5) 00959 #else 00960 if (digit < 0 || digit > 5) //Allow our out of range multicast address 00961 #endif 00962 { 00963 result = false; 00964 IF_SERIAL_DEBUG_MINIMAL(printf_P(PSTR("*** WARNING *** Invalid address 0%o\n\r"),node);); 00965 break; 00966 } 00967 node >>= 3; 00968 } 00969 00970 return result; 00971 } 00972 00973 /******************************************************************/ 00974 #if defined (RF24NetworkMulticast) 00975 void RF24Network::multicastLevel(uint8_t level) 00976 { 00977 multicast_level = level; 00978 //radio.stopListening(); 00979 radio.openReadingPipe(0,pipe_address(levelToAddress(level),0)); 00980 //radio.startListening(); 00981 } 00982 00983 uint16_t levelToAddress(uint8_t level) 00984 { 00985 00986 uint16_t levelAddr = 1; 00987 if(level) { 00988 levelAddr = levelAddr << ((level-1) * 3); 00989 } else { 00990 return 0; 00991 } 00992 return levelAddr; 00993 } 00994 #endif 00995 /******************************************************************/ 00996 00997 uint64_t pipe_address( uint16_t node, uint8_t pipe ) 00998 { 00999 01000 static uint8_t address_translation[] = { 0xc3,0x3c,0x33,0xce,0x3e,0xe3,0xec }; 01001 uint64_t result = 0xCCCCCCCCCCLL; 01002 uint8_t* out = reinterpret_cast<uint8_t*>(&result); 01003 01004 // Translate the address to use our optimally chosen radio address bytes 01005 uint8_t count = 1; 01006 uint16_t dec = node; 01007 01008 while(dec) { 01009 #if defined (RF24NetworkMulticast) 01010 if(pipe != 0 || !node) 01011 #endif 01012 out[count]=address_translation[(dec % 8)]; // Convert our decimal values to octal, translate them to address bytes, and set our address 01013 01014 dec /= 8; 01015 count++; 01016 } 01017 01018 #if defined (RF24NetworkMulticast) 01019 if(pipe != 0 || !node) 01020 #endif 01021 out[0] = address_translation[pipe]; 01022 #if defined (RF24NetworkMulticast) 01023 else 01024 out[1] = address_translation[count-1]; 01025 #endif 01026 01027 01028 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)); 01029 01030 return result; 01031 } 01032 01033 01034 /************************ Sleep Mode ******************************************/ 01035 01036 #if defined ENABLE_SLEEP_MODE 01037 01038 void wakeUp() 01039 { 01040 wasInterrupted=true; 01041 sleep_cycles_remaining = 0; 01042 } 01043 01044 ISR(WDT_vect) 01045 { 01046 --sleep_cycles_remaining; 01047 } 01048 01049 01050 bool RF24Network::sleepNode( unsigned int cycles, int interruptPin ) 01051 { 01052 01053 01054 sleep_cycles_remaining = cycles; 01055 set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here 01056 sleep_enable(); 01057 //if(interruptPin != 255){ 01058 // wasInterrupted = false; //Reset Flag 01059 // attachInterrupt(interruptPin,wakeUp, LOW); 01060 //} 01061 01062 WDTCSR |= _BV(WDIE); 01063 01064 while(sleep_cycles_remaining) { 01065 sleep_mode(); // System sleeps here 01066 } // The WDT_vect interrupt wakes the MCU from here 01067 sleep_disable(); // System continues execution here when watchdog timed out 01068 //detachInterrupt(interruptPin); 01069 01070 WDTCSR &= ~_BV(WDIE); 01071 01072 return !wasInterrupted; 01073 } 01074 01075 void RF24Network::setup_watchdog(uint8_t prescalar) 01076 { 01077 01078 uint8_t wdtcsr = prescalar & 7; 01079 if ( prescalar & 8 ) 01080 wdtcsr |= _BV(WDP3); 01081 MCUSR &= ~_BV(WDRF); // Clear the WD System Reset Flag 01082 01083 WDTCSR = _BV(WDCE) | _BV(WDE); // Write the WD Change enable bit to enable changing the prescaler and enable system reset 01084 WDTCSR = _BV(WDCE) | wdtcsr | _BV(WDIE); // Write the prescalar bits (how long to sleep, enable the interrupt to wake the MCU 01085 } 01086 01087 #endif
Generated on Mon Jul 25 2022 18:46:42 by
1.7.2