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 // RF22Mesh.h
charly 0:79c6d0071c4c 2 //
charly 0:79c6d0071c4c 3 // Author: Mike McCauley (mikem@open.com.au)
charly 0:79c6d0071c4c 4 // Copyright (C) 2011 Mike McCauley
charly 5:0386600f3408 5 // $Id: RF22Mesh.h,v 1.4 2012/05/30 01:51:25 mikem Exp $
charly 0:79c6d0071c4c 6 // ported to mbed by Karl Zweimueller
charly 0:79c6d0071c4c 7
charly 0:79c6d0071c4c 8 #ifndef RF22Mesh_h
charly 0:79c6d0071c4c 9 #define RF22Mesh_h
charly 0:79c6d0071c4c 10
charly 0:79c6d0071c4c 11 #include <RF22Router.h>
charly 0:79c6d0071c4c 12
charly 0:79c6d0071c4c 13 // Types of RF22Mesh message, used to set msgType in the RF22MeshHeader
charly 0:79c6d0071c4c 14 #define RF22_MESH_MESSAGE_TYPE_APPLICATION 0
charly 0:79c6d0071c4c 15 #define RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST 1
charly 0:79c6d0071c4c 16 #define RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE 2
charly 0:79c6d0071c4c 17 #define RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE 3
charly 0:79c6d0071c4c 18
charly 0:79c6d0071c4c 19 /////////////////////////////////////////////////////////////////////
charly 0:79c6d0071c4c 20 /// \class RF22Mesh RF22Mesh.h <RF22Mesh.h>
charly 0:79c6d0071c4c 21 /// \brief RF22 subclass for sending addressed, optionally acknowledged datagrams
charly 0:79c6d0071c4c 22 /// multi-hop routed across a network, with automatic route discovery
charly 0:79c6d0071c4c 23 ///
charly 0:79c6d0071c4c 24 /// Extends RF22Router to add automatic route discovery within a mesh of adjacent nodes,
charly 0:79c6d0071c4c 25 /// and route signalling.
charly 0:79c6d0071c4c 26 ///
charly 0:79c6d0071c4c 27 /// Unlike RF22Router, RF22Mesh can be used in networks where the network topology is fluid, or unknown,
charly 0:79c6d0071c4c 28 /// or if nodes can mode around or go in or out of service. When a node wants to send a
charly 0:79c6d0071c4c 29 /// message to another node, it will automcatically discover a route to the destaintion node and use it.
charly 0:79c6d0071c4c 30 /// If the route becomes unavailable, a new route will be discovered.
charly 0:79c6d0071c4c 31 ///
charly 0:79c6d0071c4c 32 /// \par Route Discovery
charly 0:79c6d0071c4c 33 ///
charly 0:79c6d0071c4c 34 /// When a RF22Mesh mesh node is initialised, it doe not know any routes to any other nodes
charly 0:79c6d0071c4c 35 /// (see RF22Router for details on route and the routing table).
charly 0:79c6d0071c4c 36 /// When you attempt to send a message with sendtoWait, will first check to see if there is a route to the
charly 0:79c6d0071c4c 37 /// destinastion node in the routing tabl;e. If not, it wil initialite 'Route Discovery'.
charly 0:79c6d0071c4c 38 /// When a node needs to discover a route to another node, it broadcasts MeshRouteDiscoveryMessage
charly 0:79c6d0071c4c 39 /// with a message type of RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST.
charly 0:79c6d0071c4c 40 /// Any node that receives such a request checks to see if it is a request for a route to itself
charly 0:79c6d0071c4c 41 /// (in which case it makes a unicast reply to the originating node with a
charly 0:79c6d0071c4c 42 /// MeshRouteDiscoveryMessage
charly 0:79c6d0071c4c 43 /// with a message type of RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE)
charly 0:79c6d0071c4c 44 /// otherwise it rebroadcasts the request, after adding itself to the list of nodes visited so
charly 0:79c6d0071c4c 45 /// far by the request.
charly 0:79c6d0071c4c 46 ///
charly 0:79c6d0071c4c 47 /// If a node receives a RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST that already has itself
charly 0:79c6d0071c4c 48 /// listed in the visited nodes, it knows it has already seen and rebroadcast this request,
charly 0:79c6d0071c4c 49 /// and threfore ignores it. This prevents broadcast storms.
charly 0:79c6d0071c4c 50 /// When a node receives a RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST it can use the list of
charly 0:79c6d0071c4c 51 /// nodes aready visited to deduce routes back towards the originating (requesting node).
charly 0:79c6d0071c4c 52 /// This also means that when the destination node of the request is reached, it (and all
charly 0:79c6d0071c4c 53 /// the previous nodes the request visited) will have a route back to the originating node.
charly 0:79c6d0071c4c 54 /// This means the unicast RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE
charly 0:79c6d0071c4c 55 /// reply will be routed successfully back to the original route requester.
charly 0:79c6d0071c4c 56 ///
charly 0:79c6d0071c4c 57 /// The RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE sent back by the destination node contains
charly 0:79c6d0071c4c 58 /// the full list of nodes that were visited on the way to the destination.
charly 0:79c6d0071c4c 59 /// Therefore, intermediate nodes that route the reply back towards the originating node can use the
charly 0:79c6d0071c4c 60 /// node list in the reply to deduce routes to all the nodes between it and the destination node.
charly 0:79c6d0071c4c 61 ///
charly 0:79c6d0071c4c 62 /// Therefore, RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST and
charly 0:79c6d0071c4c 63 /// RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE together ensure the original requester and all
charly 0:79c6d0071c4c 64 /// the intermediate nodes know how to route to the source and destination nodes and every node along the path.
charly 0:79c6d0071c4c 65 ///
charly 0:79c6d0071c4c 66 /// Note that there is a race condition here that can effect routing on multipath routes. For example,
charly 0:79c6d0071c4c 67 /// if the route to the destination can traverse several paths, last reply from the destination
charly 0:79c6d0071c4c 68 /// will be the one used.
charly 0:79c6d0071c4c 69 ///
charly 0:79c6d0071c4c 70 /// \par Route Failure
charly 0:79c6d0071c4c 71 ///
charly 0:79c6d0071c4c 72 /// RF22Router (and therefore RF22Mesh) use reliable hop-to-hop delivery of messages using
charly 0:79c6d0071c4c 73 /// hop-to-hop acknowledgements, but not end-to-end acknowledgements. When sendtoWait() returns,
charly 0:79c6d0071c4c 74 /// you know that the message has been delivered to the next hop, but not if it is (or even if it can be)
charly 0:79c6d0071c4c 75 /// delivered to the destination node. If during the course of hop-to-hop routing of a message,
charly 0:79c6d0071c4c 76 /// one of the intermediate RF22Mesh nodes finds it cannot deliver to the next hop
charly 0:79c6d0071c4c 77 /// (say due to a lost route or no acknwledgement from the next hop), it replies to the
charly 0:79c6d0071c4c 78 /// originator with a unicast MeshRouteFailureMessage RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE message.
charly 0:79c6d0071c4c 79 /// Intermediate nodes (on the way beack to the originator)
charly 0:79c6d0071c4c 80 /// and the originating node use this message to delete the route to the destination
charly 0:79c6d0071c4c 81 /// node of the original message. This means that if a route to a destination becomes unusable
charly 0:79c6d0071c4c 82 /// (either because an intermediate node is off the air, or has moved out of range) a new route
charly 0:79c6d0071c4c 83 /// will be established the next time a message is to be sent.
charly 0:79c6d0071c4c 84 ///
charly 0:79c6d0071c4c 85 /// \par Message Format
charly 0:79c6d0071c4c 86 ///
charly 0:79c6d0071c4c 87 /// RF22Mesh uses a number of message formats layered on top of RF22Router:
charly 0:79c6d0071c4c 88 /// - MeshApplicationMessage (message type RF22_MESH_MESSAGE_TYPE_APPLICATION).
charly 0:79c6d0071c4c 89 /// Carries an application layer message for the caller of RF22Mesh
charly 0:79c6d0071c4c 90 /// - MeshRouteDiscoveryMessage (message types RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST
charly 0:79c6d0071c4c 91 /// and RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE). Carries Route Discovery messages
charly 0:79c6d0071c4c 92 /// (broadcast) and replies (unicast).
charly 0:79c6d0071c4c 93 /// - MeshRouteFailureMessage (message type RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE) Informs nodes of
charly 0:79c6d0071c4c 94 /// route failures.
charly 0:79c6d0071c4c 95 ///
charly 0:79c6d0071c4c 96 /// Part of the Arduino RF22 library for operating with HopeRF RF22 compatible transceivers
charly 0:79c6d0071c4c 97 /// (see http://www.hoperf.com)
charly 0:79c6d0071c4c 98 class RF22Mesh : public RF22Router
charly 0:79c6d0071c4c 99 {
charly 0:79c6d0071c4c 100 public:
charly 0:79c6d0071c4c 101
charly 0:79c6d0071c4c 102 /// The maximum length permitted for the application payload data in a RF22Mesh message
charly 0:79c6d0071c4c 103 #define RF22_MESH_MAX_MESSAGE_LEN (RF22_ROUTER_MAX_MESSAGE_LEN - sizeof(RF22Mesh::MeshMessageHeader))
charly 0:79c6d0071c4c 104
charly 0:79c6d0071c4c 105 /// Structure of the basic RF22Mesh header.
charly 0:79c6d0071c4c 106 typedef struct
charly 0:79c6d0071c4c 107 {
charly 0:79c6d0071c4c 108 uint8_t msgType; ///< Type of RF22Mesh message, one of RF22_MESH_MESSAGE_TYPE_*
charly 0:79c6d0071c4c 109 } MeshMessageHeader;
charly 0:79c6d0071c4c 110
charly 0:79c6d0071c4c 111 /// Signals an application layer message for the caller of RF22Mesh
charly 0:79c6d0071c4c 112 typedef struct
charly 0:79c6d0071c4c 113 {
charly 0:79c6d0071c4c 114 MeshMessageHeader header; ///< msgType = RF22_MESH_MESSAGE_TYPE_APPLICATION
charly 0:79c6d0071c4c 115 uint8_t data[RF22_MESH_MAX_MESSAGE_LEN]; ///< Applicaiotn layer payload data
charly 0:79c6d0071c4c 116 } MeshApplicationMessage;
charly 0:79c6d0071c4c 117
charly 0:79c6d0071c4c 118 /// Signals a route discovery request or reply
charly 0:79c6d0071c4c 119 /// At present only supports physical dest addresses of length 1 octet
charly 0:79c6d0071c4c 120 typedef struct
charly 0:79c6d0071c4c 121 {
charly 0:79c6d0071c4c 122 MeshMessageHeader header; ///< msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_*
charly 5:0386600f3408 123 uint8_t destlen; ///< Reserved. Must be 1.g
charly 0:79c6d0071c4c 124 uint8_t dest; ///< The address of the destination node whose route is being sought
charly 0:79c6d0071c4c 125 uint8_t route[RF22_MESH_MAX_MESSAGE_LEN - 1]; ///< List of node addresses visited so far. Length is implcit
charly 0:79c6d0071c4c 126 } MeshRouteDiscoveryMessage;
charly 0:79c6d0071c4c 127
charly 0:79c6d0071c4c 128 /// Signals a route failure
charly 0:79c6d0071c4c 129 typedef struct
charly 0:79c6d0071c4c 130 {
charly 0:79c6d0071c4c 131 MeshMessageHeader header; ///< msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE
charly 0:79c6d0071c4c 132 uint8_t dest; ///< The address of the destination towards which the route failed
charly 0:79c6d0071c4c 133 } MeshRouteFailureMessage;
charly 0:79c6d0071c4c 134
charly 0:79c6d0071c4c 135 /// Constructor.
charly 0:79c6d0071c4c 136 /// \param[in] thisAddress The address to assign to this node. Defaults to 0
charly 0:79c6d0071c4c 137 /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF22 before
charly 5:0386600f3408 138 /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega)
charly 0:79c6d0071c4c 139 /// \param[in] interrupt The interrupt number to use. Default is interrupt 0 (Arduino input pin 2)
charly 5:0386600f3408 140 RF22Mesh(uint8_t thisAddress , PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt );
charly 0:79c6d0071c4c 141
charly 0:79c6d0071c4c 142 /// Sends a message to the destination node. Initialises the RF22Router message header
charly 0:79c6d0071c4c 143 /// (the SOURCE address is set to the address of this node, HOPS to 0) and calls
charly 0:79c6d0071c4c 144 /// route() which looks up in the routing table the next hop to deliver to.
charly 0:79c6d0071c4c 145 /// If no route is known, initiates route discovery and waits for a reply.
charly 0:79c6d0071c4c 146 /// Then sends the message to the next hop
charly 0:79c6d0071c4c 147 /// Then waits for an acknowledgement from the next hop
charly 0:79c6d0071c4c 148 /// (but not from the destination node (if that is different).
charly 0:79c6d0071c4c 149 /// \param [in] buf The application message data
charly 0:79c6d0071c4c 150 /// \param [in] len Number of octets in the application message data. 0 is permitted
charly 0:79c6d0071c4c 151 /// \param [in] dest The destination node address
charly 0:79c6d0071c4c 152 /// \return The result code:
charly 0:79c6d0071c4c 153 /// - RF22_ROUTER_ERROR_NONE Message was routed and deliverd to the next hop
charly 0:79c6d0071c4c 154 /// (not necessarily to the final dest address)
charly 0:79c6d0071c4c 155 /// - RF22_ROUTER_ERROR_NO_ROUTE There was no route for dest in the local routing table
charly 0:79c6d0071c4c 156 /// - RF22_ROUTER_ERROR_UNABLE_TO_DELIVER Noyt able to deliver to the next hop
charly 0:79c6d0071c4c 157 /// (usually because it dod not acknowledge due to being off the air or out of range
charly 0:79c6d0071c4c 158 uint8_t sendtoWait(uint8_t* buf, uint8_t len, uint8_t dest);
charly 0:79c6d0071c4c 159
charly 0:79c6d0071c4c 160 /// Starts the receiver if it is not running already.
charly 0:79c6d0071c4c 161 /// If there is a valid application layer message available for this node (or RF22_BROADCAST_ADDRESS),
charly 0:79c6d0071c4c 162 /// send an acknowledgement to the last hop
charly 0:79c6d0071c4c 163 /// address (blocking until this is complete), then copy the application message payload data
charly 0:79c6d0071c4c 164 /// to buf and return true
charly 0:79c6d0071c4c 165 /// else return false.
charly 0:79c6d0071c4c 166 /// If a message is copied, *len is set to the length..
charly 0:79c6d0071c4c 167 /// If from is not NULL, the originator SOURCE address is placed in *source.
charly 0:79c6d0071c4c 168 /// If to is not NULL, the DEST address is placed in *dest. This might be this nodes address or
charly 0:79c6d0071c4c 169 /// RF22_BROADCAST_ADDRESS.
charly 0:79c6d0071c4c 170 /// This is the preferred function for getting messages addressed to this node.
charly 0:79c6d0071c4c 171 /// If the message is not a broadcast, acknowledge to the sender before returning.
charly 0:79c6d0071c4c 172 /// \param[in] buf Location to copy the received message
charly 0:79c6d0071c4c 173 /// \param[in,out] len Available space in buf. Set to the actual number of octets copied.
charly 0:79c6d0071c4c 174 /// \param[in] source If present and not NULL, the referenced uint8_t will be set to the SOURCE address
charly 0:79c6d0071c4c 175 /// \param[in] dest If present and not NULL, the referenced uint8_t will be set to the DEST address
charly 0:79c6d0071c4c 176 /// \param[in] id If present and not NULL, the referenced uint8_t will be set to the ID
charly 0:79c6d0071c4c 177 /// \param[in] flags If present and not NULL, the referenced uint8_t will be set to the FLAGS
charly 0:79c6d0071c4c 178 /// (not just those addressed to this node).
charly 0:79c6d0071c4c 179 /// \return true if a valid message was recvived for this node and copied to buf
charly 0:79c6d0071c4c 180 boolean recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* source = NULL, uint8_t* dest = NULL, uint8_t* id = NULL, uint8_t* flags = NULL);
charly 0:79c6d0071c4c 181
charly 0:79c6d0071c4c 182 /// Starts the receiver if it is not running already.
charly 0:79c6d0071c4c 183 /// Similar to recvfromAck(), this will block until either a valid application layer
charly 0:79c6d0071c4c 184 /// message available for this node
charly 0:79c6d0071c4c 185 /// or the timeout expires.
charly 0:79c6d0071c4c 186 /// \param[in] buf Location to copy the received message
charly 0:79c6d0071c4c 187 /// \param[in,out] len Available space in buf. Set to the actual number of octets copied.
charly 0:79c6d0071c4c 188 /// \param[in] timeout Maximum time to wait in milliseconds
charly 0:79c6d0071c4c 189 /// \param[in] source If present and not NULL, the referenced uint8_t will be set to the SOURCE address
charly 0:79c6d0071c4c 190 /// \param[in] dest If present and not NULL, the referenced uint8_t will be set to the DEST address
charly 0:79c6d0071c4c 191 /// \param[in] id If present and not NULL, the referenced uint8_t will be set to the ID
charly 0:79c6d0071c4c 192 /// \param[in] flags If present and not NULL, the referenced uint8_t will be set to the FLAGS
charly 0:79c6d0071c4c 193 /// (not just those addressed to this node).
charly 0:79c6d0071c4c 194 /// \return true if a valid message was copied to buf
charly 0:79c6d0071c4c 195 boolean recvfromAckTimeout(uint8_t* buf, uint8_t* len, uint16_t timeout, uint8_t* source = NULL, uint8_t* dest = NULL, uint8_t* id = NULL, uint8_t* flags = NULL);
charly 0:79c6d0071c4c 196
charly 0:79c6d0071c4c 197 protected:
charly 0:79c6d0071c4c 198
charly 0:79c6d0071c4c 199 /// Internal function that inspects messages being received and adjusts the routing table if necessary.
charly 0:79c6d0071c4c 200 /// Called by recvfromAck() immediately after it gets the message from RF22ReliableDatagram
charly 0:79c6d0071c4c 201 /// \param [in] message Pointer to the RF22Router message that was received.
charly 0:79c6d0071c4c 202 /// \param [in] messageLen Length of message in octets
charly 0:79c6d0071c4c 203 virtual void peekAtMessage(RoutedMessage* message, uint8_t messageLen);
charly 0:79c6d0071c4c 204
charly 0:79c6d0071c4c 205 /// Internal function that inspects messages being received and adjusts the routing table if necessary.
charly 0:79c6d0071c4c 206 /// This is virtual, which lets subclasses override or intercept the route() function.
charly 0:79c6d0071c4c 207 /// Called by sendtoWait after the message header has been filled in.
charly 0:79c6d0071c4c 208 /// \param [in] message Pointer to the RF22Router message to be sent.
charly 0:79c6d0071c4c 209 /// \param [in] messageLen Length of message in octets
charly 0:79c6d0071c4c 210 virtual uint8_t route(RoutedMessage* message, uint8_t messageLen);
charly 0:79c6d0071c4c 211
charly 0:79c6d0071c4c 212 /// Try to resolve a route for the given address. Blocks while discovering the route
charly 0:79c6d0071c4c 213 /// which may take up to 4000 msec.
charly 0:79c6d0071c4c 214 /// Virtual so subclasses can override.
charly 0:79c6d0071c4c 215 /// \param [in] address The physical addres to resolve
charly 0:79c6d0071c4c 216 /// \return true if the address was resolved and added to the local routing table
charly 0:79c6d0071c4c 217 virtual boolean doArp(uint8_t address);
charly 0:79c6d0071c4c 218
charly 0:79c6d0071c4c 219 /// Tests if the given address of length addresslen is indentical to the
charly 0:79c6d0071c4c 220 /// physical addres of this node.
charly 0:79c6d0071c4c 221 /// RF22Mesh always ikmplements p[hysical addresses as the 1 octet address of the node
charly 0:79c6d0071c4c 222 /// given by _thisAddress
charly 0:79c6d0071c4c 223 /// Called by recvfromAck() to test whether a RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST
charly 0:79c6d0071c4c 224 /// is for this node.
charly 0:79c6d0071c4c 225 /// Subclasses may want to override to implemnt mode complicated or longer physical addresses
charly 0:79c6d0071c4c 226 /// \param [in] address Address of the pyysical addres being tested
charly 0:79c6d0071c4c 227 /// \param [in] addresslen Lengthof the address in bytes
charly 0:79c6d0071c4c 228 /// \return true if the physical address of this node is identical to address
charly 0:79c6d0071c4c 229 virtual boolean isPhysicalAddress(uint8_t* address, uint8_t addresslen);
charly 0:79c6d0071c4c 230
charly 0:79c6d0071c4c 231 private:
charly 0:79c6d0071c4c 232 /// Temporary mesage buffer
charly 0:79c6d0071c4c 233 static uint8_t _tmpMessage[RF22_ROUTER_MAX_MESSAGE_LEN];
charly 0:79c6d0071c4c 234
charly 0:79c6d0071c4c 235 };
charly 0:79c6d0071c4c 236
charly 0:79c6d0071c4c 237 #endif