fd
Dependents: xtoff3 CYS_Receiver
Fork of RF24Network by
RF24Network.cpp@2:a5f8e04bd02b, 2015-11-05 (annotated)
- 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?
User | Revision | Line number | New 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 |