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:54:47 2015 +0000
Revision:
3:dfc8da7ac18c
Parent:
2:a5f8e04bd02b
Child:
4:75c5aa56411f
general code cleanup after updating library

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