Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of RF22 by
RF22Router.cpp
00001 // RF22Router.cpp 00002 // 00003 // Define addressed datagram 00004 // 00005 // Part of the Arduino RF22 library for operating with HopeRF RF22 compatible transceivers 00006 // (see http://www.hoperf.com) 00007 // RF22Datagram will be received only by the addressed node or all nodes within range if the 00008 // to address is RF22_BROADCAST_ADDRESS 00009 // 00010 // Author: Mike McCauley (mikem@open.com.au) 00011 // Copyright (C) 2011 Mike McCauley 00012 // $Id: RF22Router.cpp,v 1.7 2012/05/30 01:51:25 mikem Exp $ 00013 // ported to mbed by Karl Zweimueller 00014 00015 #include <mbed.h> 00016 #include <RF22Router.h> 00017 //#include <SPI.h> 00018 00019 00020 RF22Router::RoutedMessage RF22Router::_tmpMessage; 00021 00022 //////////////////////////////////////////////////////////////////// 00023 // Constructors 00024 RF22Router::RF22Router(uint8_t thisAddress ,PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt ) 00025 : RF22ReliableDatagram(thisAddress, slaveSelectPin, mosi, miso, sclk, interrupt ) 00026 { 00027 _max_hops = RF22_DEFAULT_MAX_HOPS; 00028 clearRoutingTable(); 00029 } 00030 00031 //////////////////////////////////////////////////////////////////// 00032 // Public methods 00033 boolean RF22Router::init() 00034 { 00035 boolean ret = RF22ReliableDatagram::init(); 00036 if (ret) 00037 _max_hops = RF22_DEFAULT_MAX_HOPS; 00038 return ret; 00039 } 00040 00041 //////////////////////////////////////////////////////////////////// 00042 void RF22Router::setMaxHops(uint8_t max_hops) 00043 { 00044 _max_hops = max_hops; 00045 } 00046 00047 //////////////////////////////////////////////////////////////////// 00048 void RF22Router::addRouteTo(uint8_t dest, uint8_t next_hop, uint8_t state) 00049 { 00050 uint8_t i; 00051 00052 // First look for an existing entry we can update 00053 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++) 00054 { 00055 if (_routes[i].dest == dest) 00056 { 00057 _routes[i].dest = dest; 00058 _routes[i].next_hop = next_hop; 00059 _routes[i].state = state; 00060 return; 00061 } 00062 } 00063 00064 // Look for an invalid entry we can use 00065 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++) 00066 { 00067 if (_routes[i].state == Invalid) 00068 { 00069 _routes[i].dest = dest; 00070 _routes[i].next_hop = next_hop; 00071 _routes[i].state = state; 00072 return; 00073 } 00074 } 00075 00076 // Need to make room for a new one 00077 retireOldestRoute(); 00078 // Should be an invalid slot now 00079 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++) 00080 { 00081 if (_routes[i].state == Invalid) 00082 { 00083 _routes[i].dest = dest; 00084 _routes[i].next_hop = next_hop; 00085 _routes[i].state = state; 00086 } 00087 } 00088 } 00089 00090 //////////////////////////////////////////////////////////////////// 00091 RF22Router::RoutingTableEntry* RF22Router::getRouteTo(uint8_t dest) 00092 { 00093 uint8_t i; 00094 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++) 00095 if (_routes[i].dest == dest && _routes[i].state != Invalid) 00096 return &_routes[i]; 00097 return NULL; 00098 } 00099 00100 //////////////////////////////////////////////////////////////////// 00101 void RF22Router::deleteRoute(uint8_t index) 00102 { 00103 // Delete a route by copying following routes on top of it 00104 memcpy(&_routes[index], &_routes[index+1], 00105 sizeof(RoutingTableEntry) * (RF22_ROUTING_TABLE_SIZE - index - 1)); 00106 _routes[RF22_ROUTING_TABLE_SIZE - 1].state = Invalid; 00107 } 00108 00109 //////////////////////////////////////////////////////////////////// 00110 void RF22Router::printRoutingTable() 00111 { 00112 #ifdef RF22_HAVE_SERIAL 00113 uint8_t i; 00114 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++) 00115 { 00116 Serial.print(i, DEC); 00117 Serial.print(" Dest: "); 00118 Serial.print(_routes[i].dest, DEC); 00119 Serial.print(" Next Hop: "); 00120 Serial.print(_routes[i].next_hop, DEC); 00121 Serial.print(" State: "); 00122 Serial.println(_routes[i].state, DEC); 00123 } 00124 #endif 00125 } 00126 00127 //////////////////////////////////////////////////////////////////// 00128 boolean RF22Router::deleteRouteTo(uint8_t dest) 00129 { 00130 uint8_t i; 00131 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++) 00132 { 00133 if (_routes[i].dest == dest) 00134 { 00135 deleteRoute(i); 00136 return true; 00137 } 00138 } 00139 return false; 00140 } 00141 00142 //////////////////////////////////////////////////////////////////// 00143 void RF22Router::retireOldestRoute() 00144 { 00145 // We just obliterate the first in the table and clear the last 00146 deleteRoute(0); 00147 } 00148 00149 //////////////////////////////////////////////////////////////////// 00150 void RF22Router::clearRoutingTable() 00151 { 00152 uint8_t i; 00153 for (i = 0; i < RF22_ROUTING_TABLE_SIZE; i++) 00154 _routes[i].state = Invalid; 00155 } 00156 00157 00158 uint8_t RF22Router::sendtoWait(uint8_t* buf, uint8_t len, uint8_t dest) 00159 { 00160 return sendtoWait(buf, len, dest, _thisAddress); 00161 } 00162 00163 //////////////////////////////////////////////////////////////////// 00164 // Waits for delivery to the next hop (but not for delivery to the final destination) 00165 uint8_t RF22Router::sendtoWait(uint8_t* buf, uint8_t len, uint8_t dest, uint8_t source) 00166 { 00167 if (((uint16_t)len + sizeof(RoutedMessageHeader)) > RF22_MAX_MESSAGE_LEN) 00168 return RF22_ROUTER_ERROR_INVALID_LENGTH; 00169 00170 // Construct a RF22 RouterMessage message 00171 _tmpMessage.header.source = source; 00172 _tmpMessage.header.dest = dest; 00173 _tmpMessage.header.hops = 0; 00174 _tmpMessage.header.id = _lastE2ESequenceNumber++; 00175 _tmpMessage.header.flags = 0; 00176 memcpy(_tmpMessage.data, buf, len); 00177 00178 return route(&_tmpMessage, sizeof(RoutedMessageHeader)+len); 00179 } 00180 00181 //////////////////////////////////////////////////////////////////// 00182 uint8_t RF22Router::route(RoutedMessage* message, uint8_t messageLen) 00183 { 00184 // Reliably deliver it if possible. See if we have a route: 00185 uint8_t next_hop = RF22_BROADCAST_ADDRESS; 00186 if (message->header.dest != RF22_BROADCAST_ADDRESS) 00187 { 00188 RoutingTableEntry* route = getRouteTo(message->header.dest); 00189 if (!route) 00190 return RF22_ROUTER_ERROR_NO_ROUTE; 00191 next_hop = route->next_hop; 00192 } 00193 00194 if (!RF22ReliableDatagram::sendtoWait((uint8_t*)message, messageLen, next_hop)) 00195 return RF22_ROUTER_ERROR_UNABLE_TO_DELIVER; 00196 00197 return RF22_ROUTER_ERROR_NONE; 00198 } 00199 00200 //////////////////////////////////////////////////////////////////// 00201 // Subclasses may want to override this to peek at messages going past 00202 void RF22Router::peekAtMessage(RoutedMessage* message, uint8_t messageLen) 00203 { 00204 // Default does nothing 00205 } 00206 00207 //////////////////////////////////////////////////////////////////// 00208 boolean RF22Router::recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* source, uint8_t* dest, uint8_t* id, uint8_t* flags) 00209 { 00210 uint8_t tmpMessageLen = sizeof(_tmpMessage); 00211 uint8_t _from; 00212 uint8_t _to; 00213 uint8_t _id; 00214 uint8_t _flags; 00215 if (RF22ReliableDatagram::recvfromAck((uint8_t*)&_tmpMessage, &tmpMessageLen, &_from, &_to, &_id, &_flags)) 00216 { 00217 // Here we simulate networks with limited visibility between nodes 00218 // so we can test routing 00219 #ifdef RF22_TEST_NETWORK 00220 if ( 00221 #if RF22_TEST_NETWORK==1 00222 // This looks like 1-2-3-4 00223 (_thisAddress == 1 && _from == 2) 00224 || (_thisAddress == 2 && (_from == 1 || _from == 3)) 00225 || (_thisAddress == 3 && (_from == 2 || _from == 4)) 00226 || (_thisAddress == 4 && _from == 3) 00227 00228 #elif RF22_TEST_NETWORK==2 00229 // This looks like 1-2-4 00230 // | | | 00231 // --3-- 00232 (_thisAddress == 1 && (_from == 2 || _from == 3)) 00233 || _thisAddress == 2 00234 || _thisAddress == 3 00235 || (_thisAddress == 4 && (_from == 2 || _from == 3)) 00236 00237 #elif RF22_TEST_NETWORK==3 00238 // This looks like 1-2-4 00239 // | | 00240 // --3-- 00241 (_thisAddress == 1 && (_from == 2 || _from == 3)) 00242 || (_thisAddress == 2 && (_from == 1 || _from == 4)) 00243 || (_thisAddress == 3 && (_from == 1 || _from == 4)) 00244 || (_thisAddress == 4 && (_from == 2 || _from == 3)) 00245 00246 #elif RF22_TEST_NETWORK==4 00247 // This looks like 1-2-3 00248 // | 00249 // 4 00250 (_thisAddress == 1 && _from == 2) 00251 || _thisAddress == 2 00252 || (_thisAddress == 3 && _from == 2) 00253 || (_thisAddress == 4 && _from == 2) 00254 00255 #endif 00256 ) 00257 { 00258 // OK 00259 } 00260 else 00261 { 00262 return false; // Pretend we got nothing 00263 } 00264 #endif 00265 00266 peekAtMessage(&_tmpMessage, tmpMessageLen); 00267 // See if its for us or has to be routed 00268 if (_tmpMessage.header.dest == _thisAddress || _tmpMessage.header.dest == RF22_BROADCAST_ADDRESS) 00269 { 00270 // Deliver it here 00271 if (source) *source = _tmpMessage.header.source; 00272 if (dest) *dest = _tmpMessage.header.dest; 00273 if (id) *id = _tmpMessage.header.id; 00274 if (flags) *flags = _tmpMessage.header.flags; 00275 uint8_t msgLen = tmpMessageLen - sizeof(RoutedMessageHeader); 00276 if (*len > msgLen) 00277 *len = msgLen; 00278 memcpy(buf, _tmpMessage.data, *len); 00279 return true; // Its for you! 00280 } 00281 else if ( _tmpMessage.header.dest != RF22_BROADCAST_ADDRESS 00282 && _tmpMessage.header.hops++ < _max_hops) 00283 { 00284 // Maybe it has to be routed to the next hop 00285 // REVISIT: if it fails due to no route or unable to deliver to the next hop, 00286 // tell the originator. BUT HOW? 00287 route(&_tmpMessage, tmpMessageLen); 00288 } 00289 // Discard it and maybe wait for another 00290 } 00291 return false; 00292 } 00293 00294 //////////////////////////////////////////////////////////////////// 00295 boolean RF22Router::recvfromAckTimeout(uint8_t* buf, uint8_t* len, uint16_t timeout, uint8_t* source, uint8_t* dest, uint8_t* id, uint8_t* flags) 00296 { 00297 Timer t; 00298 00299 t.start(); 00300 unsigned long endtime = t.read_ms() + timeout; 00301 while (t.read_ms() < endtime) 00302 { 00303 if (recvfromAck(buf, len, source, dest, id, flags)) 00304 return true; 00305 } 00306 return false; 00307 }
Generated on Wed Jul 13 2022 22:24:22 by
