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
RF22ReliableDatagram.h@9:46fb41f4259d, 2013-08-29 (annotated)
- 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?
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 |