Dependents:   New

Committer:
SangSTBK
Date:
Mon Jul 02 01:29:58 2012 +0000
Revision:
0:e16ffa7cb900
RF

Who changed what in which revision?

UserRevisionLine numberNew contents of line
SangSTBK 0:e16ffa7cb900 1 // RF22Router.cpp
SangSTBK 0:e16ffa7cb900 2 //
SangSTBK 0:e16ffa7cb900 3 // Define addressed datagram
SangSTBK 0:e16ffa7cb900 4 //
SangSTBK 0:e16ffa7cb900 5 // Part of the Arduino RF22 library for operating with HopeRF RF22 compatible transceivers
SangSTBK 0:e16ffa7cb900 6 // (see http://www.hoperf.com)
SangSTBK 0:e16ffa7cb900 7 // RF22Datagram will be received only by the addressed node or all nodes within range if the
SangSTBK 0:e16ffa7cb900 8 // to address is RF22_BROADCAST_ADDRESS
SangSTBK 0:e16ffa7cb900 9 //
SangSTBK 0:e16ffa7cb900 10 // Author: Mike McCauley (mikem@open.com.au)
SangSTBK 0:e16ffa7cb900 11 // Copyright (C) 2011 Mike McCauley
SangSTBK 0:e16ffa7cb900 12 // $Id: RF22Router.cpp,v 1.6 2011/02/15 01:18:03 mikem Exp $
SangSTBK 0:e16ffa7cb900 13 // ported to mbed by Karl Zweimueller
SangSTBK 0:e16ffa7cb900 14
SangSTBK 0:e16ffa7cb900 15 #include <mbed.h>
SangSTBK 0:e16ffa7cb900 16 #include <RF22Router.h>
SangSTBK 0:e16ffa7cb900 17 //#include <SPI.h>
SangSTBK 0:e16ffa7cb900 18
SangSTBK 0:e16ffa7cb900 19
SangSTBK 0:e16ffa7cb900 20 RF22Router::RoutedMessage RF22Router::_tmpMessage;
SangSTBK 0:e16ffa7cb900 21
SangSTBK 0:e16ffa7cb900 22 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 23 // Constructors
SangSTBK 0:e16ffa7cb900 24 RF22Router::RF22Router(uint8_t thisAddress ,PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt )
SangSTBK 0:e16ffa7cb900 25 : RF22ReliableDatagram(thisAddress, slaveSelectPin, mosi, miso, sclk, interrupt )
SangSTBK 0:e16ffa7cb900 26 {
SangSTBK 0:e16ffa7cb900 27 _max_hops = RF22_DEFAULT_MAX_HOPS;
SangSTBK 0:e16ffa7cb900 28 clearRoutingTable();
SangSTBK 0:e16ffa7cb900 29 }
SangSTBK 0:e16ffa7cb900 30
SangSTBK 0:e16ffa7cb900 31 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 32 // Public methods
SangSTBK 0:e16ffa7cb900 33 boolean RF22Router::init()
SangSTBK 0:e16ffa7cb900 34 {
SangSTBK 0:e16ffa7cb900 35 boolean ret = RF22ReliableDatagram::init();
SangSTBK 0:e16ffa7cb900 36 if (ret)
SangSTBK 0:e16ffa7cb900 37 _max_hops = RF22_DEFAULT_MAX_HOPS;
SangSTBK 0:e16ffa7cb900 38 return ret;
SangSTBK 0:e16ffa7cb900 39 }
SangSTBK 0:e16ffa7cb900 40
SangSTBK 0:e16ffa7cb900 41 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 42 void RF22Router::setMaxHops(uint8_t max_hops)
SangSTBK 0:e16ffa7cb900 43 {
SangSTBK 0:e16ffa7cb900 44 _max_hops = max_hops;
SangSTBK 0:e16ffa7cb900 45 }
SangSTBK 0:e16ffa7cb900 46
SangSTBK 0:e16ffa7cb900 47 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 48 void RF22Router::addRouteTo(uint8_t dest, uint8_t next_hop, uint8_t state)
SangSTBK 0:e16ffa7cb900 49 {
SangSTBK 0:e16ffa7cb900 50 uint8_t i;
SangSTBK 0:e16ffa7cb900 51
SangSTBK 0:e16ffa7cb900 52 // First look for an existing entry we can update
SangSTBK 0:e16ffa7cb900 53 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++)
SangSTBK 0:e16ffa7cb900 54 {
SangSTBK 0:e16ffa7cb900 55 if (_routes[i].dest == dest)
SangSTBK 0:e16ffa7cb900 56 {
SangSTBK 0:e16ffa7cb900 57 _routes[i].dest = dest;
SangSTBK 0:e16ffa7cb900 58 _routes[i].next_hop = next_hop;
SangSTBK 0:e16ffa7cb900 59 _routes[i].state = state;
SangSTBK 0:e16ffa7cb900 60 return;
SangSTBK 0:e16ffa7cb900 61 }
SangSTBK 0:e16ffa7cb900 62 }
SangSTBK 0:e16ffa7cb900 63
SangSTBK 0:e16ffa7cb900 64 // Look for an invalid entry we can use
SangSTBK 0:e16ffa7cb900 65 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++)
SangSTBK 0:e16ffa7cb900 66 {
SangSTBK 0:e16ffa7cb900 67 if (_routes[i].state == Invalid)
SangSTBK 0:e16ffa7cb900 68 {
SangSTBK 0:e16ffa7cb900 69 _routes[i].dest = dest;
SangSTBK 0:e16ffa7cb900 70 _routes[i].next_hop = next_hop;
SangSTBK 0:e16ffa7cb900 71 _routes[i].state = state;
SangSTBK 0:e16ffa7cb900 72 return;
SangSTBK 0:e16ffa7cb900 73 }
SangSTBK 0:e16ffa7cb900 74 }
SangSTBK 0:e16ffa7cb900 75
SangSTBK 0:e16ffa7cb900 76 // Need to make room for a new one
SangSTBK 0:e16ffa7cb900 77 retireOldestRoute();
SangSTBK 0:e16ffa7cb900 78 // Should be an invalid slot now
SangSTBK 0:e16ffa7cb900 79 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++)
SangSTBK 0:e16ffa7cb900 80 {
SangSTBK 0:e16ffa7cb900 81 if (_routes[i].state == Invalid)
SangSTBK 0:e16ffa7cb900 82 {
SangSTBK 0:e16ffa7cb900 83 _routes[i].dest = dest;
SangSTBK 0:e16ffa7cb900 84 _routes[i].next_hop = next_hop;
SangSTBK 0:e16ffa7cb900 85 _routes[i].state = state;
SangSTBK 0:e16ffa7cb900 86 }
SangSTBK 0:e16ffa7cb900 87 }
SangSTBK 0:e16ffa7cb900 88 }
SangSTBK 0:e16ffa7cb900 89
SangSTBK 0:e16ffa7cb900 90 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 91 RF22Router::RoutingTableEntry* RF22Router::getRouteTo(uint8_t dest)
SangSTBK 0:e16ffa7cb900 92 {
SangSTBK 0:e16ffa7cb900 93 uint8_t i;
SangSTBK 0:e16ffa7cb900 94 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++)
SangSTBK 0:e16ffa7cb900 95 if (_routes[i].dest == dest && _routes[i].state != Invalid)
SangSTBK 0:e16ffa7cb900 96 return &_routes[i];
SangSTBK 0:e16ffa7cb900 97 return NULL;
SangSTBK 0:e16ffa7cb900 98 }
SangSTBK 0:e16ffa7cb900 99
SangSTBK 0:e16ffa7cb900 100 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 101 void RF22Router::deleteRoute(uint8_t index)
SangSTBK 0:e16ffa7cb900 102 {
SangSTBK 0:e16ffa7cb900 103 // Delete a route by copying following routes on top of it
SangSTBK 0:e16ffa7cb900 104 memcpy(&_routes[index], &_routes[index+1],
SangSTBK 0:e16ffa7cb900 105 sizeof(RoutingTableEntry) * (RF22_ROUTING_TABLE_SIZE - index - 1));
SangSTBK 0:e16ffa7cb900 106 _routes[RF22_ROUTING_TABLE_SIZE - 1].state = Invalid;
SangSTBK 0:e16ffa7cb900 107 }
SangSTBK 0:e16ffa7cb900 108
SangSTBK 0:e16ffa7cb900 109 #ifdef RF22_HAVE_SERIAL
SangSTBK 0:e16ffa7cb900 110 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 111 void RF22Router::printRoutingTable()
SangSTBK 0:e16ffa7cb900 112 {
SangSTBK 0:e16ffa7cb900 113 uint8_t i;
SangSTBK 0:e16ffa7cb900 114 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++)
SangSTBK 0:e16ffa7cb900 115 {
SangSTBK 0:e16ffa7cb900 116 Serial.print(i, DEC);
SangSTBK 0:e16ffa7cb900 117 Serial.print(" Dest: ");
SangSTBK 0:e16ffa7cb900 118 Serial.print(_routes[i].dest, DEC);
SangSTBK 0:e16ffa7cb900 119 Serial.print(" Next Hop: ");
SangSTBK 0:e16ffa7cb900 120 Serial.print(_routes[i].next_hop, DEC);
SangSTBK 0:e16ffa7cb900 121 Serial.print(" State: ");
SangSTBK 0:e16ffa7cb900 122 Serial.println(_routes[i].state, DEC);
SangSTBK 0:e16ffa7cb900 123 }
SangSTBK 0:e16ffa7cb900 124 }
SangSTBK 0:e16ffa7cb900 125 #endif
SangSTBK 0:e16ffa7cb900 126
SangSTBK 0:e16ffa7cb900 127 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 128 boolean RF22Router::deleteRouteTo(uint8_t dest)
SangSTBK 0:e16ffa7cb900 129 {
SangSTBK 0:e16ffa7cb900 130 uint8_t i;
SangSTBK 0:e16ffa7cb900 131 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++)
SangSTBK 0:e16ffa7cb900 132 {
SangSTBK 0:e16ffa7cb900 133 if (_routes[i].dest == dest)
SangSTBK 0:e16ffa7cb900 134 {
SangSTBK 0:e16ffa7cb900 135 deleteRoute(i);
SangSTBK 0:e16ffa7cb900 136 return true;
SangSTBK 0:e16ffa7cb900 137 }
SangSTBK 0:e16ffa7cb900 138 }
SangSTBK 0:e16ffa7cb900 139 return false;
SangSTBK 0:e16ffa7cb900 140 }
SangSTBK 0:e16ffa7cb900 141
SangSTBK 0:e16ffa7cb900 142 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 143 void RF22Router::retireOldestRoute()
SangSTBK 0:e16ffa7cb900 144 {
SangSTBK 0:e16ffa7cb900 145 // We just obliterate the first in the table and clear the last
SangSTBK 0:e16ffa7cb900 146 deleteRoute(0);
SangSTBK 0:e16ffa7cb900 147 }
SangSTBK 0:e16ffa7cb900 148
SangSTBK 0:e16ffa7cb900 149 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 150 void RF22Router::clearRoutingTable()
SangSTBK 0:e16ffa7cb900 151 {
SangSTBK 0:e16ffa7cb900 152 uint8_t i;
SangSTBK 0:e16ffa7cb900 153 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++)
SangSTBK 0:e16ffa7cb900 154 _routes[i].state = Invalid;
SangSTBK 0:e16ffa7cb900 155 }
SangSTBK 0:e16ffa7cb900 156
SangSTBK 0:e16ffa7cb900 157
SangSTBK 0:e16ffa7cb900 158 uint8_t RF22Router::sendtoWait(uint8_t* buf, uint8_t len, uint8_t dest)
SangSTBK 0:e16ffa7cb900 159 {
SangSTBK 0:e16ffa7cb900 160 return sendtoWait(buf, len, dest, _thisAddress);
SangSTBK 0:e16ffa7cb900 161 }
SangSTBK 0:e16ffa7cb900 162
SangSTBK 0:e16ffa7cb900 163 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 164 // Waits for delivery to the next hop (but not for delivery to the final destination)
SangSTBK 0:e16ffa7cb900 165 uint8_t RF22Router::sendtoWait(uint8_t* buf, uint8_t len, uint8_t dest, uint8_t source)
SangSTBK 0:e16ffa7cb900 166 {
SangSTBK 0:e16ffa7cb900 167 if (((uint16_t)len + sizeof(RoutedMessageHeader)) > RF22_MAX_MESSAGE_LEN)
SangSTBK 0:e16ffa7cb900 168 return RF22_ROUTER_ERROR_INVALID_LENGTH;
SangSTBK 0:e16ffa7cb900 169
SangSTBK 0:e16ffa7cb900 170 // Construct a RF22 RouterMessage message
SangSTBK 0:e16ffa7cb900 171 _tmpMessage.header.source = source;
SangSTBK 0:e16ffa7cb900 172 _tmpMessage.header.dest = dest;
SangSTBK 0:e16ffa7cb900 173 _tmpMessage.header.hops = 0;
SangSTBK 0:e16ffa7cb900 174 _tmpMessage.header.id = _lastE2ESequenceNumber++;
SangSTBK 0:e16ffa7cb900 175 _tmpMessage.header.flags = 0;
SangSTBK 0:e16ffa7cb900 176 memcpy(_tmpMessage.data, buf, len);
SangSTBK 0:e16ffa7cb900 177
SangSTBK 0:e16ffa7cb900 178 return route(&_tmpMessage, sizeof(RoutedMessageHeader)+len);
SangSTBK 0:e16ffa7cb900 179 }
SangSTBK 0:e16ffa7cb900 180
SangSTBK 0:e16ffa7cb900 181 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 182 uint8_t RF22Router::route(RoutedMessage* message, uint8_t messageLen)
SangSTBK 0:e16ffa7cb900 183 {
SangSTBK 0:e16ffa7cb900 184 // Reliably deliver it if possible. See if we have a route:
SangSTBK 0:e16ffa7cb900 185 uint8_t next_hop = RF22_BROADCAST_ADDRESS;
SangSTBK 0:e16ffa7cb900 186 if (message->header.dest != RF22_BROADCAST_ADDRESS)
SangSTBK 0:e16ffa7cb900 187 {
SangSTBK 0:e16ffa7cb900 188 RoutingTableEntry* route = getRouteTo(message->header.dest);
SangSTBK 0:e16ffa7cb900 189 if (!route)
SangSTBK 0:e16ffa7cb900 190 return RF22_ROUTER_ERROR_NO_ROUTE;
SangSTBK 0:e16ffa7cb900 191 next_hop = route->next_hop;
SangSTBK 0:e16ffa7cb900 192 }
SangSTBK 0:e16ffa7cb900 193
SangSTBK 0:e16ffa7cb900 194 if (!RF22ReliableDatagram::sendtoWait((uint8_t*)message, messageLen, next_hop))
SangSTBK 0:e16ffa7cb900 195 return RF22_ROUTER_ERROR_UNABLE_TO_DELIVER;
SangSTBK 0:e16ffa7cb900 196
SangSTBK 0:e16ffa7cb900 197 return RF22_ROUTER_ERROR_NONE;
SangSTBK 0:e16ffa7cb900 198 }
SangSTBK 0:e16ffa7cb900 199
SangSTBK 0:e16ffa7cb900 200 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 201 // Subclasses may want to override this to peek at messages going past
SangSTBK 0:e16ffa7cb900 202 void RF22Router::peekAtMessage(RoutedMessage* message, uint8_t messageLen)
SangSTBK 0:e16ffa7cb900 203 {
SangSTBK 0:e16ffa7cb900 204 // Default does nothing
SangSTBK 0:e16ffa7cb900 205 }
SangSTBK 0:e16ffa7cb900 206
SangSTBK 0:e16ffa7cb900 207 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 208 boolean RF22Router::recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* source, uint8_t* dest, uint8_t* id, uint8_t* flags)
SangSTBK 0:e16ffa7cb900 209 {
SangSTBK 0:e16ffa7cb900 210 uint8_t tmpMessageLen = sizeof(_tmpMessage);
SangSTBK 0:e16ffa7cb900 211 uint8_t _from;
SangSTBK 0:e16ffa7cb900 212 uint8_t _to;
SangSTBK 0:e16ffa7cb900 213 uint8_t _id;
SangSTBK 0:e16ffa7cb900 214 uint8_t _flags;
SangSTBK 0:e16ffa7cb900 215 if (RF22ReliableDatagram::recvfromAck((uint8_t*)&_tmpMessage, &tmpMessageLen, &_from, &_to, &_id, &_flags))
SangSTBK 0:e16ffa7cb900 216 {
SangSTBK 0:e16ffa7cb900 217 // Here we simulate networks with limited visibility between nodes
SangSTBK 0:e16ffa7cb900 218 // so we can test routing
SangSTBK 0:e16ffa7cb900 219 #ifdef RF22_TEST_NETWORK
SangSTBK 0:e16ffa7cb900 220 if (
SangSTBK 0:e16ffa7cb900 221 #if RF22_TEST_NETWORK==1
SangSTBK 0:e16ffa7cb900 222 // This looks like 1-2-3-4
SangSTBK 0:e16ffa7cb900 223 (_thisAddress == 1 && _from == 2)
SangSTBK 0:e16ffa7cb900 224 || (_thisAddress == 2 && (_from == 1 || _from == 3))
SangSTBK 0:e16ffa7cb900 225 || (_thisAddress == 3 && (_from == 2 || _from == 4))
SangSTBK 0:e16ffa7cb900 226 || (_thisAddress == 4 && _from == 3)
SangSTBK 0:e16ffa7cb900 227
SangSTBK 0:e16ffa7cb900 228 #elif RF22_TEST_NETWORK==2
SangSTBK 0:e16ffa7cb900 229 // This looks like 1-2-4
SangSTBK 0:e16ffa7cb900 230 // | | |
SangSTBK 0:e16ffa7cb900 231 // --3--
SangSTBK 0:e16ffa7cb900 232 (_thisAddress == 1 && (_from == 2 || _from == 3))
SangSTBK 0:e16ffa7cb900 233 || _thisAddress == 2
SangSTBK 0:e16ffa7cb900 234 || _thisAddress == 3
SangSTBK 0:e16ffa7cb900 235 || (_thisAddress == 4 && (_from == 2 || _from == 3))
SangSTBK 0:e16ffa7cb900 236
SangSTBK 0:e16ffa7cb900 237 #elif RF22_TEST_NETWORK==3
SangSTBK 0:e16ffa7cb900 238 // This looks like 1-2-4
SangSTBK 0:e16ffa7cb900 239 // | |
SangSTBK 0:e16ffa7cb900 240 // --3--
SangSTBK 0:e16ffa7cb900 241 (_thisAddress == 1 && (_from == 2 || _from == 3))
SangSTBK 0:e16ffa7cb900 242 || (_thisAddress == 2 && (_from == 1 || _from == 4))
SangSTBK 0:e16ffa7cb900 243 || (_thisAddress == 3 && (_from == 1 || _from == 4))
SangSTBK 0:e16ffa7cb900 244 || (_thisAddress == 4 && (_from == 2 || _from == 3))
SangSTBK 0:e16ffa7cb900 245
SangSTBK 0:e16ffa7cb900 246 #elif RF22_TEST_NETWORK==4
SangSTBK 0:e16ffa7cb900 247 // This looks like 1-2-3
SangSTBK 0:e16ffa7cb900 248 // |
SangSTBK 0:e16ffa7cb900 249 // 4
SangSTBK 0:e16ffa7cb900 250 (_thisAddress == 1 && _from == 2)
SangSTBK 0:e16ffa7cb900 251 || _thisAddress == 2
SangSTBK 0:e16ffa7cb900 252 || (_thisAddress == 3 && _from == 2)
SangSTBK 0:e16ffa7cb900 253 || (_thisAddress == 4 && _from == 2)
SangSTBK 0:e16ffa7cb900 254
SangSTBK 0:e16ffa7cb900 255 #endif
SangSTBK 0:e16ffa7cb900 256 )
SangSTBK 0:e16ffa7cb900 257 {
SangSTBK 0:e16ffa7cb900 258 // OK
SangSTBK 0:e16ffa7cb900 259 }
SangSTBK 0:e16ffa7cb900 260 else
SangSTBK 0:e16ffa7cb900 261 {
SangSTBK 0:e16ffa7cb900 262 return false; // Pretend we got nothing
SangSTBK 0:e16ffa7cb900 263 }
SangSTBK 0:e16ffa7cb900 264 #endif
SangSTBK 0:e16ffa7cb900 265
SangSTBK 0:e16ffa7cb900 266 peekAtMessage(&_tmpMessage, tmpMessageLen);
SangSTBK 0:e16ffa7cb900 267 // See if its for us or has to be routed
SangSTBK 0:e16ffa7cb900 268 if (_tmpMessage.header.dest == _thisAddress || _tmpMessage.header.dest == RF22_BROADCAST_ADDRESS)
SangSTBK 0:e16ffa7cb900 269 {
SangSTBK 0:e16ffa7cb900 270 // Deliver it here
SangSTBK 0:e16ffa7cb900 271 if (source) *source = _tmpMessage.header.source;
SangSTBK 0:e16ffa7cb900 272 if (dest) *dest = _tmpMessage.header.dest;
SangSTBK 0:e16ffa7cb900 273 if (id) *id = _tmpMessage.header.id;
SangSTBK 0:e16ffa7cb900 274 if (flags) *flags = _tmpMessage.header.flags;
SangSTBK 0:e16ffa7cb900 275 uint8_t msgLen = tmpMessageLen - sizeof(RoutedMessageHeader);
SangSTBK 0:e16ffa7cb900 276 if (*len > msgLen)
SangSTBK 0:e16ffa7cb900 277 *len = msgLen;
SangSTBK 0:e16ffa7cb900 278 memcpy(buf, _tmpMessage.data, *len);
SangSTBK 0:e16ffa7cb900 279 return true; // Its for you!
SangSTBK 0:e16ffa7cb900 280 }
SangSTBK 0:e16ffa7cb900 281 else if ( _tmpMessage.header.dest != RF22_BROADCAST_ADDRESS
SangSTBK 0:e16ffa7cb900 282 && _tmpMessage.header.hops++ < _max_hops)
SangSTBK 0:e16ffa7cb900 283 {
SangSTBK 0:e16ffa7cb900 284 // Maybe it has to be routed to the next hop
SangSTBK 0:e16ffa7cb900 285 // REVISIT: if it fails due to no route or unable to deliver to the next hop,
SangSTBK 0:e16ffa7cb900 286 // tell the originator. BUT HOW?
SangSTBK 0:e16ffa7cb900 287 route(&_tmpMessage, tmpMessageLen);
SangSTBK 0:e16ffa7cb900 288 }
SangSTBK 0:e16ffa7cb900 289 // Discard it and maybe wait for another
SangSTBK 0:e16ffa7cb900 290 }
SangSTBK 0:e16ffa7cb900 291 return false;
SangSTBK 0:e16ffa7cb900 292 }
SangSTBK 0:e16ffa7cb900 293
SangSTBK 0:e16ffa7cb900 294 ////////////////////////////////////////////////////////////////////
SangSTBK 0:e16ffa7cb900 295 boolean RF22Router::recvfromAckTimeout(uint8_t* buf, uint8_t* len, uint16_t timeout, uint8_t* source, uint8_t* dest, uint8_t* id, uint8_t* flags)
SangSTBK 0:e16ffa7cb900 296 {
SangSTBK 0:e16ffa7cb900 297 Timer t;
SangSTBK 0:e16ffa7cb900 298
SangSTBK 0:e16ffa7cb900 299 t.start();
SangSTBK 0:e16ffa7cb900 300 unsigned long endtime = t.read_ms() + timeout;
SangSTBK 0:e16ffa7cb900 301 while (t.read_ms() < endtime)
SangSTBK 0:e16ffa7cb900 302 {
SangSTBK 0:e16ffa7cb900 303 if (recvfromAck(buf, len, source, dest, id, flags))
SangSTBK 0:e16ffa7cb900 304 return true;
SangSTBK 0:e16ffa7cb900 305 }
SangSTBK 0:e16ffa7cb900 306 return false;
SangSTBK 0:e16ffa7cb900 307 }
SangSTBK 0:e16ffa7cb900 308