RadioHead

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RHGenericDriver.h Source File

RHGenericDriver.h

00001 // RHGenericDriver.h
00002 // Author: Mike McCauley (mikem@airspayce.com)
00003 // Copyright (C) 2014 Mike McCauley
00004 // $Id: RHGenericDriver.h,v 1.19 2017/03/08 09:30:47 mikem Exp mikem $
00005 //
00006 // Ported to mbed - support only a single radio - Dan Julio - 5/2017 
00007 //
00008 
00009 #ifndef RHGenericDriver_h
00010 #define RHGenericDriver_h
00011 
00012 #include "RadioHead.h"
00013 #include "mbed.h"
00014 #include "max32630fthr.h"
00015 #include <stdint.h>
00016 
00017 // Defines bits of the FLAGS header reserved for use by the RadioHead library and 
00018 // the flags available for use by applications
00019 #define RH_FLAGS_RESERVED                 0xf0
00020 #define RH_FLAGS_APPLICATION_SPECIFIC     0x0f
00021 #define RH_FLAGS_NONE                     0
00022 
00023 // Default timeout for waitCAD() in ms
00024 #define RH_CAD_DEFAULT_TIMEOUT            10000
00025 
00026 /////////////////////////////////////////////////////////////////////
00027 /// \class RHGenericDriver RHGenericDriver.h <RHGenericDriver.h>
00028 /// \brief Abstract base class for a RadioHead driver.
00029 ///
00030 /// This class defines the functions that must be provided by any RadioHead driver.
00031 /// Different types of driver will implement all the abstract functions, and will perhaps override 
00032 /// other functions in this subclass, or perhaps add new functions specifically required by that driver.
00033 /// Do not directly instantiate this class: it is only to be subclassed by driver classes.
00034 ///
00035 /// Subclasses are expected to implement a half-duplex, unreliable, error checked, unaddressed packet transport.
00036 /// They are expected to carry a message payload with an appropriate maximum length for the transport hardware
00037 /// and to also carry unaltered 4 message headers: TO, FROM, ID, FLAGS
00038 ///
00039 /// \par Headers
00040 ///
00041 /// Each message sent and received by a RadioHead driver includes 4 headers:
00042 /// -TO The node address that the message is being sent to (broadcast RH_BROADCAST_ADDRESS (255) is permitted)
00043 /// -FROM The node address of the sending node
00044 /// -ID A message ID, distinct (over short time scales) for each message sent by a particilar node
00045 /// -FLAGS A bitmask of flags. The most significant 4 bits are reserved for use by RadioHead. The least
00046 /// significant 4 bits are reserved for applications.
00047 class RHGenericDriver
00048 {
00049 public:
00050     /// \brief Defines different operating modes for the transport hardware
00051     ///
00052     /// These are the different values that can be adopted by the _mode variable and 
00053     /// returned by the mode() member function,
00054     typedef enum
00055     {
00056     RHModeInitialising = 0, ///< Transport is initialising. Initial default value until init() is called..
00057     RHModeSleep,            ///< Transport hardware is in low power sleep mode (if supported)
00058     RHModeIdle,             ///< Transport is idle.
00059     RHModeTx,               ///< Transport is in the process of transmitting a message.
00060     RHModeRx,               ///< Transport is in the process of receiving a message.
00061     RHModeCad               ///< Transport is in the process of detecting channel activity (if supported)
00062     } RHMode;
00063 
00064     /// Constructor
00065     RHGenericDriver();
00066 
00067     /// Initialise the Driver transport hardware and software.
00068     /// Make sure the Driver is properly configured before calling init().
00069     /// \return true if initialisation succeeded.
00070     virtual bool init();
00071 
00072     /// Tests whether a new message is available
00073     /// from the Driver. 
00074     /// On most drivers, if there is an uncollected received message, and there is no message
00075     /// currently bing transmitted, this will also put the Driver into RHModeRx mode until
00076     /// a message is actually received by the transport, when it will be returned to RHModeIdle.
00077     /// This can be called multiple times in a timeout loop.
00078     /// \return true if a new, complete, error-free uncollected message is available to be retreived by recv().
00079     virtual bool available() = 0;
00080 
00081     /// Turns the receiver on if it not already on.
00082     /// If there is a valid message available, copy it to buf and return true
00083     /// else return false.
00084     /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
00085     /// You should be sure to call this function frequently enough to not miss any messages
00086     /// It is recommended that you call it in your main loop.
00087     /// \param[in] buf Location to copy the received message
00088     /// \param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied.
00089     /// \return true if a valid message was copied to buf
00090     virtual bool recv(uint8_t* buf, uint8_t* len) = 0;
00091 
00092     /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
00093     /// Then optionally waits for Channel Activity Detection (CAD) 
00094     /// to show the channnel is clear (if the radio supports CAD) by calling waitCAD().
00095     /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
00096     /// of 0 is NOT permitted. If the message is too long for the underlying radio technology, send() will
00097     /// return false and will not send the message.
00098     /// \param[in] data Array of data to be sent
00099     /// \param[in] len Number of bytes of data to send (> 0)
00100     /// specify the maximum time in ms to wait. If 0 (the default) do not wait for CAD before transmitting.
00101     /// \return true if the message length was valid and it was correctly queued for transmit. Return false
00102     /// if CAD was requested and the CAD timeout timed out before clear channel was detected.
00103     virtual bool send(const uint8_t* data, uint8_t len) = 0;
00104 
00105     /// Returns the maximum message length 
00106     /// available in this Driver.
00107     /// \return The maximum legal message length
00108     virtual uint8_t maxMessageLength() = 0;
00109 
00110     /// Starts the receiver and blocks until a valid received 
00111     /// message is available.
00112     virtual void            waitAvailable();
00113 
00114     /// Blocks until the transmitter 
00115     /// is no longer transmitting.
00116     virtual bool            waitPacketSent();
00117 
00118     /// Blocks until the transmitter is no longer transmitting.
00119     /// or until the timeout occuers, whichever happens first
00120     /// \param[in] timeout Maximum time to wait in milliseconds.
00121     /// \return true if the radio completed transmission within the timeout period. False if it timed out.
00122     virtual bool            waitPacketSent(uint16_t timeout);
00123 
00124     /// Starts the receiver and blocks until a received message is available or a timeout
00125     /// \param[in] timeout Maximum time to wait in milliseconds.
00126     /// \return true if a message is available
00127     virtual bool            waitAvailableTimeout(uint16_t timeout);
00128 
00129     // Bent G Christensen (bentor@gmail.com), 08/15/2016
00130     /// Channel Activity Detection (CAD).
00131     /// Blocks until channel activity is finished or CAD timeout occurs.
00132     /// Uses the radio's CAD function (if supported) to detect channel activity.
00133     /// Implements random delays of 100 to 1000ms while activity is detected and until timeout.
00134     /// Caution: the random() function is not seeded. If you want non-deterministic behaviour, consider
00135     /// using something like randomSeed(analogRead(A0)); in your sketch.
00136     /// Permits the implementation of listen-before-talk mechanism (Collision Avoidance).
00137     /// Calls the isChannelActive() member function for the radio (if supported) 
00138     /// to determine if the channel is active. If the radio does not support isChannelActive(),
00139     /// always returns true immediately
00140     /// \return true if the radio-specific CAD (as returned by isChannelActive())
00141     /// shows the channel is clear within the timeout period (or the timeout period is 0), else returns false.
00142     virtual bool            waitCAD();
00143 
00144     /// Sets the Channel Activity Detection timeout in milliseconds to be used by waitCAD().
00145     /// The default is 0, which means do not wait for CAD detection.
00146     /// CAD detection depends on support for isChannelActive() by your particular radio.
00147     void setCADTimeout(unsigned long cad_timeout);
00148 
00149     /// Determine if the currently selected radio channel is active.
00150     /// This is expected to be subclassed by specific radios to implement their Channel Activity Detection
00151     /// if supported. If the radio does not support CAD, returns true immediately. If a RadioHead radio 
00152     /// supports isChannelActive() it will be documented in the radio specific documentation.
00153     /// This is called automatically by waitCAD().
00154     /// \return true if the radio-specific CAD (as returned by override of isChannelActive()) shows the
00155     /// current radio channel as active, else false. If there is no radio-specific CAD, returns false.
00156     virtual bool            isChannelActive();
00157 
00158     /// Sets the address of this node. Defaults to 0xFF. Subclasses or the user may want to change this.
00159     /// This will be used to test the adddress in incoming messages. In non-promiscuous mode,
00160     /// only messages with a TO header the same as thisAddress or the broadcast addess (0xFF) will be accepted.
00161     /// In promiscuous mode, all messages will be accepted regardless of the TO header.
00162     /// In a conventional multinode system, all nodes will have a unique address 
00163     /// (which you could store in EEPROM).
00164     /// You would normally set the header FROM address to be the same as thisAddress (though you dont have to, 
00165     /// allowing the possibilty of address spoofing).
00166     /// \param[in] thisAddress The address of this node.
00167     virtual void setThisAddress(uint8_t thisAddress);
00168 
00169     /// Sets the TO header to be sent in all subsequent messages
00170     /// \param[in] to The new TO header value
00171     virtual void           setHeaderTo(uint8_t to);
00172 
00173     /// Sets the FROM header to be sent in all subsequent messages
00174     /// \param[in] from The new FROM header value
00175     virtual void           setHeaderFrom(uint8_t from);
00176 
00177     /// Sets the ID header to be sent in all subsequent messages
00178     /// \param[in] id The new ID header value
00179     virtual void           setHeaderId(uint8_t id);
00180 
00181     /// Sets and clears bits in the FLAGS header to be sent in all subsequent messages
00182     /// First it clears he FLAGS according to the clear argument, then sets the flags according to the 
00183     /// set argument. The default for clear always clears the application specific flags.
00184     /// \param[in] set bitmask of bits to be set. Flags are cleared with the clear mask before being set.
00185     /// \param[in] clear bitmask of flags to clear. Defaults to RH_FLAGS_APPLICATION_SPECIFIC
00186     ///            which clears the application specific flags, resulting in new application specific flags
00187     ///            identical to the set.
00188     virtual void           setHeaderFlags(uint8_t set, uint8_t clear = RH_FLAGS_APPLICATION_SPECIFIC);
00189 
00190     /// Tells the receiver to accept messages with any TO address, not just messages
00191     /// addressed to thisAddress or the broadcast address
00192     /// \param[in] promiscuous true if you wish to receive messages with any TO address
00193     virtual void           setPromiscuous(bool promiscuous);
00194 
00195     /// Returns the TO header of the last received message
00196     /// \return The TO header
00197     virtual uint8_t        headerTo();
00198 
00199     /// Returns the FROM header of the last received message
00200     /// \return The FROM header
00201     virtual uint8_t        headerFrom();
00202 
00203     /// Returns the ID header of the last received message
00204     /// \return The ID header
00205     virtual uint8_t        headerId();
00206 
00207     /// Returns the FLAGS header of the last received message
00208     /// \return The FLAGS header
00209     virtual uint8_t        headerFlags();
00210 
00211     /// Returns the most recent RSSI (Receiver Signal Strength Indicator).
00212     /// Usually it is the RSSI of the last received message, which is measured when the preamble is received.
00213     /// If you called readRssi() more recently, it will return that more recent value.
00214     /// \return The most recent RSSI measurement in dBm.
00215     int8_t        lastRssi();
00216 
00217     /// Returns the operating mode of the library.
00218     /// \return the current mode, one of RF69_MODE_*
00219     RHMode          mode();
00220 
00221     /// Sets the operating mode of the transport.
00222     void            setMode(RHMode mode);
00223 
00224     /// Sets the transport hardware into low-power sleep mode
00225     /// (if supported). May be overridden by specific drivers to initialte sleep mode.
00226     /// If successful, the transport will stay in sleep mode until woken by 
00227     /// changing mode it idle, transmit or receive (eg by calling send(), recv(), available() etc)
00228     /// \return true if sleep mode is supported by transport hardware and the RadioHead driver, and if sleep mode
00229     ///         was successfully entered. If sleep mode is not suported, return false.
00230     virtual bool    sleep();
00231 
00232     /// Prints a data buffer in HEX.
00233     /// For diagnostic use
00234     /// \param[in] prompt string to preface the print
00235     /// \param[in] buf Location of the buffer to print
00236     /// \param[in] len Length of the buffer in octets.
00237     static void    printBuffer(const char* prompt, const uint8_t* buf, uint8_t len);
00238 
00239     /// Returns the count of the number of bad received packets (ie packets with bad lengths, checksum etc)
00240     /// which were rejected and not delivered to the application.
00241     /// Caution: not all drivers can correctly report this count. Some underlying hardware only report
00242     /// good packets.
00243     /// \return The number of bad packets received.
00244     uint16_t       rxBad();
00245 
00246     /// Returns the count of the number of 
00247     /// good received packets
00248     /// \return The number of good packets received.
00249     uint16_t       rxGood();
00250 
00251     /// Returns the count of the number of 
00252     /// packets successfully transmitted (though not necessarily received by the destination)
00253     /// \return The number of packets successfully transmitted
00254     uint16_t       txGood();
00255 
00256 protected:
00257 
00258     /// The current transport operating mode
00259     volatile RHMode     _mode;
00260 
00261     /// This node id
00262     uint8_t             _thisAddress;
00263     
00264     /// Whether the transport is in promiscuous mode
00265     bool                _promiscuous;
00266 
00267     /// TO header in the last received mesasge
00268     volatile uint8_t    _rxHeaderTo;
00269 
00270     /// FROM header in the last received mesasge
00271     volatile uint8_t    _rxHeaderFrom;
00272 
00273     /// ID header in the last received mesasge
00274     volatile uint8_t    _rxHeaderId;
00275 
00276     /// FLAGS header in the last received mesasge
00277     volatile uint8_t    _rxHeaderFlags;
00278 
00279     /// TO header to send in all messages
00280     uint8_t             _txHeaderTo;
00281 
00282     /// FROM header to send in all messages
00283     uint8_t             _txHeaderFrom;
00284 
00285     /// ID header to send in all messages
00286     uint8_t             _txHeaderId;
00287 
00288     /// FLAGS header to send in all messages
00289     uint8_t             _txHeaderFlags;
00290 
00291     /// The value of the last received RSSI value, in some transport specific units
00292     volatile int8_t     _lastRssi;
00293 
00294     /// Count of the number of bad messages (eg bad checksum etc) received
00295     volatile uint16_t   _rxBad;
00296 
00297     /// Count of the number of successfully transmitted messaged
00298     volatile uint16_t   _rxGood;
00299 
00300     /// Count of the number of bad messages (correct checksum etc) received
00301     volatile uint16_t   _txGood;
00302     
00303     /// Channel activity detected
00304     volatile bool       _cad;
00305 
00306     /// Channel activity timeout in ms
00307     unsigned int        _cad_timeout;
00308 
00309 private:
00310     
00311     Timer               _waitTimer;
00312 
00313 };
00314 
00315 
00316 #endif