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