Dependents:   New

Committer:
SangSTBK
Date:
Mon Jul 02 01:29:58 2012 +0000
Revision:
0:e16ffa7cb900
RF

Who changed what in which revision?

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