User | Revision | Line number | New 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
|
|