RadioHead
RHGenericDriver.h
1 // RHGenericDriver.h
2 // Author: Mike McCauley (mikem@airspayce.com)
3 // Copyright (C) 2014 Mike McCauley
4 // $Id: RHGenericDriver.h,v 1.23 2018/09/23 23:54:01 mikem Exp $
5 
6 #ifndef RHGenericDriver_h
7 #define RHGenericDriver_h
8 
9 #include <RadioHead.h>
10 
11 // Defines bits of the FLAGS header reserved for use by the RadioHead library and
12 // the flags available for use by applications
13 #define RH_FLAGS_RESERVED 0xf0
14 #define RH_FLAGS_APPLICATION_SPECIFIC 0x0f
15 #define RH_FLAGS_NONE 0
16 
17 // Default timeout for waitCAD() in ms
18 #define RH_CAD_DEFAULT_TIMEOUT 10000
19 
20 /////////////////////////////////////////////////////////////////////
21 /// \class RHGenericDriver RHGenericDriver.h <RHGenericDriver.h>
22 /// \brief Abstract base class for a RadioHead driver.
23 ///
24 /// This class defines the functions that must be provided by any RadioHead driver.
25 /// Different types of driver will implement all the abstract functions, and will perhaps override
26 /// other functions in this subclass, or perhaps add new functions specifically required by that driver.
27 /// Do not directly instantiate this class: it is only to be subclassed by driver classes.
28 ///
29 /// Subclasses are expected to implement a half-duplex, unreliable, error checked, unaddressed packet transport.
30 /// They are expected to carry a message payload with an appropriate maximum length for the transport hardware
31 /// and to also carry unaltered 4 message headers: TO, FROM, ID, FLAGS
32 ///
33 /// \par Headers
34 ///
35 /// Each message sent and received by a RadioHead driver includes 4 headers:
36 /// -TO The node address that the message is being sent to (broadcast RH_BROADCAST_ADDRESS (255) is permitted)
37 /// -FROM The node address of the sending node
38 /// -ID A message ID, distinct (over short time scales) for each message sent by a particilar node
39 /// -FLAGS A bitmask of flags. The most significant 4 bits are reserved for use by RadioHead. The least
40 /// significant 4 bits are reserved for applications.
42 {
43 public:
44  /// \brief Defines different operating modes for the transport hardware
45  ///
46  /// These are the different values that can be adopted by the _mode variable and
47  /// returned by the mode() member function,
48  typedef enum
49  {
50  RHModeInitialising = 0, ///< Transport is initialising. Initial default value until init() is called..
51  RHModeSleep, ///< Transport hardware is in low power sleep mode (if supported)
52  RHModeIdle, ///< Transport is idle.
53  RHModeTx, ///< Transport is in the process of transmitting a message.
54  RHModeRx, ///< Transport is in the process of receiving a message.
55  RHModeCad ///< Transport is in the process of detecting channel activity (if supported)
56  } RHMode;
57 
58  /// Constructor
60 
61  /// Initialise the Driver transport hardware and software.
62  /// Make sure the Driver is properly configured before calling init().
63  /// \return true if initialisation succeeded.
64  virtual bool init();
65 
66  /// Tests whether a new message is available
67  /// from the Driver.
68  /// On most drivers, if there is an uncollected received message, and there is no message
69  /// currently bing transmitted, this will also put the Driver into RHModeRx mode until
70  /// a message is actually received by the transport, when it will be returned to RHModeIdle.
71  /// This can be called multiple times in a timeout loop.
72  /// \return true if a new, complete, error-free uncollected message is available to be retreived by recv().
73  virtual bool available() = 0;
74 
75  /// Turns the receiver on if it not already on.
76  /// If there is a valid message available, copy it to buf and return true
77  /// else return false.
78  /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
79  /// You should be sure to call this function frequently enough to not miss any messages
80  /// It is recommended that you call it in your main loop.
81  /// \param[in] buf Location to copy the received message
82  /// \param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied.
83  /// \return true if a valid message was copied to buf
84  virtual bool recv(uint8_t* buf, uint8_t* len) = 0;
85 
86  /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
87  /// Then optionally waits for Channel Activity Detection (CAD)
88  /// to show the channnel is clear (if the radio supports CAD) by calling waitCAD().
89  /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
90  /// of 0 is NOT permitted. If the message is too long for the underlying radio technology, send() will
91  /// return false and will not send the message.
92  /// \param[in] data Array of data to be sent
93  /// \param[in] len Number of bytes of data to send (> 0)
94  /// specify the maximum time in ms to wait. If 0 (the default) do not wait for CAD before transmitting.
95  /// \return true if the message length was valid and it was correctly queued for transmit. Return false
96  /// if CAD was requested and the CAD timeout timed out before clear channel was detected.
97  virtual bool send(const uint8_t* data, uint8_t len) = 0;
98 
99  /// Returns the maximum message length
100  /// available in this Driver.
101  /// \return The maximum legal message length
102  virtual uint8_t maxMessageLength() = 0;
103 
104  /// Starts the receiver and blocks until a valid received
105  /// message is available.
106  virtual void waitAvailable();
107 
108  /// Blocks until the transmitter
109  /// is no longer transmitting.
110  virtual bool waitPacketSent();
111 
112  /// Blocks until the transmitter is no longer transmitting.
113  /// or until the timeout occuers, whichever happens first
114  /// \param[in] timeout Maximum time to wait in milliseconds.
115  /// \return true if the radio completed transmission within the timeout period. False if it timed out.
116  virtual bool waitPacketSent(uint16_t timeout);
117 
118  /// Starts the receiver and blocks until a received message is available or a timeout
119  /// \param[in] timeout Maximum time to wait in milliseconds.
120  /// \return true if a message is available
121  virtual bool waitAvailableTimeout(uint16_t timeout);
122 
123  // Bent G Christensen (bentor@gmail.com), 08/15/2016
124  /// Channel Activity Detection (CAD).
125  /// Blocks until channel activity is finished or CAD timeout occurs.
126  /// Uses the radio's CAD function (if supported) to detect channel activity.
127  /// Implements random delays of 100 to 1000ms while activity is detected and until timeout.
128  /// Caution: the random() function is not seeded. If you want non-deterministic behaviour, consider
129  /// using something like randomSeed(analogRead(A0)); in your sketch.
130  /// Permits the implementation of listen-before-talk mechanism (Collision Avoidance).
131  /// Calls the isChannelActive() member function for the radio (if supported)
132  /// to determine if the channel is active. If the radio does not support isChannelActive(),
133  /// always returns true immediately
134  /// \return true if the radio-specific CAD (as returned by isChannelActive())
135  /// shows the channel is clear within the timeout period (or the timeout period is 0), else returns false.
136  virtual bool waitCAD();
137 
138  /// Sets the Channel Activity Detection timeout in milliseconds to be used by waitCAD().
139  /// The default is 0, which means do not wait for CAD detection.
140  /// CAD detection depends on support for isChannelActive() by your particular radio.
141  void setCADTimeout(unsigned long cad_timeout);
142 
143  /// Determine if the currently selected radio channel is active.
144  /// This is expected to be subclassed by specific radios to implement their Channel Activity Detection
145  /// if supported. If the radio does not support CAD, returns true immediately. If a RadioHead radio
146  /// supports isChannelActive() it will be documented in the radio specific documentation.
147  /// This is called automatically by waitCAD().
148  /// \return true if the radio-specific CAD (as returned by override of isChannelActive()) shows the
149  /// current radio channel as active, else false. If there is no radio-specific CAD, returns false.
150  virtual bool isChannelActive();
151 
152  /// Sets the address of this node. Defaults to 0xFF. Subclasses or the user may want to change this.
153  /// This will be used to test the adddress in incoming messages. In non-promiscuous mode,
154  /// only messages with a TO header the same as thisAddress or the broadcast addess (0xFF) will be accepted.
155  /// In promiscuous mode, all messages will be accepted regardless of the TO header.
156  /// In a conventional multinode system, all nodes will have a unique address
157  /// (which you could store in EEPROM).
158  /// You would normally set the header FROM address to be the same as thisAddress (though you dont have to,
159  /// allowing the possibilty of address spoofing).
160  /// \param[in] thisAddress The address of this node.
161  virtual void setThisAddress(uint8_t thisAddress);
162 
163  /// Sets the TO header to be sent in all subsequent messages
164  /// \param[in] to The new TO header value
165  virtual void setHeaderTo(uint8_t to);
166 
167  /// Sets the FROM header to be sent in all subsequent messages
168  /// \param[in] from The new FROM header value
169  virtual void setHeaderFrom(uint8_t from);
170 
171  /// Sets the ID header to be sent in all subsequent messages
172  /// \param[in] id The new ID header value
173  virtual void setHeaderId(uint8_t id);
174 
175  /// Sets and clears bits in the FLAGS header to be sent in all subsequent messages
176  /// First it clears he FLAGS according to the clear argument, then sets the flags according to the
177  /// set argument. The default for clear always clears the application specific flags.
178  /// \param[in] set bitmask of bits to be set. Flags are cleared with the clear mask before being set.
179  /// \param[in] clear bitmask of flags to clear. Defaults to RH_FLAGS_APPLICATION_SPECIFIC
180  /// which clears the application specific flags, resulting in new application specific flags
181  /// identical to the set.
182  virtual void setHeaderFlags(uint8_t set, uint8_t clear = RH_FLAGS_APPLICATION_SPECIFIC);
183 
184  /// Tells the receiver to accept messages with any TO address, not just messages
185  /// addressed to thisAddress or the broadcast address
186  /// \param[in] promiscuous true if you wish to receive messages with any TO address
187  virtual void setPromiscuous(bool promiscuous);
188 
189  /// Returns the TO header of the last received message
190  /// \return The TO header
191  virtual uint8_t headerTo();
192 
193  /// Returns the FROM header of the last received message
194  /// \return The FROM header
195  virtual uint8_t headerFrom();
196 
197  /// Returns the ID header of the last received message
198  /// \return The ID header
199  virtual uint8_t headerId();
200 
201  /// Returns the FLAGS header of the last received message
202  /// \return The FLAGS header
203  virtual uint8_t headerFlags();
204 
205  /// Returns the most recent RSSI (Receiver Signal Strength Indicator).
206  /// Usually it is the RSSI of the last received message, which is measured when the preamble is received.
207  /// If you called readRssi() more recently, it will return that more recent value.
208  /// \return The most recent RSSI measurement in dBm.
209  virtual int16_t lastRssi();
210 
211  /// Returns the operating mode of the library.
212  /// \return the current mode, one of RF69_MODE_*
213  virtual RHMode mode();
214 
215  /// Sets the operating mode of the transport.
216  virtual void setMode(RHMode mode);
217 
218  /// Sets the transport hardware into low-power sleep mode
219  /// (if supported). May be overridden by specific drivers to initialte sleep mode.
220  /// If successful, the transport will stay in sleep mode until woken by
221  /// changing mode it idle, transmit or receive (eg by calling send(), recv(), available() etc)
222  /// \return true if sleep mode is supported by transport hardware and the RadioHead driver, and if sleep mode
223  /// was successfully entered. If sleep mode is not suported, return false.
224  virtual bool sleep();
225 
226  /// Prints a data buffer in HEX.
227  /// For diagnostic use
228  /// \param[in] prompt string to preface the print
229  /// \param[in] buf Location of the buffer to print
230  /// \param[in] len Length of the buffer in octets.
231  static void printBuffer(const char* prompt, const uint8_t* buf, uint8_t len);
232 
233  /// Returns the count of the number of bad received packets (ie packets with bad lengths, checksum etc)
234  /// which were rejected and not delivered to the application.
235  /// Caution: not all drivers can correctly report this count. Some underlying hardware only report
236  /// good packets.
237  /// \return The number of bad packets received.
238  virtual uint16_t rxBad();
239 
240  /// Returns the count of the number of
241  /// good received packets
242  /// \return The number of good packets received.
243  virtual uint16_t rxGood();
244 
245  /// Returns the count of the number of
246  /// packets successfully transmitted (though not necessarily received by the destination)
247  /// \return The number of packets successfully transmitted
248  virtual uint16_t txGood();
249 
250 protected:
251 
252  /// The current transport operating mode
253  volatile RHMode _mode;
254 
255  /// This node id
256  uint8_t _thisAddress;
257 
258  /// Whether the transport is in promiscuous mode
260 
261  /// TO header in the last received mesasge
262  volatile uint8_t _rxHeaderTo;
263 
264  /// FROM header in the last received mesasge
265  volatile uint8_t _rxHeaderFrom;
266 
267  /// ID header in the last received mesasge
268  volatile uint8_t _rxHeaderId;
269 
270  /// FLAGS header in the last received mesasge
271  volatile uint8_t _rxHeaderFlags;
272 
273  /// TO header to send in all messages
274  uint8_t _txHeaderTo;
275 
276  /// FROM header to send in all messages
277  uint8_t _txHeaderFrom;
278 
279  /// ID header to send in all messages
280  uint8_t _txHeaderId;
281 
282  /// FLAGS header to send in all messages
283  uint8_t _txHeaderFlags;
284 
285  /// The value of the last received RSSI value, in some transport specific units
286  volatile int16_t _lastRssi;
287 
288  /// Count of the number of bad messages (eg bad checksum etc) received
289  volatile uint16_t _rxBad;
290 
291  /// Count of the number of successfully transmitted messaged
292  volatile uint16_t _rxGood;
293 
294  /// Count of the number of bad messages (correct checksum etc) received
295  volatile uint16_t _txGood;
296 
297  /// Channel activity detected
298  volatile bool _cad;
299 
300  /// Channel activity timeout in ms
301  unsigned int _cad_timeout;
302 
303 private:
304 
305 };
306 
307 #endif
RHGenericDriver::_rxGood
volatile uint16_t _rxGood
Count of the number of successfully transmitted messaged.
Definition: RHGenericDriver.h:292
RHGenericDriver::setCADTimeout
void setCADTimeout(unsigned long cad_timeout)
Definition: RHGenericDriver.cpp:209
RHGenericDriver::maxMessageLength
virtual uint8_t maxMessageLength()=0
RHGenericDriver::RHModeCad
@ RHModeCad
Transport is in the process of detecting channel activity (if supported)
Definition: RHGenericDriver.h:55
RHGenericDriver::available
virtual bool available()=0
RHGenericDriver::_rxHeaderFrom
volatile uint8_t _rxHeaderFrom
FROM header in the last received mesasge.
Definition: RHGenericDriver.h:265
RHGenericDriver::waitAvailableTimeout
virtual bool waitAvailableTimeout(uint16_t timeout)
Definition: RHGenericDriver.cpp:38
RHGenericDriver::txGood
virtual uint16_t txGood()
Definition: RHGenericDriver.cpp:204
RHGenericDriver::_lastRssi
volatile int16_t _lastRssi
The value of the last received RSSI value, in some transport specific units.
Definition: RHGenericDriver.h:286
RHGenericDriver::_rxBad
volatile uint16_t _rxBad
Count of the number of bad messages (eg bad checksum etc) received.
Definition: RHGenericDriver.h:289
RHGenericDriver::headerFlags
virtual uint8_t headerFlags()
Definition: RHGenericDriver.cpp:149
RHGenericDriver::isChannelActive
virtual bool isChannelActive()
Definition: RHGenericDriver.cpp:98
RHGenericDriver::_rxHeaderTo
volatile uint8_t _rxHeaderTo
TO header in the last received mesasge.
Definition: RHGenericDriver.h:262
RHGenericDriver::_txHeaderFrom
uint8_t _txHeaderFrom
FROM header to send in all messages.
Definition: RHGenericDriver.h:277
RHGenericDriver
Abstract base class for a RadioHead driver.
Definition: RHGenericDriver.h:41
RHGenericDriver::headerId
virtual uint8_t headerId()
Definition: RHGenericDriver.cpp:144
RHGenericDriver::RHMode
RHMode
Defines different operating modes for the transport hardware.
Definition: RHGenericDriver.h:48
RHGenericDriver::_thisAddress
uint8_t _thisAddress
This node id.
Definition: RHGenericDriver.h:256
RHGenericDriver::_txGood
volatile uint16_t _txGood
Count of the number of bad messages (correct checksum etc) received.
Definition: RHGenericDriver.h:295
RHGenericDriver::setPromiscuous
virtual void setPromiscuous(bool promiscuous)
Definition: RHGenericDriver.cpp:103
RHGenericDriver::headerFrom
virtual uint8_t headerFrom()
Definition: RHGenericDriver.cpp:139
RHGenericDriver::_promiscuous
bool _promiscuous
Whether the transport is in promiscuous mode.
Definition: RHGenericDriver.h:259
RHGenericDriver::setThisAddress
virtual void setThisAddress(uint8_t thisAddress)
Definition: RHGenericDriver.cpp:108
RHGenericDriver::setHeaderId
virtual void setHeaderId(uint8_t id)
Definition: RHGenericDriver.cpp:123
RHGenericDriver::_rxHeaderFlags
volatile uint8_t _rxHeaderFlags
FLAGS header in the last received mesasge.
Definition: RHGenericDriver.h:271
RHGenericDriver::lastRssi
virtual int16_t lastRssi()
Definition: RHGenericDriver.cpp:154
RHGenericDriver::sleep
virtual bool sleep()
Definition: RHGenericDriver.cpp:169
RHGenericDriver::rxGood
virtual uint16_t rxGood()
Definition: RHGenericDriver.cpp:199
RHGenericDriver::recv
virtual bool recv(uint8_t *buf, uint8_t *len)=0
RHGenericDriver::send
virtual bool send(const uint8_t *data, uint8_t len)=0
RHGenericDriver::RHModeSleep
@ RHModeSleep
Transport hardware is in low power sleep mode (if supported)
Definition: RHGenericDriver.h:51
RHGenericDriver::rxBad
virtual uint16_t rxBad()
Definition: RHGenericDriver.cpp:194
RHGenericDriver::_cad
volatile bool _cad
Channel activity detected.
Definition: RHGenericDriver.h:298
RHGenericDriver::RHGenericDriver
RHGenericDriver()
Constructor.
Definition: RHGenericDriver.cpp:8
RHGenericDriver::setHeaderTo
virtual void setHeaderTo(uint8_t to)
Definition: RHGenericDriver.cpp:113
RHGenericDriver::_txHeaderId
uint8_t _txHeaderId
ID header to send in all messages.
Definition: RHGenericDriver.h:280
RHGenericDriver::_txHeaderTo
uint8_t _txHeaderTo
TO header to send in all messages.
Definition: RHGenericDriver.h:274
RHGenericDriver::setHeaderFrom
virtual void setHeaderFrom(uint8_t from)
Definition: RHGenericDriver.cpp:118
RHGenericDriver::init
virtual bool init()
Definition: RHGenericDriver.cpp:23
RHGenericDriver::_txHeaderFlags
uint8_t _txHeaderFlags
FLAGS header to send in all messages.
Definition: RHGenericDriver.h:283
RHGenericDriver::headerTo
virtual uint8_t headerTo()
Definition: RHGenericDriver.cpp:134
RHGenericDriver::printBuffer
static void printBuffer(const char *prompt, const uint8_t *buf, uint8_t len)
Definition: RHGenericDriver.cpp:175
RHGenericDriver::_rxHeaderId
volatile uint8_t _rxHeaderId
ID header in the last received mesasge.
Definition: RHGenericDriver.h:268
RHGenericDriver::setHeaderFlags
virtual void setHeaderFlags(uint8_t set, uint8_t clear=RH_FLAGS_APPLICATION_SPECIFIC)
Definition: RHGenericDriver.cpp:128
RHGenericDriver::RHModeIdle
@ RHModeIdle
Transport is idle.
Definition: RHGenericDriver.h:52
RHGenericDriver::_cad_timeout
unsigned int _cad_timeout
Channel activity timeout in ms.
Definition: RHGenericDriver.h:301
RHGenericDriver::waitPacketSent
virtual bool waitPacketSent()
Definition: RHGenericDriver.cpp:52
RHGenericDriver::_mode
volatile RHMode _mode
The current transport operating mode.
Definition: RHGenericDriver.h:253
RHGenericDriver::RHModeTx
@ RHModeTx
Transport is in the process of transmitting a message.
Definition: RHGenericDriver.h:53
RHGenericDriver::RHModeInitialising
@ RHModeInitialising
Transport is initialising. Initial default value until init() is called..
Definition: RHGenericDriver.h:50
RHGenericDriver::mode
virtual RHMode mode()
Definition: RHGenericDriver.cpp:159
RHGenericDriver::RHModeRx
@ RHModeRx
Transport is in the process of receiving a message.
Definition: RHGenericDriver.h:54
RHGenericDriver::setMode
virtual void setMode(RHMode mode)
Sets the operating mode of the transport.
Definition: RHGenericDriver.cpp:164
RHGenericDriver::waitAvailable
virtual void waitAvailable()
Definition: RHGenericDriver.cpp:29
RHGenericDriver::waitCAD
virtual bool waitCAD()
Definition: RHGenericDriver.cpp:72