Library for HopeRF RFM22 transceiver module ported to mbed. Original Software from Mike McCauley (mikem@open.com.au) . See http://www.open.com.au/mikem/arduino/RF22/

Fork of RF22 by Karl Zweimüller

Committer:
floha
Date:
Thu Aug 29 21:57:14 2013 +0000
Revision:
9:46fb41f4259d
Parent:
5:0386600f3408
changed the LED default numbers in the RF22 constructor as the former values interfered with pins used on an KL25Z board. The library didn't work with those.

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 }