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

Committer:
akashvibhute
Date:
Thu Apr 21 04:10:31 2016 +0000
Revision:
5:b1110d26a900
Parent:
4:75c5aa56411f
Library re-ported with all the latest and greatest stuff from Manicbug; Synced with TMRh20's RF24 library on Apr/18/2015 from https://github.com/TMRh20

Who changed what in which revision?

UserRevisionLine numberNew contents of line
akashvibhute 0:c3db0798d9aa 1 /*
akashvibhute 0:c3db0798d9aa 2 Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
akashvibhute 0:c3db0798d9aa 3
akashvibhute 0:c3db0798d9aa 4 This program is free software; you can redistribute it and/or
akashvibhute 0:c3db0798d9aa 5 modify it under the terms of the GNU General Public License
akashvibhute 0:c3db0798d9aa 6 version 2 as published by the Free Software Foundation.
akashvibhute 0:c3db0798d9aa 7 */
akashvibhute 4:75c5aa56411f 8
akashvibhute 3:dfc8da7ac18c 9 /*
akashvibhute 4:75c5aa56411f 10 * Mbed support added by Akash Vibhute <akash.roboticist@gmail.com>
akashvibhute 4:75c5aa56411f 11 * Porting completed on Nov/05/2015
akashvibhute 4:75c5aa56411f 12 *
akashvibhute 4:75c5aa56411f 13 * Updated 1: Synced with TMRh20's RF24 library on Nov/04/2015 from https://github.com/TMRh20
akashvibhute 4:75c5aa56411f 14 * Updated 2: Synced with TMRh20's RF24 library on Apr/18/2015 from https://github.com/TMRh20
akashvibhute 4:75c5aa56411f 15 *
akashvibhute 4:75c5aa56411f 16 */
akashvibhute 4:75c5aa56411f 17
akashvibhute 5:b1110d26a900 18
akashvibhute 4:75c5aa56411f 19 #include "RF24Network_config.h"
akashvibhute 4:75c5aa56411f 20 #include "RF24.h"
akashvibhute 4:75c5aa56411f 21 #include "RF24Network.h"
akashvibhute 2:a5f8e04bd02b 22
akashvibhute 4:75c5aa56411f 23 #if defined (ENABLE_SLEEP_MODE)
akashvibhute 4:75c5aa56411f 24 volatile byte sleep_cycles_remaining;
akashvibhute 4:75c5aa56411f 25 volatile bool wasInterrupted;
akashvibhute 4:75c5aa56411f 26 #endif
akashvibhute 0:c3db0798d9aa 27
akashvibhute 2:a5f8e04bd02b 28 uint16_t RF24NetworkHeader::next_id = 1;
akashvibhute 2:a5f8e04bd02b 29 #if defined ENABLE_NETWORK_STATS
akashvibhute 2:a5f8e04bd02b 30 uint32_t RF24Network::nFails = 0;
akashvibhute 2:a5f8e04bd02b 31 uint32_t RF24Network::nOK = 0;
akashvibhute 2:a5f8e04bd02b 32 #endif
akashvibhute 0:c3db0798d9aa 33 uint64_t pipe_address( uint16_t node, uint8_t pipe );
akashvibhute 2:a5f8e04bd02b 34 #if defined (RF24NetworkMulticast)
akashvibhute 2:a5f8e04bd02b 35 uint16_t levelToAddress( uint8_t level );
akashvibhute 2:a5f8e04bd02b 36 #endif
akashvibhute 0:c3db0798d9aa 37 bool is_valid_address( uint16_t node );
akashvibhute 0:c3db0798d9aa 38
akashvibhute 0:c3db0798d9aa 39 /******************************************************************/
akashvibhute 2:a5f8e04bd02b 40 #if !defined (DUAL_HEAD_RADIO)
akashvibhute 4:75c5aa56411f 41 RF24Network::RF24Network( RF24& _radio ): radio(_radio), next_frame(frame_queue)
akashvibhute 0:c3db0798d9aa 42 {
akashvibhute 4:75c5aa56411f 43 #if !defined ( DISABLE_FRAGMENTATION )
akashvibhute 4:75c5aa56411f 44 frag_queue.message_buffer=&frag_queue_message_buffer[0];
akashvibhute 4:75c5aa56411f 45 frag_ptr = &frag_queue;
akashvibhute 4:75c5aa56411f 46 #endif
akashvibhute 4:75c5aa56411f 47 txTime=0; networkFlags=0; returnSysMsgs=0; multicastRelay=0;
akashvibhute 0:c3db0798d9aa 48 }
akashvibhute 2:a5f8e04bd02b 49 #else
akashvibhute 2:a5f8e04bd02b 50 RF24Network::RF24Network( RF24& _radio, RF24& _radio1 ): radio(_radio), radio1(_radio1), next_frame(frame_queue)
akashvibhute 2:a5f8e04bd02b 51 {
akashvibhute 4:75c5aa56411f 52 #if !defined ( DISABLE_FRAGMENTATION )
akashvibhute 4:75c5aa56411f 53 frag_queue.message_buffer=&frag_queue_message_buffer[0];
akashvibhute 4:75c5aa56411f 54 frag_ptr = &frag_queue;
akashvibhute 4:75c5aa56411f 55 #endif
akashvibhute 4:75c5aa56411f 56 txTime=0; networkFlags=0; returnSysMsgs=0; multicastRelay=0;
akashvibhute 2:a5f8e04bd02b 57 }
akashvibhute 2:a5f8e04bd02b 58 #endif
akashvibhute 0:c3db0798d9aa 59 /******************************************************************/
akashvibhute 0:c3db0798d9aa 60
akashvibhute 0:c3db0798d9aa 61 void RF24Network::begin(uint8_t _channel, uint16_t _node_address )
akashvibhute 0:c3db0798d9aa 62 {
akashvibhute 4:75c5aa56411f 63 mainTimer.start();
akashvibhute 4:75c5aa56411f 64 if (! is_valid_address(_node_address) )
akashvibhute 4:75c5aa56411f 65 return;
akashvibhute 0:c3db0798d9aa 66
akashvibhute 4:75c5aa56411f 67 node_address = _node_address;
akashvibhute 3:dfc8da7ac18c 68
akashvibhute 4:75c5aa56411f 69 if ( ! radio.isValid() ){
akashvibhute 4:75c5aa56411f 70 return;
akashvibhute 4:75c5aa56411f 71 }
akashvibhute 0:c3db0798d9aa 72
akashvibhute 4:75c5aa56411f 73 // Set up the radio the way we want it to look
akashvibhute 4:75c5aa56411f 74 if(_channel != USE_CURRENT_CHANNEL){
akashvibhute 4:75c5aa56411f 75 radio.setChannel(_channel);
akashvibhute 4:75c5aa56411f 76 }
akashvibhute 4:75c5aa56411f 77 //radio.enableDynamicAck();
akashvibhute 4:75c5aa56411f 78 radio.setAutoAck(0,0);
akashvibhute 4:75c5aa56411f 79
akashvibhute 4:75c5aa56411f 80 #if defined (ENABLE_DYNAMIC_PAYLOADS)
akashvibhute 4:75c5aa56411f 81 radio.enableDynamicPayloads();
akashvibhute 4:75c5aa56411f 82 #endif
akashvibhute 4:75c5aa56411f 83
akashvibhute 4:75c5aa56411f 84 // Use different retry periods to reduce data collisions
akashvibhute 4:75c5aa56411f 85 uint8_t retryVar = (((node_address % 6)+1) *2) + 3;
akashvibhute 4:75c5aa56411f 86 radio.setRetries(retryVar, 5); // max about 85ms per attempt
akashvibhute 4:75c5aa56411f 87 txTimeout = 25;
akashvibhute 4:75c5aa56411f 88 routeTimeout = txTimeout*3; // Adjust for max delay per node within a single chain
akashvibhute 2:a5f8e04bd02b 89
akashvibhute 2:a5f8e04bd02b 90
akashvibhute 2:a5f8e04bd02b 91 #if defined (DUAL_HEAD_RADIO)
akashvibhute 4:75c5aa56411f 92 radio1.setChannel(_channel);
akashvibhute 4:75c5aa56411f 93 radio1.enableDynamicAck();
akashvibhute 4:75c5aa56411f 94 radio1.enableDynamicPayloads();
akashvibhute 2:a5f8e04bd02b 95 #endif
akashvibhute 2:a5f8e04bd02b 96
akashvibhute 4:75c5aa56411f 97 // Setup our address helper cache
akashvibhute 4:75c5aa56411f 98 setup_address();
akashvibhute 2:a5f8e04bd02b 99
akashvibhute 4:75c5aa56411f 100 // Open up all listening pipes
akashvibhute 4:75c5aa56411f 101 uint8_t i = 6;
akashvibhute 4:75c5aa56411f 102 while (i--){
akashvibhute 4:75c5aa56411f 103 radio.openReadingPipe(i,pipe_address(_node_address,i));
akashvibhute 4:75c5aa56411f 104 }
akashvibhute 4:75c5aa56411f 105 radio.startListening();
akashvibhute 3:dfc8da7ac18c 106
akashvibhute 0:c3db0798d9aa 107 }
akashvibhute 0:c3db0798d9aa 108
akashvibhute 0:c3db0798d9aa 109 /******************************************************************/
akashvibhute 0:c3db0798d9aa 110
akashvibhute 2:a5f8e04bd02b 111 #if defined ENABLE_NETWORK_STATS
akashvibhute 4:75c5aa56411f 112 void RF24Network::failures(uint32_t *_fails, uint32_t *_ok){
akashvibhute 4:75c5aa56411f 113 *_fails = nFails;
akashvibhute 4:75c5aa56411f 114 *_ok = nOK;
akashvibhute 2:a5f8e04bd02b 115 }
akashvibhute 2:a5f8e04bd02b 116 #endif
akashvibhute 2:a5f8e04bd02b 117
akashvibhute 2:a5f8e04bd02b 118 /******************************************************************/
akashvibhute 2:a5f8e04bd02b 119
akashvibhute 2:a5f8e04bd02b 120 uint8_t RF24Network::update(void)
akashvibhute 0:c3db0798d9aa 121 {
akashvibhute 4:75c5aa56411f 122 // if there is data ready
akashvibhute 4:75c5aa56411f 123 uint8_t pipe_num;
akashvibhute 4:75c5aa56411f 124 uint8_t returnVal = 0;
akashvibhute 4:75c5aa56411f 125
akashvibhute 4:75c5aa56411f 126 // If bypass is enabled, continue although incoming user data may be dropped
akashvibhute 4:75c5aa56411f 127 // Allows system payloads to be read while user cache is full
akashvibhute 4:75c5aa56411f 128 // Incoming Hold prevents data from being read from the radio, preventing incoming payloads from being acked
akashvibhute 4:75c5aa56411f 129
akashvibhute 4:75c5aa56411f 130 if(!(networkFlags & FLAG_BYPASS_HOLDS)){
akashvibhute 4:75c5aa56411f 131 if( (networkFlags & FLAG_HOLD_INCOMING) || (next_frame-frame_queue) + 34 > MAIN_BUFFER_SIZE ){
akashvibhute 4:75c5aa56411f 132 if(!available()){
akashvibhute 4:75c5aa56411f 133 networkFlags &= ~FLAG_HOLD_INCOMING;
akashvibhute 4:75c5aa56411f 134 }else{
akashvibhute 4:75c5aa56411f 135 return 0;
akashvibhute 4:75c5aa56411f 136 }
akashvibhute 2:a5f8e04bd02b 137 }
akashvibhute 4:75c5aa56411f 138 }
akashvibhute 4:75c5aa56411f 139
akashvibhute 4:75c5aa56411f 140
akashvibhute 4:75c5aa56411f 141
akashvibhute 4:75c5aa56411f 142 while ( radio.isValid() && radio.available(&pipe_num) ){
akashvibhute 0:c3db0798d9aa 143
akashvibhute 4:75c5aa56411f 144 #if defined (ENABLE_DYNAMIC_PAYLOADS)
akashvibhute 4:75c5aa56411f 145 if( (frame_size = radio.getDynamicPayloadSize() ) < sizeof(RF24NetworkHeader)){
akashvibhute 4:75c5aa56411f 146 wait_ms(10);
akashvibhute 4:75c5aa56411f 147 continue;
akashvibhute 4:75c5aa56411f 148 }
akashvibhute 4:75c5aa56411f 149 #else
akashvibhute 4:75c5aa56411f 150 frame_size=32;
akashvibhute 4:75c5aa56411f 151 #endif
akashvibhute 4:75c5aa56411f 152 // Dump the payloads until we've gotten everything
akashvibhute 4:75c5aa56411f 153 // Fetch the payload, and see if this was the last one.
akashvibhute 4:75c5aa56411f 154 radio.read( frame_buffer, frame_size );
akashvibhute 4:75c5aa56411f 155
akashvibhute 4:75c5aa56411f 156 // Read the beginning of the frame as the header
akashvibhute 4:75c5aa56411f 157 RF24NetworkHeader *header = (RF24NetworkHeader*)(&frame_buffer);
akashvibhute 4:75c5aa56411f 158
akashvibhute 4:75c5aa56411f 159 IF_SERIAL_DEBUG(printf_P(PSTR("%lu: MAC Received on %u %s\n\r"),millis(),pipe_num,header->toString()));
akashvibhute 4:75c5aa56411f 160 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));
akashvibhute 3:dfc8da7ac18c 161
akashvibhute 4:75c5aa56411f 162
akashvibhute 4:75c5aa56411f 163 // Throw it away if it's not a valid address
akashvibhute 4:75c5aa56411f 164 if ( !is_valid_address(header->to_node) ){
akashvibhute 4:75c5aa56411f 165 continue;
akashvibhute 4:75c5aa56411f 166 }
akashvibhute 4:75c5aa56411f 167
akashvibhute 4:75c5aa56411f 168 uint8_t returnVal = header->type;
akashvibhute 0:c3db0798d9aa 169
akashvibhute 4:75c5aa56411f 170 // Is this for us?
akashvibhute 4:75c5aa56411f 171 if ( header->to_node == node_address ){
akashvibhute 4:75c5aa56411f 172
akashvibhute 4:75c5aa56411f 173 if(header->type == NETWORK_PING){
akashvibhute 4:75c5aa56411f 174 continue;
akashvibhute 4:75c5aa56411f 175 }
akashvibhute 4:75c5aa56411f 176 if(header->type == NETWORK_ADDR_RESPONSE ){
akashvibhute 4:75c5aa56411f 177 uint16_t requester = 04444;
akashvibhute 4:75c5aa56411f 178 if(requester != node_address){
akashvibhute 4:75c5aa56411f 179 header->to_node = requester;
akashvibhute 4:75c5aa56411f 180 write(header->to_node,USER_TX_TO_PHYSICAL_ADDRESS);
akashvibhute 4:75c5aa56411f 181 wait_ms(10);
akashvibhute 2:a5f8e04bd02b 182 write(header->to_node,USER_TX_TO_PHYSICAL_ADDRESS);
akashvibhute 4:75c5aa56411f 183 //printf("Fwd add response to 0%o\n",requester);
akashvibhute 4:75c5aa56411f 184 continue;
akashvibhute 4:75c5aa56411f 185 }
akashvibhute 4:75c5aa56411f 186 }
akashvibhute 4:75c5aa56411f 187 if(header->type == NETWORK_REQ_ADDRESS && node_address){
akashvibhute 4:75c5aa56411f 188 //printf("Fwd add req to 0\n");
akashvibhute 4:75c5aa56411f 189 header->from_node = node_address;
akashvibhute 4:75c5aa56411f 190 header->to_node = 0;
akashvibhute 4:75c5aa56411f 191 write(header->to_node,TX_NORMAL);
akashvibhute 4:75c5aa56411f 192 continue;
akashvibhute 4:75c5aa56411f 193 }
akashvibhute 4:75c5aa56411f 194
akashvibhute 4:75c5aa56411f 195 if( (returnSysMsgs && header->type > 127) || header->type == NETWORK_ACK ){
akashvibhute 4:75c5aa56411f 196 IF_SERIAL_DEBUG_ROUTING( printf_P(PSTR("%lu MAC: System payload rcvd %d\n"),millis(),returnVal); );
akashvibhute 4:75c5aa56411f 197 //if( (header->type < 148 || header->type > 150) && header->type != NETWORK_MORE_FRAGMENTS_NACK && header->type != EXTERNAL_DATA_TYPE && header->type!= NETWORK_LAST_FRAGMENT){
akashvibhute 4:75c5aa56411f 198 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){
akashvibhute 4:75c5aa56411f 199 return returnVal;
akashvibhute 4:75c5aa56411f 200 }
akashvibhute 4:75c5aa56411f 201 }
akashvibhute 3:dfc8da7ac18c 202
akashvibhute 4:75c5aa56411f 203 if( enqueue(header) == 2 ){ //External data received
akashvibhute 4:75c5aa56411f 204 #if defined (SERIAL_DEBUG_MINIMAL)
akashvibhute 4:75c5aa56411f 205 printf("ret ext\n");
akashvibhute 4:75c5aa56411f 206 #endif
akashvibhute 4:75c5aa56411f 207 return EXTERNAL_DATA_TYPE;
akashvibhute 4:75c5aa56411f 208 }
akashvibhute 4:75c5aa56411f 209 }else{
akashvibhute 0:c3db0798d9aa 210
akashvibhute 4:75c5aa56411f 211 #if defined (RF24NetworkMulticast)
akashvibhute 2:a5f8e04bd02b 212
akashvibhute 4:75c5aa56411f 213 if( header->to_node == 0100){
akashvibhute 4:75c5aa56411f 214
akashvibhute 3:dfc8da7ac18c 215
akashvibhute 4:75c5aa56411f 216 if(header->type == NETWORK_POLL ){
akashvibhute 4:75c5aa56411f 217 if( !(networkFlags & FLAG_NO_POLL) && node_address != 04444 ){
akashvibhute 4:75c5aa56411f 218 header->to_node = header->from_node;
akashvibhute 4:75c5aa56411f 219 header->from_node = node_address;
akashvibhute 4:75c5aa56411f 220 wait_ms(parent_pipe);
akashvibhute 4:75c5aa56411f 221 write(header->to_node,USER_TX_TO_PHYSICAL_ADDRESS);
akashvibhute 4:75c5aa56411f 222 }
akashvibhute 4:75c5aa56411f 223 continue;
akashvibhute 4:75c5aa56411f 224 }
akashvibhute 4:75c5aa56411f 225 uint8_t val = enqueue(header);
akashvibhute 4:75c5aa56411f 226
akashvibhute 4:75c5aa56411f 227 if(multicastRelay){
akashvibhute 4:75c5aa56411f 228 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); );
akashvibhute 4:75c5aa56411f 229 write(levelToAddress(multicast_level)<<3,4);
akashvibhute 4:75c5aa56411f 230 }
akashvibhute 4:75c5aa56411f 231 if( val == 2 ){ //External data received
akashvibhute 4:75c5aa56411f 232 //Serial.println("ret ext multicast");
akashvibhute 4:75c5aa56411f 233 return EXTERNAL_DATA_TYPE;
akashvibhute 4:75c5aa56411f 234 }
akashvibhute 2:a5f8e04bd02b 235
akashvibhute 4:75c5aa56411f 236 }else{
akashvibhute 4:75c5aa56411f 237 write(header->to_node,1); //Send it on, indicate it is a routed payload
akashvibhute 4:75c5aa56411f 238 }
akashvibhute 4:75c5aa56411f 239 #else
akashvibhute 4:75c5aa56411f 240 write(header->to_node,1); //Send it on, indicate it is a routed payload
akashvibhute 4:75c5aa56411f 241 #endif
akashvibhute 4:75c5aa56411f 242 }
akashvibhute 4:75c5aa56411f 243
akashvibhute 4:75c5aa56411f 244 }
akashvibhute 4:75c5aa56411f 245 return returnVal;
akashvibhute 0:c3db0798d9aa 246 }
akashvibhute 0:c3db0798d9aa 247
akashvibhute 2:a5f8e04bd02b 248 /******************************************************************/
akashvibhute 2:a5f8e04bd02b 249
akashvibhute 2:a5f8e04bd02b 250 uint8_t RF24Network::enqueue(RF24NetworkHeader* header)
akashvibhute 0:c3db0798d9aa 251 {
akashvibhute 4:75c5aa56411f 252 bool result = false;
akashvibhute 4:75c5aa56411f 253 uint16_t message_size = frame_size - sizeof(RF24NetworkHeader);
akashvibhute 4:75c5aa56411f 254
akashvibhute 4:75c5aa56411f 255 IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Enqueue @%x "),mainTimer.read_ms(),next_frame-frame_queue));
akashvibhute 4:75c5aa56411f 256
akashvibhute 4:75c5aa56411f 257 #if !defined ( DISABLE_FRAGMENTATION )
akashvibhute 2:a5f8e04bd02b 258
akashvibhute 4:75c5aa56411f 259 bool isFragment = header->type == NETWORK_FIRST_FRAGMENT || header->type == NETWORK_MORE_FRAGMENTS || header->type == NETWORK_LAST_FRAGMENT || header->type == NETWORK_MORE_FRAGMENTS_NACK ;
akashvibhute 2:a5f8e04bd02b 260
akashvibhute 4:75c5aa56411f 261 if(isFragment){
akashvibhute 2:a5f8e04bd02b 262
akashvibhute 4:75c5aa56411f 263 if(header->type == NETWORK_FIRST_FRAGMENT){
akashvibhute 4:75c5aa56411f 264 // Drop frames exceeding max size and duplicates (MAX_PAYLOAD_SIZE needs to be divisible by 24)
akashvibhute 4:75c5aa56411f 265 if(header->reserved > (MAX_PAYLOAD_SIZE / max_frame_payload_size) ){
akashvibhute 2:a5f8e04bd02b 266
akashvibhute 4:75c5aa56411f 267 #if defined (SERIAL_DEBUG_FRAGMENTATION) || defined (SERIAL_DEBUG_MINIMAL)
akashvibhute 4:75c5aa56411f 268 printf_P(PSTR("Frag frame with %d frags exceeds MAX_PAYLOAD_SIZE or out of sequence\n"),header->reserved);
akashvibhute 4:75c5aa56411f 269 #endif
akashvibhute 4:75c5aa56411f 270 frag_queue.header.reserved = 0;
akashvibhute 4:75c5aa56411f 271 return false;
akashvibhute 4:75c5aa56411f 272 }else
akashvibhute 4:75c5aa56411f 273 if(frag_queue.header.id == header->id && frag_queue.header.from_node == header->from_node){
akashvibhute 4:75c5aa56411f 274 return true;
akashvibhute 4:75c5aa56411f 275 }
akashvibhute 4:75c5aa56411f 276
akashvibhute 4:75c5aa56411f 277 if( (header->reserved * 24) > (MAX_PAYLOAD_SIZE - (next_frame-frame_queue)) ){
akashvibhute 4:75c5aa56411f 278 networkFlags |= FLAG_HOLD_INCOMING;
akashvibhute 4:75c5aa56411f 279 radio.stopListening();
akashvibhute 4:75c5aa56411f 280 }
akashvibhute 4:75c5aa56411f 281
akashvibhute 4:75c5aa56411f 282 memcpy(&frag_queue,&frame_buffer,8);
akashvibhute 4:75c5aa56411f 283 memcpy(frag_queue.message_buffer,frame_buffer+sizeof(RF24NetworkHeader),message_size);
akashvibhute 4:75c5aa56411f 284
akashvibhute 3:dfc8da7ac18c 285 //IF_SERIAL_DEBUG_FRAGMENTATION( Serial.print(F("queue first, total frags ")); Serial.println(header->reserved); );
akashvibhute 4:75c5aa56411f 286 //Store the total size of the stored frame in message_size
akashvibhute 4:75c5aa56411f 287 frag_queue.message_size = message_size;
akashvibhute 4:75c5aa56411f 288 --frag_queue.header.reserved;
akashvibhute 4:75c5aa56411f 289
akashvibhute 4:75c5aa56411f 290 IF_SERIAL_DEBUG_FRAGMENTATION_L2( for(int i=0; i<frag_queue.message_size;i++){ Serial.println(frag_queue.message_buffer[i],HEX); } );
akashvibhute 4:75c5aa56411f 291
akashvibhute 4:75c5aa56411f 292 return true;
akashvibhute 2:a5f8e04bd02b 293
akashvibhute 4:75c5aa56411f 294 }else // NETWORK_MORE_FRAGMENTS
akashvibhute 4:75c5aa56411f 295 if(header->type == NETWORK_LAST_FRAGMENT || header->type == NETWORK_MORE_FRAGMENTS || header->type == NETWORK_MORE_FRAGMENTS_NACK){
akashvibhute 4:75c5aa56411f 296
akashvibhute 4:75c5aa56411f 297 if(frag_queue.message_size + message_size > MAX_PAYLOAD_SIZE){
akashvibhute 4:75c5aa56411f 298 #if defined (SERIAL_DEBUG_FRAGMENTATION) || defined (SERIAL_DEBUG_MINIMAL)
akashvibhute 4:75c5aa56411f 299 Serial.print(F("Drop frag ")); Serial.print(header->reserved);
akashvibhute 4:75c5aa56411f 300 Serial.println(F(" Size exceeds max"));
akashvibhute 4:75c5aa56411f 301 #endif
akashvibhute 4:75c5aa56411f 302 frag_queue.header.reserved=0;
akashvibhute 4:75c5aa56411f 303 return false;
akashvibhute 4:75c5aa56411f 304 }
akashvibhute 4:75c5aa56411f 305 if( frag_queue.header.reserved == 0 || (header->type != NETWORK_LAST_FRAGMENT && header->reserved != frag_queue.header.reserved ) || frag_queue.header.id != header->id ){
akashvibhute 4:75c5aa56411f 306 #if defined (SERIAL_DEBUG_FRAGMENTATION) || defined (SERIAL_DEBUG_MINIMAL)
akashvibhute 4:75c5aa56411f 307 Serial.print(F("Drop frag ")); Serial.print(header->reserved);
akashvibhute 4:75c5aa56411f 308 //Serial.print(F(" header id ")); Serial.print(header->id);
akashvibhute 4:75c5aa56411f 309 Serial.println(F(" Out of order "));
akashvibhute 4:75c5aa56411f 310 #endif
akashvibhute 4:75c5aa56411f 311 return false;
akashvibhute 4:75c5aa56411f 312 }
akashvibhute 4:75c5aa56411f 313
akashvibhute 4:75c5aa56411f 314 memcpy(frag_queue.message_buffer+frag_queue.message_size,frame_buffer+sizeof(RF24NetworkHeader),message_size);
akashvibhute 4:75c5aa56411f 315 frag_queue.message_size += message_size;
akashvibhute 4:75c5aa56411f 316
akashvibhute 4:75c5aa56411f 317 if(header->type != NETWORK_LAST_FRAGMENT){
akashvibhute 4:75c5aa56411f 318 --frag_queue.header.reserved;
akashvibhute 4:75c5aa56411f 319 return true;
akashvibhute 4:75c5aa56411f 320 }
akashvibhute 4:75c5aa56411f 321 frag_queue.header.reserved = 0;
akashvibhute 4:75c5aa56411f 322 frag_queue.header.type = header->reserved;
akashvibhute 4:75c5aa56411f 323
akashvibhute 4:75c5aa56411f 324 IF_SERIAL_DEBUG_FRAGMENTATION( printf_P(PSTR("fq 3: %d\n"),frag_queue.message_size); );
akashvibhute 4:75c5aa56411f 325 IF_SERIAL_DEBUG_FRAGMENTATION_L2(for(int i=0; i< frag_queue.message_size;i++){ Serial.println(frag_queue.message_buffer[i],HEX); } );
akashvibhute 4:75c5aa56411f 326
akashvibhute 4:75c5aa56411f 327 //Frame assembly complete, copy to main buffer if OK
akashvibhute 4:75c5aa56411f 328 if(frag_queue.header.type == EXTERNAL_DATA_TYPE){
akashvibhute 4:75c5aa56411f 329 return 2;
akashvibhute 4:75c5aa56411f 330 }
akashvibhute 4:75c5aa56411f 331 #if defined (DISABLE_USER_PAYLOADS)
akashvibhute 4:75c5aa56411f 332 return 0;
akashvibhute 4:75c5aa56411f 333 #endif
akashvibhute 4:75c5aa56411f 334
akashvibhute 4:75c5aa56411f 335 if(MAX_PAYLOAD_SIZE - (next_frame-frame_queue) >= frag_queue.message_size){
akashvibhute 4:75c5aa56411f 336 memcpy(next_frame,&frag_queue,10);
akashvibhute 4:75c5aa56411f 337 memcpy(next_frame+10,frag_queue.message_buffer,frag_queue.message_size);
akashvibhute 4:75c5aa56411f 338 next_frame += (10+frag_queue.message_size);
akashvibhute 4:75c5aa56411f 339 #if !defined(ARDUINO_ARCH_AVR)
akashvibhute 4:75c5aa56411f 340 if(uint8_t padding = (frag_queue.message_size+10)%4){
akashvibhute 4:75c5aa56411f 341 next_frame += 4 - padding;
akashvibhute 4:75c5aa56411f 342 }
akashvibhute 4:75c5aa56411f 343 #endif
akashvibhute 4:75c5aa56411f 344 IF_SERIAL_DEBUG_FRAGMENTATION( printf_P(PSTR("enq size %d\n"),frag_queue.message_size); );
akashvibhute 4:75c5aa56411f 345 return true;
akashvibhute 4:75c5aa56411f 346 }else{
akashvibhute 4:75c5aa56411f 347 radio.stopListening();
akashvibhute 4:75c5aa56411f 348 networkFlags |= FLAG_HOLD_INCOMING;
akashvibhute 4:75c5aa56411f 349 }
akashvibhute 4:75c5aa56411f 350 IF_SERIAL_DEBUG_FRAGMENTATION( printf_P(PSTR("Drop frag payload, queue full\n")); );
akashvibhute 4:75c5aa56411f 351 return false;
akashvibhute 4:75c5aa56411f 352 }//If more or last fragments
akashvibhute 2:a5f8e04bd02b 353
akashvibhute 4:75c5aa56411f 354 }else //else is not a fragment
akashvibhute 4:75c5aa56411f 355 #endif // End fragmentation enabled
akashvibhute 0:c3db0798d9aa 356
akashvibhute 4:75c5aa56411f 357 // Copy the current frame into the frame queue
akashvibhute 2:a5f8e04bd02b 358
akashvibhute 2:a5f8e04bd02b 359 #if !defined( DISABLE_FRAGMENTATION )
akashvibhute 0:c3db0798d9aa 360
akashvibhute 4:75c5aa56411f 361 if(header->type == EXTERNAL_DATA_TYPE){
akashvibhute 4:75c5aa56411f 362 memcpy(&frag_queue,&frame_buffer,8);
akashvibhute 4:75c5aa56411f 363 frag_queue.message_buffer = frame_buffer+sizeof(RF24NetworkHeader);
akashvibhute 4:75c5aa56411f 364 frag_queue.message_size = message_size;
akashvibhute 4:75c5aa56411f 365 return 2;
akashvibhute 4:75c5aa56411f 366 }
akashvibhute 4:75c5aa56411f 367 #endif
akashvibhute 2:a5f8e04bd02b 368 #if defined (DISABLE_USER_PAYLOADS)
akashvibhute 4:75c5aa56411f 369 return 0;
akashvibhute 4:75c5aa56411f 370 }
akashvibhute 2:a5f8e04bd02b 371 #else
akashvibhute 4:75c5aa56411f 372 if(message_size + (next_frame-frame_queue) <= MAIN_BUFFER_SIZE){
akashvibhute 4:75c5aa56411f 373 memcpy(next_frame,&frame_buffer,8);
akashvibhute 4:75c5aa56411f 374 memcpy(next_frame+8,&message_size,2);
akashvibhute 4:75c5aa56411f 375 memcpy(next_frame+10,frame_buffer+8,message_size);
akashvibhute 4:75c5aa56411f 376
akashvibhute 4:75c5aa56411f 377 //IF_SERIAL_DEBUG_FRAGMENTATION( for(int i=0; i<message_size;i++){ Serial.print(next_frame[i],HEX); Serial.print(" : "); } Serial.println(""); );
akashvibhute 4:75c5aa56411f 378
akashvibhute 4:75c5aa56411f 379 next_frame += (message_size + 10);
akashvibhute 4:75c5aa56411f 380 #if !defined(ARDUINO_ARCH_AVR)
akashvibhute 4:75c5aa56411f 381 if(uint8_t padding = (message_size+10)%4){
akashvibhute 4:75c5aa56411f 382 next_frame += 4 - padding;
akashvibhute 3:dfc8da7ac18c 383 }
akashvibhute 4:75c5aa56411f 384 #endif
akashvibhute 4:75c5aa56411f 385 //IF_SERIAL_DEBUG_FRAGMENTATION( Serial.print("Enq "); Serial.println(next_frame-frame_queue); );//printf_P(PSTR("enq %d\n"),next_frame-frame_queue); );
akashvibhute 4:75c5aa56411f 386
akashvibhute 4:75c5aa56411f 387 result = true;
akashvibhute 4:75c5aa56411f 388 }else{
akashvibhute 4:75c5aa56411f 389 result = false;
akashvibhute 4:75c5aa56411f 390 IF_SERIAL_DEBUG(printf_P(PSTR("NET **Drop Payload** Buffer Full")));
akashvibhute 4:75c5aa56411f 391 }
akashvibhute 4:75c5aa56411f 392 return result;
akashvibhute 0:c3db0798d9aa 393 }
akashvibhute 4:75c5aa56411f 394 #endif
akashvibhute 0:c3db0798d9aa 395
akashvibhute 0:c3db0798d9aa 396 /******************************************************************/
akashvibhute 0:c3db0798d9aa 397
akashvibhute 0:c3db0798d9aa 398 bool RF24Network::available(void)
akashvibhute 0:c3db0798d9aa 399 {
akashvibhute 4:75c5aa56411f 400 // Are there frames on the queue for us?
akashvibhute 4:75c5aa56411f 401 return (next_frame > frame_queue);
akashvibhute 2:a5f8e04bd02b 402
akashvibhute 0:c3db0798d9aa 403 }
akashvibhute 0:c3db0798d9aa 404
akashvibhute 0:c3db0798d9aa 405 /******************************************************************/
akashvibhute 0:c3db0798d9aa 406
akashvibhute 2:a5f8e04bd02b 407 uint16_t RF24Network::parent() const
akashvibhute 0:c3db0798d9aa 408 {
akashvibhute 4:75c5aa56411f 409 if ( node_address == 0 )
akashvibhute 4:75c5aa56411f 410 return -1;
akashvibhute 4:75c5aa56411f 411 else
akashvibhute 4:75c5aa56411f 412 return parent_node;
akashvibhute 2:a5f8e04bd02b 413 }
akashvibhute 0:c3db0798d9aa 414
akashvibhute 2:a5f8e04bd02b 415 /******************************************************************/
akashvibhute 2:a5f8e04bd02b 416 /*uint8_t RF24Network::peekData(){
akashvibhute 4:75c5aa56411f 417
akashvibhute 4:75c5aa56411f 418 return frame_queue[0];
akashvibhute 2:a5f8e04bd02b 419 }*/
akashvibhute 2:a5f8e04bd02b 420
akashvibhute 2:a5f8e04bd02b 421 uint16_t RF24Network::peek(RF24NetworkHeader& header)
akashvibhute 2:a5f8e04bd02b 422 {
akashvibhute 4:75c5aa56411f 423 if ( available() )
akashvibhute 4:75c5aa56411f 424 {
akashvibhute 2:a5f8e04bd02b 425
akashvibhute 4:75c5aa56411f 426 RF24NetworkFrame *frame = (RF24NetworkFrame*)(frame_queue);
akashvibhute 4:75c5aa56411f 427 memcpy(&header,&frame->header,sizeof(RF24NetworkHeader));
akashvibhute 4:75c5aa56411f 428 uint16_t msg_size;
akashvibhute 4:75c5aa56411f 429 memcpy(&msg_size,frame+8,2);
akashvibhute 4:75c5aa56411f 430 return msg_size;
akashvibhute 4:75c5aa56411f 431 }
akashvibhute 4:75c5aa56411f 432 return 0;
akashvibhute 2:a5f8e04bd02b 433 }
akashvibhute 2:a5f8e04bd02b 434
akashvibhute 2:a5f8e04bd02b 435 /******************************************************************/
akashvibhute 2:a5f8e04bd02b 436
akashvibhute 2:a5f8e04bd02b 437 uint16_t RF24Network::read(RF24NetworkHeader& header,void* message, uint16_t maxlen)
akashvibhute 2:a5f8e04bd02b 438 {
akashvibhute 4:75c5aa56411f 439 uint16_t bufsize = 0;
akashvibhute 2:a5f8e04bd02b 440
akashvibhute 4:75c5aa56411f 441
akashvibhute 4:75c5aa56411f 442 if ( available() )
akashvibhute 4:75c5aa56411f 443 {
akashvibhute 4:75c5aa56411f 444
akashvibhute 4:75c5aa56411f 445 memcpy(&header,frame_queue,8);
akashvibhute 4:75c5aa56411f 446 memcpy(&bufsize,frame_queue+8,2);
akashvibhute 3:dfc8da7ac18c 447
akashvibhute 4:75c5aa56411f 448 if (maxlen > 0)
akashvibhute 4:75c5aa56411f 449 {
akashvibhute 4:75c5aa56411f 450 maxlen = rf24_min(maxlen,bufsize);
akashvibhute 4:75c5aa56411f 451 memcpy(message,frame_queue+10,maxlen);
akashvibhute 4:75c5aa56411f 452 IF_SERIAL_DEBUG(printf("%lu: NET message size %d\n",millis(),bufsize););
akashvibhute 2:a5f8e04bd02b 453
akashvibhute 4:75c5aa56411f 454
akashvibhute 4:75c5aa56411f 455 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") ) );
akashvibhute 4:75c5aa56411f 456
akashvibhute 4:75c5aa56411f 457 }
akashvibhute 4:75c5aa56411f 458 memmove(frame_queue,frame_queue+bufsize+10,sizeof(frame_queue)- bufsize);
akashvibhute 4:75c5aa56411f 459 next_frame-=bufsize+10;
akashvibhute 4:75c5aa56411f 460
akashvibhute 4:75c5aa56411f 461 if(uint8_t padding = (bufsize+10)%4){
akashvibhute 4:75c5aa56411f 462 next_frame -= 4 - padding;
akashvibhute 4:75c5aa56411f 463 }
akashvibhute 4:75c5aa56411f 464
akashvibhute 4:75c5aa56411f 465 //IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Received %s\n\r"),millis(),header.toString()));
akashvibhute 4:75c5aa56411f 466 }
akashvibhute 2:a5f8e04bd02b 467
akashvibhute 4:75c5aa56411f 468 return bufsize;
akashvibhute 0:c3db0798d9aa 469 }
akashvibhute 0:c3db0798d9aa 470
akashvibhute 2:a5f8e04bd02b 471
akashvibhute 2:a5f8e04bd02b 472 #if defined RF24NetworkMulticast
akashvibhute 2:a5f8e04bd02b 473 /******************************************************************/
akashvibhute 4:75c5aa56411f 474 bool RF24Network::multicast(RF24NetworkHeader& header,const void* message, uint16_t len, uint8_t level){
akashvibhute 4:75c5aa56411f 475 // Fill out the header
akashvibhute 4:75c5aa56411f 476 header.to_node = 0100;
akashvibhute 4:75c5aa56411f 477 header.from_node = node_address;
akashvibhute 4:75c5aa56411f 478 return write(header, message, len, levelToAddress(level));
akashvibhute 2:a5f8e04bd02b 479 }
akashvibhute 2:a5f8e04bd02b 480 #endif
akashvibhute 2:a5f8e04bd02b 481
akashvibhute 2:a5f8e04bd02b 482 /******************************************************************/
akashvibhute 4:75c5aa56411f 483 bool RF24Network::write(RF24NetworkHeader& header,const void* message, uint16_t len){
akashvibhute 4:75c5aa56411f 484 return write(header,message,len,070);
akashvibhute 2:a5f8e04bd02b 485 }
akashvibhute 2:a5f8e04bd02b 486 /******************************************************************/
akashvibhute 4:75c5aa56411f 487 bool RF24Network::write(RF24NetworkHeader& header,const void* message, uint16_t len, uint16_t writeDirect){
akashvibhute 4:75c5aa56411f 488
akashvibhute 2:a5f8e04bd02b 489 //Allows time for requests (RF24Mesh) to get through between failed writes on busy nodes
akashvibhute 4:75c5aa56411f 490 while(mainTimer.read_ms()-txTime < 25){ if(update() > 127){break;} }
akashvibhute 4:75c5aa56411f 491 wait_us(200);
akashvibhute 2:a5f8e04bd02b 492
akashvibhute 2:a5f8e04bd02b 493 #if defined (DISABLE_FRAGMENTATION)
akashvibhute 2:a5f8e04bd02b 494 frame_size = rf24_min(len+sizeof(RF24NetworkHeader),MAX_FRAME_SIZE);
akashvibhute 4:75c5aa56411f 495 return _write(header,message,rf24_min(len,max_frame_payload_size),writeDirect);
akashvibhute 4:75c5aa56411f 496 #else
akashvibhute 4:75c5aa56411f 497 if(len <= max_frame_payload_size){
akashvibhute 4:75c5aa56411f 498 //Normal Write (Un-Fragmented)
akashvibhute 4:75c5aa56411f 499 frame_size = len + sizeof(RF24NetworkHeader);
akashvibhute 4:75c5aa56411f 500 if(_write(header,message,len,writeDirect)){
akashvibhute 4:75c5aa56411f 501 return 1;
akashvibhute 2:a5f8e04bd02b 502 }
akashvibhute 4:75c5aa56411f 503 txTime = mainTimer.read_ms();
akashvibhute 4:75c5aa56411f 504 return 0;
akashvibhute 4:75c5aa56411f 505 }
akashvibhute 4:75c5aa56411f 506 //Check payload size
akashvibhute 4:75c5aa56411f 507 if (len > MAX_PAYLOAD_SIZE) {
akashvibhute 4:75c5aa56411f 508 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););
akashvibhute 4:75c5aa56411f 509 return false;
akashvibhute 4:75c5aa56411f 510 }
akashvibhute 4:75c5aa56411f 511
akashvibhute 4:75c5aa56411f 512 //Divide the message payload into chunks of max_frame_payload_size
akashvibhute 4:75c5aa56411f 513 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)
akashvibhute 4:75c5aa56411f 514
akashvibhute 4:75c5aa56411f 515 uint8_t msgCount = 0;
akashvibhute 2:a5f8e04bd02b 516
akashvibhute 4:75c5aa56411f 517 //IF_SERIAL_DEBUG_FRAGMENTATION(printf("%lu: FRG Total message fragments %d\n\r",millis(),fragment_id););
akashvibhute 4:75c5aa56411f 518
akashvibhute 4:75c5aa56411f 519 if(header.to_node != 0100){
akashvibhute 4:75c5aa56411f 520 networkFlags |= FLAG_FAST_FRAG;
akashvibhute 4:75c5aa56411f 521 #if !defined (DUAL_HEAD_RADIO)
akashvibhute 4:75c5aa56411f 522 radio.stopListening();
akashvibhute 4:75c5aa56411f 523 #endif
akashvibhute 4:75c5aa56411f 524 }
akashvibhute 4:75c5aa56411f 525
akashvibhute 4:75c5aa56411f 526 uint8_t retriesPerFrag = 0;
akashvibhute 4:75c5aa56411f 527 uint8_t type = header.type;
akashvibhute 4:75c5aa56411f 528 bool ok = 0;
akashvibhute 4:75c5aa56411f 529
akashvibhute 4:75c5aa56411f 530 while (fragment_id > 0) {
akashvibhute 4:75c5aa56411f 531
akashvibhute 4:75c5aa56411f 532 //Copy and fill out the header
akashvibhute 4:75c5aa56411f 533 //RF24NetworkHeader fragmentHeader = header;
akashvibhute 4:75c5aa56411f 534 header.reserved = fragment_id;
akashvibhute 2:a5f8e04bd02b 535
akashvibhute 4:75c5aa56411f 536 if (fragment_id == 1) {
akashvibhute 4:75c5aa56411f 537 header.type = NETWORK_LAST_FRAGMENT; //Set the last fragment flag to indicate the last fragment
akashvibhute 4:75c5aa56411f 538 header.reserved = type; //The reserved field is used to transmit the header type
akashvibhute 4:75c5aa56411f 539 } else {
akashvibhute 4:75c5aa56411f 540 if (msgCount == 0) {
akashvibhute 4:75c5aa56411f 541 header.type = NETWORK_FIRST_FRAGMENT;
akashvibhute 4:75c5aa56411f 542 }else{
akashvibhute 4:75c5aa56411f 543 header.type = NETWORK_MORE_FRAGMENTS; //Set the more fragments flag to indicate a fragmented frame
akashvibhute 4:75c5aa56411f 544 }
akashvibhute 4:75c5aa56411f 545 }
akashvibhute 4:75c5aa56411f 546
akashvibhute 4:75c5aa56411f 547 uint16_t offset = msgCount*max_frame_payload_size;
akashvibhute 4:75c5aa56411f 548 uint16_t fragmentLen = rf24_min((uint16_t)(len-offset),max_frame_payload_size);
akashvibhute 2:a5f8e04bd02b 549
akashvibhute 4:75c5aa56411f 550 //Try to send the payload chunk with the copied header
akashvibhute 4:75c5aa56411f 551 frame_size = sizeof(RF24NetworkHeader)+fragmentLen;
akashvibhute 4:75c5aa56411f 552 ok = _write(header,((char *)message)+offset,fragmentLen,writeDirect);
akashvibhute 4:75c5aa56411f 553
akashvibhute 4:75c5aa56411f 554 if (!ok) {
akashvibhute 4:75c5aa56411f 555 wait_ms(2);
akashvibhute 4:75c5aa56411f 556 ++retriesPerFrag;
akashvibhute 4:75c5aa56411f 557
akashvibhute 4:75c5aa56411f 558 }else{
akashvibhute 4:75c5aa56411f 559 retriesPerFrag = 0;
akashvibhute 4:75c5aa56411f 560 fragment_id--;
akashvibhute 4:75c5aa56411f 561 msgCount++;
akashvibhute 4:75c5aa56411f 562 }
akashvibhute 4:75c5aa56411f 563
akashvibhute 4:75c5aa56411f 564 //if(writeDirect != 070){ delay(2); } //Delay 2ms between sending multicast payloads
akashvibhute 4:75c5aa56411f 565
akashvibhute 4:75c5aa56411f 566 if (!ok && retriesPerFrag >= 3) {
akashvibhute 4:75c5aa56411f 567 //IF_SERIAL_DEBUG_FRAGMENTATION(printf("%lu: FRG TX with fragmentID '%d' failed after %d fragments. Abort.\n\r",millis(),fragment_id,msgCount););
akashvibhute 4:75c5aa56411f 568 break;
akashvibhute 2:a5f8e04bd02b 569 }
akashvibhute 2:a5f8e04bd02b 570
akashvibhute 4:75c5aa56411f 571
akashvibhute 4:75c5aa56411f 572 //Message was successful sent
akashvibhute 4:75c5aa56411f 573 #if defined SERIAL_DEBUG_FRAGMENTATION_L2
akashvibhute 4:75c5aa56411f 574 printf("%lu: FRG message transmission with fragmentID '%d' sucessfull.\n\r",mainTimer.read_ms(),fragment_id);
akashvibhute 4:75c5aa56411f 575 #endif
akashvibhute 2:a5f8e04bd02b 576
akashvibhute 4:75c5aa56411f 577 }
akashvibhute 4:75c5aa56411f 578 header.type = type;
akashvibhute 4:75c5aa56411f 579 #if !defined (DUAL_HEAD_RADIO)
akashvibhute 4:75c5aa56411f 580 if(networkFlags & FLAG_FAST_FRAG){
akashvibhute 4:75c5aa56411f 581 ok = radio.txStandBy(txTimeout);
akashvibhute 4:75c5aa56411f 582 radio.startListening();
akashvibhute 4:75c5aa56411f 583 radio.setAutoAck(0,0);
akashvibhute 4:75c5aa56411f 584 }
akashvibhute 4:75c5aa56411f 585 networkFlags &= ~FLAG_FAST_FRAG;
akashvibhute 4:75c5aa56411f 586
akashvibhute 4:75c5aa56411f 587 if(!ok){
akashvibhute 4:75c5aa56411f 588 return false;
akashvibhute 4:75c5aa56411f 589 }
akashvibhute 4:75c5aa56411f 590 #endif
akashvibhute 4:75c5aa56411f 591 //int frag_delay = uint8_t(len/48);
akashvibhute 4:75c5aa56411f 592 //delay( rf24_min(len/48,20));
akashvibhute 2:a5f8e04bd02b 593
akashvibhute 4:75c5aa56411f 594 //Return true if all the chunks where sent successfully
akashvibhute 4:75c5aa56411f 595
akashvibhute 4:75c5aa56411f 596 IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG total message fragments sent %i. \n",mainTimer.read_ms(),msgCount); );
akashvibhute 4:75c5aa56411f 597 if(fragment_id > 0){
akashvibhute 4:75c5aa56411f 598 txTime = mainTimer.read_ms();
akashvibhute 4:75c5aa56411f 599 return false;
akashvibhute 4:75c5aa56411f 600 }
akashvibhute 4:75c5aa56411f 601 return true;
akashvibhute 4:75c5aa56411f 602
akashvibhute 2:a5f8e04bd02b 603 #endif //Fragmentation enabled
akashvibhute 2:a5f8e04bd02b 604 }
akashvibhute 0:c3db0798d9aa 605 /******************************************************************/
akashvibhute 0:c3db0798d9aa 606
akashvibhute 2:a5f8e04bd02b 607 bool RF24Network::_write(RF24NetworkHeader& header,const void* message, uint16_t len, uint16_t writeDirect)
akashvibhute 0:c3db0798d9aa 608 {
akashvibhute 4:75c5aa56411f 609 // Fill out the header
akashvibhute 4:75c5aa56411f 610 header.from_node = node_address;
akashvibhute 4:75c5aa56411f 611
akashvibhute 4:75c5aa56411f 612 // Build the full frame to send
akashvibhute 4:75c5aa56411f 613 memcpy(frame_buffer,&header,sizeof(RF24NetworkHeader));
akashvibhute 4:75c5aa56411f 614
akashvibhute 4:75c5aa56411f 615 IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Sending %s\n\r"),mainTimer.read_ms(),header.toString()));
akashvibhute 2:a5f8e04bd02b 616
akashvibhute 4:75c5aa56411f 617 if (len){
akashvibhute 4:75c5aa56411f 618 memcpy(frame_buffer + sizeof(RF24NetworkHeader),message,len);
akashvibhute 4:75c5aa56411f 619
akashvibhute 4:75c5aa56411f 620 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") ) );
akashvibhute 4:75c5aa56411f 621 }
akashvibhute 0:c3db0798d9aa 622
akashvibhute 4:75c5aa56411f 623 // If the user is trying to send it to himself
akashvibhute 4:75c5aa56411f 624 /*if ( header.to_node == node_address ){
akashvibhute 4:75c5aa56411f 625 #if defined (RF24_LINUX)
akashvibhute 4:75c5aa56411f 626 RF24NetworkFrame frame = RF24NetworkFrame(header,message,rf24_min(MAX_FRAME_SIZE-sizeof(RF24NetworkHeader),len));
akashvibhute 4:75c5aa56411f 627 #else
akashvibhute 4:75c5aa56411f 628 RF24NetworkFrame frame(header,len);
akashvibhute 4:75c5aa56411f 629 #endif
akashvibhute 4:75c5aa56411f 630 // Just queue it in the received queue
akashvibhute 4:75c5aa56411f 631 return enqueue(frame);
akashvibhute 4:75c5aa56411f 632 }*/
akashvibhute 4:75c5aa56411f 633 // Otherwise send it out over the air
akashvibhute 4:75c5aa56411f 634
akashvibhute 4:75c5aa56411f 635
akashvibhute 4:75c5aa56411f 636 if(writeDirect != 070){
akashvibhute 4:75c5aa56411f 637 uint8_t sendType = USER_TX_TO_LOGICAL_ADDRESS; // Payload is multicast to the first node, and routed normally to the next
akashvibhute 4:75c5aa56411f 638
akashvibhute 4:75c5aa56411f 639 if(header.to_node == 0100){
akashvibhute 4:75c5aa56411f 640 sendType = USER_TX_MULTICAST;
akashvibhute 4:75c5aa56411f 641 }
akashvibhute 4:75c5aa56411f 642 if(header.to_node == writeDirect){
akashvibhute 4:75c5aa56411f 643 sendType = USER_TX_TO_PHYSICAL_ADDRESS; // Payload is multicast to the first node, which is the recipient
akashvibhute 4:75c5aa56411f 644 }
akashvibhute 4:75c5aa56411f 645 return write(writeDirect,sendType);
akashvibhute 4:75c5aa56411f 646 }
akashvibhute 4:75c5aa56411f 647 return write(header.to_node,TX_NORMAL);
akashvibhute 4:75c5aa56411f 648
akashvibhute 0:c3db0798d9aa 649 }
akashvibhute 0:c3db0798d9aa 650
akashvibhute 0:c3db0798d9aa 651 /******************************************************************/
akashvibhute 0:c3db0798d9aa 652
akashvibhute 2:a5f8e04bd02b 653 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
akashvibhute 0:c3db0798d9aa 654 {
akashvibhute 4:75c5aa56411f 655 bool ok = false;
akashvibhute 4:75c5aa56411f 656 bool isAckType = false;
akashvibhute 4:75c5aa56411f 657 if(frame_buffer[6] > 64 && frame_buffer[6] < 192 ){ isAckType=true; }
akashvibhute 4:75c5aa56411f 658
akashvibhute 4:75c5aa56411f 659 /*if( ( (frame_buffer[7] % 2) && frame_buffer[6] == NETWORK_MORE_FRAGMENTS) ){
akashvibhute 4:75c5aa56411f 660 isAckType = 0;
akashvibhute 4:75c5aa56411f 661 }*/
akashvibhute 4:75c5aa56411f 662
akashvibhute 4:75c5aa56411f 663 // Throw it away if it's not a valid address
akashvibhute 4:75c5aa56411f 664 if ( !is_valid_address(to_node) )
akashvibhute 4:75c5aa56411f 665 return false;
akashvibhute 4:75c5aa56411f 666
akashvibhute 4:75c5aa56411f 667 //Load info into our conversion structure, and get the converted address info
akashvibhute 4:75c5aa56411f 668 logicalToPhysicalStruct conversion = { to_node,directTo,0};
akashvibhute 4:75c5aa56411f 669 logicalToPhysicalAddress(&conversion);
akashvibhute 4:75c5aa56411f 670
akashvibhute 3:dfc8da7ac18c 671
akashvibhute 4:75c5aa56411f 672 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));
akashvibhute 3:dfc8da7ac18c 673
akashvibhute 4:75c5aa56411f 674 /**Write it*/
akashvibhute 4:75c5aa56411f 675 ok=write_to_pipe(conversion.send_node, conversion.send_pipe, conversion.multicast);
akashvibhute 4:75c5aa56411f 676
akashvibhute 4:75c5aa56411f 677
akashvibhute 4:75c5aa56411f 678 if(!ok){
akashvibhute 2:a5f8e04bd02b 679
akashvibhute 4:75c5aa56411f 680 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););
akashvibhute 4:75c5aa56411f 681 }
akashvibhute 4:75c5aa56411f 682
akashvibhute 4:75c5aa56411f 683
akashvibhute 4:75c5aa56411f 684 if( directTo == TX_ROUTED && ok && conversion.send_node == to_node && isAckType){
akashvibhute 4:75c5aa56411f 685
akashvibhute 4:75c5aa56411f 686 RF24NetworkHeader* header = (RF24NetworkHeader*)&frame_buffer;
akashvibhute 4:75c5aa56411f 687 header->type = NETWORK_ACK; // Set the payload type to NETWORK_ACK
akashvibhute 4:75c5aa56411f 688 header->to_node = header->from_node; // Change the 'to' address to the 'from' address
akashvibhute 2:a5f8e04bd02b 689
akashvibhute 4:75c5aa56411f 690 conversion.send_node = header->from_node;
akashvibhute 4:75c5aa56411f 691 conversion.send_pipe = TX_ROUTED;
akashvibhute 4:75c5aa56411f 692 conversion.multicast = 0;
akashvibhute 4:75c5aa56411f 693 logicalToPhysicalAddress(&conversion);
akashvibhute 4:75c5aa56411f 694
akashvibhute 4:75c5aa56411f 695 //Write the data using the resulting physical address
akashvibhute 4:75c5aa56411f 696 frame_size = sizeof(RF24NetworkHeader);
akashvibhute 4:75c5aa56411f 697 write_to_pipe(conversion.send_node, conversion.send_pipe, conversion.multicast);
akashvibhute 4:75c5aa56411f 698
akashvibhute 4:75c5aa56411f 699 //dynLen=0;
akashvibhute 3:dfc8da7ac18c 700
akashvibhute 4:75c5aa56411f 701 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); );
akashvibhute 4:75c5aa56411f 702
akashvibhute 4:75c5aa56411f 703 }
akashvibhute 4:75c5aa56411f 704
akashvibhute 2:a5f8e04bd02b 705
akashvibhute 3:dfc8da7ac18c 706
akashvibhute 4:75c5aa56411f 707 if( ok && conversion.send_node != to_node && (directTo==0 || directTo==3) && isAckType){
akashvibhute 4:75c5aa56411f 708 #if !defined (DUAL_HEAD_RADIO)
akashvibhute 4:75c5aa56411f 709 // Now, continue listening
akashvibhute 4:75c5aa56411f 710 if(networkFlags & FLAG_FAST_FRAG){
akashvibhute 4:75c5aa56411f 711 radio.txStandBy(txTimeout);
akashvibhute 4:75c5aa56411f 712 networkFlags &= ~FLAG_FAST_FRAG;
akashvibhute 4:75c5aa56411f 713 radio.setAutoAck(0,0);
akashvibhute 4:75c5aa56411f 714 }
akashvibhute 4:75c5aa56411f 715 radio.startListening();
akashvibhute 4:75c5aa56411f 716 #endif
akashvibhute 4:75c5aa56411f 717 uint32_t reply_time = mainTimer.read_ms();
akashvibhute 0:c3db0798d9aa 718
akashvibhute 4:75c5aa56411f 719 while( update() != NETWORK_ACK){
akashvibhute 2:a5f8e04bd02b 720
akashvibhute 4:75c5aa56411f 721 if(mainTimer.read_ms() - reply_time > routeTimeout){
akashvibhute 4:75c5aa56411f 722
akashvibhute 4:75c5aa56411f 723 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); );
akashvibhute 0:c3db0798d9aa 724
akashvibhute 4:75c5aa56411f 725 ok=false;
akashvibhute 4:75c5aa56411f 726 break;
akashvibhute 4:75c5aa56411f 727 }
akashvibhute 4:75c5aa56411f 728 }
akashvibhute 2:a5f8e04bd02b 729 }
akashvibhute 4:75c5aa56411f 730 if( !(networkFlags & FLAG_FAST_FRAG) ){
akashvibhute 4:75c5aa56411f 731 #if !defined (DUAL_HEAD_RADIO)
akashvibhute 4:75c5aa56411f 732 // Now, continue listening
akashvibhute 4:75c5aa56411f 733 radio.startListening();
akashvibhute 4:75c5aa56411f 734 #endif
akashvibhute 4:75c5aa56411f 735 }
akashvibhute 2:a5f8e04bd02b 736
akashvibhute 2:a5f8e04bd02b 737 #if defined ENABLE_NETWORK_STATS
akashvibhute 4:75c5aa56411f 738 if(ok == true){
akashvibhute 4:75c5aa56411f 739 ++nOK;
akashvibhute 4:75c5aa56411f 740 }else{ ++nFails;
akashvibhute 4:75c5aa56411f 741 }
akashvibhute 0:c3db0798d9aa 742 #endif
akashvibhute 4:75c5aa56411f 743 return ok;
akashvibhute 0:c3db0798d9aa 744 }
akashvibhute 0:c3db0798d9aa 745
akashvibhute 0:c3db0798d9aa 746 /******************************************************************/
akashvibhute 0:c3db0798d9aa 747
akashvibhute 4:75c5aa56411f 748 // Provided the to_node and directTo option, it will return the resulting node and pipe
akashvibhute 4:75c5aa56411f 749 bool RF24Network::logicalToPhysicalAddress(logicalToPhysicalStruct *conversionInfo){
akashvibhute 3:dfc8da7ac18c 750
akashvibhute 4:75c5aa56411f 751 //Create pointers so this makes sense.. kind of
akashvibhute 4:75c5aa56411f 752 //We take in the to_node(logical) now, at the end of the function, output the send_node(physical) address, etc.
akashvibhute 4:75c5aa56411f 753 //back to the original memory address that held the logical information.
akashvibhute 4:75c5aa56411f 754 uint16_t *to_node = &conversionInfo->send_node;
akashvibhute 4:75c5aa56411f 755 uint8_t *directTo = &conversionInfo->send_pipe;
akashvibhute 4:75c5aa56411f 756 bool *multicast = &conversionInfo->multicast;
akashvibhute 4:75c5aa56411f 757
akashvibhute 4:75c5aa56411f 758 // Where do we send this? By default, to our parent
akashvibhute 4:75c5aa56411f 759 uint16_t pre_conversion_send_node = parent_node;
akashvibhute 3:dfc8da7ac18c 760
akashvibhute 4:75c5aa56411f 761 // On which pipe
akashvibhute 4:75c5aa56411f 762 uint8_t pre_conversion_send_pipe = parent_pipe;
akashvibhute 4:75c5aa56411f 763
akashvibhute 4:75c5aa56411f 764 if(*directTo > TX_ROUTED ){
akashvibhute 4:75c5aa56411f 765 pre_conversion_send_node = *to_node;
akashvibhute 4:75c5aa56411f 766 *multicast = 1;
akashvibhute 4:75c5aa56411f 767 //if(*directTo == USER_TX_MULTICAST || *directTo == USER_TX_TO_PHYSICAL_ADDRESS){
akashvibhute 4:75c5aa56411f 768 pre_conversion_send_pipe=0;
akashvibhute 4:75c5aa56411f 769 //}
akashvibhute 4:75c5aa56411f 770 }
akashvibhute 4:75c5aa56411f 771 // If the node is a direct child,
akashvibhute 4:75c5aa56411f 772 else
akashvibhute 4:75c5aa56411f 773 if ( is_direct_child(*to_node) )
akashvibhute 4:75c5aa56411f 774 {
akashvibhute 4:75c5aa56411f 775 // Send directly
akashvibhute 4:75c5aa56411f 776 pre_conversion_send_node = *to_node;
akashvibhute 4:75c5aa56411f 777 // To its listening pipe
akashvibhute 4:75c5aa56411f 778 pre_conversion_send_pipe = 5;
akashvibhute 4:75c5aa56411f 779 }
akashvibhute 4:75c5aa56411f 780 // If the node is a child of a child
akashvibhute 4:75c5aa56411f 781 // talk on our child's listening pipe,
akashvibhute 4:75c5aa56411f 782 // and let the direct child relay it.
akashvibhute 4:75c5aa56411f 783 else if ( is_descendant(*to_node) )
akashvibhute 4:75c5aa56411f 784 {
akashvibhute 4:75c5aa56411f 785 pre_conversion_send_node = direct_child_route_to(*to_node);
akashvibhute 4:75c5aa56411f 786 pre_conversion_send_pipe = 5;
akashvibhute 4:75c5aa56411f 787 }
akashvibhute 4:75c5aa56411f 788
akashvibhute 4:75c5aa56411f 789 *to_node = pre_conversion_send_node;
akashvibhute 4:75c5aa56411f 790 *directTo = pre_conversion_send_pipe;
akashvibhute 4:75c5aa56411f 791
akashvibhute 4:75c5aa56411f 792 return 1;
akashvibhute 4:75c5aa56411f 793
akashvibhute 2:a5f8e04bd02b 794 }
akashvibhute 2:a5f8e04bd02b 795
akashvibhute 2:a5f8e04bd02b 796 /********************************************************/
akashvibhute 2:a5f8e04bd02b 797
akashvibhute 4:75c5aa56411f 798
akashvibhute 2:a5f8e04bd02b 799 bool RF24Network::write_to_pipe( uint16_t node, uint8_t pipe, bool multicast )
akashvibhute 0:c3db0798d9aa 800 {
akashvibhute 4:75c5aa56411f 801 bool ok = false;
akashvibhute 4:75c5aa56411f 802 uint64_t out_pipe = pipe_address( node, pipe );
akashvibhute 4:75c5aa56411f 803
akashvibhute 4:75c5aa56411f 804 #if !defined (DUAL_HEAD_RADIO)
akashvibhute 4:75c5aa56411f 805 // Open the correct pipe for writing.
akashvibhute 4:75c5aa56411f 806 // First, stop listening so we can talk
akashvibhute 0:c3db0798d9aa 807
akashvibhute 4:75c5aa56411f 808 if(!(networkFlags & FLAG_FAST_FRAG)){
akashvibhute 4:75c5aa56411f 809 radio.stopListening();
akashvibhute 4:75c5aa56411f 810 }
akashvibhute 4:75c5aa56411f 811
akashvibhute 4:75c5aa56411f 812 if(multicast){ radio.setAutoAck(0,0);}else{radio.setAutoAck(0,1);}
akashvibhute 4:75c5aa56411f 813
akashvibhute 4:75c5aa56411f 814 radio.openWritingPipe(out_pipe);
akashvibhute 3:dfc8da7ac18c 815
akashvibhute 4:75c5aa56411f 816 ok = radio.writeFast(frame_buffer, frame_size,multicast);
akashvibhute 4:75c5aa56411f 817
akashvibhute 4:75c5aa56411f 818 if(!(networkFlags & FLAG_FAST_FRAG)){
akashvibhute 3:dfc8da7ac18c 819 ok = radio.txStandBy(txTimeout);
akashvibhute 3:dfc8da7ac18c 820 radio.setAutoAck(0,0);
akashvibhute 4:75c5aa56411f 821 }
akashvibhute 4:75c5aa56411f 822
akashvibhute 2:a5f8e04bd02b 823 #else
akashvibhute 4:75c5aa56411f 824 radio1.openWritingPipe(out_pipe);
akashvibhute 4:75c5aa56411f 825 radio1.writeFast(frame_buffer, frame_size);
akashvibhute 4:75c5aa56411f 826 ok = radio1.txStandBy(txTimeout,multicast);
akashvibhute 0:c3db0798d9aa 827
akashvibhute 2:a5f8e04bd02b 828 #endif
akashvibhute 2:a5f8e04bd02b 829
akashvibhute 4:75c5aa56411f 830 /* #if defined (__arm__) || defined (RF24_LINUX)
akashvibhute 4:75c5aa56411f 831 IF_SERIAL_DEBUG(printf_P(PSTR("%u: MAC Sent on %x %s\n\r"),millis(),(uint32_t)out_pipe,ok?PSTR("ok"):PSTR("failed")));
akashvibhute 4:75c5aa56411f 832 #else
akashvibhute 4:75c5aa56411f 833 IF_SERIAL_DEBUG(printf_P(PSTR("%lu: MAC Sent on %lx %S\n\r"),millis(),(uint32_t)out_pipe,ok?PSTR("ok"):PSTR("failed")));
akashvibhute 4:75c5aa56411f 834 #endif
akashvibhute 4:75c5aa56411f 835 */
akashvibhute 4:75c5aa56411f 836 return ok;
akashvibhute 0:c3db0798d9aa 837 }
akashvibhute 0:c3db0798d9aa 838
akashvibhute 0:c3db0798d9aa 839 /******************************************************************/
akashvibhute 0:c3db0798d9aa 840
akashvibhute 0:c3db0798d9aa 841 const char* RF24NetworkHeader::toString(void) const
akashvibhute 0:c3db0798d9aa 842 {
akashvibhute 4:75c5aa56411f 843 static char buffer[45];
akashvibhute 4:75c5aa56411f 844 //snprintf_P(buffer,sizeof(buffer),PSTR("id %04x from 0%o to 0%o type %c"),id,from_node,to_node,type);
akashvibhute 4:75c5aa56411f 845 //sprintf_P(buffer,PSTR("id %u from 0%o to 0%o type %d"),id,from_node,to_node,type);
akashvibhute 4:75c5aa56411f 846 return buffer;
akashvibhute 0:c3db0798d9aa 847 }
akashvibhute 0:c3db0798d9aa 848
akashvibhute 0:c3db0798d9aa 849 /******************************************************************/
akashvibhute 0:c3db0798d9aa 850
akashvibhute 0:c3db0798d9aa 851 bool RF24Network::is_direct_child( uint16_t node )
akashvibhute 0:c3db0798d9aa 852 {
akashvibhute 4:75c5aa56411f 853 bool result = false;
akashvibhute 0:c3db0798d9aa 854
akashvibhute 4:75c5aa56411f 855 // A direct child of ours has the same low numbers as us, and only
akashvibhute 4:75c5aa56411f 856 // one higher number.
akashvibhute 4:75c5aa56411f 857 //
akashvibhute 4:75c5aa56411f 858 // e.g. node 0234 is a direct child of 034, and node 01234 is a
akashvibhute 4:75c5aa56411f 859 // descendant but not a direct child
akashvibhute 0:c3db0798d9aa 860
akashvibhute 4:75c5aa56411f 861 // First, is it even a descendant?
akashvibhute 4:75c5aa56411f 862 if ( is_descendant(node) )
akashvibhute 4:75c5aa56411f 863 {
akashvibhute 4:75c5aa56411f 864 // Does it only have ONE more level than us?
akashvibhute 4:75c5aa56411f 865 uint16_t child_node_mask = ( ~ node_mask ) << 3;
akashvibhute 4:75c5aa56411f 866 result = ( node & child_node_mask ) == 0 ;
akashvibhute 4:75c5aa56411f 867 }
akashvibhute 4:75c5aa56411f 868 return result;
akashvibhute 0:c3db0798d9aa 869 }
akashvibhute 0:c3db0798d9aa 870
akashvibhute 0:c3db0798d9aa 871 /******************************************************************/
akashvibhute 0:c3db0798d9aa 872
akashvibhute 0:c3db0798d9aa 873 bool RF24Network::is_descendant( uint16_t node )
akashvibhute 0:c3db0798d9aa 874 {
akashvibhute 4:75c5aa56411f 875 return ( node & node_mask ) == node_address;
akashvibhute 0:c3db0798d9aa 876 }
akashvibhute 0:c3db0798d9aa 877
akashvibhute 0:c3db0798d9aa 878 /******************************************************************/
akashvibhute 0:c3db0798d9aa 879
akashvibhute 0:c3db0798d9aa 880 void RF24Network::setup_address(void)
akashvibhute 0:c3db0798d9aa 881 {
akashvibhute 4:75c5aa56411f 882 // First, establish the node_mask
akashvibhute 4:75c5aa56411f 883 uint16_t node_mask_check = 0xFFFF;
akashvibhute 4:75c5aa56411f 884 #if defined (RF24NetworkMulticast)
akashvibhute 4:75c5aa56411f 885 uint8_t count = 0;
akashvibhute 4:75c5aa56411f 886 #endif
akashvibhute 4:75c5aa56411f 887
akashvibhute 4:75c5aa56411f 888 while ( node_address & node_mask_check ){
akashvibhute 4:75c5aa56411f 889 node_mask_check <<= 3;
akashvibhute 4:75c5aa56411f 890 #if defined (RF24NetworkMulticast)
akashvibhute 4:75c5aa56411f 891 count++;
akashvibhute 4:75c5aa56411f 892 }
akashvibhute 4:75c5aa56411f 893 multicast_level = count;
akashvibhute 4:75c5aa56411f 894 #else
akashvibhute 4:75c5aa56411f 895 }
akashvibhute 4:75c5aa56411f 896 #endif
akashvibhute 4:75c5aa56411f 897
akashvibhute 4:75c5aa56411f 898 node_mask = ~ node_mask_check;
akashvibhute 0:c3db0798d9aa 899
akashvibhute 4:75c5aa56411f 900 // parent mask is the next level down
akashvibhute 4:75c5aa56411f 901 uint16_t parent_mask = node_mask >> 3;
akashvibhute 0:c3db0798d9aa 902
akashvibhute 4:75c5aa56411f 903 // parent node is the part IN the mask
akashvibhute 4:75c5aa56411f 904 parent_node = node_address & parent_mask;
akashvibhute 0:c3db0798d9aa 905
akashvibhute 4:75c5aa56411f 906 // parent pipe is the part OUT of the mask
akashvibhute 4:75c5aa56411f 907 uint16_t i = node_address;
akashvibhute 4:75c5aa56411f 908 uint16_t m = parent_mask;
akashvibhute 4:75c5aa56411f 909 while (m)
akashvibhute 4:75c5aa56411f 910 {
akashvibhute 4:75c5aa56411f 911 i >>= 3;
akashvibhute 4:75c5aa56411f 912 m >>= 3;
akashvibhute 4:75c5aa56411f 913 }
akashvibhute 4:75c5aa56411f 914 parent_pipe = i;
akashvibhute 0:c3db0798d9aa 915
akashvibhute 4:75c5aa56411f 916 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););
akashvibhute 2:a5f8e04bd02b 917
akashvibhute 2:a5f8e04bd02b 918 }
akashvibhute 2:a5f8e04bd02b 919
akashvibhute 2:a5f8e04bd02b 920 /******************************************************************/
akashvibhute 2:a5f8e04bd02b 921 uint16_t RF24Network::addressOfPipe( uint16_t node, uint8_t pipeNo )
akashvibhute 2:a5f8e04bd02b 922 {
akashvibhute 4:75c5aa56411f 923 //Say this node is 013 (1011), mask is 077 or (00111111)
akashvibhute 4:75c5aa56411f 924 //Say we want to use pipe 3 (11)
akashvibhute 4:75c5aa56411f 925 //6 bits in node mask, so shift pipeNo 6 times left and | into address
akashvibhute 4:75c5aa56411f 926 uint16_t m = node_mask >> 3;
akashvibhute 4:75c5aa56411f 927 uint8_t i=0;
akashvibhute 4:75c5aa56411f 928
akashvibhute 4:75c5aa56411f 929 while (m){ //While there are bits left in the node mask
akashvibhute 4:75c5aa56411f 930 m>>=1; //Shift to the right
akashvibhute 4:75c5aa56411f 931 i++; //Count the # of increments
akashvibhute 4:75c5aa56411f 932 }
akashvibhute 4:75c5aa56411f 933 return node | (pipeNo << i);
akashvibhute 0:c3db0798d9aa 934 }
akashvibhute 0:c3db0798d9aa 935
akashvibhute 0:c3db0798d9aa 936 /******************************************************************/
akashvibhute 0:c3db0798d9aa 937
akashvibhute 0:c3db0798d9aa 938 uint16_t RF24Network::direct_child_route_to( uint16_t node )
akashvibhute 0:c3db0798d9aa 939 {
akashvibhute 4:75c5aa56411f 940 // Presumes that this is in fact a child!!
akashvibhute 4:75c5aa56411f 941 uint16_t child_mask = ( node_mask << 3 ) | 0B111;
akashvibhute 4:75c5aa56411f 942 return node & child_mask;
akashvibhute 4:75c5aa56411f 943
akashvibhute 0:c3db0798d9aa 944 }
akashvibhute 0:c3db0798d9aa 945
akashvibhute 0:c3db0798d9aa 946 /******************************************************************/
akashvibhute 2:a5f8e04bd02b 947 /*
akashvibhute 0:c3db0798d9aa 948 uint8_t RF24Network::pipe_to_descendant( uint16_t node )
akashvibhute 0:c3db0798d9aa 949 {
akashvibhute 4:75c5aa56411f 950 uint16_t i = node;
akashvibhute 0:c3db0798d9aa 951 uint16_t m = node_mask;
akashvibhute 2:a5f8e04bd02b 952
akashvibhute 0:c3db0798d9aa 953 while (m)
akashvibhute 0:c3db0798d9aa 954 {
akashvibhute 0:c3db0798d9aa 955 i >>= 3;
akashvibhute 0:c3db0798d9aa 956 m >>= 3;
akashvibhute 0:c3db0798d9aa 957 }
akashvibhute 0:c3db0798d9aa 958
akashvibhute 2:a5f8e04bd02b 959 return i & 0B111;
akashvibhute 2:a5f8e04bd02b 960 }*/
akashvibhute 0:c3db0798d9aa 961
akashvibhute 0:c3db0798d9aa 962 /******************************************************************/
akashvibhute 0:c3db0798d9aa 963
akashvibhute 2:a5f8e04bd02b 964 bool RF24Network::is_valid_address( uint16_t node )
akashvibhute 0:c3db0798d9aa 965 {
akashvibhute 4:75c5aa56411f 966 bool result = true;
akashvibhute 0:c3db0798d9aa 967
akashvibhute 4:75c5aa56411f 968 while(node)
akashvibhute 4:75c5aa56411f 969 {
akashvibhute 4:75c5aa56411f 970 uint8_t digit = node & 0B111;
akashvibhute 4:75c5aa56411f 971 #if !defined (RF24NetworkMulticast)
akashvibhute 4:75c5aa56411f 972 if (digit < 1 || digit > 5)
akashvibhute 4:75c5aa56411f 973 #else
akashvibhute 4:75c5aa56411f 974 if (digit < 0 || digit > 5) //Allow our out of range multicast address
akashvibhute 4:75c5aa56411f 975 #endif
akashvibhute 4:75c5aa56411f 976 {
akashvibhute 4:75c5aa56411f 977 result = false;
akashvibhute 4:75c5aa56411f 978 IF_SERIAL_DEBUG_MINIMAL(printf_P(PSTR("*** WARNING *** Invalid address 0%o\n\r"),node););
akashvibhute 4:75c5aa56411f 979 break;
akashvibhute 0:c3db0798d9aa 980 }
akashvibhute 4:75c5aa56411f 981 node >>= 3;
akashvibhute 4:75c5aa56411f 982 }
akashvibhute 0:c3db0798d9aa 983
akashvibhute 4:75c5aa56411f 984 return result;
akashvibhute 0:c3db0798d9aa 985 }
akashvibhute 0:c3db0798d9aa 986
akashvibhute 0:c3db0798d9aa 987 /******************************************************************/
akashvibhute 2:a5f8e04bd02b 988 #if defined (RF24NetworkMulticast)
akashvibhute 4:75c5aa56411f 989 void RF24Network::multicastLevel(uint8_t level){
akashvibhute 4:75c5aa56411f 990 multicast_level = level;
akashvibhute 4:75c5aa56411f 991 //radio.stopListening();
akashvibhute 4:75c5aa56411f 992 radio.openReadingPipe(0,pipe_address(levelToAddress(level),0));
akashvibhute 4:75c5aa56411f 993 //radio.startListening();
akashvibhute 4:75c5aa56411f 994 }
akashvibhute 4:75c5aa56411f 995
akashvibhute 4:75c5aa56411f 996 uint16_t levelToAddress(uint8_t level){
akashvibhute 4:75c5aa56411f 997
akashvibhute 4:75c5aa56411f 998 uint16_t levelAddr = 1;
akashvibhute 4:75c5aa56411f 999 if(level){
akashvibhute 4:75c5aa56411f 1000 levelAddr = levelAddr << ((level-1) * 3);
akashvibhute 4:75c5aa56411f 1001 }else{
akashvibhute 4:75c5aa56411f 1002 return 0;
akashvibhute 4:75c5aa56411f 1003 }
akashvibhute 4:75c5aa56411f 1004 return levelAddr;
akashvibhute 4:75c5aa56411f 1005 }
akashvibhute 2:a5f8e04bd02b 1006 #endif
akashvibhute 2:a5f8e04bd02b 1007 /******************************************************************/
akashvibhute 0:c3db0798d9aa 1008
akashvibhute 0:c3db0798d9aa 1009 uint64_t pipe_address( uint16_t node, uint8_t pipe )
akashvibhute 0:c3db0798d9aa 1010 {
akashvibhute 4:75c5aa56411f 1011
akashvibhute 4:75c5aa56411f 1012 static uint8_t address_translation[] = { 0xc3,0x3c,0x33,0xce,0x3e,0xe3,0xec };
akashvibhute 4:75c5aa56411f 1013 uint64_t result = 0xCCCCCCCCCCLL;
akashvibhute 4:75c5aa56411f 1014 uint8_t* out = reinterpret_cast<uint8_t*>(&result);
akashvibhute 4:75c5aa56411f 1015
akashvibhute 4:75c5aa56411f 1016 // Translate the address to use our optimally chosen radio address bytes
akashvibhute 4:75c5aa56411f 1017 uint8_t count = 1; uint16_t dec = node;
akashvibhute 3:dfc8da7ac18c 1018
akashvibhute 4:75c5aa56411f 1019 while(dec){
akashvibhute 4:75c5aa56411f 1020 #if defined (RF24NetworkMulticast)
akashvibhute 4:75c5aa56411f 1021 if(pipe != 0 || !node)
akashvibhute 4:75c5aa56411f 1022 #endif
akashvibhute 4:75c5aa56411f 1023 out[count]=address_translation[(dec % 8)]; // Convert our decimal values to octal, translate them to address bytes, and set our address
akashvibhute 4:75c5aa56411f 1024
akashvibhute 4:75c5aa56411f 1025 dec /= 8;
akashvibhute 4:75c5aa56411f 1026 count++;
akashvibhute 4:75c5aa56411f 1027 }
akashvibhute 4:75c5aa56411f 1028
akashvibhute 4:75c5aa56411f 1029 #if defined (RF24NetworkMulticast)
akashvibhute 4:75c5aa56411f 1030 if(pipe != 0 || !node)
akashvibhute 4:75c5aa56411f 1031 #endif
akashvibhute 4:75c5aa56411f 1032 out[0] = address_translation[pipe];
akashvibhute 4:75c5aa56411f 1033 #if defined (RF24NetworkMulticast)
akashvibhute 4:75c5aa56411f 1034 else
akashvibhute 4:75c5aa56411f 1035 out[1] = address_translation[count-1];
akashvibhute 4:75c5aa56411f 1036 #endif
akashvibhute 0:c3db0798d9aa 1037
akashvibhute 4:75c5aa56411f 1038
akashvibhute 4:75c5aa56411f 1039
akashvibhute 0:c3db0798d9aa 1040
akashvibhute 4:75c5aa56411f 1041 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));
akashvibhute 0:c3db0798d9aa 1042
akashvibhute 4:75c5aa56411f 1043
akashvibhute 4:75c5aa56411f 1044 return result;
akashvibhute 0:c3db0798d9aa 1045 }
akashvibhute 0:c3db0798d9aa 1046
akashvibhute 2:a5f8e04bd02b 1047
akashvibhute 2:a5f8e04bd02b 1048 /************************ Sleep Mode ******************************************/
akashvibhute 2:a5f8e04bd02b 1049
akashvibhute 2:a5f8e04bd02b 1050
akashvibhute 4:75c5aa56411f 1051 /**/
akashvibhute 2:a5f8e04bd02b 1052
akashvibhute 2:a5f8e04bd02b 1053