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 Nov 05 05:40:44 2015 +0000
Revision:
2:a5f8e04bd02b
Parent:
1:caf146ffe8b0
Child:
3:dfc8da7ac18c
Updated with TMRh20's RF24 library on Nov/04/2015 from https://github.com/TMRh20; Porting completed on Nov/05/2015

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