HopeRF
HRFReliableDatagram.h
1 // HRFReliableDatagram.h
2 //
3 // Author: Mike McCauley (mikem@airspayce.com)
4 // Copyright (C) 2009 Mike McCauley
5 // $Id: HRFReliableDatagram.h,v 1.1 2009/08/15 05:32:58 mikem Exp mikem $
6 
7 #ifndef HRFReliableDatagram_h
8 #define HRFReliableDatagram_h
9 
10 #include <HRFDatagram.h>
11 
12 // Mask for the Sequence Number in FLAG/SQN
13 #define HRF_SQN_MASK 0x7f
14 
15 // The acknowledgement bit in the FLAG/SQN
16 #define HRF_FLAG_ACK 0x80
17 
18 // The maximum payload length
19 #define HRF_MAX_RELIABLE_DATAGRAM_PAYLOAD HRF_MAX_DATAGRAM_PAYLOAD-1
20 
21 /////////////////////////////////////////////////////////////////////
22 /// \class HRFReliableDatagram HRFReliableDatagram.h <HRFReliableDatagram.h>
23 /// \brief Class for sending addressed, acknowledged, retransmitted datagrams.
24 ///
25 /// Extends HRFDatagram to define addressed, reliable datagrams with acknowledgement and retransmission.
26 /// Based on HRFDatagram, adds flags and sequence numbers. HRFReliableDatagram is reliable in the sense
27 /// that messages are acknowledged, and unacknowledged messages are retransmitted until acknowledged or the
28 /// retries are exhausted.
29 /// When addressed messages are collected by the application (recvfromAck), an acknowledgement is automatically sent.
30 /// When addressed messages are sent (by sendtoWait), it will wait for an ack, and retransmit
31 /// after timeout until an ack is received or retries are exhausted
32 /// ReliableDatagrams have format LEN DEST SRC FLAG/SQN payload FCS-LO FCS-HI
33 /// Low 7 bits of FLAG/SQN is the sequence number. Most significant bit is the ACK flag.
34 ///
35 /// Part of the Arduino HopeRF library for operating with HopeRF HM-TR transceivers
36 /// (see http://www.hoperf.com)
38 {
39 private:
40  /// The last sequence number to be used
41  /// Defaults to 0
42  uint8_t _lastSequenceNumber;
43 
44  // Retransmit timeout (milliseconds)
45  /// Defaults to 1000
46  long _timeout;
47 
48  // Retries (0 means one try only)
49  /// Defaults to 3
50  uint8_t _retries;
51 
52  /// Array of the last seen sequence number indexed by node address that sent it
53  /// It is used for duplicate detection. Duplicated messages are re-acknowledged when received
54  /// (this is generally due to lost ACKs, causing the sender to retransmit, even though we have already
55  /// received that message)
56  uint8_t _seenSequenceNumbers[256];
57 
58 public:
59  /// \param[in] serial The instance of HardwareSerial to use for IO. Defaults to &Serial,
60  /// \param[in] thisAddress The address to assign to this node. Defaults to 0
61  HRFReliableDatagram(HardwareSerial* serial = &Serial, uint8_t thisAddress = 0);
62 
63  /// Sets the retransmit timeout. If sendtoWait is waiting for an ack longer than this time (in milliseconds),
64  /// it will retransmit the message. Defaults to 1000ms. The timeout is measured from the beginning of
65  /// transmission of the message. It must be longer than the transmit time of the request plus the transmit
66  /// time of the acknowledgement (6 octets) plus the latency of the receiver.
67  /// \param[in] timeout The new timeout period in milliseconds
68  virtual void setTimeout(long timeout);
69 
70  /// Sets the max number of retries. Defaults to 3. If set to 0, the message will only be sent once.
71  /// sendtoWait will give up if there is no ack received after all transmissions time out.
72  /// param[in] retries The maximum number a retries.
73  virtual void setRetries(uint8_t retries);
74 
75  /// Send the message and waits for an ack. Returns true if an acknowledgement is received.
76  /// Synchronous: any message other than the desired ACK received while waiting is discarded.
77  /// Blocks until an ACK is received or all retries are exhausted (ie up to retries*timeout milliseconds).
78  /// \param[in] address The address to send the message to.
79  /// \param[in] buf Pointer to the binary message to send
80  /// \param[in] len Number of octets to send
81  /// \return true if the message was transmitted and an acknowledgement is received.
82  /// \return false if the message is too long (>HRF_MAX_DATAGRAM_PAYLOAD).
83  virtual uint8_t sendtoWait(uint8_t address, uint8_t* buf, uint8_t len);
84 
85  /// If there is a valid message available for this node, send an acknowledgement to the SRC
86  /// address (blocking until this is complete), then copy the message to buf and return true
87  /// else return false.
88  /// If a message is copied, *len is set to the length..
89  /// If from is not NULL, the SRC address is placed in *from.
90  /// If to is not NULL, the DEST address is placed in *to.
91  /// This is the preferred function for getting messages addressed to this node.
92  /// If the message is not a broadcast, acknowledge to the sender before returning.
93  /// \param[in] buf Location to copy the received message
94  /// \param[in] len Available space in buf. Set to the actual number of octets copied.
95  /// \param[in] from If present and not NULL, the referenced uint8_t will be set to the SRC address
96  /// \param[in] to If present and not NULL, the referenced uint8_t will be set to the DEST address
97  virtual uint8_t recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* from = NULL, uint8_t* to = NULL);
98 };
99 
100 #endif
101