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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RF24Network.cpp Source File

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