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