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
RF22ReliableDatagram.h@5:0386600f3408, 2013-03-02 (annotated)
- Committer:
- charly
- Date:
- Sat Mar 02 20:49:07 2013 +0000
- Revision:
- 5:0386600f3408
- Parent:
- 0:79c6d0071c4c
Updated to Revision 1.25 of original package
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
charly | 0:79c6d0071c4c | 1 | // RF22ReliableDatagram.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: RF22ReliableDatagram.h,v 1.7 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 RF22ReliableDatagram_h |
charly | 0:79c6d0071c4c | 9 | #define RF22ReliableDatagram_h |
charly | 0:79c6d0071c4c | 10 | |
charly | 0:79c6d0071c4c | 11 | #include <RF22Datagram.h> |
charly | 0:79c6d0071c4c | 12 | |
charly | 0:79c6d0071c4c | 13 | // The acknowledgement bit in the FLAGS |
charly | 0:79c6d0071c4c | 14 | #define RF22_FLAGS_ACK 0x80 |
charly | 0:79c6d0071c4c | 15 | |
charly | 0:79c6d0071c4c | 16 | ///////////////////////////////////////////////////////////////////// |
charly | 0:79c6d0071c4c | 17 | /// \class RF22ReliableDatagram RF22ReliableDatagram.h <RF22ReliableDatagram.h> |
charly | 0:79c6d0071c4c | 18 | /// \brief RF22 subclass for sending addressed, acknowledged, retransmitted datagrams. |
charly | 0:79c6d0071c4c | 19 | /// |
charly | 0:79c6d0071c4c | 20 | /// Extends RF22Datagram to define addressed, reliable datagrams with acknowledgement and retransmission. |
charly | 0:79c6d0071c4c | 21 | /// Based on RF22Datagram, adds flags and sequence numbers. RF22ReliableDatagram is reliable in the sense |
charly | 0:79c6d0071c4c | 22 | /// that messages are acknowledged, and unacknowledged messages are retransmitted until acknowledged or the |
charly | 0:79c6d0071c4c | 23 | /// retries are exhausted. |
charly | 0:79c6d0071c4c | 24 | /// When addressed messages are sent (by sendtoWait()), it will wait for an ack, and retransmit |
charly | 0:79c6d0071c4c | 25 | /// after timeout until an ack is received or retries are exhausted. |
charly | 0:79c6d0071c4c | 26 | /// When addressed messages are collected by the application (by recvfromAck()), |
charly | 0:79c6d0071c4c | 27 | /// an acknowledgement is automatically sent. |
charly | 0:79c6d0071c4c | 28 | /// |
charly | 0:79c6d0071c4c | 29 | /// The retransmit timeout is randomly varied between timeout and timeout*2 to prevent collisions on all |
charly | 0:79c6d0071c4c | 30 | /// retries when 2 nodes happen to start sending at the same time . |
charly | 0:79c6d0071c4c | 31 | /// |
charly | 0:79c6d0071c4c | 32 | /// Each new message sent by sendtoWait() has its ID incremented. |
charly | 0:79c6d0071c4c | 33 | /// |
charly | 0:79c6d0071c4c | 34 | /// An ack consists of a message with: |
charly | 0:79c6d0071c4c | 35 | /// - TO set to the from address of the original message |
charly | 0:79c6d0071c4c | 36 | /// - FROM set to this node address |
charly | 0:79c6d0071c4c | 37 | /// - ID set to the ID of the original message |
charly | 0:79c6d0071c4c | 38 | /// - FLAGS with the RF22_FLAGS_ACK bit set |
charly | 0:79c6d0071c4c | 39 | /// |
charly | 0:79c6d0071c4c | 40 | /// Part of the Arduino RF22 library for operating with HopeRF RF22 compatible transceivers |
charly | 0:79c6d0071c4c | 41 | /// (see http://www.hoperf.com) |
charly | 0:79c6d0071c4c | 42 | class RF22ReliableDatagram : public RF22Datagram |
charly | 0:79c6d0071c4c | 43 | { |
charly | 0:79c6d0071c4c | 44 | public: |
charly | 0:79c6d0071c4c | 45 | /// Constructor. |
charly | 0:79c6d0071c4c | 46 | /// \param[in] thisAddress The address to assign to this node. Defaults to 0 |
charly | 0:79c6d0071c4c | 47 | /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF22 before |
charly | 5:0386600f3408 | 48 | /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega) |
charly | 0:79c6d0071c4c | 49 | /// \param[in] interrupt The interrupt number to use. Default is interrupt 0 (Arduino input pin 2) |
charly | 0:79c6d0071c4c | 50 | RF22ReliableDatagram(uint8_t thisAddress ,PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt ); |
charly | 0:79c6d0071c4c | 51 | |
charly | 0:79c6d0071c4c | 52 | /// Sets the minimum retransmit timeout. If sendtoWait is waiting for an ack |
charly | 0:79c6d0071c4c | 53 | /// longer than this time (in milliseconds), |
charly | 0:79c6d0071c4c | 54 | /// it will retransmit the message. Defaults to 200ms. The timeout is measured from the end of |
charly | 0:79c6d0071c4c | 55 | /// transmission of the message. It must be at least longer than the the transmit |
charly | 5:0386600f3408 | 56 | /// time of the acknowledgement (preamble+6 octets) plus the latency/poll time of the receiver. |
charly | 5:0386600f3408 | 57 | /// For fast modulation schemes you can considerably shorten this time. |
charly | 0:79c6d0071c4c | 58 | /// The actual timeout is randomly varied between timeout and timeout*2. |
charly | 0:79c6d0071c4c | 59 | /// \param[in] timeout The new timeout period in milliseconds |
charly | 0:79c6d0071c4c | 60 | void setTimeout(uint16_t timeout); |
charly | 0:79c6d0071c4c | 61 | |
charly | 0:79c6d0071c4c | 62 | /// Sets the max number of retries. Defaults to 3. If set to 0, the message will only be sent once. |
charly | 0:79c6d0071c4c | 63 | /// sendtoWait will give up and return false if there is no ack received after all transmissions time out. |
charly | 0:79c6d0071c4c | 64 | /// param[in] retries The maximum number a retries. |
charly | 0:79c6d0071c4c | 65 | void setRetries(uint8_t retries); |
charly | 0:79c6d0071c4c | 66 | |
charly | 0:79c6d0071c4c | 67 | /// Send the message and waits for an ack. Returns true if an acknowledgement is received. |
charly | 0:79c6d0071c4c | 68 | /// Synchronous: any message other than the desired ACK received while waiting is discarded. |
charly | 0:79c6d0071c4c | 69 | /// Blocks until an ACK is received or all retries are exhausted (ie up to retries*timeout milliseconds). |
charly | 0:79c6d0071c4c | 70 | /// \param[in] address The address to send the message to. |
charly | 0:79c6d0071c4c | 71 | /// \param[in] buf Pointer to the binary message to send |
charly | 0:79c6d0071c4c | 72 | /// \param[in] len Number of octets to send |
charly | 0:79c6d0071c4c | 73 | /// \return true if the message was transmitted and an acknowledgement was received. |
charly | 0:79c6d0071c4c | 74 | boolean sendtoWait(uint8_t* buf, uint8_t len, uint8_t address); |
charly | 0:79c6d0071c4c | 75 | |
charly | 0:79c6d0071c4c | 76 | /// If there is a valid message available for this node, send an acknowledgement to the SRC |
charly | 0:79c6d0071c4c | 77 | /// address (blocking until this is complete), then copy the message to buf and return true |
charly | 0:79c6d0071c4c | 78 | /// else return false. |
charly | 0:79c6d0071c4c | 79 | /// If a message is copied, *len is set to the length.. |
charly | 0:79c6d0071c4c | 80 | /// If from is not NULL, the SRC address is placed in *from. |
charly | 0:79c6d0071c4c | 81 | /// If to is not NULL, the DEST address is placed in *to. |
charly | 0:79c6d0071c4c | 82 | /// This is the preferred function for getting messages addressed to this node. |
charly | 0:79c6d0071c4c | 83 | /// If the message is not a broadcast, acknowledge to the sender before returning. |
charly | 0:79c6d0071c4c | 84 | /// You should be sure to call this function frequently enough to not miss any messages |
charly | 0:79c6d0071c4c | 85 | /// It is recommended that you call it in your main loop. |
charly | 0:79c6d0071c4c | 86 | /// \param[in] buf Location to copy the received message |
charly | 0:79c6d0071c4c | 87 | /// \param[in,out] len Available space in buf. Set to the actual number of octets copied. |
charly | 0:79c6d0071c4c | 88 | /// \param[in] from If present and not NULL, the referenced uint8_t will be set to the SRC address |
charly | 0:79c6d0071c4c | 89 | /// \param[in] to If present and not NULL, the referenced uint8_t will be set to the DEST address |
charly | 0:79c6d0071c4c | 90 | /// \param[in] id If present and not NULL, the referenced uint8_t will be set to the ID |
charly | 0:79c6d0071c4c | 91 | /// \param[in] flags If present and not NULL, the referenced uint8_t will be set to the FLAGS |
charly | 0:79c6d0071c4c | 92 | /// (not just those addressed to this node). |
charly | 0:79c6d0071c4c | 93 | /// \return true if a valid message was copied to buf |
charly | 0:79c6d0071c4c | 94 | boolean recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* from = NULL, uint8_t* to = NULL, uint8_t* id = NULL, uint8_t* flags = NULL); |
charly | 0:79c6d0071c4c | 95 | |
charly | 0:79c6d0071c4c | 96 | /// Similar to recvfromAck(), this will block until either a valid message available for this node |
charly | 0:79c6d0071c4c | 97 | /// or the timeout expires. Starts the receiver automatically. |
charly | 0:79c6d0071c4c | 98 | /// You should be sure to call this function frequently enough to not miss any messages |
charly | 0:79c6d0071c4c | 99 | /// It is recommended that you call it in your main loop. |
charly | 0:79c6d0071c4c | 100 | /// \param[in] buf Location to copy the received message |
charly | 0:79c6d0071c4c | 101 | /// \param[in,out] len Available space in buf. Set to the actual number of octets copied. |
charly | 0:79c6d0071c4c | 102 | /// \param[in] timeout Maximum time to wait in milliseconds |
charly | 0:79c6d0071c4c | 103 | /// \param[in] from If present and not NULL, the referenced uint8_t will be set to the SRC address |
charly | 0:79c6d0071c4c | 104 | /// \param[in] to If present and not NULL, the referenced uint8_t will be set to the DEST address |
charly | 0:79c6d0071c4c | 105 | /// \param[in] id If present and not NULL, the referenced uint8_t will be set to the ID |
charly | 0:79c6d0071c4c | 106 | /// \param[in] flags If present and not NULL, the referenced uint8_t will be set to the FLAGS |
charly | 0:79c6d0071c4c | 107 | /// (not just those addressed to this node). |
charly | 0:79c6d0071c4c | 108 | /// \return true if a valid message was copied to buf |
charly | 0:79c6d0071c4c | 109 | boolean recvfromAckTimeout(uint8_t* buf, uint8_t* len, uint16_t timeout, uint8_t* from = NULL, uint8_t* to = NULL, uint8_t* id = NULL, uint8_t* flags = NULL); |
charly | 0:79c6d0071c4c | 110 | |
charly | 0:79c6d0071c4c | 111 | /// Returns the number of retransmissions |
charly | 0:79c6d0071c4c | 112 | /// we have had to send |
charly | 0:79c6d0071c4c | 113 | /// \return The number of retransmissions since initialisation. |
charly | 0:79c6d0071c4c | 114 | uint16_t retransmissions(); |
charly | 0:79c6d0071c4c | 115 | |
charly | 0:79c6d0071c4c | 116 | protected: |
charly | 0:79c6d0071c4c | 117 | /// Send an ACK for the message id to the given from address |
charly | 0:79c6d0071c4c | 118 | /// Blocks until the ACK has been sent |
charly | 0:79c6d0071c4c | 119 | void acknowledge(uint8_t id, uint8_t from); |
charly | 0:79c6d0071c4c | 120 | |
charly | 0:79c6d0071c4c | 121 | /// Checks whether the message currently in the Rx buffer is a new message, not previously received |
charly | 0:79c6d0071c4c | 122 | /// based on the from address and the sequence. If it is new, it is acknowledged and returns true |
charly | 0:79c6d0071c4c | 123 | /// \return true if there is a message received and it is a new message |
charly | 0:79c6d0071c4c | 124 | boolean haveNewMessage(); |
charly | 0:79c6d0071c4c | 125 | |
charly | 0:79c6d0071c4c | 126 | private: |
charly | 0:79c6d0071c4c | 127 | /// Count of retransmissions we have had to send |
charly | 0:79c6d0071c4c | 128 | uint16_t _retransmissions; |
charly | 0:79c6d0071c4c | 129 | |
charly | 0:79c6d0071c4c | 130 | /// The last sequence number to be used |
charly | 0:79c6d0071c4c | 131 | /// Defaults to 0 |
charly | 0:79c6d0071c4c | 132 | uint8_t _lastSequenceNumber; |
charly | 0:79c6d0071c4c | 133 | |
charly | 0:79c6d0071c4c | 134 | // Retransmit timeout (milliseconds) |
charly | 0:79c6d0071c4c | 135 | /// Defaults to 200 |
charly | 0:79c6d0071c4c | 136 | uint16_t _timeout; |
charly | 0:79c6d0071c4c | 137 | |
charly | 0:79c6d0071c4c | 138 | // Retries (0 means one try only) |
charly | 0:79c6d0071c4c | 139 | /// Defaults to 3 |
charly | 0:79c6d0071c4c | 140 | uint8_t _retries; |
charly | 0:79c6d0071c4c | 141 | |
charly | 0:79c6d0071c4c | 142 | /// Array of the last seen sequence number indexed by node address that sent it |
charly | 0:79c6d0071c4c | 143 | /// It is used for duplicate detection. Duplicated messages are re-acknowledged when received |
charly | 0:79c6d0071c4c | 144 | /// (this is generally due to lost ACKs, causing the sender to retransmit, even though we have already |
charly | 0:79c6d0071c4c | 145 | /// received that message) |
charly | 0:79c6d0071c4c | 146 | uint8_t _seenIds[256]; |
charly | 0:79c6d0071c4c | 147 | |
charly | 0:79c6d0071c4c | 148 | |
charly | 0:79c6d0071c4c | 149 | }; |
charly | 0:79c6d0071c4c | 150 | |
charly | 0:79c6d0071c4c | 151 | #endif |