Library for HopeRF RFM22 / RFM22B transceiver module ported to mbed. Original Software from Mike McCauley (mikem@open.com.au) . See http://www.open.com.au/mikem/arduino/RF22/
Dependents: RF22_MAX_test_Send Geofence_receiver Geofence_sender Geofence_sender ... more
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 Tue Jul 12 2022 12:34:31 by 1.7.2