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

More Info about RFM22-modules like connecting and a demo-program see RF22-Notebook

Committer:
charly
Date:
Mon Sep 02 20:32:54 2013 +0000
Revision:
9:4002a2c117cc
Parent:
5:0386600f3408
removed DEBUG-LEDs LED1 .. LED4 as they make problems on other platforms (KL25Z)

Who changed what in which revision?

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