RadioHead

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RH_RF95.h Source File

RH_RF95.h

00001 // RH_RF95.h
00002 //
00003 // Definitions for HopeRF LoRa radios per:
00004 // http://www.hoperf.com/upload/rf/RFM95_96_97_98W.pdf
00005 // http://www.hoperf.cn/upload/rfchip/RF96_97_98.pdf
00006 //
00007 // Author: Mike McCauley (mikem@airspayce.com)
00008 // Copyright (C) 2014 Mike McCauley
00009 // $Id: RH_RF95.h,v 1.16 2017/03/04 00:59:41 mikem Exp $
00010 //
00011 // Ported to mbed - support only a single radio - Dan Julio - 5/2017 
00012 // 
00013 
00014 #ifndef RH_RF95_h
00015 #define RH_RF95_h
00016 
00017 #include <RHGenericDriver.h>
00018 #include "swspi.h"
00019 
00020 // Max number of octets the LORA Rx/Tx FIFO can hold
00021 #define RH_RF95_FIFO_SIZE 255
00022 
00023 // This is the maximum number of bytes that can be carried by the LORA.
00024 // We use some for headers, keeping fewer for RadioHead messages
00025 #define RH_RF95_MAX_PAYLOAD_LEN RH_RF95_FIFO_SIZE
00026 
00027 // The length of the headers we add.
00028 // The headers are inside the LORA's payload
00029 #define RH_RF95_HEADER_LEN 4
00030 
00031 // This is the maximum message length that can be supported by this driver. 
00032 // Can be pre-defined to a smaller size (to save SRAM) prior to including this header
00033 // Here we allow for 1 byte message length, 4 bytes headers, user data and 2 bytes of FCS
00034 #ifndef RH_RF95_MAX_MESSAGE_LEN
00035  #define RH_RF95_MAX_MESSAGE_LEN (RH_RF95_MAX_PAYLOAD_LEN - RH_RF95_HEADER_LEN)
00036 #endif
00037 
00038 // The crystal oscillator frequency of the module
00039 #define RH_RF95_FXOSC 32000000.0
00040 
00041 // The Frequency Synthesizer step = RH_RF95_FXOSC / 2^^19
00042 #define RH_RF95_FSTEP  (RH_RF95_FXOSC / 524288)
00043 
00044 
00045 // Register names (LoRa Mode, from table 85)
00046 #define RH_RF95_REG_00_FIFO                                0x00
00047 #define RH_RF95_REG_01_OP_MODE                             0x01
00048 #define RH_RF95_REG_02_RESERVED                            0x02
00049 #define RH_RF95_REG_03_RESERVED                            0x03
00050 #define RH_RF95_REG_04_RESERVED                            0x04
00051 #define RH_RF95_REG_05_RESERVED                            0x05
00052 #define RH_RF95_REG_06_FRF_MSB                             0x06
00053 #define RH_RF95_REG_07_FRF_MID                             0x07
00054 #define RH_RF95_REG_08_FRF_LSB                             0x08
00055 #define RH_RF95_REG_09_PA_CONFIG                           0x09
00056 #define RH_RF95_REG_0A_PA_RAMP                             0x0a
00057 #define RH_RF95_REG_0B_OCP                                 0x0b
00058 #define RH_RF95_REG_0C_LNA                                 0x0c
00059 #define RH_RF95_REG_0D_FIFO_ADDR_PTR                       0x0d
00060 #define RH_RF95_REG_0E_FIFO_TX_BASE_ADDR                   0x0e
00061 #define RH_RF95_REG_0F_FIFO_RX_BASE_ADDR                   0x0f
00062 #define RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR                0x10
00063 #define RH_RF95_REG_11_IRQ_FLAGS_MASK                      0x11
00064 #define RH_RF95_REG_12_IRQ_FLAGS                           0x12
00065 #define RH_RF95_REG_13_RX_NB_BYTES                         0x13
00066 #define RH_RF95_REG_14_RX_HEADER_CNT_VALUE_MSB             0x14
00067 #define RH_RF95_REG_15_RX_HEADER_CNT_VALUE_LSB             0x15
00068 #define RH_RF95_REG_16_RX_PACKET_CNT_VALUE_MSB             0x16
00069 #define RH_RF95_REG_17_RX_PACKET_CNT_VALUE_LSB             0x17
00070 #define RH_RF95_REG_18_MODEM_STAT                          0x18
00071 #define RH_RF95_REG_19_PKT_SNR_VALUE                       0x19
00072 #define RH_RF95_REG_1A_PKT_RSSI_VALUE                      0x1a
00073 #define RH_RF95_REG_1B_RSSI_VALUE                          0x1b
00074 #define RH_RF95_REG_1C_HOP_CHANNEL                         0x1c
00075 #define RH_RF95_REG_1D_MODEM_CONFIG1                       0x1d
00076 #define RH_RF95_REG_1E_MODEM_CONFIG2                       0x1e
00077 #define RH_RF95_REG_1F_SYMB_TIMEOUT_LSB                    0x1f
00078 #define RH_RF95_REG_20_PREAMBLE_MSB                        0x20
00079 #define RH_RF95_REG_21_PREAMBLE_LSB                        0x21
00080 #define RH_RF95_REG_22_PAYLOAD_LENGTH                      0x22
00081 #define RH_RF95_REG_23_MAX_PAYLOAD_LENGTH                  0x23
00082 #define RH_RF95_REG_24_HOP_PERIOD                          0x24
00083 #define RH_RF95_REG_25_FIFO_RX_BYTE_ADDR                   0x25
00084 #define RH_RF95_REG_26_MODEM_CONFIG3                       0x26
00085 
00086 #define RH_RF95_REG_27_PPM_CORRECTION                      0x27
00087 #define RH_RF95_REG_28_FEI_MSB                             0x28
00088 #define RH_RF95_REG_29_FEI_MID                             0x29
00089 #define RH_RF95_REG_2A_FEI_LSB                             0x2a
00090 #define RH_RF95_REG_2C_RSSI_WIDEBAND                       0x2c
00091 #define RH_RF95_REG_31_DETECT_OPTIMIZ                      0x31
00092 #define RH_RF95_REG_33_INVERT_IQ                           0x33
00093 #define RH_RF95_REG_37_DETECTION_THRESHOLD                 0x37
00094 #define RH_RF95_REG_39_SYNC_WORD                           0x39
00095 
00096 #define RH_RF95_REG_40_DIO_MAPPING1                        0x40
00097 #define RH_RF95_REG_41_DIO_MAPPING2                        0x41
00098 #define RH_RF95_REG_42_VERSION                             0x42
00099 
00100 #define RH_RF95_REG_4B_TCXO                                0x4b
00101 #define RH_RF95_REG_4D_PA_DAC                              0x4d
00102 #define RH_RF95_REG_5B_FORMER_TEMP                         0x5b
00103 #define RH_RF95_REG_61_AGC_REF                             0x61
00104 #define RH_RF95_REG_62_AGC_THRESH1                         0x62
00105 #define RH_RF95_REG_63_AGC_THRESH2                         0x63
00106 #define RH_RF95_REG_64_AGC_THRESH3                         0x64
00107 
00108 // RH_RF95_REG_01_OP_MODE                             0x01
00109 #define RH_RF95_LONG_RANGE_MODE                       0x80
00110 #define RH_RF95_ACCESS_SHARED_REG                     0x40
00111 #define RH_RF95_LOW_FREQUENCY_MODE                    0x08
00112 #define RH_RF95_MODE                                  0x07
00113 #define RH_RF95_MODE_SLEEP                            0x00
00114 #define RH_RF95_MODE_STDBY                            0x01
00115 #define RH_RF95_MODE_FSTX                             0x02
00116 #define RH_RF95_MODE_TX                               0x03
00117 #define RH_RF95_MODE_FSRX                             0x04
00118 #define RH_RF95_MODE_RXCONTINUOUS                     0x05
00119 #define RH_RF95_MODE_RXSINGLE                         0x06
00120 #define RH_RF95_MODE_CAD                              0x07
00121 
00122 // RH_RF95_REG_09_PA_CONFIG                           0x09
00123 #define RH_RF95_PA_SELECT                             0x80
00124 #define RH_RF95_MAX_POWER                             0x70
00125 #define RH_RF95_OUTPUT_POWER                          0x0f
00126 
00127 // RH_RF95_REG_0A_PA_RAMP                             0x0a
00128 #define RH_RF95_LOW_PN_TX_PLL_OFF                     0x10
00129 #define RH_RF95_PA_RAMP                               0x0f
00130 #define RH_RF95_PA_RAMP_3_4MS                         0x00
00131 #define RH_RF95_PA_RAMP_2MS                           0x01
00132 #define RH_RF95_PA_RAMP_1MS                           0x02
00133 #define RH_RF95_PA_RAMP_500US                         0x03
00134 #define RH_RF95_PA_RAMP_250US                         0x0
00135 #define RH_RF95_PA_RAMP_125US                         0x05
00136 #define RH_RF95_PA_RAMP_100US                         0x06
00137 #define RH_RF95_PA_RAMP_62US                          0x07
00138 #define RH_RF95_PA_RAMP_50US                          0x08
00139 #define RH_RF95_PA_RAMP_40US                          0x09
00140 #define RH_RF95_PA_RAMP_31US                          0x0a
00141 #define RH_RF95_PA_RAMP_25US                          0x0b
00142 #define RH_RF95_PA_RAMP_20US                          0x0c
00143 #define RH_RF95_PA_RAMP_15US                          0x0d
00144 #define RH_RF95_PA_RAMP_12US                          0x0e
00145 #define RH_RF95_PA_RAMP_10US                          0x0f
00146 
00147 // RH_RF95_REG_0B_OCP                                 0x0b
00148 #define RH_RF95_OCP_ON                                0x20
00149 #define RH_RF95_OCP_TRIM                              0x1f
00150 
00151 // RH_RF95_REG_0C_LNA                                 0x0c
00152 #define RH_RF95_LNA_GAIN                              0xe0
00153 #define RH_RF95_LNA_GAIN_G1                           0x20
00154 #define RH_RF95_LNA_GAIN_G2                           0x40
00155 #define RH_RF95_LNA_GAIN_G3                           0x60                
00156 #define RH_RF95_LNA_GAIN_G4                           0x80
00157 #define RH_RF95_LNA_GAIN_G5                           0xa0
00158 #define RH_RF95_LNA_GAIN_G6                           0xc0
00159 #define RH_RF95_LNA_BOOST_LF                          0x18
00160 #define RH_RF95_LNA_BOOST_LF_DEFAULT                  0x00
00161 #define RH_RF95_LNA_BOOST_HF                          0x03
00162 #define RH_RF95_LNA_BOOST_HF_DEFAULT                  0x00
00163 #define RH_RF95_LNA_BOOST_HF_150PC                    0x11
00164 
00165 // RH_RF95_REG_11_IRQ_FLAGS_MASK                      0x11
00166 #define RH_RF95_RX_TIMEOUT_MASK                       0x80
00167 #define RH_RF95_RX_DONE_MASK                          0x40
00168 #define RH_RF95_PAYLOAD_CRC_ERROR_MASK                0x20
00169 #define RH_RF95_VALID_HEADER_MASK                     0x10
00170 #define RH_RF95_TX_DONE_MASK                          0x08
00171 #define RH_RF95_CAD_DONE_MASK                         0x04
00172 #define RH_RF95_FHSS_CHANGE_CHANNEL_MASK              0x02
00173 #define RH_RF95_CAD_DETECTED_MASK                     0x01
00174 
00175 // RH_RF95_REG_12_IRQ_FLAGS                           0x12
00176 #define RH_RF95_RX_TIMEOUT                            0x80
00177 #define RH_RF95_RX_DONE                               0x40
00178 #define RH_RF95_PAYLOAD_CRC_ERROR                     0x20
00179 #define RH_RF95_VALID_HEADER                          0x10
00180 #define RH_RF95_TX_DONE                               0x08
00181 #define RH_RF95_CAD_DONE                              0x04
00182 #define RH_RF95_FHSS_CHANGE_CHANNEL                   0x02
00183 #define RH_RF95_CAD_DETECTED                          0x01
00184 
00185 // RH_RF95_REG_18_MODEM_STAT                          0x18
00186 #define RH_RF95_RX_CODING_RATE                        0xe0
00187 #define RH_RF95_MODEM_STATUS_CLEAR                    0x10
00188 #define RH_RF95_MODEM_STATUS_HEADER_INFO_VALID        0x08
00189 #define RH_RF95_MODEM_STATUS_RX_ONGOING               0x04
00190 #define RH_RF95_MODEM_STATUS_SIGNAL_SYNCHRONIZED      0x02
00191 #define RH_RF95_MODEM_STATUS_SIGNAL_DETECTED          0x01
00192 
00193 // RH_RF95_REG_1C_HOP_CHANNEL                         0x1c
00194 #define RH_RF95_PLL_TIMEOUT                           0x80
00195 #define RH_RF95_RX_PAYLOAD_CRC_IS_ON                  0x40
00196 #define RH_RF95_FHSS_PRESENT_CHANNEL                  0x3f
00197 
00198 // RH_RF95_REG_1D_MODEM_CONFIG1                       0x1d
00199 #define RH_RF95_BW                                    0xf0
00200 
00201 #define RH_RF95_BW_7_8KHZ                             0x00
00202 #define RH_RF95_BW_10_4KHZ                            0x10
00203 #define RH_RF95_BW_15_6KHZ                            0x20
00204 #define RH_RF95_BW_20_8KHZ                            0x30
00205 #define RH_RF95_BW_31_25KHZ                           0x40
00206 #define RH_RF95_BW_41_7KHZ                            0x50
00207 #define RH_RF95_BW_62_5KHZ                            0x60
00208 #define RH_RF95_BW_125KHZ                             0x70
00209 #define RH_RF95_BW_250KHZ                             0x80
00210 #define RH_RF95_BW_500KHZ                             0x90
00211 #define RH_RF95_CODING_RATE                           0x0e
00212 #define RH_RF95_CODING_RATE_4_5                       0x02
00213 #define RH_RF95_CODING_RATE_4_6                       0x04
00214 #define RH_RF95_CODING_RATE_4_7                       0x06
00215 #define RH_RF95_CODING_RATE_4_8                       0x08
00216 #define RH_RF95_IMPLICIT_HEADER_MODE_ON               0x01
00217 
00218 // RH_RF95_REG_1E_MODEM_CONFIG2                       0x1e
00219 #define RH_RF95_SPREADING_FACTOR                      0xf0
00220 #define RH_RF95_SPREADING_FACTOR_64CPS                0x60
00221 #define RH_RF95_SPREADING_FACTOR_128CPS               0x70
00222 #define RH_RF95_SPREADING_FACTOR_256CPS               0x80
00223 #define RH_RF95_SPREADING_FACTOR_512CPS               0x90
00224 #define RH_RF95_SPREADING_FACTOR_1024CPS              0xa0
00225 #define RH_RF95_SPREADING_FACTOR_2048CPS              0xb0
00226 #define RH_RF95_SPREADING_FACTOR_4096CPS              0xc0
00227 #define RH_RF95_TX_CONTINUOUS_MOE                     0x08
00228 
00229 #define RH_RF95_PAYLOAD_CRC_ON                        0x04
00230 #define RH_RF95_SYM_TIMEOUT_MSB                       0x03
00231 
00232 // RH_RF95_REG_4B_TCXO                                0x4b
00233 #define RH_RF95_TCXO_TCXO_INPUT_ON                    0x10
00234 
00235 // RH_RF95_REG_4D_PA_DAC                              0x4d
00236 #define RH_RF95_PA_DAC_DISABLE                        0x04
00237 #define RH_RF95_PA_DAC_ENABLE                         0x07
00238 
00239 /////////////////////////////////////////////////////////////////////
00240 /// \class RH_RF95 RH_RF95.h <RH_RF95.h>
00241 /// \brief Driver to send and receive unaddressed, unreliable datagrams via a LoRa 
00242 /// capable radio transceiver.
00243 ///
00244 /// For Semtech SX1276/77/78/79 and HopeRF RF95/96/97/98 and other similar LoRa capable radios.
00245 /// Based on http://www.hoperf.com/upload/rf/RFM95_96_97_98W.pdf
00246 /// and http://www.hoperf.cn/upload/rfchip/RF96_97_98.pdf
00247 /// and http://www.semtech.com/images/datasheet/LoraDesignGuide_STD.pdf
00248 /// and http://www.semtech.com/images/datasheet/sx1276.pdf
00249 /// and http://www.semtech.com/images/datasheet/sx1276_77_78_79.pdf
00250 /// FSK/GFSK/OOK modes are not (yet) supported.
00251 ///
00252 /// Works with
00253 /// - the excellent MiniWirelessLoRa from Anarduino http://www.anarduino.com/miniwireless
00254 /// - The excellent Modtronix inAir4 http://modtronix.com/inair4.html 
00255 /// and inAir9 modules http://modtronix.com/inair9.html.
00256 /// - the excellent Rocket Scream Mini Ultra Pro with the RFM95W 
00257 ///   http://www.rocketscream.com/blog/product/mini-ultra-pro-with-radio/
00258 /// - Lora1276 module from NiceRF http://www.nicerf.com/product_view.aspx?id=99
00259 /// - Adafruit Feather M0 with RFM95 
00260 ///
00261 /// \par Overview
00262 ///
00263 /// This class provides basic functions for sending and receiving unaddressed, 
00264 /// unreliable datagrams of arbitrary length to 251 octets per packet.
00265 ///
00266 /// Manager classes may use this class to implement reliable, addressed datagrams and streams, 
00267 /// mesh routers, repeaters, translators etc.
00268 ///
00269 /// Naturally, for any 2 radios to communicate that must be configured to use the same frequency and 
00270 /// modulation scheme.
00271 ///
00272 /// This Driver provides an object-oriented interface for sending and receiving data messages with Hope-RF
00273 /// RFM95/96/97/98(W), Semtech SX1276/77/78/79 and compatible radio modules in LoRa mode.
00274 ///
00275 /// The Hope-RF (http://www.hoperf.com) RFM95/96/97/98(W) and Semtech SX1276/77/78/79 is a low-cost ISM transceiver
00276 /// chip. It supports FSK, GFSK, OOK over a wide range of frequencies and
00277 /// programmable data rates, and it also supports the proprietary LoRA (Long Range) mode, which
00278 /// is the only mode supported in this RadioHead driver.
00279 ///
00280 /// This Driver provides functions for sending and receiving messages of up
00281 /// to 251 octets on any frequency supported by the radio, in a range of
00282 /// predefined Bandwidths, Spreading Factors and Coding Rates.  Frequency can be set with
00283 /// 61Hz precision to any frequency from 240.0MHz to 960.0MHz. Caution: most modules only support a more limited
00284 /// range of frequencies due to antenna tuning.
00285 ///
00286 /// Up to 2 modules can be connected to an Arduino (3 on a Mega),
00287 /// permitting the construction of translators and frequency changers, etc.
00288 ///
00289 /// Support for other features such as transmitter power control etc is
00290 /// also provided.
00291 ///
00292 /// Tested on MinWirelessLoRa with arduino-1.0.5
00293 /// on OpenSuSE 13.1. 
00294 /// Also tested with Teensy3.1, Modtronix inAir4 and Arduino 1.6.5 on OpenSuSE 13.1
00295 ///
00296 /// \par Packet Format
00297 ///
00298 /// All messages sent and received by this RH_RF95 Driver conform to this packet format:
00299 ///
00300 /// - LoRa mode:
00301 /// - 8 symbol PREAMBLE
00302 /// - Explicit header with header CRC (handled internally by the radio)
00303 /// - 4 octets HEADER: (TO, FROM, ID, FLAGS)
00304 /// - 0 to 251 octets DATA 
00305 /// - CRC (handled internally by the radio)
00306 ///
00307 /// \par Connecting RFM95/96/97/98 and Semtech SX1276/77/78/79 to Arduino
00308 ///
00309 /// We tested with Anarduino MiniWirelessLoRA, which is an Arduino Duemilanove compatible with a RFM96W
00310 /// module on-board. Therefore it needs no connections other than the USB
00311 /// programming connection and an antenna to make it work.
00312 ///
00313 /// If you have a bare RFM95/96/97/98 that you want to connect to an Arduino, you
00314 /// might use these connections (untested): CAUTION: you must use a 3.3V type
00315 /// Arduino, otherwise you will also need voltage level shifters between the
00316 /// Arduino and the RFM95.  CAUTION, you must also ensure you connect an
00317 /// antenna.
00318 /// 
00319 /// \code
00320 ///                 Arduino      RFM95/96/97/98
00321 ///                 GND----------GND   (ground in)
00322 ///                 3V3----------3.3V  (3.3V in)
00323 /// interrupt 0 pin D2-----------DIO0  (interrupt request out)
00324 ///          SS pin D10----------NSS   (CS chip select in)
00325 ///         SCK pin D13----------SCK   (SPI clock in)
00326 ///        MOSI pin D11----------MOSI  (SPI Data in)
00327 ///        MISO pin D12----------MISO  (SPI Data out)
00328 /// \endcode
00329 /// With these connections, you can then use the default constructor RH_RF95().
00330 /// You can override the default settings for the SS pin and the interrupt in
00331 /// the RH_RF95 constructor if you wish to connect the slave select SS to other
00332 /// than the normal one for your Arduino (D10 for Diecimila, Uno etc and D53
00333 /// for Mega) or the interrupt request to other than pin D2 (Caution,
00334 /// different processors have different constraints as to the pins available
00335 /// for interrupts).
00336 ///
00337 /// You can connect a Modtronix inAir4 or inAir9 directly to a 3.3V part such as a Teensy 3.1 like
00338 /// this (tested).
00339 /// \code
00340 ///                 Teensy      inAir4 inAir9
00341 ///                 GND----------GND   (ground in)
00342 ///                 3V3----------3.3V  (3.3V in)
00343 /// interrupt 0 pin D2-----------D00   (interrupt request out)
00344 ///          SS pin D10----------CS    (CS chip select in)
00345 ///         SCK pin D13----------CK    (SPI clock in)
00346 ///        MOSI pin D11----------SI    (SPI Data in)
00347 ///        MISO pin D12----------SO    (SPI Data out)
00348 /// \endcode
00349 /// With these connections, you can then use the default constructor RH_RF95().
00350 /// you must also set the transmitter power with useRFO:
00351 /// driver.setTxPower(13, true);
00352 ///
00353 /// Note that if you are using Modtronix inAir4 or inAir9,or any other module which uses the
00354 /// transmitter RFO pins and not the PA_BOOST pins
00355 /// that you must configure the power transmitter power for -1 to 14 dBm and with useRFO true. 
00356 /// Failure to do that will result in extremely low transmit powers.
00357 ///
00358 /// If you have an Arduino M0 Pro from arduino.org, 
00359 /// you should note that you cannot use Pin 2 for the interrupt line 
00360 /// (Pin 2 is for the NMI only). The same comments apply to Pin 4 on Arduino Zero from arduino.cc.
00361 /// Instead you can use any other pin (we use Pin 3) and initialise RH_RF69 like this:
00362 /// \code
00363 /// // Slave Select is pin 10, interrupt is Pin 3
00364 /// RH_RF95 driver(10, 3);
00365 /// \endcode
00366 ///
00367 /// If you have a Rocket Scream Mini Ultra Pro with the RFM95W:
00368 /// - Ensure you have Arduino SAMD board support 1.6.5 or later in Arduino IDE 1.6.8 or later.
00369 /// - The radio SS is hardwired to pin D5 and the DIO0 interrupt to pin D2, 
00370 /// so you need to initialise the radio like this:
00371 /// \code
00372 /// RH_RF95 driver(5, 2);
00373 /// \endcode
00374 /// - The name of the serial port on that board is 'SerialUSB', not 'Serial', so this may be helpful at the top of our
00375 ///   sample sketches:
00376 /// \code
00377 /// #define Serial SerialUSB
00378 /// \endcode
00379 /// - You also need this in setup before radio initialisation  
00380 /// \code
00381 /// // Ensure serial flash is not interfering with radio communication on SPI bus
00382 ///  pinMode(4, OUTPUT);
00383 ///  digitalWrite(4, HIGH);
00384 /// \endcode
00385 /// - and if you have a 915MHz part, you need this after driver/manager intitalisation:
00386 /// \code
00387 /// rf95.setFrequency(915.0);
00388 /// \endcode
00389 /// which adds up to modifying sample sketches something like:
00390 /// \code
00391 /// #include <SPI.h>
00392 /// #include <RH_RF95.h>
00393 /// RH_RF95 rf95(5, 2); // Rocket Scream Mini Ultra Pro with the RFM95W
00394 /// #define Serial SerialUSB
00395 /// 
00396 /// void setup() 
00397 /// {
00398 ///   // Ensure serial flash is not interfering with radio communication on SPI bus
00399 ///   pinMode(4, OUTPUT);
00400 ///   digitalWrite(4, HIGH);
00401 /// 
00402 ///   Serial.begin(9600);
00403 ///   while (!Serial) ; // Wait for serial port to be available
00404 ///   if (!rf95.init())
00405 ///     Serial.println("init failed");
00406 ///   rf95.setFrequency(915.0);
00407 /// }
00408 /// ...
00409 /// \endcode
00410 ///
00411 /// For Adafruit Feather M0 with RFM95, construct the driver like this:
00412 /// \code
00413 /// RH_RF95 rf95(8, 3);
00414 /// \endcode
00415 ///
00416 /// It is possible to have 2 or more radios connected to one Arduino, provided
00417 /// each radio has its own SS and interrupt line (SCK, SDI and SDO are common
00418 /// to all radios)
00419 ///
00420 /// Caution: on some Arduinos such as the Mega 2560, if you set the slave
00421 /// select pin to be other than the usual SS pin (D53 on Mega 2560), you may
00422 /// need to set the usual SS pin to be an output to force the Arduino into SPI
00423 /// master mode.
00424 ///
00425 /// Caution: Power supply requirements of the RFM module may be relevant in some circumstances: 
00426 /// RFM95/96/97/98 modules are capable of pulling 120mA+ at full power, where Arduino's 3.3V line can
00427 /// give 50mA. You may need to make provision for alternate power supply for
00428 /// the RFM module, especially if you wish to use full transmit power, and/or you have
00429 /// other shields demanding power. Inadequate power for the RFM is likely to cause symptoms such as:
00430 /// - reset's/bootups terminate with "init failed" messages
00431 /// - random termination of communication after 5-30 packets sent/received
00432 /// - "fake ok" state, where initialization passes fluently, but communication doesn't happen
00433 /// - shields hang Arduino boards, especially during the flashing
00434 ///
00435 /// \par Interrupts
00436 ///
00437 /// The RH_RF95 driver uses interrupts to react to events in the RFM module,
00438 /// such as the reception of a new packet, or the completion of transmission
00439 /// of a packet.  The RH_RF95 driver interrupt service routine reads status from
00440 /// and writes data to the the RFM module via the SPI interface. It is very
00441 /// important therefore, that if you are using the RH_RF95 driver with another
00442 /// SPI based deviced, that you disable interrupts while you transfer data to
00443 /// and from that other device.  Use cli() to disable interrupts and sei() to
00444 /// reenable them.
00445 ///
00446 /// \par Memory
00447 ///
00448 /// The RH_RF95 driver requires non-trivial amounts of memory. The sample
00449 /// programs all compile to about 8kbytes each, which will fit in the
00450 /// flash proram memory of most Arduinos. However, the RAM requirements are
00451 /// more critical. Therefore, you should be vary sparing with RAM use in
00452 /// programs that use the RH_RF95 driver.
00453 ///
00454 /// It is often hard to accurately identify when you are hitting RAM limits on Arduino. 
00455 /// The symptoms can include:
00456 /// - Mysterious crashes and restarts
00457 /// - Changes in behaviour when seemingly unrelated changes are made (such as adding print() statements)
00458 /// - Hanging
00459 /// - Output from Serial.print() not appearing
00460 ///
00461 /// \par Range
00462 ///
00463 /// We have made some simple range tests under the following conditions:
00464 /// - rf95_client base station connected to a VHF discone antenna at 8m height above ground
00465 /// - rf95_server mobile connected to 17.3cm 1/4 wavelength antenna at 1m height, no ground plane.
00466 /// - Both configured for 13dBm, 434MHz, Bw = 125 kHz, Cr = 4/8, Sf = 4096chips/symbol, CRC on. Slow+long range
00467 /// - Minimum reported RSSI seen for successful comms was about -91
00468 /// - Range over flat ground through heavy trees and vegetation approx 2km.
00469 /// - At 20dBm (100mW) otherwise identical conditions approx 3km.
00470 /// - At 20dBm, along salt water flat sandy beach, 3.2km.
00471 ///
00472 /// It should be noted that at this data rate, a 12 octet message takes 2 seconds to transmit.
00473 ///
00474 /// At 20dBm (100mW) with Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. 
00475 /// (Default medium range) in the conditions described above.
00476 /// - Range over flat ground through heavy trees and vegetation approx 2km.
00477 ///
00478 /// Caution: the performance of this radio, especially with narrow bandwidths is strongly dependent on the
00479 /// accuracy and stability of the chip clock. HopeRF and Semtech do not appear to 
00480 /// recommend bandwidths of less than 62.5 kHz 
00481 /// unless you have the optional Temperature Compensated Crystal Oscillator (TCXO) installed and 
00482 /// enabled on your radio module. See the refernece manual for more data.
00483 /// Also https://lowpowerlab.com/forum/rf-range-antennas-rfm69-library/lora-library-experiences-range/15/
00484 /// and http://www.semtech.com/images/datasheet/an120014-xo-guidance-lora-modulation.pdf
00485 /// 
00486 /// \par Transmitter Power
00487 ///
00488 /// You can control the transmitter power on the RF transceiver
00489 /// with the RH_RF95::setTxPower() function. The argument can be any of
00490 /// +5 to +23 (for modules that use PA_BOOST)
00491 /// -1 to +14 (for modules that use RFO transmitter pin)
00492 /// The default is 13. Eg:
00493 /// \code
00494 /// driver.setTxPower(10); // use PA_BOOST transmitter pin
00495 /// driver.setTxPower(10, true); // use PA_RFO pin transmitter pin
00496 /// \endcode
00497 ///
00498 /// We have made some actual power measurements against
00499 /// programmed power for Anarduino MiniWirelessLoRa (which has RFM96W-433Mhz installed)
00500 /// - MiniWirelessLoRa RFM96W-433Mhz, USB power
00501 /// - 30cm RG316 soldered direct to RFM96W module ANT and GND
00502 /// - SMA connector
00503 /// - 12db attenuator
00504 /// - SMA connector
00505 /// - MiniKits AD8307 HF/VHF Power Head (calibrated against Rohde&Schwartz 806.2020 test set)
00506 /// - Tektronix TDS220 scope to measure the Vout from power head
00507 /// \code
00508 /// Program power           Measured Power
00509 ///    dBm                         dBm
00510 ///      5                           5
00511 ///      7                           7
00512 ///      9                           8
00513 ///     11                          11
00514 ///     13                          13
00515 ///     15                          15
00516 ///     17                          16
00517 ///     19                          18
00518 ///     20                          20 
00519 ///     21                          21 
00520 ///     22                          22 
00521 ///     23                          23 
00522 /// \endcode
00523 ///
00524 /// We have also measured the actual power output from a Modtronix inAir4 http://modtronix.com/inair4.html
00525 /// connected to a Teensy 3.1:
00526 /// Teensy 3.1 this is a 3.3V part, connected directly to:
00527 /// Modtronix inAir4 with SMA antenna connector, connected as above:
00528 /// 10cm SMA-SMA cable
00529 /// - MiniKits AD8307 HF/VHF Power Head (calibrated against Rohde&Schwartz 806.2020 test set)
00530 /// - Tektronix TDS220 scope to measure the Vout from power head
00531 /// \code
00532 /// Program power           Measured Power
00533 ///    dBm                         dBm
00534 ///      -1                         0
00535 ///      1                          2
00536 ///      3                          4
00537 ///      5                          7
00538 ///      7                         10
00539 ///      9                         13
00540 ///     11                         14.2
00541 ///     13                         15
00542 ///     14                         16
00543 /// \endcode
00544 /// (Caution: we dont claim laboratory accuracy for these power measurements)
00545 /// You would not expect to get anywhere near these powers to air with a simple 1/4 wavelength wire antenna.
00546 class RH_RF95 : public RHGenericDriver
00547 {
00548 public:
00549     /// \brief Defines register values for a set of modem configuration registers
00550     ///
00551     /// Defines register values for a set of modem configuration registers
00552     /// that can be passed to setModemRegisters() if none of the choices in
00553     /// ModemConfigChoice suit your need setModemRegisters() writes the
00554     /// register values from this structure to the appropriate registers
00555     /// to set the desired spreading factor, coding rate and bandwidth
00556     typedef struct
00557     {
00558     uint8_t    reg_1d;   ///< Value for register RH_RF95_REG_1D_MODEM_CONFIG1
00559     uint8_t    reg_1e;   ///< Value for register RH_RF95_REG_1E_MODEM_CONFIG2
00560     uint8_t    reg_26;   ///< Value for register RH_RF95_REG_26_MODEM_CONFIG3
00561     } ModemConfig;
00562   
00563     /// Choices for setModemConfig() for a selected subset of common
00564     /// data rates. If you need another configuration,
00565     /// determine the necessary settings and call setModemRegisters() with your
00566     /// desired settings. It might be helpful to use the LoRa calculator mentioned in 
00567     /// http://www.semtech.com/images/datasheet/LoraDesignGuide_STD.pdf
00568     /// These are indexes into MODEM_CONFIG_TABLE. We strongly recommend you use these symbolic
00569     /// definitions and not their integer equivalents: its possible that new values will be
00570     /// introduced in later versions (though we will try to avoid it).
00571     /// Caution: if you are using slow packet rates and long packets with RHReliableDatagram or subclasses
00572     /// you may need to change the RHReliableDatagram timeout for reliable operations.
00573     /// Caution: for some slow rates nad with ReliableDatagrams youi may need to increase the reply timeout 
00574     /// with manager.setTimeout() to
00575     /// deal with the long transmission times.
00576     typedef enum
00577     {
00578     Bw125Cr45Sf128 = 0,    ///< Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Default medium range
00579     Bw500Cr45Sf128,            ///< Bw = 500 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Fast+short range
00580     Bw31_25Cr48Sf512,      ///< Bw = 31.25 kHz, Cr = 4/8, Sf = 512chips/symbol, CRC on. Slow+long range
00581     Bw125Cr48Sf4096,           ///< Bw = 125 kHz, Cr = 4/8, Sf = 4096chips/symbol, CRC on. Slow+long range
00582     } ModemConfigChoice;
00583 
00584     /// Constructor. You can have multiple instances, but each instance must have its own
00585     /// interrupt and slave select pin. After constructing, you must call init() to initialise the interface
00586     /// and the radio module. A maximum of 3 instances can co-exist on one processor, provided there are sufficient
00587     /// distinct interrupt lines, one for each instance.
00588     /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RH_RF22 before
00589     /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega, D10 for Maple)
00590     /// \param[in] interruptPin The interrupt Pin number that is connected to the RFM DIO0 interrupt line. 
00591     /// Defaults to pin 2, as required by Anarduino MinWirelessLoRa module.
00592     /// Caution: You must specify an interrupt capable pin.
00593     /// On many Arduino boards, there are limitations as to which pins may be used as interrupts.
00594     /// On Leonardo pins 0, 1, 2 or 3. On Mega2560 pins 2, 3, 18, 19, 20, 21. On Due and Teensy, any digital pin.
00595     /// On Arduino Zero from arduino.cc, any digital pin other than 4.
00596     /// On Arduino M0 Pro from arduino.org, any digital pin other than 2.
00597     /// On other Arduinos pins 2 or 3. 
00598     /// See http://arduino.cc/en/Reference/attachInterrupt for more details.
00599     /// On Chipkit Uno32, pins 38, 2, 7, 8, 35.
00600     /// On other boards, any digital pin may be used.
00601     /// \param[in] spi Pointer to the SPI interface object to use. 
00602     /// \param[in] ssNum the swspi slave select number to use
00603     RH_RF95(swspi& spi, int ssNum);
00604   
00605     /// Initialise the Driver transport hardware and software.
00606     /// Make sure the Driver is properly configured before calling init().
00607     /// \return true if initialisation succeeded.
00608     virtual bool    init();
00609 
00610     /// Prints the value of all chip registers
00611     /// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
00612     /// For debugging purposes only.
00613     /// \return true on success
00614     bool printRegisters();
00615 
00616     /// Sets all the registered required to configure the data modem in the RF95/96/97/98, including the bandwidth, 
00617     /// spreading factor etc. You can use this to configure the modem with custom configurations if none of the 
00618     /// canned configurations in ModemConfigChoice suit you.
00619     /// \param[in] config A ModemConfig structure containing values for the modem configuration registers.
00620     void           setModemRegisters(const ModemConfig* config);
00621 
00622     /// Select one of the predefined modem configurations. If you need a modem configuration not provided 
00623     /// here, use setModemRegisters() with your own ModemConfig.
00624     /// \param[in] index The configuration choice.
00625     /// \return true if index is a valid choice.
00626     bool        setModemConfig(ModemConfigChoice index);
00627 
00628     /// Tests whether a new message is available
00629     /// from the Driver. 
00630     /// On most drivers, this will also put the Driver into RHModeRx mode until
00631     /// a message is actually received by the transport, when it wil be returned to RHModeIdle.
00632     /// This can be called multiple times in a timeout loop
00633     /// \return true if a new, complete, error-free uncollected message is available to be retreived by recv()
00634     virtual bool    available();
00635 
00636     /// Turns the receiver on if it not already on.
00637     /// If there is a valid message available, copy it to buf and return true
00638     /// else return false.
00639     /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
00640     /// You should be sure to call this function frequently enough to not miss any messages
00641     /// It is recommended that you call it in your main loop.
00642     /// \param[in] buf Location to copy the received message
00643     /// \param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied.
00644     /// \return true if a valid message was copied to buf
00645     virtual bool    recv(uint8_t* buf, uint8_t* len);
00646 
00647     /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
00648     /// Then optionally waits for Channel Activity Detection (CAD) 
00649     /// to show the channnel is clear (if the radio supports CAD) by calling waitCAD().
00650     /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
00651     /// of 0 is permitted. 
00652     /// \param[in] data Array of data to be sent
00653     /// \param[in] len Number of bytes of data to send
00654     /// specify the maximum time in ms to wait. If 0 (the default) do not wait for CAD before transmitting.
00655     /// \return true if the message length was valid and it was correctly queued for transmit. Return false
00656     /// if CAD was requested and the CAD timeout timed out before clear channel was detected.
00657     virtual bool    send(const uint8_t* data, uint8_t len);
00658 
00659     /// Sets the length of the preamble
00660     /// in bytes. 
00661     /// Caution: this should be set to the same 
00662     /// value on all nodes in your network. Default is 8.
00663     /// Sets the message preamble length in RH_RF95_REG_??_PREAMBLE_?SB
00664     /// \param[in] bytes Preamble length in bytes.  
00665     void           setPreambleLength(uint16_t bytes);
00666 
00667     /// Returns the maximum message length 
00668     /// available in this Driver.
00669     /// \return The maximum legal message length
00670     virtual uint8_t maxMessageLength();
00671 
00672     /// Sets the transmitter and receiver 
00673     /// centre frequency.
00674     /// \param[in] centre Frequency in MHz. 137.0 to 1020.0. Caution: RFM95/96/97/98 comes in several
00675     /// different frequency ranges, and setting a frequency outside that range of your radio will probably not work
00676     /// \return true if the selected frquency centre is within range
00677     bool        setFrequency(float centre);
00678 
00679     /// If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running, 
00680     /// disables them.
00681     void           setModeIdle();
00682 
00683     /// If current mode is Tx or Idle, changes it to Rx. 
00684     /// Starts the receiver in the RF95/96/97/98.
00685     void           setModeRx();
00686 
00687     /// If current mode is Rx or Idle, changes it to Rx. F
00688     /// Starts the transmitter in the RF95/96/97/98.
00689     void           setModeTx();
00690 
00691     /// Sets the transmitter power output level, and configures the transmitter pin.
00692     /// Be a good neighbour and set the lowest power level you need.
00693     /// Some SX1276/77/78/79 and compatible modules (such as RFM95/96/97/98) 
00694     /// use the PA_BOOST transmitter pin for high power output (and optionally the PA_DAC)
00695     /// while some (such as the Modtronix inAir4 and inAir9) 
00696     /// use the RFO transmitter pin for lower power but higher efficiency.
00697     /// You must set the appropriate power level and useRFO argument for your module.
00698     /// Check with your module manufacturer which transmtter pin is used on your module
00699     /// to ensure you are setting useRFO correctly. 
00700     /// Failure to do so will result in very low 
00701     /// transmitter power output.
00702     /// Caution: legal power limits may apply in certain countries.
00703     /// After init(), the power will be set to 13dBm, with useRFO false (ie PA_BOOST enabled).
00704     /// \param[in] power Transmitter power level in dBm. For RFM95/96/97/98 LORA with useRFO false, 
00705     /// valid values are from +5 to +23.
00706     /// For Modtronix inAir4 and inAir9 with useRFO true (ie RFO pins in use), 
00707     /// valid values are from -1 to 14.
00708     /// \param[in] useRFO If true, enables the use of the RFO transmitter pins instead of
00709     /// the PA_BOOST pin (false). Choose the correct setting for your module.
00710     void           setTxPower(int8_t power, bool useRFO = false);
00711 
00712     /// Sets the radio into low-power sleep mode.
00713     /// If successful, the transport will stay in sleep mode until woken by 
00714     /// changing mode it idle, transmit or receive (eg by calling send(), recv(), available() etc)
00715     /// Caution: there is a time penalty as the radio takes a finite time to wake from sleep mode.
00716     /// \return true if sleep mode was successfully entered.
00717     virtual bool    sleep();
00718 
00719     // Bent G Christensen (bentor@gmail.com), 08/15/2016
00720     /// Use the radio's Channel Activity Detect (CAD) function to detect channel activity.
00721     /// Sets the RF95 radio into CAD mode and waits until CAD detection is complete.
00722     /// To be used in a listen-before-talk mechanism (Collision Avoidance)
00723     /// with a reasonable time backoff algorithm.
00724     /// This is called automatically by waitCAD().
00725     /// \return true if channel is in use.  
00726     virtual bool    isChannelActive();
00727 
00728     /// Enable TCXO mode
00729     /// Call this immediately after init(), to force your radio to use an external 
00730     /// frequency source, such as a Temperature Compensated Crystal Oscillator (TCXO).
00731     /// See the comments in the main documentation about the sensitivity of this radio to
00732     /// clock frequency especially when using narrow bandwidths.
00733     /// Leaves the module in sleep mode.
00734     /// Caution, this function has not been tested by us.
00735     void enableTCXO();
00736 
00737     /// Returns the last measured frequency error.
00738     /// The LoRa receiver estimates the frequency offset between the receiver centre frequency
00739     /// and that of the received LoRa signal. This function returns the estimates offset (in Hz) 
00740     /// of the last received message. Caution: this measurement is not absolute, but is measured 
00741     /// relative to the local receiver's oscillator. 
00742     /// Apparent errors may be due to the transmitter, the receiver or both.
00743     /// \return The estimated centre frequency offset in Hz of the last received message. 
00744     /// If the modem bandwidth selector in 
00745     /// register RH_RF95_REG_1D_MODEM_CONFIG1 is invalid, returns 0.
00746     int frequencyError();
00747 
00748     /// Returns the Signal-to-noise ratio (SNR) of the last received message, as measured
00749     /// by the receiver.
00750     /// \return SNR of the last received message in dB
00751     int lastSNR();
00752 
00753     /// This is a low level function to handle the interrupts for one instance of RH_RF95.
00754     /// Must be called from user code in mbed because the swspi library mutex cannot be
00755     /// executed in an ISR.  It should be executed when the ISR pin is seen low.
00756     void           handleInterrupt();
00757 
00758 protected:
00759     /// Examine the revceive buffer to determine whether the message is for this node
00760     void validateRxBuf();
00761 
00762     /// Clear our local receive buffer
00763     void clearRxBuf();
00764 
00765 private:
00766     /// SPI
00767     swspi&              _spi;
00768     int                 _ssn;
00769     
00770     /// Number of octets in the buffer
00771     volatile uint8_t    _bufLen;
00772     
00773     /// The receiver/transmitter buffer
00774     uint8_t             _buf[RH_RF95_MAX_PAYLOAD_LEN];
00775 
00776     /// True when there is a valid message in the buffer
00777     volatile bool       _rxBufValid;
00778 
00779     // True if we are using the HF port (779.0 MHz and above)
00780     bool                _usingHFport;
00781 
00782     // Last measured SNR, dB
00783     int8_t              _lastSNR;
00784 };
00785 
00786 /// @example rf95_client.pde
00787 /// @example rf95_server.pde
00788 /// @example rf95_reliable_datagram_client.pde
00789 /// @example rf95_reliable_datagram_server.pde
00790 
00791 #endif
00792