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: ISEN_RF24Network_Node_01 ISEN_RF24Network_Node_02
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 Fri Jul 29 2022 11:20:12 by
1.7.2