Ported Arduino RF24Network library.

Committer:
zcw607
Date:
Mon Mar 09 21:23:56 2015 +0000
Revision:
1:b5836d9f8de5
Parent:
0:df0a8886a0e9
Clean up errors

Who changed what in which revision?

UserRevisionLine numberNew contents of line
zcw607 0:df0a8886a0e9 1 /*
zcw607 0:df0a8886a0e9 2 Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
zcw607 0:df0a8886a0e9 3
zcw607 0:df0a8886a0e9 4 This program is free software; you can redistribute it and/or
zcw607 0:df0a8886a0e9 5 modify it under the terms of the GNU General Public License
zcw607 0:df0a8886a0e9 6 version 2 as published by the Free Software Foundation.
zcw607 0:df0a8886a0e9 7 */
zcw607 0:df0a8886a0e9 8
zcw607 0:df0a8886a0e9 9 #include "RF24Network_config.h"
zcw607 0:df0a8886a0e9 10 #include "RF24.h"
zcw607 0:df0a8886a0e9 11 #include "RF24Network.h"
zcw607 0:df0a8886a0e9 12
zcw607 0:df0a8886a0e9 13 uint16_t RF24NetworkHeader::next_id = 1;
zcw607 0:df0a8886a0e9 14
zcw607 0:df0a8886a0e9 15 uint64_t pipe_address( uint16_t node, uint8_t pipe );
zcw607 0:df0a8886a0e9 16 bool is_valid_address( uint16_t node );
zcw607 0:df0a8886a0e9 17
zcw607 0:df0a8886a0e9 18 /******************************************************************/
zcw607 0:df0a8886a0e9 19
zcw607 0:df0a8886a0e9 20 RF24Network::RF24Network( RF24& _radio ): radio(_radio), next_frame(frame_queue)
zcw607 0:df0a8886a0e9 21 {
zcw607 0:df0a8886a0e9 22 }
zcw607 0:df0a8886a0e9 23
zcw607 0:df0a8886a0e9 24 /******************************************************************/
zcw607 0:df0a8886a0e9 25
zcw607 0:df0a8886a0e9 26 void RF24Network::begin(uint8_t _channel, uint16_t _node_address )
zcw607 0:df0a8886a0e9 27 {
zcw607 0:df0a8886a0e9 28 if (! is_valid_address(_node_address) )
zcw607 0:df0a8886a0e9 29 return;
zcw607 0:df0a8886a0e9 30
zcw607 0:df0a8886a0e9 31 node_address = _node_address;
zcw607 0:df0a8886a0e9 32
zcw607 0:df0a8886a0e9 33 // Set up the radio the way we want it to look
zcw607 0:df0a8886a0e9 34 radio.setChannel(_channel);
zcw607 0:df0a8886a0e9 35 radio.setDataRate(RF24_1MBPS);
zcw607 0:df0a8886a0e9 36 radio.setCRCLength(RF24_CRC_16);
zcw607 0:df0a8886a0e9 37
zcw607 0:df0a8886a0e9 38 // Setup our address helper cache
zcw607 0:df0a8886a0e9 39 setup_address();
zcw607 0:df0a8886a0e9 40
zcw607 0:df0a8886a0e9 41 // Open up all listening pipes
zcw607 0:df0a8886a0e9 42 int i = 6;
zcw607 0:df0a8886a0e9 43 while (i--)
zcw607 0:df0a8886a0e9 44 radio.openReadingPipe(i,pipe_address(_node_address,i));
zcw607 0:df0a8886a0e9 45 radio.startListening();
zcw607 0:df0a8886a0e9 46
zcw607 0:df0a8886a0e9 47 // Spew debugging state about the radio
zcw607 0:df0a8886a0e9 48 radio.printDetails();
zcw607 0:df0a8886a0e9 49 }
zcw607 0:df0a8886a0e9 50
zcw607 0:df0a8886a0e9 51 /******************************************************************/
zcw607 0:df0a8886a0e9 52
zcw607 0:df0a8886a0e9 53 void RF24Network::update(void)
zcw607 0:df0a8886a0e9 54 {
zcw607 0:df0a8886a0e9 55 // if there is data ready
zcw607 0:df0a8886a0e9 56 uint8_t pipe_num;
zcw607 0:df0a8886a0e9 57 while ( radio.available(&pipe_num) )
zcw607 0:df0a8886a0e9 58 {
zcw607 0:df0a8886a0e9 59 // Dump the payloads until we've gotten everything
zcw607 1:b5836d9f8de5 60 bool done = false;
zcw607 0:df0a8886a0e9 61 while (!done)
zcw607 0:df0a8886a0e9 62 {
zcw607 0:df0a8886a0e9 63 // Fetch the payload, and see if this was the last one.
zcw607 0:df0a8886a0e9 64 done = radio.read( frame_buffer, sizeof(frame_buffer) );
zcw607 0:df0a8886a0e9 65
zcw607 0:df0a8886a0e9 66 // Read the beginning of the frame as the header
zcw607 0:df0a8886a0e9 67 const RF24NetworkHeader& header = * reinterpret_cast<RF24NetworkHeader*>(frame_buffer);
zcw607 0:df0a8886a0e9 68
zcw607 1:b5836d9f8de5 69 //IF_SERIAL_DEBUG(printf_P(PSTR("%lu: MAC Received on %u %s\n\r"),millis(),pipe_num,header.toString()));
zcw607 1:b5836d9f8de5 70 //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));
zcw607 0:df0a8886a0e9 71
zcw607 0:df0a8886a0e9 72 // Throw it away if it's not a valid address
zcw607 0:df0a8886a0e9 73 if ( !is_valid_address(header.to_node) )
zcw607 0:df0a8886a0e9 74 continue;
zcw607 0:df0a8886a0e9 75
zcw607 0:df0a8886a0e9 76 // Is this for us?
zcw607 0:df0a8886a0e9 77 if ( header.to_node == node_address )
zcw607 0:df0a8886a0e9 78 // Add it to the buffer of frames for us
zcw607 0:df0a8886a0e9 79 enqueue();
zcw607 0:df0a8886a0e9 80 else
zcw607 0:df0a8886a0e9 81 // Relay it
zcw607 0:df0a8886a0e9 82 write(header.to_node);
zcw607 0:df0a8886a0e9 83
zcw607 0:df0a8886a0e9 84 // NOT NEEDED anymore. Now all reading pipes are open to start.
zcw607 0:df0a8886a0e9 85 #if 0
zcw607 0:df0a8886a0e9 86 // If this was for us, from one of our children, but on our listening
zcw607 0:df0a8886a0e9 87 // pipe, it could mean that we are not listening to them. If so, open up
zcw607 0:df0a8886a0e9 88 // and listen to their talking pipe
zcw607 0:df0a8886a0e9 89
zcw607 0:df0a8886a0e9 90 if ( header.to_node == node_address && pipe_num == 0 && is_descendant(header.from_node) )
zcw607 0:df0a8886a0e9 91 {
zcw607 0:df0a8886a0e9 92 uint8_t pipe = pipe_to_descendant(header.from_node);
zcw607 0:df0a8886a0e9 93 radio.openReadingPipe(pipe,pipe_address(node_address,pipe));
zcw607 0:df0a8886a0e9 94
zcw607 0:df0a8886a0e9 95 // Also need to open pipe 1 so the system can get the full 5-byte address of the pipe.
zcw607 0:df0a8886a0e9 96 radio.openReadingPipe(1,pipe_address(node_address,1));
zcw607 0:df0a8886a0e9 97 }
zcw607 0:df0a8886a0e9 98 #endif
zcw607 0:df0a8886a0e9 99 }
zcw607 0:df0a8886a0e9 100 }
zcw607 0:df0a8886a0e9 101 }
zcw607 0:df0a8886a0e9 102
zcw607 0:df0a8886a0e9 103 /******************************************************************/
zcw607 0:df0a8886a0e9 104
zcw607 0:df0a8886a0e9 105 bool RF24Network::enqueue(void)
zcw607 0:df0a8886a0e9 106 {
zcw607 0:df0a8886a0e9 107 bool result = false;
zcw607 0:df0a8886a0e9 108
zcw607 1:b5836d9f8de5 109 //IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Enqueue @%x "),millis(),next_frame-frame_queue));
zcw607 0:df0a8886a0e9 110
zcw607 0:df0a8886a0e9 111 // Copy the current frame into the frame queue
zcw607 0:df0a8886a0e9 112 if ( next_frame < frame_queue + sizeof(frame_queue) )
zcw607 0:df0a8886a0e9 113 {
zcw607 0:df0a8886a0e9 114 memcpy(next_frame,frame_buffer, frame_size );
zcw607 0:df0a8886a0e9 115 next_frame += frame_size;
zcw607 0:df0a8886a0e9 116
zcw607 0:df0a8886a0e9 117 result = true;
zcw607 1:b5836d9f8de5 118 //IF_SERIAL_DEBUG(printf_P(PSTR("ok\n\r")));
zcw607 0:df0a8886a0e9 119 }
zcw607 0:df0a8886a0e9 120 else
zcw607 0:df0a8886a0e9 121 {
zcw607 1:b5836d9f8de5 122 //IF_SERIAL_DEBUG(printf_P(PSTR("failed\n\r")));
zcw607 0:df0a8886a0e9 123 }
zcw607 0:df0a8886a0e9 124
zcw607 0:df0a8886a0e9 125 return result;
zcw607 0:df0a8886a0e9 126 }
zcw607 0:df0a8886a0e9 127
zcw607 0:df0a8886a0e9 128 /******************************************************************/
zcw607 0:df0a8886a0e9 129
zcw607 0:df0a8886a0e9 130 bool RF24Network::available(void)
zcw607 0:df0a8886a0e9 131 {
zcw607 0:df0a8886a0e9 132 // Are there frames on the queue for us?
zcw607 0:df0a8886a0e9 133 return (next_frame > frame_queue);
zcw607 0:df0a8886a0e9 134 }
zcw607 0:df0a8886a0e9 135
zcw607 0:df0a8886a0e9 136 /******************************************************************/
zcw607 0:df0a8886a0e9 137
zcw607 0:df0a8886a0e9 138 void RF24Network::peek(RF24NetworkHeader& header)
zcw607 0:df0a8886a0e9 139 {
zcw607 0:df0a8886a0e9 140 if ( available() )
zcw607 0:df0a8886a0e9 141 {
zcw607 0:df0a8886a0e9 142 // Copy the next available frame from the queue into the provided buffer
zcw607 0:df0a8886a0e9 143 memcpy(&header,next_frame-frame_size,sizeof(RF24NetworkHeader));
zcw607 0:df0a8886a0e9 144 }
zcw607 0:df0a8886a0e9 145 }
zcw607 0:df0a8886a0e9 146
zcw607 0:df0a8886a0e9 147 /******************************************************************/
zcw607 0:df0a8886a0e9 148
zcw607 0:df0a8886a0e9 149 size_t RF24Network::read(RF24NetworkHeader& header,void* message, size_t maxlen)
zcw607 0:df0a8886a0e9 150 {
zcw607 0:df0a8886a0e9 151 size_t bufsize = 0;
zcw607 0:df0a8886a0e9 152
zcw607 0:df0a8886a0e9 153 if ( available() )
zcw607 0:df0a8886a0e9 154 {
zcw607 0:df0a8886a0e9 155 // Move the pointer back one in the queue
zcw607 0:df0a8886a0e9 156 next_frame -= frame_size;
zcw607 0:df0a8886a0e9 157 uint8_t* frame = next_frame;
zcw607 0:df0a8886a0e9 158
zcw607 0:df0a8886a0e9 159 // How much buffer size should we actually copy?
zcw607 0:df0a8886a0e9 160 bufsize = min(maxlen,frame_size-sizeof(RF24NetworkHeader));
zcw607 0:df0a8886a0e9 161
zcw607 0:df0a8886a0e9 162 // Copy the next available frame from the queue into the provided buffer
zcw607 0:df0a8886a0e9 163 memcpy(&header,frame,sizeof(RF24NetworkHeader));
zcw607 0:df0a8886a0e9 164 memcpy(message,frame+sizeof(RF24NetworkHeader),bufsize);
zcw607 0:df0a8886a0e9 165
zcw607 1:b5836d9f8de5 166 //IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Received %s\n\r"),millis(),header.toString()));
zcw607 0:df0a8886a0e9 167 }
zcw607 0:df0a8886a0e9 168
zcw607 0:df0a8886a0e9 169 return bufsize;
zcw607 0:df0a8886a0e9 170 }
zcw607 0:df0a8886a0e9 171
zcw607 0:df0a8886a0e9 172 /******************************************************************/
zcw607 0:df0a8886a0e9 173
zcw607 0:df0a8886a0e9 174 bool RF24Network::write(RF24NetworkHeader& header,const void* message, size_t len)
zcw607 0:df0a8886a0e9 175 {
zcw607 0:df0a8886a0e9 176 // Fill out the header
zcw607 0:df0a8886a0e9 177 header.from_node = node_address;
zcw607 0:df0a8886a0e9 178
zcw607 0:df0a8886a0e9 179 // Build the full frame to send
zcw607 0:df0a8886a0e9 180 memcpy(frame_buffer,&header,sizeof(RF24NetworkHeader));
zcw607 0:df0a8886a0e9 181 if (len)
zcw607 0:df0a8886a0e9 182 memcpy(frame_buffer + sizeof(RF24NetworkHeader),message,min(frame_size-sizeof(RF24NetworkHeader),len));
zcw607 0:df0a8886a0e9 183
zcw607 1:b5836d9f8de5 184 //IF_SERIAL_DEBUG(printf_P(PSTR("%lu: NET Sending %s\n\r"),millis(),header.toString()));
zcw607 0:df0a8886a0e9 185 if (len)
zcw607 0:df0a8886a0e9 186 {
zcw607 1:b5836d9f8de5 187 //IF_SERIAL_DEBUG(const uint16_t* i = reinterpret_cast<const uint16_t*>(message);printf_P(PSTR("%lu: NET message %04x\n\r"),millis(),*i));
zcw607 0:df0a8886a0e9 188 }
zcw607 0:df0a8886a0e9 189
zcw607 0:df0a8886a0e9 190 // If the user is trying to send it to himself
zcw607 0:df0a8886a0e9 191 if ( header.to_node == node_address )
zcw607 0:df0a8886a0e9 192 // Just queue it in the received queue
zcw607 0:df0a8886a0e9 193 return enqueue();
zcw607 0:df0a8886a0e9 194 else
zcw607 0:df0a8886a0e9 195 // Otherwise send it out over the air
zcw607 0:df0a8886a0e9 196 return write(header.to_node);
zcw607 0:df0a8886a0e9 197 }
zcw607 0:df0a8886a0e9 198
zcw607 0:df0a8886a0e9 199 /******************************************************************/
zcw607 0:df0a8886a0e9 200
zcw607 0:df0a8886a0e9 201 bool RF24Network::write(uint16_t to_node)
zcw607 0:df0a8886a0e9 202 {
zcw607 0:df0a8886a0e9 203 bool ok = false;
zcw607 0:df0a8886a0e9 204
zcw607 0:df0a8886a0e9 205 // Throw it away if it's not a valid address
zcw607 0:df0a8886a0e9 206 if ( !is_valid_address(to_node) )
zcw607 0:df0a8886a0e9 207 return false;
zcw607 0:df0a8886a0e9 208
zcw607 0:df0a8886a0e9 209 // First, stop listening so we can talk.
zcw607 0:df0a8886a0e9 210 //radio.stopListening();
zcw607 0:df0a8886a0e9 211
zcw607 0:df0a8886a0e9 212 // Where do we send this? By default, to our parent
zcw607 0:df0a8886a0e9 213 uint16_t send_node = parent_node;
zcw607 0:df0a8886a0e9 214 // On which pipe
zcw607 0:df0a8886a0e9 215 uint8_t send_pipe = parent_pipe;
zcw607 0:df0a8886a0e9 216
zcw607 0:df0a8886a0e9 217 // If the node is a direct child,
zcw607 0:df0a8886a0e9 218 if ( is_direct_child(to_node) )
zcw607 0:df0a8886a0e9 219 {
zcw607 0:df0a8886a0e9 220 // Send directly
zcw607 0:df0a8886a0e9 221 send_node = to_node;
zcw607 0:df0a8886a0e9 222
zcw607 0:df0a8886a0e9 223 // To its listening pipe
zcw607 0:df0a8886a0e9 224 send_pipe = 0;
zcw607 0:df0a8886a0e9 225 }
zcw607 0:df0a8886a0e9 226 // If the node is a child of a child
zcw607 0:df0a8886a0e9 227 // talk on our child's listening pipe,
zcw607 0:df0a8886a0e9 228 // and let the direct child relay it.
zcw607 0:df0a8886a0e9 229 else if ( is_descendant(to_node) )
zcw607 0:df0a8886a0e9 230 {
zcw607 0:df0a8886a0e9 231 send_node = direct_child_route_to(to_node);
zcw607 0:df0a8886a0e9 232 send_pipe = 0;
zcw607 0:df0a8886a0e9 233 }
zcw607 0:df0a8886a0e9 234
zcw607 1:b5836d9f8de5 235 //IF_SERIAL_DEBUG(printf_P(PSTR("%lu: MAC Sending to 0%o via 0%o on pipe %x\n\r"),millis(),to_node,send_node,send_pipe));
zcw607 0:df0a8886a0e9 236
zcw607 0:df0a8886a0e9 237 // First, stop listening so we can talk
zcw607 0:df0a8886a0e9 238 radio.stopListening();
zcw607 0:df0a8886a0e9 239
zcw607 0:df0a8886a0e9 240 // Put the frame on the pipe
zcw607 0:df0a8886a0e9 241 ok = write_to_pipe( send_node, send_pipe );
zcw607 0:df0a8886a0e9 242
zcw607 0:df0a8886a0e9 243 // NOT NEEDED anymore. Now all reading pipes are open to start.
zcw607 0:df0a8886a0e9 244 #if 0
zcw607 0:df0a8886a0e9 245 // If we are talking on our talking pipe, it's possible that no one is listening.
zcw607 0:df0a8886a0e9 246 // If this fails, try sending it on our parent's listening pipe. That will wake
zcw607 0:df0a8886a0e9 247 // it up, and next time it will listen to us.
zcw607 0:df0a8886a0e9 248
zcw607 0:df0a8886a0e9 249 if ( !ok && send_node == parent_node )
zcw607 0:df0a8886a0e9 250 ok = write_to_pipe( parent_node, 0 );
zcw607 0:df0a8886a0e9 251 #endif
zcw607 0:df0a8886a0e9 252
zcw607 0:df0a8886a0e9 253 // Now, continue listening
zcw607 0:df0a8886a0e9 254 radio.startListening();
zcw607 0:df0a8886a0e9 255
zcw607 0:df0a8886a0e9 256 return ok;
zcw607 0:df0a8886a0e9 257 }
zcw607 0:df0a8886a0e9 258
zcw607 0:df0a8886a0e9 259 /******************************************************************/
zcw607 0:df0a8886a0e9 260
zcw607 0:df0a8886a0e9 261 bool RF24Network::write_to_pipe( uint16_t node, uint8_t pipe )
zcw607 0:df0a8886a0e9 262 {
zcw607 0:df0a8886a0e9 263 bool ok = false;
zcw607 0:df0a8886a0e9 264
zcw607 0:df0a8886a0e9 265 uint64_t out_pipe = pipe_address( node, pipe );
zcw607 0:df0a8886a0e9 266
zcw607 0:df0a8886a0e9 267 // Open the correct pipe for writing.
zcw607 0:df0a8886a0e9 268 radio.openWritingPipe(out_pipe);
zcw607 0:df0a8886a0e9 269
zcw607 0:df0a8886a0e9 270 // Retry a few times
zcw607 0:df0a8886a0e9 271 short attempts = 5;
zcw607 0:df0a8886a0e9 272 do
zcw607 0:df0a8886a0e9 273 {
zcw607 0:df0a8886a0e9 274 ok = radio.write( frame_buffer, frame_size );
zcw607 0:df0a8886a0e9 275 }
zcw607 0:df0a8886a0e9 276 while ( !ok && --attempts );
zcw607 0:df0a8886a0e9 277
zcw607 1:b5836d9f8de5 278 //IF_SERIAL_DEBUG(printf_P(PSTR("%lu: MAC Sent on %lx %S\n\r"),millis(),(uint32_t)out_pipe,ok?PSTR("ok"):PSTR("failed")));
zcw607 0:df0a8886a0e9 279
zcw607 0:df0a8886a0e9 280 return ok;
zcw607 0:df0a8886a0e9 281 }
zcw607 0:df0a8886a0e9 282
zcw607 0:df0a8886a0e9 283 /******************************************************************/
zcw607 0:df0a8886a0e9 284
zcw607 0:df0a8886a0e9 285 const char* RF24NetworkHeader::toString(void) const
zcw607 0:df0a8886a0e9 286 {
zcw607 0:df0a8886a0e9 287 static char buffer[45];
zcw607 1:b5836d9f8de5 288 //snprintf_P(buffer,sizeof(buffer),("id %04x from 0%o to 0%o type %c"),id,from_node,to_node,type);
zcw607 0:df0a8886a0e9 289 return buffer;
zcw607 0:df0a8886a0e9 290 }
zcw607 0:df0a8886a0e9 291
zcw607 0:df0a8886a0e9 292 /******************************************************************/
zcw607 0:df0a8886a0e9 293
zcw607 0:df0a8886a0e9 294 bool RF24Network::is_direct_child( uint16_t node )
zcw607 0:df0a8886a0e9 295 {
zcw607 0:df0a8886a0e9 296 bool result = false;
zcw607 0:df0a8886a0e9 297
zcw607 0:df0a8886a0e9 298 // A direct child of ours has the same low numbers as us, and only
zcw607 0:df0a8886a0e9 299 // one higher number.
zcw607 0:df0a8886a0e9 300 //
zcw607 0:df0a8886a0e9 301 // e.g. node 0234 is a direct child of 034, and node 01234 is a
zcw607 0:df0a8886a0e9 302 // descendant but not a direct child
zcw607 0:df0a8886a0e9 303
zcw607 0:df0a8886a0e9 304 // First, is it even a descendant?
zcw607 0:df0a8886a0e9 305 if ( is_descendant(node) )
zcw607 0:df0a8886a0e9 306 {
zcw607 0:df0a8886a0e9 307 // Does it only have ONE more level than us?
zcw607 0:df0a8886a0e9 308 uint16_t child_node_mask = ( ~ node_mask ) << 3;
zcw607 0:df0a8886a0e9 309 result = ( node & child_node_mask ) == 0 ;
zcw607 0:df0a8886a0e9 310 }
zcw607 0:df0a8886a0e9 311
zcw607 0:df0a8886a0e9 312 return result;
zcw607 0:df0a8886a0e9 313 }
zcw607 0:df0a8886a0e9 314
zcw607 0:df0a8886a0e9 315 /******************************************************************/
zcw607 0:df0a8886a0e9 316
zcw607 0:df0a8886a0e9 317 bool RF24Network::is_descendant( uint16_t node )
zcw607 0:df0a8886a0e9 318 {
zcw607 0:df0a8886a0e9 319 return ( node & node_mask ) == node_address;
zcw607 0:df0a8886a0e9 320 }
zcw607 0:df0a8886a0e9 321
zcw607 0:df0a8886a0e9 322 /******************************************************************/
zcw607 0:df0a8886a0e9 323
zcw607 0:df0a8886a0e9 324 void RF24Network::setup_address(void)
zcw607 0:df0a8886a0e9 325 {
zcw607 0:df0a8886a0e9 326 // First, establish the node_mask
zcw607 0:df0a8886a0e9 327 uint16_t node_mask_check = 0xFFFF;
zcw607 0:df0a8886a0e9 328 while ( node_address & node_mask_check )
zcw607 0:df0a8886a0e9 329 node_mask_check <<= 3;
zcw607 0:df0a8886a0e9 330
zcw607 0:df0a8886a0e9 331 node_mask = ~ node_mask_check;
zcw607 0:df0a8886a0e9 332
zcw607 0:df0a8886a0e9 333 // parent mask is the next level down
zcw607 0:df0a8886a0e9 334 uint16_t parent_mask = node_mask >> 3;
zcw607 0:df0a8886a0e9 335
zcw607 0:df0a8886a0e9 336 // parent node is the part IN the mask
zcw607 0:df0a8886a0e9 337 parent_node = node_address & parent_mask;
zcw607 0:df0a8886a0e9 338
zcw607 0:df0a8886a0e9 339 // parent pipe is the part OUT of the mask
zcw607 0:df0a8886a0e9 340 uint16_t i = node_address;
zcw607 0:df0a8886a0e9 341 uint16_t m = parent_mask;
zcw607 0:df0a8886a0e9 342 while (m)
zcw607 0:df0a8886a0e9 343 {
zcw607 0:df0a8886a0e9 344 i >>= 3;
zcw607 0:df0a8886a0e9 345 m >>= 3;
zcw607 0:df0a8886a0e9 346 }
zcw607 0:df0a8886a0e9 347 parent_pipe = i;
zcw607 0:df0a8886a0e9 348
zcw607 0:df0a8886a0e9 349 #ifdef SERIAL_DEBUG
zcw607 0:df0a8886a0e9 350 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);
zcw607 0:df0a8886a0e9 351 #endif
zcw607 0:df0a8886a0e9 352 }
zcw607 0:df0a8886a0e9 353
zcw607 0:df0a8886a0e9 354 /******************************************************************/
zcw607 0:df0a8886a0e9 355
zcw607 0:df0a8886a0e9 356 uint16_t RF24Network::direct_child_route_to( uint16_t node )
zcw607 0:df0a8886a0e9 357 {
zcw607 0:df0a8886a0e9 358 // Presumes that this is in fact a child!!
zcw607 0:df0a8886a0e9 359
zcw607 1:b5836d9f8de5 360 uint16_t child_mask = ( node_mask << 3 ) | 7;
zcw607 0:df0a8886a0e9 361 return node & child_mask ;
zcw607 0:df0a8886a0e9 362 }
zcw607 0:df0a8886a0e9 363
zcw607 0:df0a8886a0e9 364 /******************************************************************/
zcw607 0:df0a8886a0e9 365
zcw607 0:df0a8886a0e9 366 uint8_t RF24Network::pipe_to_descendant( uint16_t node )
zcw607 0:df0a8886a0e9 367 {
zcw607 0:df0a8886a0e9 368 uint16_t i = node;
zcw607 0:df0a8886a0e9 369 uint16_t m = node_mask;
zcw607 0:df0a8886a0e9 370
zcw607 0:df0a8886a0e9 371 while (m)
zcw607 0:df0a8886a0e9 372 {
zcw607 0:df0a8886a0e9 373 i >>= 3;
zcw607 0:df0a8886a0e9 374 m >>= 3;
zcw607 0:df0a8886a0e9 375 }
zcw607 0:df0a8886a0e9 376
zcw607 1:b5836d9f8de5 377 return i & 7;
zcw607 0:df0a8886a0e9 378 }
zcw607 0:df0a8886a0e9 379
zcw607 0:df0a8886a0e9 380 /******************************************************************/
zcw607 0:df0a8886a0e9 381
zcw607 0:df0a8886a0e9 382 bool is_valid_address( uint16_t node )
zcw607 0:df0a8886a0e9 383 {
zcw607 0:df0a8886a0e9 384 bool result = true;
zcw607 0:df0a8886a0e9 385
zcw607 0:df0a8886a0e9 386 while(node)
zcw607 0:df0a8886a0e9 387 {
zcw607 1:b5836d9f8de5 388 uint8_t digit = node & 7;
zcw607 0:df0a8886a0e9 389 if (digit < 1 || digit > 5)
zcw607 0:df0a8886a0e9 390 {
zcw607 0:df0a8886a0e9 391 result = false;
zcw607 1:b5836d9f8de5 392 //printf_P(("*** WARNING *** Invalid address 0%o\n\r"),node);
zcw607 0:df0a8886a0e9 393 break;
zcw607 0:df0a8886a0e9 394 }
zcw607 0:df0a8886a0e9 395 node >>= 3;
zcw607 0:df0a8886a0e9 396 }
zcw607 0:df0a8886a0e9 397
zcw607 0:df0a8886a0e9 398 return result;
zcw607 0:df0a8886a0e9 399 }
zcw607 0:df0a8886a0e9 400
zcw607 0:df0a8886a0e9 401 /******************************************************************/
zcw607 0:df0a8886a0e9 402
zcw607 0:df0a8886a0e9 403 uint64_t pipe_address( uint16_t node, uint8_t pipe )
zcw607 0:df0a8886a0e9 404 {
zcw607 0:df0a8886a0e9 405 static uint8_t pipe_segment[] = { 0x3c, 0x5a, 0x69, 0x96, 0xa5, 0xc3 };
zcw607 0:df0a8886a0e9 406
zcw607 0:df0a8886a0e9 407 uint64_t result;
zcw607 0:df0a8886a0e9 408 uint8_t* out = reinterpret_cast<uint8_t*>(&result);
zcw607 0:df0a8886a0e9 409
zcw607 0:df0a8886a0e9 410 out[0] = pipe_segment[pipe];
zcw607 0:df0a8886a0e9 411
zcw607 0:df0a8886a0e9 412 uint8_t w;
zcw607 0:df0a8886a0e9 413 short i = 4;
zcw607 0:df0a8886a0e9 414 short shift = 12;
zcw607 0:df0a8886a0e9 415 while(i--)
zcw607 0:df0a8886a0e9 416 {
zcw607 0:df0a8886a0e9 417 w = ( node >> shift ) & 0xF ;
zcw607 0:df0a8886a0e9 418 w |= ~w << 4;
zcw607 0:df0a8886a0e9 419 out[i+1] = w;
zcw607 0:df0a8886a0e9 420
zcw607 0:df0a8886a0e9 421 shift -= 4;
zcw607 0:df0a8886a0e9 422 }
zcw607 0:df0a8886a0e9 423
zcw607 1:b5836d9f8de5 424 //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));
zcw607 0:df0a8886a0e9 425
zcw607 0:df0a8886a0e9 426 return result;
zcw607 0:df0a8886a0e9 427 }
zcw607 0:df0a8886a0e9 428
zcw607 0:df0a8886a0e9 429 // vim:ai:cin:sts=2 sw=2 ft=cpp
zcw607 1:b5836d9f8de5 430
zcw607 1:b5836d9f8de5 431 uint8_t RF24Network::min(uint8_t a, uint8_t b)
zcw607 1:b5836d9f8de5 432 {
zcw607 1:b5836d9f8de5 433 if(a < b)
zcw607 1:b5836d9f8de5 434 return a;
zcw607 1:b5836d9f8de5 435 else
zcw607 1:b5836d9f8de5 436 return b;
zcw607 1:b5836d9f8de5 437 }