David Rimer / RadioHead-148
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RH_RF69.h Source File

RH_RF69.h

00001 // RH_RF69.h
00002 // Author: Mike McCauley (mikem@airspayce.com)
00003 // Copyright (C) 2014 Mike McCauley
00004 // $Id: RH_RF69.h,v 1.29 2015/05/17 00:11:26 mikem Exp $
00005 //
00006 ///
00007 
00008 
00009 #ifndef RH_RF69_h
00010 #define RH_RF69_h
00011 
00012 #include <RHGenericSPI.h>
00013 #include <RHSPIDriver.h>
00014 
00015 // The crystal oscillator frequency of the RF69 module
00016 #define RH_RF69_FXOSC 32000000.0
00017 
00018 // The Frequency Synthesizer step = RH_RF69_FXOSC / 2^^19
00019 #define RH_RF69_FSTEP  (RH_RF69_FXOSC / 524288)
00020 
00021 // This is the maximum number of interrupts the driver can support
00022 // Most Arduinos can handle 2, Megas can handle more
00023 #define RH_RF69_NUM_INTERRUPTS 3
00024 
00025 // This is the bit in the SPI address that marks it as a write
00026 #define RH_RF69_SPI_WRITE_MASK 0x80
00027 
00028 // Max number of octets the RH_RF69 Rx and Tx FIFOs can hold
00029 #define RH_RF69_FIFO_SIZE 66
00030 
00031 // Maximum encryptable payload length the RF69 can support
00032 #define RH_RF69_MAX_ENCRYPTABLE_PAYLOAD_LEN 64
00033 
00034 // The length of the headers we add.
00035 // The headers are inside the RF69's payload and are therefore encrypted if encryption is enabled
00036 #define RH_RF69_HEADER_LEN 4
00037 
00038 // This is the maximum message length that can be supported by this driver. Limited by
00039 // the size of the FIFO, since we are unable to support on-the-fly filling and emptying 
00040 // of the FIFO.
00041 // Can be pre-defined to a smaller size (to save SRAM) prior to including this header
00042 // Here we allow for 4 bytes of address and header and payload to be included in the 64 byte encryption limit.
00043 // the one byte payload length is not encrpyted
00044 #ifndef RH_RF69_MAX_MESSAGE_LEN
00045 #define RH_RF69_MAX_MESSAGE_LEN (RH_RF69_MAX_ENCRYPTABLE_PAYLOAD_LEN - RH_RF69_HEADER_LEN)
00046 #endif
00047 
00048 // Keep track of the mode the RF69 is in
00049 #define RH_RF69_MODE_IDLE         0
00050 #define RH_RF69_MODE_RX           1
00051 #define RH_RF69_MODE_TX           2
00052 
00053 // This is the default node address,
00054 #define RH_RF69_DEFAULT_NODE_ADDRESS 0
00055 
00056 // Register names
00057 #define RH_RF69_REG_00_FIFO                                 0x00
00058 #define RH_RF69_REG_01_OPMODE                               0x01
00059 #define RH_RF69_REG_02_DATAMODUL                            0x02
00060 #define RH_RF69_REG_03_BITRATEMSB                           0x03
00061 #define RH_RF69_REG_04_BITRATELSB                           0x04
00062 #define RH_RF69_REG_05_FDEVMSB                              0x05
00063 #define RH_RF69_REG_06_FDEVLSB                              0x06
00064 #define RH_RF69_REG_07_FRFMSB                               0x07
00065 #define RH_RF69_REG_08_FRFMID                               0x08
00066 #define RH_RF69_REG_09_FRFLSB                               0x09
00067 #define RH_RF69_REG_0A_OSC1                                 0x0a
00068 #define RH_RF69_REG_0B_AFCCTRL                              0x0b
00069 #define RH_RF69_REG_0C_RESERVED                             0x0c
00070 #define RH_RF69_REG_0D_LISTEN1                              0x0d
00071 #define RH_RF69_REG_0E_LISTEN2                              0x0e
00072 #define RH_RF69_REG_0F_LISTEN3                              0x0f
00073 #define RH_RF69_REG_10_VERSION                              0x10
00074 #define RH_RF69_REG_11_PALEVEL                              0x11
00075 #define RH_RF69_REG_12_PARAMP                               0x12
00076 #define RH_RF69_REG_13_OCP                                  0x13
00077 #define RH_RF69_REG_14_RESERVED                             0x14
00078 #define RH_RF69_REG_15_RESERVED                             0x15
00079 #define RH_RF69_REG_16_RESERVED                             0x16
00080 #define RH_RF69_REG_17_RESERVED                             0x17
00081 #define RH_RF69_REG_18_LNA                                  0x18
00082 #define RH_RF69_REG_19_RXBW                                 0x19
00083 #define RH_RF69_REG_1A_AFCBW                                0x1a
00084 #define RH_RF69_REG_1B_OOKPEAK                              0x1b
00085 #define RH_RF69_REG_1C_OOKAVG                               0x1c
00086 #define RH_RF69_REG_1D_OOKFIX                               0x1d
00087 #define RH_RF69_REG_1E_AFCFEI                               0x1e
00088 #define RH_RF69_REG_1F_AFCMSB                               0x1f
00089 #define RH_RF69_REG_20_AFCLSB                               0x20
00090 #define RH_RF69_REG_21_FEIMSB                               0x21
00091 #define RH_RF69_REG_22_FEILSB                               0x22
00092 #define RH_RF69_REG_23_RSSICONFIG                           0x23
00093 #define RH_RF69_REG_24_RSSIVALUE                            0x24
00094 #define RH_RF69_REG_25_DIOMAPPING1                          0x25
00095 #define RH_RF69_REG_26_DIOMAPPING2                          0x26
00096 #define RH_RF69_REG_27_IRQFLAGS1                            0x27
00097 #define RH_RF69_REG_28_IRQFLAGS2                            0x28
00098 #define RH_RF69_REG_29_RSSITHRESH                           0x29
00099 #define RH_RF69_REG_2A_RXTIMEOUT1                           0x2a
00100 #define RH_RF69_REG_2B_RXTIMEOUT2                           0x2b
00101 #define RH_RF69_REG_2C_PREAMBLEMSB                          0x2c
00102 #define RH_RF69_REG_2D_PREAMBLELSB                          0x2d
00103 #define RH_RF69_REG_2E_SYNCCONFIG                           0x2e
00104 #define RH_RF69_REG_2F_SYNCVALUE1                           0x2f
00105 // another 7 sync word bytes follow, 30 through 36 inclusive
00106 #define RH_RF69_REG_37_PACKETCONFIG1                        0x37
00107 #define RH_RF69_REG_38_PAYLOADLENGTH                        0x38
00108 #define RH_RF69_REG_39_NODEADRS                             0x39
00109 #define RH_RF69_REG_3A_BROADCASTADRS                        0x3a
00110 #define RH_RF69_REG_3B_AUTOMODES                            0x3b
00111 #define RH_RF69_REG_3C_FIFOTHRESH                           0x3c
00112 #define RH_RF69_REG_3D_PACKETCONFIG2                        0x3d
00113 #define RH_RF69_REG_3E_AESKEY1                              0x3e
00114 // Another 15 AES key bytes follow
00115 #define RH_RF69_REG_4E_TEMP1                                0x4e
00116 #define RH_RF69_REG_4F_TEMP2                                0x4f
00117 #define RH_RF69_REG_58_TESTLNA                              0x58
00118 #define RH_RF69_REG_5A_TESTPA1                              0x5a
00119 #define RH_RF69_REG_5C_TESTPA2                              0x5c
00120 #define RH_RF69_REG_6F_TESTDAGC                             0x6f
00121 #define RH_RF69_REG_71_TESTAFC                              0x71
00122 
00123 // These register masks etc are named wherever possible
00124 // corresponding to the bit and field names in the RFM69 Manual
00125 
00126 // RH_RF69_REG_01_OPMODE
00127 #define RH_RF69_OPMODE_SEQUENCEROFF                         0x80
00128 #define RH_RF69_OPMODE_LISTENON                             0x40
00129 #define RH_RF69_OPMODE_LISTENABORT                          0x20
00130 #define RH_RF69_OPMODE_MODE                                 0x1c
00131 #define RH_RF69_OPMODE_MODE_SLEEP                           0x00
00132 #define RH_RF69_OPMODE_MODE_STDBY                           0x04
00133 #define RH_RF69_OPMODE_MODE_FS                              0x08
00134 #define RH_RF69_OPMODE_MODE_TX                              0x0c
00135 #define RH_RF69_OPMODE_MODE_RX                              0x10
00136 
00137 // RH_RF69_REG_02_DATAMODUL
00138 #define RH_RF69_DATAMODUL_DATAMODE                          0x60
00139 #define RH_RF69_DATAMODUL_DATAMODE_PACKET                   0x00
00140 #define RH_RF69_DATAMODUL_DATAMODE_CONT_WITH_SYNC           0x40
00141 #define RH_RF69_DATAMODUL_DATAMODE_CONT_WITHOUT_SYNC        0x60
00142 #define RH_RF69_DATAMODUL_MODULATIONTYPE                    0x18
00143 #define RH_RF69_DATAMODUL_MODULATIONTYPE_FSK                0x00
00144 #define RH_RF69_DATAMODUL_MODULATIONTYPE_OOK                0x08
00145 #define RH_RF69_DATAMODUL_MODULATIONSHAPING                 0x03
00146 #define RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_NONE        0x00
00147 #define RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_BT1_0       0x01
00148 #define RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_BT0_5       0x02
00149 #define RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_BT0_3       0x03
00150 #define RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_NONE        0x00
00151 #define RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_BR          0x01
00152 #define RH_RF69_DATAMODUL_MODULATIONSHAPING_OOK_2BR         0x02
00153 
00154 // RH_RF69_REG_11_PALEVEL
00155 #define RH_RF69_PALEVEL_PA0ON                               0x80
00156 #define RH_RF69_PALEVEL_PA1ON                               0x40
00157 #define RH_RF69_PALEVEL_PA2ON                               0x20
00158 #define RH_RF69_PALEVEL_OUTPUTPOWER                         0x1f
00159 
00160 // RH_RF69_REG_23_RSSICONFIG
00161 #define RH_RF69_RSSICONFIG_RSSIDONE                         0x02
00162 #define RH_RF69_RSSICONFIG_RSSISTART                        0x01
00163 
00164 // RH_RF69_REG_25_DIOMAPPING1
00165 #define RH_RF69_DIOMAPPING1_DIO0MAPPING                     0xc0
00166 #define RH_RF69_DIOMAPPING1_DIO0MAPPING_00                  0x00
00167 #define RH_RF69_DIOMAPPING1_DIO0MAPPING_01                  0x40
00168 #define RH_RF69_DIOMAPPING1_DIO0MAPPING_10                  0x80
00169 #define RH_RF69_DIOMAPPING1_DIO0MAPPING_11                  0xc0
00170 
00171 #define RH_RF69_DIOMAPPING1_DIO1MAPPING                     0x30
00172 #define RH_RF69_DIOMAPPING1_DIO1MAPPING_00                  0x00
00173 #define RH_RF69_DIOMAPPING1_DIO1MAPPING_01                  0x10
00174 #define RH_RF69_DIOMAPPING1_DIO1MAPPING_10                  0x20
00175 #define RH_RF69_DIOMAPPING1_DIO1MAPPING_11                  0x30
00176 
00177 #define RH_RF69_DIOMAPPING1_DIO2MAPPING                     0x0c
00178 #define RH_RF69_DIOMAPPING1_DIO2MAPPING_00                  0x00
00179 #define RH_RF69_DIOMAPPING1_DIO2MAPPING_01                  0x04
00180 #define RH_RF69_DIOMAPPING1_DIO2MAPPING_10                  0x08
00181 #define RH_RF69_DIOMAPPING1_DIO2MAPPING_11                  0x0c
00182 
00183 #define RH_RF69_DIOMAPPING1_DIO3MAPPING                     0x03
00184 #define RH_RF69_DIOMAPPING1_DIO3MAPPING_00                  0x00
00185 #define RH_RF69_DIOMAPPING1_DIO3MAPPING_01                  0x01
00186 #define RH_RF69_DIOMAPPING1_DIO3MAPPING_10                  0x02
00187 #define RH_RF69_DIOMAPPING1_DIO3MAPPING_11                  0x03
00188 
00189 // RH_RF69_REG_26_DIOMAPPING2
00190 #define RH_RF69_DIOMAPPING2_DIO4MAPPING                     0xc0
00191 #define RH_RF69_DIOMAPPING2_DIO4MAPPING_00                  0x00
00192 #define RH_RF69_DIOMAPPING2_DIO4MAPPING_01                  0x40
00193 #define RH_RF69_DIOMAPPING2_DIO4MAPPING_10                  0x80
00194 #define RH_RF69_DIOMAPPING2_DIO4MAPPING_11                  0xc0
00195 
00196 #define RH_RF69_DIOMAPPING2_DIO5MAPPING                     0x30
00197 #define RH_RF69_DIOMAPPING2_DIO5MAPPING_00                  0x00
00198 #define RH_RF69_DIOMAPPING2_DIO5MAPPING_01                  0x10
00199 #define RH_RF69_DIOMAPPING2_DIO5MAPPING_10                  0x20
00200 #define RH_RF69_DIOMAPPING2_DIO5MAPPING_11                  0x30
00201 
00202 #define RH_RF69_DIOMAPPING2_CLKOUT                          0x07
00203 #define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_                   0x00
00204 #define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_2                  0x01
00205 #define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_4                  0x02
00206 #define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_8                  0x03
00207 #define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_16                 0x04
00208 #define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_32                 0x05
00209 #define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_RC                 0x06
00210 #define RH_RF69_DIOMAPPING2_CLKOUT_FXOSC_OFF                0x07
00211 
00212 // RH_RF69_REG_27_IRQFLAGS1
00213 #define RH_RF69_IRQFLAGS1_MODEREADY                         0x80
00214 #define RH_RF69_IRQFLAGS1_RXREADY                           0x40
00215 #define RH_RF69_IRQFLAGS1_TXREADY                           0x20
00216 #define RH_RF69_IRQFLAGS1_PLLLOCK                           0x10
00217 #define RH_RF69_IRQFLAGS1_RSSI                              0x08
00218 #define RH_RF69_IRQFLAGS1_TIMEOUT                           0x04
00219 #define RH_RF69_IRQFLAGS1_AUTOMODE                          0x02
00220 #define RH_RF69_IRQFLAGS1_SYNADDRESSMATCH                   0x01
00221 
00222 // RH_RF69_REG_28_IRQFLAGS2
00223 #define RH_RF69_IRQFLAGS2_FIFOFULL                          0x80
00224 #define RH_RF69_IRQFLAGS2_FIFONOTEMPTY                      0x40
00225 #define RH_RF69_IRQFLAGS2_FIFOLEVEL                         0x20
00226 #define RH_RF69_IRQFLAGS2_FIFOOVERRUN                       0x10
00227 #define RH_RF69_IRQFLAGS2_PACKETSENT                        0x08
00228 #define RH_RF69_IRQFLAGS2_PAYLOADREADY                      0x04
00229 #define RH_RF69_IRQFLAGS2_CRCOK                             0x02
00230 
00231 // RH_RF69_REG_2E_SYNCCONFIG
00232 #define RH_RF69_SYNCCONFIG_SYNCON                           0x80
00233 #define RH_RF69_SYNCCONFIG_FIFOFILLCONDITION_MANUAL         0x40
00234 #define RH_RF69_SYNCCONFIG_SYNCSIZE                         0x38
00235 #define RH_RF69_SYNCCONFIG_SYNCSIZE_1                       0x00
00236 #define RH_RF69_SYNCCONFIG_SYNCSIZE_2                       0x08
00237 #define RH_RF69_SYNCCONFIG_SYNCSIZE_3                       0x10
00238 #define RH_RF69_SYNCCONFIG_SYNCSIZE_4                       0x18
00239 #define RH_RF69_SYNCCONFIG_SYNCSIZE_5                       0x20
00240 #define RH_RF69_SYNCCONFIG_SYNCSIZE_6                       0x28
00241 #define RH_RF69_SYNCCONFIG_SYNCSIZE_7                       0x30
00242 #define RH_RF69_SYNCCONFIG_SYNCSIZE_8                       0x38
00243 #define RH_RF69_SYNCCONFIG_SYNCSIZE_SYNCTOL                 0x07
00244 
00245 // RH_RF69_REG_37_PACKETCONFIG1
00246 #define RH_RF69_PACKETCONFIG1_PACKETFORMAT_VARIABLE         0x80
00247 #define RH_RF69_PACKETCONFIG1_DCFREE                        0x60
00248 #define RH_RF69_PACKETCONFIG1_DCFREE_NONE                   0x00
00249 #define RH_RF69_PACKETCONFIG1_DCFREE_MANCHESTER             0x20
00250 #define RH_RF69_PACKETCONFIG1_DCFREE_WHITENING              0x40
00251 #define RH_RF69_PACKETCONFIG1_DCFREE_RESERVED               0x60
00252 #define RH_RF69_PACKETCONFIG1_CRC_ON                        0x10
00253 #define RH_RF69_PACKETCONFIG1_CRCAUTOCLEAROFF               0x08
00254 #define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING              0x06
00255 #define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NONE         0x00
00256 #define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NODE         0x02
00257 #define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NODE_BC      0x04
00258 #define RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_RESERVED     0x06
00259 
00260 // RH_RF69_REG_3C_FIFOTHRESH
00261 #define RH_RF69_FIFOTHRESH_TXSTARTCONDITION_NOTEMPTY        0x80
00262 #define RH_RF69_FIFOTHRESH_FIFOTHRESHOLD                    0x7f
00263 
00264 // RH_RF69_REG_3D_PACKETCONFIG2
00265 #define RH_RF69_PACKETCONFIG2_INTERPACKETRXDELAY            0xf0
00266 #define RH_RF69_PACKETCONFIG2_RESTARTRX                     0x04
00267 #define RH_RF69_PACKETCONFIG2_AUTORXRESTARTON               0x02
00268 #define RH_RF69_PACKETCONFIG2_AESON                         0x01
00269 
00270 // RH_RF69_REG_4E_TEMP1
00271 #define RH_RF69_TEMP1_TEMPMEASSTART                         0x08
00272 #define RH_RF69_TEMP1_TEMPMEASRUNNING                       0x04
00273 
00274 // RH_RF69_REG_5A_TESTPA1
00275 #define RH_RF69_TESTPA1_NORMAL                              0x55
00276 #define RH_RF69_TESTPA1_BOOST                               0x5d
00277 
00278 // RH_RF69_REG_5C_TESTPA2
00279 #define RH_RF69_TESTPA2_NORMAL                              0x70
00280 #define RH_RF69_TESTPA2_BOOST                               0x7c
00281 
00282 // RH_RF69_REG_6F_TESTDAGC
00283 #define RH_RF69_TESTDAGC_CONTINUOUSDAGC_NORMAL              0x00
00284 #define RH_RF69_TESTDAGC_CONTINUOUSDAGC_IMPROVED_LOWBETAON  0x20
00285 #define RH_RF69_TESTDAGC_CONTINUOUSDAGC_IMPROVED_LOWBETAOFF 0x30
00286 
00287 // Define this to include Serial printing in diagnostic routines
00288 #define RH_RF69_HAVE_SERIAL
00289 
00290 
00291 /////////////////////////////////////////////////////////////////////
00292 /// \class RH_RF69 RH_RF69.h <RH_RF69.h>
00293 /// \brief Driver to send and receive unaddressed, unreliable datagrams via an RF69 and compatible radio transceiver.
00294 ///
00295 /// Works with 
00296 /// - the excellent Moteino and Moteino-USB 
00297 /// boards from LowPowerLab http://lowpowerlab.com/moteino/
00298 /// - compatible chips and modules such as RFM69W, RFM69HW, RFM69CW, RFM69HCW (Semtech SX1231, SX1231H),
00299 /// - RFM69 modules from http://www.hoperfusa.com such as http://www.hoperfusa.com/details.jsp?pid=145
00300 /// - Anarduino MiniWireless -CW and -HW boards http://www.anarduino.com/miniwireless/ including
00301 ///  the marvellous high powered MinWireless-HW (with 20dBm output for excellent range)
00302 ///
00303 /// \par Overview
00304 ///
00305 /// This class provides basic functions for sending and receiving unaddressed, 
00306 /// unreliable datagrams of arbitrary length to 64 octets per packet.
00307 ///
00308 /// Manager classes may use this class to implement reliable, addressed datagrams and streams, 
00309 /// mesh routers, repeaters, translators etc.
00310 ///
00311 /// Naturally, for any 2 radios to communicate that must be configured to use the same frequency and 
00312 /// modulation scheme.
00313 ///
00314 /// This Driver provides an object-oriented interface for sending and receiving data messages with Hope-RF
00315 /// RF69B and compatible radio modules, such as the RFM69 module.
00316 ///
00317 /// The Hope-RF (http://www.hoperf.com) RF69 is a low-cost ISM transceiver
00318 /// chip. It supports FSK, GFSK, OOK over a wide range of frequencies and
00319 /// programmable data rates. It also suports AES encryption of up to 64 octets
00320 /// of payload It is available prepackaged on modules such as the RFM69W. And
00321 /// such modules can be prepacked on processor boards such as the Moteino from
00322 /// LowPowerLabs (which is what we used to develop the RH_RF69 driver)
00323 ///
00324 /// This Driver provides functions for sending and receiving messages of up
00325 /// to 60 octets on any frequency supported by the RF69, in a range of
00326 /// predefined data rates and frequency deviations.  Frequency can be set with
00327 /// 61Hz precision to any frequency from 240.0MHz to 960.0MHz. Caution: most modules only support a more limited
00328 /// range of frequencies due to antenna tuning.
00329 ///
00330 /// Up to 2 RF69B modules can be connected to an Arduino (3 on a Mega),
00331 /// permitting the construction of translators and frequency changers, etc.
00332 ///
00333 /// The following modulation types are suppported with a range of modem configurations for 
00334 /// common data rates and frequency deviations:
00335 /// - GFSK Gaussian Frequency Shift Keying
00336 /// - FSK Frequency Shift Keying
00337 ///
00338 /// Support for other RF69 features such as on-chip temperature measurement, 
00339 /// transmitter power control etc is also provided.
00340 ///
00341 /// Tested on USB-Moteino with arduino-1.0.5
00342 /// on OpenSuSE 13.1
00343 ///
00344 /// \par Packet Format
00345 ///
00346 /// All messages sent and received by this RH_RF69 Driver conform to this packet format:
00347 ///
00348 /// - 4 octets PREAMBLE
00349 /// - 2 octets SYNC 0x2d, 0xd4 (configurable, so you can use this as a network filter)
00350 /// - 1 octet RH_RF69 payload length
00351 /// - 4 octets HEADER: (TO, FROM, ID, FLAGS)
00352 /// - 0 to 60 octets DATA 
00353 /// - 2 octets CRC computed with CRC16(IBM), computed on HEADER and DATA
00354 ///
00355 /// For technical reasons, the message format is not protocol compatible with the
00356 /// 'HopeRF Radio Transceiver Message Library for Arduino'
00357 /// http://www.airspayce.com/mikem/arduino/HopeRF from the same author. Nor is
00358 /// it compatible with messages sent by 'Virtual Wire'
00359 /// http://www.airspayce.com/mikem/arduino/VirtualWire.pdf also from the same
00360 /// author.  Nor is it compatible with messages sent by 'RF22'
00361 /// http://www.airspayce.com/mikem/arduino/RF22 also from the same author.
00362 ///
00363 /// \par Connecting RFM-69 to Arduino
00364 ///
00365 /// We tested with Moteino, which is an Arduino Uno compatible with the RFM69W
00366 /// module on-board. Therefore it needs no connections other than the USB
00367 /// programming connection and an antenna to make it work.
00368 ///
00369 /// If you have a bare RFM69W that you want to connect to an Arduino, you
00370 /// might use these connections (untested): CAUTION: you must use a 3.3V type
00371 /// Arduino, otherwise you will also need voltage level shifters between the
00372 /// Arduino and the RFM69.  CAUTION, you must also ensure you connect an
00373 /// antenna
00374 /// 
00375 /// \code
00376 ///                 Arduino      RFM69W
00377 ///                 GND----------GND   (ground in)
00378 ///                 3V3----------3.3V  (3.3V in)
00379 /// interrupt 0 pin D2-----------DIO0  (interrupt request out)
00380 ///          SS pin D10----------NSS   (chip select in)
00381 ///         SCK pin D13----------SCK   (SPI clock in)
00382 ///        MOSI pin D11----------MOSI  (SPI Data in)
00383 ///        MISO pin D12----------MISO  (SPI Data out)
00384 /// \endcode
00385 ///
00386 /// With these connections, you can then use the default constructor RH_RF69().
00387 /// You can override the default settings for the SS pin and the interrupt in
00388 /// the RH_RF69 constructor if you wish to connect the slave select SS to other
00389 /// than the normal one for your Arduino (D10 for Diecimila, Uno etc and D53
00390 /// for Mega) or the interrupt request to other than pin D2 (Caution,
00391 /// different processors have different constraints as to the pins available
00392 /// for interrupts).
00393 ///
00394 /// If you have a Teensy 3.1 and a compatible RFM69 breakout board, you will need to 
00395 /// construct the RH_RF69 instance like this:
00396 /// \code
00397 /// RH_RF69 driver(15, 16);
00398 /// \endcode
00399 ///
00400 /// If you have a MoteinoMEGA https://lowpowerlab.com/shop/moteinomega
00401 /// with RFM69 on board, you dont need to make any wiring connections 
00402 /// (the RFM69 module is soldered onto the MotienoMEGA), but you must initialise the RH_RF69
00403 /// constructor like this:
00404 /// \code
00405 /// RH_RF69 driver(4, 2);
00406 /// \endcode
00407 /// Make sure you have the MoteinoMEGA core installed in your Arduino hardware folder as described in the
00408 /// documentation for the MoteinoMEGA.
00409 ///
00410 /// It is possible to have 2 or more radios connected to one Arduino, provided
00411 /// each radio has its own SS and interrupt line (SCK, SDI and SDO are common
00412 /// to all radios)
00413 ///
00414 /// Caution: on some Arduinos such as the Mega 2560, if you set the slave
00415 /// select pin to be other than the usual SS pin (D53 on Mega 2560), you may
00416 /// need to set the usual SS pin to be an output to force the Arduino into SPI
00417 /// master mode.
00418 ///
00419 /// Caution: Power supply requirements of the RF69 module may be relevant in some circumstances: 
00420 /// RF69 modules are capable of pulling 45mA+ at full power, where Arduino's 3.3V line can
00421 /// give 50mA. You may need to make provision for alternate power supply for
00422 /// the RF69, especially if you wish to use full transmit power, and/or you have
00423 /// other shields demanding power. Inadequate power for the RF69 is likely to cause symptoms such as:
00424 /// -reset's/bootups terminate with "init failed" messages
00425 /// -random termination of communication after 5-30 packets sent/received
00426 /// -"fake ok" state, where initialization passes fluently, but communication doesn't happen
00427 /// -shields hang Arduino boards, especially during the flashing
00428 /// \par Interrupts
00429 ///
00430 /// The RH_RF69 driver uses interrupts to react to events in the RF69 module,
00431 /// such as the reception of a new packet, or the completion of transmission
00432 /// of a packet.  The RH_RF69 driver interrupt service routine reads status from
00433 /// and writes data to the the RF69 module via the SPI interface. It is very
00434 /// important therefore, that if you are using the RH_RF69 driver with another
00435 /// SPI based deviced, that you disable interrupts while you transfer data to
00436 /// and from that other device.  Use cli() to disable interrupts and sei() to
00437 /// reenable them.
00438 ///
00439 /// \par Memory
00440 ///
00441 /// The RH_RF69 driver requires non-trivial amounts of memory. The sample
00442 /// programs above all compile to about 8kbytes each, which will fit in the
00443 /// flash proram memory of most Arduinos. However, the RAM requirements are
00444 /// more critical. Therefore, you should be vary sparing with RAM use in
00445 /// programs that use the RH_RF69 driver.
00446 ///
00447 /// It is often hard to accurately identify when you are hitting RAM limits on Arduino. 
00448 /// The symptoms can include:
00449 /// - Mysterious crashes and restarts
00450 /// - Changes in behaviour when seemingly unrelated changes are made (such as adding print() statements)
00451 /// - Hanging
00452 /// - Output from Serial.print() not appearing
00453 /// 
00454 /// \par Automatic Frequency Control (AFC)
00455 ///
00456 /// The RF69 module is configured by the RH_RF69 driver to always use AFC.
00457 ///
00458 /// \par Transmitter Power
00459 ///
00460 /// You can control the transmitter power on the RF69 transceiver
00461 /// with the RH_RF69::setTxPower() function. The argument can be any of
00462 /// -18 to +13 (for RF69W) or -14 to 20 (for RF69HW) 
00463 /// The default is 13. Eg:
00464 /// \code
00465 /// driver.setTxPower(-5);
00466 /// \endcode
00467 ///
00468 /// We have made some actual power measurements against
00469 /// programmed power for Moteino (with RF69W)
00470 /// - Moteino (with RF69W), USB power
00471 /// - 10cm RG58C/U soldered direct to RFM69 module ANT and GND
00472 /// - bnc connecteor
00473 /// - 12dB attenuator
00474 /// - BNC-SMA adapter
00475 /// - MiniKits AD8307 HF/VHF Power Head (calibrated against Rohde&Schwartz 806.2020 test set)
00476 /// - Tektronix TDS220 scope to measure the Vout from power head
00477 /// \code
00478 /// Program power           Measured Power
00479 ///    dBm                         dBm
00480 ///    -18                         -17
00481 ///    -16                         -16
00482 ///    -14                         -14
00483 ///    -12                         -12
00484 ///    -10                         -9
00485 ///    -8                          -7
00486 ///    -6                          -4
00487 ///    -4                          -3
00488 ///    -2                          -2
00489 ///    0                           0.2
00490 ///    2                           3
00491 ///    4                           5
00492 ///    6                           7
00493 ///    8                           10
00494 ///    10                          13
00495 ///    12                          14
00496 ///    13                          15
00497 ///    14                         -51
00498 ///    20                         -51
00499 /// \endcode
00500 /// We have also made some actual power measurements against
00501 /// programmed power for Anarduino MiniWireless with RFM69-HW
00502 /// Anarduino MiniWireless (with RFM69-HW), USB power
00503 /// - 10cm RG58C/U soldered direct to RFM69 module ANT and GND
00504 /// - bnc connecteor
00505 /// - 2x12dB attenuators
00506 /// - BNC-SMA adapter
00507 /// - MiniKits AD8307 HF/VHF Power Head (calibrated against Rohde&Schwartz 806.2020 test set)
00508 /// - Tektronix TDS220 scope to measure the Vout from power head
00509 /// \code
00510 /// Program power           Measured Power
00511 ///    dBm                         dBm
00512 ///    -18                         no measurable output
00513 ///    0                           no measurable output
00514 ///    13                          no measurable output
00515 ///    14                          11
00516 ///    15                          12
00517 ///    16                          12.4
00518 ///    17                          14
00519 ///    18                          15
00520 ///    19                          15.8
00521 ///    20                          17
00522 /// \endcode
00523 /// (Caution: we dont claim laboratory accuracy for these measurements)
00524 /// You would not expect to get anywhere near these powers to air with a simple 1/4 wavelength wire antenna.
00525 /// Caution: although the RFM69 appears to have a PC antenna on board, you will get much better power and range even 
00526 /// with just a 1/4 wave wire antenna.
00527 ///
00528 /// \par Performance
00529 ///
00530 /// Some simple speed performance tests have been conducted.
00531 /// In general packet transmission rate will be limited by the modulation scheme.
00532 /// Also, if your code does any slow operations like Serial printing it will also limit performance. 
00533 /// We disabled any printing in the tests below.
00534 /// We tested with RH_RF69::GFSK_Rb250Fd250, which is probably the fastest scheme available.
00535 /// We tested with a 13 octet message length, over a very short distance of 10cm.
00536 ///
00537 /// Transmission (no reply) tests with modulation RH_RF69::GFSK_Rb250Fd250 and a 
00538 /// 13 octet message show about 152 messages per second transmitted and received.
00539 ///
00540 /// Transmit-and-wait-for-a-reply tests with modulation RH_RF69::GFSK_Rb250Fd250 and a 
00541 /// 13 octet message (send and receive) show about 68 round trips per second.
00542 ///
00543 class RH_RF69 : public RHSPIDriver
00544 {
00545 public:
00546 
00547     /// \brief Defines register values for a set of modem configuration registers
00548     ///
00549     /// Defines register values for a set of modem configuration registers
00550     /// that can be passed to setModemRegisters() if none of the choices in
00551     /// ModemConfigChoice suit your need setModemRegisters() writes the
00552     /// register values from this structure to the appropriate RF69 registers
00553     /// to set the desired modulation type, data rate and deviation/bandwidth.
00554     typedef struct
00555     {
00556     uint8_t    reg_02;   ///< Value for register RH_RF69_REG_02_DATAMODUL
00557     uint8_t    reg_03;   ///< Value for register RH_RF69_REG_03_BITRATEMSB
00558     uint8_t    reg_04;   ///< Value for register RH_RF69_REG_04_BITRATELSB
00559     uint8_t    reg_05;   ///< Value for register RH_RF69_REG_05_FDEVMSB
00560     uint8_t    reg_06;   ///< Value for register RH_RF69_REG_06_FDEVLSB
00561     uint8_t    reg_19;   ///< Value for register RH_RF69_REG_19_RXBW
00562     uint8_t    reg_1a;   ///< Value for register RH_RF69_REG_1A_AFCBW
00563     uint8_t    reg_37;   ///< Value for register RH_RF69_REG_37_PACKETCONFIG1
00564     } ModemConfig;
00565   
00566     /// Choices for setModemConfig() for a selected subset of common
00567     /// modulation types, and data rates. If you need another configuration,
00568     /// use the register calculator.  and call setModemRegisters() with your
00569     /// desired settings.  
00570     /// These are indexes into MODEM_CONFIG_TABLE. We strongly recommend you use these symbolic
00571     /// definitions and not their integer equivalents: its possible that new values will be
00572     /// introduced in later versions (though we will try to avoid it).
00573     /// CAUTION: some of these configurations do not work corectly and are marked as such.
00574     typedef enum
00575     {
00576     FSK_Rb2Fd5 = 0,    ///< FSK, Whitening, Rb = 2kbs,    Fd = 5kHz
00577     FSK_Rb2_4Fd4_8,    ///< FSK, Whitening, Rb = 2.4kbs,  Fd = 4.8kHz 
00578     FSK_Rb4_8Fd9_6,    ///< FSK, Whitening, Rb = 4.8kbs,  Fd = 9.6kHz 
00579     FSK_Rb9_6Fd19_2,   ///< FSK, Whitening, Rb = 9.6kbs,  Fd = 19.2kHz
00580     FSK_Rb19_2Fd38_4,  ///< FSK, Whitening, Rb = 19.2kbs, Fd = 38.4kHz
00581     FSK_Rb38_4Fd76_8,  ///< FSK, Whitening, Rb = 38.4kbs, Fd = 76.8kHz
00582     FSK_Rb57_6Fd120,   ///< FSK, Whitening, Rb = 57.6kbs, Fd = 120kHz
00583     FSK_Rb125Fd125,    ///< FSK, Whitening, Rb = 125kbs,  Fd = 125kHz
00584     FSK_Rb250Fd250,    ///< FSK, Whitening, Rb = 250kbs,  Fd = 250kHz
00585     FSK_Rb55555Fd50,   ///< FSK, Whitening, Rb = 55555kbs,Fd = 50kHz for RFM69 lib compatibility
00586 
00587     GFSK_Rb2Fd5,        ///< GFSK, Whitening, Rb = 2kbs,    Fd = 5kHz
00588     GFSK_Rb2_4Fd4_8,    ///< GFSK, Whitening, Rb = 2.4kbs,  Fd = 4.8kHz
00589     GFSK_Rb4_8Fd9_6,    ///< GFSK, Whitening, Rb = 4.8kbs,  Fd = 9.6kHz
00590     GFSK_Rb9_6Fd19_2,   ///< GFSK, Whitening, Rb = 9.6kbs,  Fd = 19.2kHz
00591     GFSK_Rb19_2Fd38_4,  ///< GFSK, Whitening, Rb = 19.2kbs, Fd = 38.4kHz
00592     GFSK_Rb38_4Fd76_8,  ///< GFSK, Whitening, Rb = 38.4kbs, Fd = 76.8kHz
00593     GFSK_Rb57_6Fd120,   ///< GFSK, Whitening, Rb = 57.6kbs, Fd = 120kHz
00594     GFSK_Rb125Fd125,    ///< GFSK, Whitening, Rb = 125kbs,  Fd = 125kHz
00595     GFSK_Rb250Fd250,    ///< GFSK, Whitening, Rb = 250kbs,  Fd = 250kHz
00596     GFSK_Rb55555Fd50,   ///< GFSK, Whitening, Rb = 55555kbs,Fd = 50kHz
00597 
00598     OOK_Rb1Bw1,         ///< OOK, Whitening, Rb = 1kbs,    Rx Bandwidth = 1kHz. 
00599     OOK_Rb1_2Bw75,      ///< OOK, Whitening, Rb = 1.2kbs,  Rx Bandwidth = 75kHz. 
00600     OOK_Rb2_4Bw4_8,     ///< OOK, Whitening, Rb = 2.4kbs,  Rx Bandwidth = 4.8kHz. 
00601     OOK_Rb4_8Bw9_6,     ///< OOK, Whitening, Rb = 4.8kbs,  Rx Bandwidth = 9.6kHz. 
00602     OOK_Rb9_6Bw19_2,    ///< OOK, Whitening, Rb = 9.6kbs,  Rx Bandwidth = 19.2kHz. 
00603     OOK_Rb19_2Bw38_4,   ///< OOK, Whitening, Rb = 19.2kbs, Rx Bandwidth = 38.4kHz. 
00604     OOK_Rb32Bw64,       ///< OOK, Whitening, Rb = 32kbs,   Rx Bandwidth = 64kHz. 
00605 
00606 //  Test,
00607     } ModemConfigChoice;
00608 
00609     /// Constructor. You can have multiple instances, but each instance must have its own
00610     /// interrupt and slave select pin. After constructing, you must call init() to initialise the interface
00611     /// and the radio module. A maximum of 3 instances can co-exist on one processor, provided there are sufficient
00612     /// distinct interrupt lines, one for each instance.
00613     /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF69 before
00614     /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega, D10 for Maple)
00615     /// \param[in] interruptPin The interrupt Pin number that is connected to the RF69 DIO0 interrupt line. 
00616     /// Defaults to pin 2.
00617     /// Caution: You must specify an interrupt capable pin.
00618     /// On many Arduino boards, there are limitations as to which pins may be used as interrupts.
00619     /// On Leonardo pins 0, 1, 2 or 3. On Mega2560 pins 2, 3, 18, 19, 20, 21. On Due and Teensy, any digital pin.
00620     /// On other Arduinos pins 2 or 3. 
00621     /// See http://arduino.cc/en/Reference/attachInterrupt for more details.
00622     /// On Chipkit Uno32, pins 38, 2, 7, 8, 35.
00623     /// On other boards, any digital pin may be used.
00624     /// \param[in] spi Pointer to the SPI interface object to use. 
00625     ///                Defaults to the standard Arduino hardware SPI interface
00626     RH_RF69(PINS slaveSelectPin, PINS interruptPin, RHGenericSPI& spi = hardware_spi);
00627   
00628     /// Initialises this instance and the radio module connected to it.
00629     /// The following steps are taken:
00630     /// - Initialise the slave select pin and the SPI interface library
00631     /// - Checks the connected RF69 module can be communicated
00632     /// - Attaches an interrupt handler
00633     /// - Configures the RF69 module
00634     /// - Sets the frequency to 434.0 MHz
00635     /// - Sets the modem data rate to FSK_Rb2Fd5
00636     /// \return  true if everything was successful
00637     bool        init();
00638 
00639     /// Reads the on-chip temperature sensor.
00640     /// The RF69 must be in Idle mode (= RF69 Standby) to measure temperature.
00641     /// The measurement is uncalibrated and without calibration, you can expect it to be far from
00642     /// correct.
00643     /// \return The measured temperature, in degrees C from -40 to 85 (uncalibrated)
00644     int8_t        temperatureRead();   
00645 
00646     /// Sets the transmitter and receiver 
00647     /// centre frequency
00648     /// \param[in] centre Frequency in MHz. 240.0 to 960.0. Caution, RF69 comes in several
00649     /// different frequency ranges, and setting a frequency outside that range of your radio will probably not work
00650     /// \param[in] afcPullInRange Not used
00651     /// \return true if the selected frquency centre is within range
00652     bool        setFrequency(float centre, float afcPullInRange = 0.05);
00653 
00654     /// Reads and returns the current RSSI value. 
00655     /// Causes the current signal strength to be measured and returned
00656     /// If you want to find the RSSI
00657     /// of the last received message, use lastRssi() instead.
00658     /// \return The current RSSI value on units of 0.5dB.
00659     int8_t        rssiRead();
00660 
00661     /// Sets the parameters for the RF69 OPMODE.
00662     /// This is a low level device access function, and should not normally ned to be used by user code. 
00663     /// Instead can use stModeRx(), setModeTx(), setModeIdle()
00664     /// \param[in] mode RF69 OPMODE to set, one of RH_RF69_OPMODE_MODE_*.
00665     void           setOpMode(uint8_t mode);
00666 
00667     /// If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running, 
00668     /// disables them.
00669     void           setModeIdle();
00670 
00671     /// If current mode is Tx or Idle, changes it to Rx. 
00672     /// Starts the receiver in the RF69.
00673     void           setModeRx();
00674 
00675     /// If current mode is Rx or Idle, changes it to Rx. F
00676     /// Starts the transmitter in the RF69.
00677     void           setModeTx();
00678 
00679     /// Sets the transmitter power output level.
00680     /// Be a good neighbour and set the lowest power level you need.
00681     /// Caution: legal power limits may apply in certain countries.
00682     /// After init(), the power will be set to 13dBm.
00683     /// \param[in] power Transmitter power level in dBm. For RF69W, valid values are from -18 to +13 
00684     /// (higher power settings disable the transmitter).
00685     /// For RF69HW, valid values are from +14 to +20. Caution: at +20dBm, duty cycle is limited to 1% and a 
00686     /// maximum VSWR of 3:1 at the antenna port.
00687     void           setTxPower(int8_t power);
00688 
00689     /// Sets all the registers required to configure the data modem in the RF69, including the data rate, 
00690     /// bandwidths etc. You can use this to configure the modem with custom configurations if none of the 
00691     /// canned configurations in ModemConfigChoice suit you.
00692     /// \param[in] config A ModemConfig structure containing values for the modem configuration registers.
00693     void           setModemRegisters(const ModemConfig* config);
00694 
00695     /// Select one of the predefined modem configurations. If you need a modem configuration not provided 
00696     /// here, use setModemRegisters() with your own ModemConfig. The default after init() is RH_RF69::GFSK_Rb250Fd250.
00697     /// \param[in] index The configuration choice.
00698     /// \return true if index is a valid choice.
00699     bool        setModemConfig(ModemConfigChoice index);
00700 
00701     /// Starts the receiver and checks whether a received message is available.
00702     /// This can be called multiple times in a timeout loop
00703     /// \return true if a complete, valid message has been received and is able to be retrieved by
00704     /// recv()
00705     bool        available();
00706 
00707     /// Turns the receiver on if it not already on.
00708     /// If there is a valid message available, copy it to buf and return true
00709     /// else return false.
00710     /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
00711     /// You should be sure to call this function frequently enough to not miss any messages
00712     /// It is recommended that you call it in your main loop.
00713     /// \param[in] buf Location to copy the received message
00714     /// \param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied.
00715     /// \return true if a valid message was copied to buf
00716     bool        recv(uint8_t* buf, uint8_t* len);
00717 
00718     /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
00719     /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
00720     /// of 0 is NOT permitted. 
00721     /// \param[in] data Array of data to be sent
00722     /// \param[in] len Number of bytes of data to send (> 0)
00723     /// \return true if the message length was valid and it was correctly queued for transmit
00724     bool        send(const uint8_t* data, uint8_t len);
00725 
00726     /// Sets the length of the preamble
00727     /// in bytes. 
00728     /// Caution: this should be set to the same 
00729     /// value on all nodes in your network. Default is 4.
00730     /// Sets the message preamble length in REG_0?_PREAMBLE?SB
00731     /// \param[in] bytes Preamble length in bytes.  
00732     void           setPreambleLength(uint16_t bytes);
00733 
00734     /// Sets the sync words for transmit and receive 
00735     /// Caution: SyncWords should be set to the same 
00736     /// value on all nodes in your network. Nodes with different SyncWords set will never receive
00737     /// each others messages, so different SyncWords can be used to isolate different
00738     /// networks from each other. Default is { 0x2d, 0xd4 }.
00739     /// \param[in] syncWords Array of sync words, 1 to 4 octets long. NULL if no sync words to be used.
00740     /// \param[in] len Number of sync words to set, 1 to 4. 0 if no sync words to be used.
00741     void           setSyncWords(const uint8_t* syncWords = NULL, uint8_t len = 0);
00742 
00743     /// Enables AES encryption and sets the AES encryption key, used
00744     /// to encrypt and decrypt all messages. The default is disabled.
00745     /// \param[in] key The key to use. Must be 16 bytes long. The same key must be installed
00746     /// in other instances of RF69, otherwise communications will not work correctly. If key is NULL,
00747     /// encryption is disabled.
00748     void           setEncryptionKey(uint8_t* key = NULL);
00749 
00750     /// Returns the time in millis since the most recent preamble was received, and when the most recent
00751     /// RSSI measurement was made.
00752     uint32_t getLastPreambleTime();
00753 
00754     /// The maximum message length supported by this driver
00755     /// \return The maximum message length supported by this driver
00756     uint8_t maxMessageLength();
00757 
00758     /// Prints the value of a single register
00759     /// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
00760     /// For debugging/testing only
00761     /// \return true if successful
00762     bool printRegister(uint8_t reg);
00763 
00764     /// Prints the value of all the RF69 registers
00765     /// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
00766     /// For debugging/testing only
00767     /// \return true if successful
00768     bool printRegisters();
00769 
00770     /// Sets the radio operating mode for the case when the driver is idle (ie not
00771     /// transmitting or receiving), allowing you to control the idle mode power requirements
00772     /// at the expense of slower transitions to transmit and receive modes.
00773     /// By default, the idle mode is RH_RF69_OPMODE_MODE_STDBY,
00774     /// but eg setIdleMode(RH_RF69_OPMODE_MODE_SLEEP) will provide a much lower
00775     /// idle current but slower transitions. Call this function after init().
00776     /// \param[in] idleMode The chip operating mode to use when the driver is idle. One of RH_RF69_OPMODE_*
00777     void setIdleMode(uint8_t idleMode);
00778 
00779     /// Sets the radio into low-power sleep mode.
00780     /// If successful, the transport will stay in sleep mode until woken by 
00781     /// changing mode it idle, transmit or receive (eg by calling send(), recv(), available() etc)
00782     /// Caution: there is a time penalty as the radio takes a finite time to wake from sleep mode.
00783     /// \return true if sleep mode was successfully entered.
00784     virtual bool    sleep();
00785 
00786 protected:
00787     /// This is a low level function to handle the interrupts for one instance of RF69.
00788     /// Called automatically by isr*()
00789     /// Should not need to be called by user code.
00790     void           handleInterrupt();
00791 
00792     /// Low level function to read the FIFO and put the received data into the receive buffer
00793     /// Should not need to be called by user code.
00794     void           readFifo();
00795 
00796 protected:
00797     /// Low level interrupt service routine for RF69 connected to interrupt 0
00798     static void         isr0();
00799 
00800     /// Low level interrupt service routine for RF69 connected to interrupt 1
00801     static void         isr1();
00802 
00803     /// Low level interrupt service routine for RF69 connected to interrupt 1
00804     static void         isr2();
00805 
00806     /// Array of instances connected to interrupts 0 and 1
00807     static RH_RF69*     _deviceForInterrupt[];
00808 
00809     /// Index of next interrupt number to use in _deviceForInterrupt
00810     static uint8_t      _interruptCount;
00811 
00812 #if (RH_PLATFORM == RH_PLATFORM_MBED)
00813     /// The configured interrupt pin connected to this instance
00814     InterruptIn             _interruptPin;
00815 #else
00816     /// The configured interrupt pin connected to this instance
00817     uint8_t             _interruptPin;
00818 #endif
00819 
00820     /// The index into _deviceForInterrupt[] for this device (if an interrupt is already allocated)
00821     /// else 0xff
00822     uint8_t             _myInterruptIndex;
00823 
00824     /// The radio OP mode to use when mode is RHModeIdle
00825     uint8_t             _idleMode; 
00826 
00827     /// The reported device type
00828     uint8_t             _deviceType;
00829 
00830     /// The selected output power in dBm
00831     int8_t              _power;
00832 
00833     /// The message length in _buf
00834     volatile uint8_t    _bufLen;
00835 
00836     /// Array of octets of teh last received message or the next to transmit message
00837     uint8_t             _buf[RH_RF69_MAX_MESSAGE_LEN];
00838 
00839     /// True when there is a valid message in the Rx buffer
00840     volatile bool    _rxBufValid;
00841 
00842     /// Time in millis since the last preamble was received (and the last time the RSSI was measured)
00843     uint32_t            _lastPreambleTime;
00844 };
00845 
00846 /// @example rf69_client.pde
00847 /// @example rf69_server.pde
00848 /// @example rf69_reliable_datagram_client.pde
00849 /// @example rf69_reliable_datagram_server.pde
00850 
00851 
00852 #endif