ISEN Nimes CSI3 / RF24Network

Dependents:   ISEN_RF24Network_Node_01 ISEN_RF24Network_Node_02

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 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