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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RF22Router.cpp Source File

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 }