Port of RadioHead version 1.48 to mbed. It is a little messy and only works for SPI at this time.

Committer:
davidr99
Date:
Thu Oct 15 01:27:00 2015 +0000
Revision:
0:ab4e012489ef
Messy start, but a port for RadioHead.; Currently the SPI modulus are the only ones that work.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
davidr99 0:ab4e012489ef 1 // RH_RF95.h
davidr99 0:ab4e012489ef 2 //
davidr99 0:ab4e012489ef 3 // Definitions for HopeRF LoRa radios per:
davidr99 0:ab4e012489ef 4 // http://www.hoperf.com/upload/rf/RFM95_96_97_98W.pdf
davidr99 0:ab4e012489ef 5 // http://www.hoperf.cn/upload/rfchip/RF96_97_98.pdf
davidr99 0:ab4e012489ef 6 //
davidr99 0:ab4e012489ef 7 // Author: Mike McCauley (mikem@airspayce.com)
davidr99 0:ab4e012489ef 8 // Copyright (C) 2014 Mike McCauley
davidr99 0:ab4e012489ef 9 // $Id: RH_RF95.h,v 1.7 2015/05/17 00:11:26 mikem Exp $
davidr99 0:ab4e012489ef 10 //
davidr99 0:ab4e012489ef 11
davidr99 0:ab4e012489ef 12 #ifndef RH_RF95_h
davidr99 0:ab4e012489ef 13 #define RH_RF95_h
davidr99 0:ab4e012489ef 14
davidr99 0:ab4e012489ef 15 #include <RHSPIDriver.h>
davidr99 0:ab4e012489ef 16
davidr99 0:ab4e012489ef 17 // This is the maximum number of interrupts the driver can support
davidr99 0:ab4e012489ef 18 // Most Arduinos can handle 2, Megas can handle more
davidr99 0:ab4e012489ef 19 #define RH_RF95_NUM_INTERRUPTS 3
davidr99 0:ab4e012489ef 20
davidr99 0:ab4e012489ef 21 // Max number of octets the LORA Rx/Tx FIFO can hold
davidr99 0:ab4e012489ef 22 #define RH_RF95_FIFO_SIZE 255
davidr99 0:ab4e012489ef 23
davidr99 0:ab4e012489ef 24 // This is the maximum number of bytes that can be carried by the LORA.
davidr99 0:ab4e012489ef 25 // We use some for headers, keeping fewer for RadioHead messages
davidr99 0:ab4e012489ef 26 #define RH_RF95_MAX_PAYLOAD_LEN RH_RF95_FIFO_SIZE
davidr99 0:ab4e012489ef 27
davidr99 0:ab4e012489ef 28 // The length of the headers we add.
davidr99 0:ab4e012489ef 29 // The headers are inside the LORA's payload
davidr99 0:ab4e012489ef 30 #define RH_RF95_HEADER_LEN 4
davidr99 0:ab4e012489ef 31
davidr99 0:ab4e012489ef 32 // This is the maximum message length that can be supported by this driver.
davidr99 0:ab4e012489ef 33 // Can be pre-defined to a smaller size (to save SRAM) prior to including this header
davidr99 0:ab4e012489ef 34 // Here we allow for 1 byte message length, 4 bytes headers, user data and 2 bytes of FCS
davidr99 0:ab4e012489ef 35 #ifndef RH_RF95_MAX_MESSAGE_LEN
davidr99 0:ab4e012489ef 36 #define RH_RF95_MAX_MESSAGE_LEN (RH_RF95_MAX_PAYLOAD_LEN - RH_RF95_HEADER_LEN)
davidr99 0:ab4e012489ef 37 #endif
davidr99 0:ab4e012489ef 38
davidr99 0:ab4e012489ef 39 // The crystal oscillator frequency of the module
davidr99 0:ab4e012489ef 40 #define RH_RF95_FXOSC 32000000.0
davidr99 0:ab4e012489ef 41
davidr99 0:ab4e012489ef 42 // The Frequency Synthesizer step = RH_RF95_FXOSC / 2^^19
davidr99 0:ab4e012489ef 43 #define RH_RF95_FSTEP (RH_RF95_FXOSC / 524288)
davidr99 0:ab4e012489ef 44
davidr99 0:ab4e012489ef 45
davidr99 0:ab4e012489ef 46 // Register names (LoRa Mode, from table 85)
davidr99 0:ab4e012489ef 47 #define RH_RF95_REG_00_FIFO 0x00
davidr99 0:ab4e012489ef 48 #define RH_RF95_REG_01_OP_MODE 0x01
davidr99 0:ab4e012489ef 49 #define RH_RF95_REG_02_RESERVED 0x02
davidr99 0:ab4e012489ef 50 #define RH_RF95_REG_03_RESERVED 0x03
davidr99 0:ab4e012489ef 51 #define RH_RF95_REG_04_RESERVED 0x04
davidr99 0:ab4e012489ef 52 #define RH_RF95_REG_05_RESERVED 0x05
davidr99 0:ab4e012489ef 53 #define RH_RF95_REG_06_FRF_MSB 0x06
davidr99 0:ab4e012489ef 54 #define RH_RF95_REG_07_FRF_MID 0x07
davidr99 0:ab4e012489ef 55 #define RH_RF95_REG_08_FRF_LSB 0x08
davidr99 0:ab4e012489ef 56 #define RH_RF95_REG_09_PA_CONFIG 0x09
davidr99 0:ab4e012489ef 57 #define RH_RF95_REG_0A_PA_RAMP 0x0a
davidr99 0:ab4e012489ef 58 #define RH_RF95_REG_0B_OCP 0x0b
davidr99 0:ab4e012489ef 59 #define RH_RF95_REG_0C_LNA 0x0c
davidr99 0:ab4e012489ef 60 #define RH_RF95_REG_0D_FIFO_ADDR_PTR 0x0d
davidr99 0:ab4e012489ef 61 #define RH_RF95_REG_0E_FIFO_TX_BASE_ADDR 0x0e
davidr99 0:ab4e012489ef 62 #define RH_RF95_REG_0F_FIFO_RX_BASE_ADDR 0x0f
davidr99 0:ab4e012489ef 63 #define RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR 0x10
davidr99 0:ab4e012489ef 64 #define RH_RF95_REG_11_IRQ_FLAGS_MASK 0x11
davidr99 0:ab4e012489ef 65 #define RH_RF95_REG_12_IRQ_FLAGS 0x12
davidr99 0:ab4e012489ef 66 #define RH_RF95_REG_13_RX_NB_BYTES 0x13
davidr99 0:ab4e012489ef 67 #define RH_RF95_REG_14_RX_HEADER_CNT_VALUE_MSB 0x14
davidr99 0:ab4e012489ef 68 #define RH_RF95_REG_15_RX_HEADER_CNT_VALUE_LSB 0x15
davidr99 0:ab4e012489ef 69 #define RH_RF95_REG_16_RX_PACKET_CNT_VALUE_MSB 0x16
davidr99 0:ab4e012489ef 70 #define RH_RF95_REG_17_RX_PACKET_CNT_VALUE_LSB 0x17
davidr99 0:ab4e012489ef 71 #define RH_RF95_REG_18_MODEM_STAT 0x18
davidr99 0:ab4e012489ef 72 #define RH_RF95_REG_19_PKT_SNR_VALUE 0x19
davidr99 0:ab4e012489ef 73 #define RH_RF95_REG_1A_PKT_RSSI_VALUE 0x1a
davidr99 0:ab4e012489ef 74 #define RH_RF95_REG_1B_RSSI_VALUE 0x1b
davidr99 0:ab4e012489ef 75 #define RH_RF95_REG_1C_HOP_CHANNEL 0x1c
davidr99 0:ab4e012489ef 76 #define RH_RF95_REG_1D_MODEM_CONFIG1 0x1d
davidr99 0:ab4e012489ef 77 #define RH_RF95_REG_1E_MODEM_CONFIG2 0x1e
davidr99 0:ab4e012489ef 78 #define RH_RF95_REG_1F_SYMB_TIMEOUT_LSB 0x1f
davidr99 0:ab4e012489ef 79 #define RH_RF95_REG_20_PREAMBLE_MSB 0x20
davidr99 0:ab4e012489ef 80 #define RH_RF95_REG_21_PREAMBLE_LSB 0x21
davidr99 0:ab4e012489ef 81 #define RH_RF95_REG_22_PAYLOAD_LENGTH 0x22
davidr99 0:ab4e012489ef 82 #define RH_RF95_REG_23_MAX_PAYLOAD_LENGTH 0x23
davidr99 0:ab4e012489ef 83 #define RH_RF95_REG_24_HOP_PERIOD 0x24
davidr99 0:ab4e012489ef 84 #define RH_RF95_REG_25_FIFO_RX_BYTE_ADDR 0x25
davidr99 0:ab4e012489ef 85 #define RH_RF95_REG_26_MODEM_CONFIG3 0x26
davidr99 0:ab4e012489ef 86
davidr99 0:ab4e012489ef 87 #define RH_RF95_REG_40_DIO_MAPPING1 0x40
davidr99 0:ab4e012489ef 88 #define RH_RF95_REG_41_DIO_MAPPING2 0x41
davidr99 0:ab4e012489ef 89 #define RH_RF95_REG_42_VERSION 0x42
davidr99 0:ab4e012489ef 90
davidr99 0:ab4e012489ef 91 #define RH_RF95_REG_4B_TCXO 0x4b
davidr99 0:ab4e012489ef 92 #define RH_RF95_REG_4D_PA_DAC 0x4d
davidr99 0:ab4e012489ef 93 #define RH_RF95_REG_5B_FORMER_TEMP 0x5b
davidr99 0:ab4e012489ef 94 #define RH_RF95_REG_61_AGC_REF 0x61
davidr99 0:ab4e012489ef 95 #define RH_RF95_REG_62_AGC_THRESH1 0x62
davidr99 0:ab4e012489ef 96 #define RH_RF95_REG_63_AGC_THRESH2 0x63
davidr99 0:ab4e012489ef 97 #define RH_RF95_REG_64_AGC_THRESH3 0x64
davidr99 0:ab4e012489ef 98
davidr99 0:ab4e012489ef 99 // RH_RF95_REG_01_OP_MODE 0x01
davidr99 0:ab4e012489ef 100 #define RH_RF95_LONG_RANGE_MODE 0x80
davidr99 0:ab4e012489ef 101 #define RH_RF95_ACCESS_SHARED_REG 0x40
davidr99 0:ab4e012489ef 102 #define RH_RF95_MODE 0x07
davidr99 0:ab4e012489ef 103 #define RH_RF95_MODE_SLEEP 0x00
davidr99 0:ab4e012489ef 104 #define RH_RF95_MODE_STDBY 0x01
davidr99 0:ab4e012489ef 105 #define RH_RF95_MODE_FSTX 0x02
davidr99 0:ab4e012489ef 106 #define RH_RF95_MODE_TX 0x03
davidr99 0:ab4e012489ef 107 #define RH_RF95_MODE_FSRX 0x04
davidr99 0:ab4e012489ef 108 #define RH_RF95_MODE_RXCONTINUOUS 0x05
davidr99 0:ab4e012489ef 109 #define RH_RF95_MODE_RXSINGLE 0x06
davidr99 0:ab4e012489ef 110 #define RH_RF95_MODE_CAD 0x07
davidr99 0:ab4e012489ef 111
davidr99 0:ab4e012489ef 112 // RH_RF95_REG_09_PA_CONFIG 0x09
davidr99 0:ab4e012489ef 113 #define RH_RF95_PA_SELECT 0x80
davidr99 0:ab4e012489ef 114 #define RH_RF95_OUTPUT_POWER 0x0f
davidr99 0:ab4e012489ef 115
davidr99 0:ab4e012489ef 116 // RH_RF95_REG_0A_PA_RAMP 0x0a
davidr99 0:ab4e012489ef 117 #define RH_RF95_LOW_PN_TX_PLL_OFF 0x10
davidr99 0:ab4e012489ef 118 #define RH_RF95_PA_RAMP 0x0f
davidr99 0:ab4e012489ef 119 #define RH_RF95_PA_RAMP_3_4MS 0x00
davidr99 0:ab4e012489ef 120 #define RH_RF95_PA_RAMP_2MS 0x01
davidr99 0:ab4e012489ef 121 #define RH_RF95_PA_RAMP_1MS 0x02
davidr99 0:ab4e012489ef 122 #define RH_RF95_PA_RAMP_500US 0x03
davidr99 0:ab4e012489ef 123 #define RH_RF95_PA_RAMP_250US 0x0
davidr99 0:ab4e012489ef 124 #define RH_RF95_PA_RAMP_125US 0x05
davidr99 0:ab4e012489ef 125 #define RH_RF95_PA_RAMP_100US 0x06
davidr99 0:ab4e012489ef 126 #define RH_RF95_PA_RAMP_62US 0x07
davidr99 0:ab4e012489ef 127 #define RH_RF95_PA_RAMP_50US 0x08
davidr99 0:ab4e012489ef 128 #define RH_RF95_PA_RAMP_40US 0x09
davidr99 0:ab4e012489ef 129 #define RH_RF95_PA_RAMP_31US 0x0a
davidr99 0:ab4e012489ef 130 #define RH_RF95_PA_RAMP_25US 0x0b
davidr99 0:ab4e012489ef 131 #define RH_RF95_PA_RAMP_20US 0x0c
davidr99 0:ab4e012489ef 132 #define RH_RF95_PA_RAMP_15US 0x0d
davidr99 0:ab4e012489ef 133 #define RH_RF95_PA_RAMP_12US 0x0e
davidr99 0:ab4e012489ef 134 #define RH_RF95_PA_RAMP_10US 0x0f
davidr99 0:ab4e012489ef 135
davidr99 0:ab4e012489ef 136 // RH_RF95_REG_0B_OCP 0x0b
davidr99 0:ab4e012489ef 137 #define RH_RF95_OCP_ON 0x20
davidr99 0:ab4e012489ef 138 #define RH_RF95_OCP_TRIM 0x1f
davidr99 0:ab4e012489ef 139
davidr99 0:ab4e012489ef 140 // RH_RF95_REG_0C_LNA 0x0c
davidr99 0:ab4e012489ef 141 #define RH_RF95_LNA_GAIN 0xe0
davidr99 0:ab4e012489ef 142 #define RH_RF95_LNA_BOOST 0x03
davidr99 0:ab4e012489ef 143 #define RH_RF95_LNA_BOOST_DEFAULT 0x00
davidr99 0:ab4e012489ef 144 #define RH_RF95_LNA_BOOST_150PC 0x11
davidr99 0:ab4e012489ef 145
davidr99 0:ab4e012489ef 146 // RH_RF95_REG_11_IRQ_FLAGS_MASK 0x11
davidr99 0:ab4e012489ef 147 #define RH_RF95_RX_TIMEOUT_MASK 0x80
davidr99 0:ab4e012489ef 148 #define RH_RF95_RX_DONE_MASK 0x40
davidr99 0:ab4e012489ef 149 #define RH_RF95_PAYLOAD_CRC_ERROR_MASK 0x20
davidr99 0:ab4e012489ef 150 #define RH_RF95_VALID_HEADER_MASK 0x10
davidr99 0:ab4e012489ef 151 #define RH_RF95_TX_DONE_MASK 0x08
davidr99 0:ab4e012489ef 152 #define RH_RF95_CAD_DONE_MASK 0x04
davidr99 0:ab4e012489ef 153 #define RH_RF95_FHSS_CHANGE_CHANNEL_MASK 0x02
davidr99 0:ab4e012489ef 154 #define RH_RF95_CAD_DETECTED_MASK 0x01
davidr99 0:ab4e012489ef 155
davidr99 0:ab4e012489ef 156 // RH_RF95_REG_12_IRQ_FLAGS 0x12
davidr99 0:ab4e012489ef 157 #define RH_RF95_RX_TIMEOUT 0x80
davidr99 0:ab4e012489ef 158 #define RH_RF95_RX_DONE 0x40
davidr99 0:ab4e012489ef 159 #define RH_RF95_PAYLOAD_CRC_ERROR 0x20
davidr99 0:ab4e012489ef 160 #define RH_RF95_VALID_HEADER 0x10
davidr99 0:ab4e012489ef 161 #define RH_RF95_TX_DONE 0x08
davidr99 0:ab4e012489ef 162 #define RH_RF95_CAD_DONE 0x04
davidr99 0:ab4e012489ef 163 #define RH_RF95_FHSS_CHANGE_CHANNEL 0x02
davidr99 0:ab4e012489ef 164 #define RH_RF95_CAD_DETECTED 0x01
davidr99 0:ab4e012489ef 165
davidr99 0:ab4e012489ef 166 // RH_RF95_REG_18_MODEM_STAT 0x18
davidr99 0:ab4e012489ef 167 #define RH_RF95_RX_CODING_RATE 0xe0
davidr99 0:ab4e012489ef 168 #define RH_RF95_MODEM_STATUS_CLEAR 0x10
davidr99 0:ab4e012489ef 169 #define RH_RF95_MODEM_STATUS_HEADER_INFO_VALID 0x08
davidr99 0:ab4e012489ef 170 #define RH_RF95_MODEM_STATUS_RX_ONGOING 0x04
davidr99 0:ab4e012489ef 171 #define RH_RF95_MODEM_STATUS_SIGNAL_SYNCHRONIZED 0x02
davidr99 0:ab4e012489ef 172 #define RH_RF95_MODEM_STATUS_SIGNAL_DETECTED 0x01
davidr99 0:ab4e012489ef 173
davidr99 0:ab4e012489ef 174 // RH_RF95_REG_1C_HOP_CHANNEL 0x1c
davidr99 0:ab4e012489ef 175 #define RH_RF95_PLL_TIMEOUT 0x80
davidr99 0:ab4e012489ef 176 #define RH_RF95_RX_PAYLOAD_CRC_IS_ON 0x40
davidr99 0:ab4e012489ef 177 #define RH_RF95_FHSS_PRESENT_CHANNEL 0x3f
davidr99 0:ab4e012489ef 178
davidr99 0:ab4e012489ef 179 // RH_RF95_REG_1D_MODEM_CONFIG1 0x1d
davidr99 0:ab4e012489ef 180 #define RH_RF95_BW 0xc0
davidr99 0:ab4e012489ef 181 #define RH_RF95_BW_125KHZ 0x00
davidr99 0:ab4e012489ef 182 #define RH_RF95_BW_250KHZ 0x40
davidr99 0:ab4e012489ef 183 #define RH_RF95_BW_500KHZ 0x80
davidr99 0:ab4e012489ef 184 #define RH_RF95_BW_RESERVED 0xc0
davidr99 0:ab4e012489ef 185 #define RH_RF95_CODING_RATE 0x38
davidr99 0:ab4e012489ef 186 #define RH_RF95_CODING_RATE_4_5 0x00
davidr99 0:ab4e012489ef 187 #define RH_RF95_CODING_RATE_4_6 0x08
davidr99 0:ab4e012489ef 188 #define RH_RF95_CODING_RATE_4_7 0x10
davidr99 0:ab4e012489ef 189 #define RH_RF95_CODING_RATE_4_8 0x18
davidr99 0:ab4e012489ef 190 #define RH_RF95_IMPLICIT_HEADER_MODE_ON 0x04
davidr99 0:ab4e012489ef 191 #define RH_RF95_RX_PAYLOAD_CRC_ON 0x02
davidr99 0:ab4e012489ef 192 #define RH_RF95_LOW_DATA_RATE_OPTIMIZE 0x01
davidr99 0:ab4e012489ef 193
davidr99 0:ab4e012489ef 194 // RH_RF95_REG_1E_MODEM_CONFIG2 0x1e
davidr99 0:ab4e012489ef 195 #define RH_RF95_SPREADING_FACTOR 0xf0
davidr99 0:ab4e012489ef 196 #define RH_RF95_SPREADING_FACTOR_64CPS 0x60
davidr99 0:ab4e012489ef 197 #define RH_RF95_SPREADING_FACTOR_128CPS 0x70
davidr99 0:ab4e012489ef 198 #define RH_RF95_SPREADING_FACTOR_256CPS 0x80
davidr99 0:ab4e012489ef 199 #define RH_RF95_SPREADING_FACTOR_512CPS 0x90
davidr99 0:ab4e012489ef 200 #define RH_RF95_SPREADING_FACTOR_1024CPS 0xa0
davidr99 0:ab4e012489ef 201 #define RH_RF95_SPREADING_FACTOR_2048CPS 0xb0
davidr99 0:ab4e012489ef 202 #define RH_RF95_SPREADING_FACTOR_4096CPS 0xc0
davidr99 0:ab4e012489ef 203 #define RH_RF95_TX_CONTINUOUS_MOE 0x08
davidr99 0:ab4e012489ef 204 #define RH_RF95_AGC_AUTO_ON 0x04
davidr99 0:ab4e012489ef 205 #define RH_RF95_SYM_TIMEOUT_MSB 0x03
davidr99 0:ab4e012489ef 206
davidr99 0:ab4e012489ef 207 // RH_RF95_REG_4D_PA_DAC 0x4d
davidr99 0:ab4e012489ef 208 #define RH_RF95_PA_DAC_DISABLE 0x04
davidr99 0:ab4e012489ef 209 #define RH_RF95_PA_DAC_ENABLE 0x07
davidr99 0:ab4e012489ef 210
davidr99 0:ab4e012489ef 211 /////////////////////////////////////////////////////////////////////
davidr99 0:ab4e012489ef 212 /// \class RH_RF95 RH_RF95.h <RH_RF95.h>
davidr99 0:ab4e012489ef 213 /// \brief Driver to send and receive unaddressed, unreliable datagrams via a LoRa
davidr99 0:ab4e012489ef 214 /// capable radio transceiver.
davidr99 0:ab4e012489ef 215 ///
davidr99 0:ab4e012489ef 216 /// For Semtech SX1276/77/78 and HopeRF RFM95/96/97/98 and other similar LoRa capable radios.
davidr99 0:ab4e012489ef 217 /// Based on http://www.hoperf.com/upload/rf/RFM95_96_97_98W.pdf
davidr99 0:ab4e012489ef 218 /// and http://www.hoperf.cn/upload/rfchip/RF96_97_98.pdf
davidr99 0:ab4e012489ef 219 /// and http://www.semtech.com/images/datasheet/LoraDesignGuide_STD.pdf
davidr99 0:ab4e012489ef 220 /// and http://www.semtech.com/images/datasheet/sx1276.pdf
davidr99 0:ab4e012489ef 221 /// FSK/GFSK/OOK modes are not (yet) supported.
davidr99 0:ab4e012489ef 222 ///
davidr99 0:ab4e012489ef 223 /// Works with
davidr99 0:ab4e012489ef 224 /// - the excellent MiniWirelessLoRa from Anarduino http://www.anarduino.com/miniwireless
davidr99 0:ab4e012489ef 225 ///
davidr99 0:ab4e012489ef 226 /// \par Overview
davidr99 0:ab4e012489ef 227 ///
davidr99 0:ab4e012489ef 228 /// This class provides basic functions for sending and receiving unaddressed,
davidr99 0:ab4e012489ef 229 /// unreliable datagrams of arbitrary length to 251 octets per packet.
davidr99 0:ab4e012489ef 230 ///
davidr99 0:ab4e012489ef 231 /// Manager classes may use this class to implement reliable, addressed datagrams and streams,
davidr99 0:ab4e012489ef 232 /// mesh routers, repeaters, translators etc.
davidr99 0:ab4e012489ef 233 ///
davidr99 0:ab4e012489ef 234 /// Naturally, for any 2 radios to communicate that must be configured to use the same frequency and
davidr99 0:ab4e012489ef 235 /// modulation scheme.
davidr99 0:ab4e012489ef 236 ///
davidr99 0:ab4e012489ef 237 /// This Driver provides an object-oriented interface for sending and receiving data messages with Hope-RF
davidr99 0:ab4e012489ef 238 /// RFM95/96/97/98(W) and compatible radio modules in LoRa mode.
davidr99 0:ab4e012489ef 239 ///
davidr99 0:ab4e012489ef 240 /// The Hope-RF (http://www.hoperf.com) RFM95/96/97/98(W) is a low-cost ISM transceiver
davidr99 0:ab4e012489ef 241 /// chip. It supports FSK, GFSK, OOK over a wide range of frequencies and
davidr99 0:ab4e012489ef 242 /// programmable data rates, and it also supports the proprietary LoRA (Long Range) mode, which
davidr99 0:ab4e012489ef 243 /// is the only mode supported in this RadioHead driver.
davidr99 0:ab4e012489ef 244 ///
davidr99 0:ab4e012489ef 245 /// This Driver provides functions for sending and receiving messages of up
davidr99 0:ab4e012489ef 246 /// to 251 octets on any frequency supported by the radio, in a range of
davidr99 0:ab4e012489ef 247 /// predefined Bandwidths, Spreading Factors and Coding Rates. Frequency can be set with
davidr99 0:ab4e012489ef 248 /// 61Hz precision to any frequency from 240.0MHz to 960.0MHz. Caution: most modules only support a more limited
davidr99 0:ab4e012489ef 249 /// range of frequencies due to antenna tuning.
davidr99 0:ab4e012489ef 250 ///
davidr99 0:ab4e012489ef 251 /// Up to 2 RFM95/96/97/98(W) modules can be connected to an Arduino (3 on a Mega),
davidr99 0:ab4e012489ef 252 /// permitting the construction of translators and frequency changers, etc.
davidr99 0:ab4e012489ef 253 ///
davidr99 0:ab4e012489ef 254 /// Support for other features such as transmitter power control etc is
davidr99 0:ab4e012489ef 255 /// also provided.
davidr99 0:ab4e012489ef 256 ///
davidr99 0:ab4e012489ef 257 /// Tested on MinWirelessLoRa with arduino-1.0.5
davidr99 0:ab4e012489ef 258 /// on OpenSuSE 13.1
davidr99 0:ab4e012489ef 259 ///
davidr99 0:ab4e012489ef 260 /// \par Packet Format
davidr99 0:ab4e012489ef 261 ///
davidr99 0:ab4e012489ef 262 /// All messages sent and received by this RH_RF95 Driver conform to this packet format:
davidr99 0:ab4e012489ef 263 ///
davidr99 0:ab4e012489ef 264 /// - LoRa mode:
davidr99 0:ab4e012489ef 265 /// - 8 symbol PREAMBLE
davidr99 0:ab4e012489ef 266 /// - Explicit header with header CRC (handled internally by the radio)
davidr99 0:ab4e012489ef 267 /// - 4 octets HEADER: (TO, FROM, ID, FLAGS)
davidr99 0:ab4e012489ef 268 /// - 0 to 251 octets DATA
davidr99 0:ab4e012489ef 269 /// - CRC (handled internally by the radio)
davidr99 0:ab4e012489ef 270 ///
davidr99 0:ab4e012489ef 271 /// \par Connecting RFM95/96/97/98 to Arduino
davidr99 0:ab4e012489ef 272 ///
davidr99 0:ab4e012489ef 273 /// We tested with Anarduino MiniWirelessLoRA, which is an Arduino Duemilanove compatible with a RFM96W
davidr99 0:ab4e012489ef 274 /// module on-board. Therefore it needs no connections other than the USB
davidr99 0:ab4e012489ef 275 /// programming connection and an antenna to make it work.
davidr99 0:ab4e012489ef 276 ///
davidr99 0:ab4e012489ef 277 /// If you have a bare RFM95/96/97/98 that you want to connect to an Arduino, you
davidr99 0:ab4e012489ef 278 /// might use these connections (untested): CAUTION: you must use a 3.3V type
davidr99 0:ab4e012489ef 279 /// Arduino, otherwise you will also need voltage level shifters between the
davidr99 0:ab4e012489ef 280 /// Arduino and the RFM95. CAUTION, you must also ensure you connect an
davidr99 0:ab4e012489ef 281 /// antenna.
davidr99 0:ab4e012489ef 282 ///
davidr99 0:ab4e012489ef 283 /// \code
davidr99 0:ab4e012489ef 284 /// Arduino RFM95/96/97/98
davidr99 0:ab4e012489ef 285 /// GND----------GND (ground in)
davidr99 0:ab4e012489ef 286 /// 3V3----------3.3V (3.3V in)
davidr99 0:ab4e012489ef 287 /// interrupt 0 pin D2-----------DIO0 (interrupt request out)
davidr99 0:ab4e012489ef 288 /// SS pin D10----------NSS (chip select in)
davidr99 0:ab4e012489ef 289 /// SCK pin D13----------SCK (SPI clock in)
davidr99 0:ab4e012489ef 290 /// MOSI pin D11----------MOSI (SPI Data in)
davidr99 0:ab4e012489ef 291 /// MISO pin D12----------MISO (SPI Data out)
davidr99 0:ab4e012489ef 292 /// \endcode
davidr99 0:ab4e012489ef 293 ///
davidr99 0:ab4e012489ef 294 /// With these connections, you can then use the default constructor RH_RF95().
davidr99 0:ab4e012489ef 295 /// You can override the default settings for the SS pin and the interrupt in
davidr99 0:ab4e012489ef 296 /// the RH_RF95 constructor if you wish to connect the slave select SS to other
davidr99 0:ab4e012489ef 297 /// than the normal one for your Arduino (D10 for Diecimila, Uno etc and D53
davidr99 0:ab4e012489ef 298 /// for Mega) or the interrupt request to other than pin D2 (Caution,
davidr99 0:ab4e012489ef 299 /// different processors have different constraints as to the pins available
davidr99 0:ab4e012489ef 300 /// for interrupts).
davidr99 0:ab4e012489ef 301 ///
davidr99 0:ab4e012489ef 302 /// It is possible to have 2 or more radios connected to one Arduino, provided
davidr99 0:ab4e012489ef 303 /// each radio has its own SS and interrupt line (SCK, SDI and SDO are common
davidr99 0:ab4e012489ef 304 /// to all radios)
davidr99 0:ab4e012489ef 305 ///
davidr99 0:ab4e012489ef 306 /// Caution: on some Arduinos such as the Mega 2560, if you set the slave
davidr99 0:ab4e012489ef 307 /// select pin to be other than the usual SS pin (D53 on Mega 2560), you may
davidr99 0:ab4e012489ef 308 /// need to set the usual SS pin to be an output to force the Arduino into SPI
davidr99 0:ab4e012489ef 309 /// master mode.
davidr99 0:ab4e012489ef 310 ///
davidr99 0:ab4e012489ef 311 /// Caution: Power supply requirements of the RFM module may be relevant in some circumstances:
davidr99 0:ab4e012489ef 312 /// RFM95/96/97/98 modules are capable of pulling 120mA+ at full power, where Arduino's 3.3V line can
davidr99 0:ab4e012489ef 313 /// give 50mA. You may need to make provision for alternate power supply for
davidr99 0:ab4e012489ef 314 /// the RFM module, especially if you wish to use full transmit power, and/or you have
davidr99 0:ab4e012489ef 315 /// other shields demanding power. Inadequate power for the RFM is likely to cause symptoms such as:
davidr99 0:ab4e012489ef 316 /// - reset's/bootups terminate with "init failed" messages
davidr99 0:ab4e012489ef 317 /// - random termination of communication after 5-30 packets sent/received
davidr99 0:ab4e012489ef 318 /// - "fake ok" state, where initialization passes fluently, but communication doesn't happen
davidr99 0:ab4e012489ef 319 /// - shields hang Arduino boards, especially during the flashing
davidr99 0:ab4e012489ef 320 ///
davidr99 0:ab4e012489ef 321 /// \par Interrupts
davidr99 0:ab4e012489ef 322 ///
davidr99 0:ab4e012489ef 323 /// The RH_RF95 driver uses interrupts to react to events in the RFM module,
davidr99 0:ab4e012489ef 324 /// such as the reception of a new packet, or the completion of transmission
davidr99 0:ab4e012489ef 325 /// of a packet. The RH_RF95 driver interrupt service routine reads status from
davidr99 0:ab4e012489ef 326 /// and writes data to the the RFM module via the SPI interface. It is very
davidr99 0:ab4e012489ef 327 /// important therefore, that if you are using the RH_RF95 driver with another
davidr99 0:ab4e012489ef 328 /// SPI based deviced, that you disable interrupts while you transfer data to
davidr99 0:ab4e012489ef 329 /// and from that other device. Use cli() to disable interrupts and sei() to
davidr99 0:ab4e012489ef 330 /// reenable them.
davidr99 0:ab4e012489ef 331 ///
davidr99 0:ab4e012489ef 332 /// \par Memory
davidr99 0:ab4e012489ef 333 ///
davidr99 0:ab4e012489ef 334 /// The RH_RF95 driver requires non-trivial amounts of memory. The sample
davidr99 0:ab4e012489ef 335 /// programs all compile to about 8kbytes each, which will fit in the
davidr99 0:ab4e012489ef 336 /// flash proram memory of most Arduinos. However, the RAM requirements are
davidr99 0:ab4e012489ef 337 /// more critical. Therefore, you should be vary sparing with RAM use in
davidr99 0:ab4e012489ef 338 /// programs that use the RH_RF95 driver.
davidr99 0:ab4e012489ef 339 ///
davidr99 0:ab4e012489ef 340 /// It is often hard to accurately identify when you are hitting RAM limits on Arduino.
davidr99 0:ab4e012489ef 341 /// The symptoms can include:
davidr99 0:ab4e012489ef 342 /// - Mysterious crashes and restarts
davidr99 0:ab4e012489ef 343 /// - Changes in behaviour when seemingly unrelated changes are made (such as adding print() statements)
davidr99 0:ab4e012489ef 344 /// - Hanging
davidr99 0:ab4e012489ef 345 /// - Output from Serial.print() not appearing
davidr99 0:ab4e012489ef 346 ///
davidr99 0:ab4e012489ef 347 /// \par Range
davidr99 0:ab4e012489ef 348 ///
davidr99 0:ab4e012489ef 349 /// We have made some simple range tests under the following conditions:
davidr99 0:ab4e012489ef 350 /// - rf95_client base station connected to a VHF discone antenna at 8m height above ground
davidr99 0:ab4e012489ef 351 /// - rf95_server mobile connected to 17.3cm 1/4 wavelength antenna at 1m height, no ground plane.
davidr99 0:ab4e012489ef 352 /// - Both configured for 13dBm, 434MHz, Bw = 125 kHz, Cr = 4/8, Sf = 4096chips/symbol, CRC on. Slow+long range
davidr99 0:ab4e012489ef 353 /// - Minimum reported RSSI seen for successful comms was about -91
davidr99 0:ab4e012489ef 354 /// - Range over flat ground through heavy trees and vegetation approx 2km.
davidr99 0:ab4e012489ef 355 /// - At 20dBm (100mW) otherwise identical conditions approx 3km.
davidr99 0:ab4e012489ef 356 /// - At 20dBm, along salt water flat sandy beach, 3.2km.
davidr99 0:ab4e012489ef 357 ///
davidr99 0:ab4e012489ef 358 /// It should be noted that at this data rate, a 12 octet message takes 2 seconds to transmit.
davidr99 0:ab4e012489ef 359 ///
davidr99 0:ab4e012489ef 360 /// At 20dBm (100mW) with Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on.
davidr99 0:ab4e012489ef 361 /// (Default medium range) in the conditions described above.
davidr99 0:ab4e012489ef 362 /// - Range over flat ground through heavy trees and vegetation approx 2km.
davidr99 0:ab4e012489ef 363 ///
davidr99 0:ab4e012489ef 364 /// \par Transmitter Power
davidr99 0:ab4e012489ef 365 ///
davidr99 0:ab4e012489ef 366 /// You can control the transmitter power on the RF transceiver
davidr99 0:ab4e012489ef 367 /// with the RH_RF95::setTxPower() function. The argument can be any of
davidr99 0:ab4e012489ef 368 /// +5 to +23
davidr99 0:ab4e012489ef 369 /// The default is 13. Eg:
davidr99 0:ab4e012489ef 370 /// \code
davidr99 0:ab4e012489ef 371 /// driver.setTxPower(10);
davidr99 0:ab4e012489ef 372 /// \endcode
davidr99 0:ab4e012489ef 373 ///
davidr99 0:ab4e012489ef 374 /// We have made some actual power measurements against
davidr99 0:ab4e012489ef 375 /// programmed power for Anarduino MiniWirelessLoRa (which has RFM96W-433Mhz installed)
davidr99 0:ab4e012489ef 376 /// - MiniWirelessLoRa RFM96W-433Mhz, USB power
davidr99 0:ab4e012489ef 377 /// - 30cm RG316 soldered direct to RFM96W module ANT and GND
davidr99 0:ab4e012489ef 378 /// - SMA connector
davidr99 0:ab4e012489ef 379 /// - 12db attenuator
davidr99 0:ab4e012489ef 380 /// - SMA connector
davidr99 0:ab4e012489ef 381 /// - MiniKits AD8307 HF/VHF Power Head (calibrated against Rohde&Schwartz 806.2020 test set)
davidr99 0:ab4e012489ef 382 /// - Tektronix TDS220 scope to measure the Vout from power head
davidr99 0:ab4e012489ef 383 /// \code
davidr99 0:ab4e012489ef 384 /// Program power Measured Power
davidr99 0:ab4e012489ef 385 /// dBm dBm
davidr99 0:ab4e012489ef 386 /// 5 5
davidr99 0:ab4e012489ef 387 /// 7 7
davidr99 0:ab4e012489ef 388 /// 9 8
davidr99 0:ab4e012489ef 389 /// 11 11
davidr99 0:ab4e012489ef 390 /// 13 13
davidr99 0:ab4e012489ef 391 /// 15 15
davidr99 0:ab4e012489ef 392 /// 17 16
davidr99 0:ab4e012489ef 393 /// 19 18
davidr99 0:ab4e012489ef 394 /// 20 20
davidr99 0:ab4e012489ef 395 /// 21 21
davidr99 0:ab4e012489ef 396 /// 22 22
davidr99 0:ab4e012489ef 397 /// 23 23
davidr99 0:ab4e012489ef 398 /// \endcode
davidr99 0:ab4e012489ef 399 /// (Caution: we dont claim laboratory accuracy for these measurements)
davidr99 0:ab4e012489ef 400 /// You would not expect to get anywhere near these powers to air with a simple 1/4 wavelength wire antenna.
davidr99 0:ab4e012489ef 401 class RH_RF95 : public RHSPIDriver
davidr99 0:ab4e012489ef 402 {
davidr99 0:ab4e012489ef 403 public:
davidr99 0:ab4e012489ef 404 /// \brief Defines register values for a set of modem configuration registers
davidr99 0:ab4e012489ef 405 ///
davidr99 0:ab4e012489ef 406 /// Defines register values for a set of modem configuration registers
davidr99 0:ab4e012489ef 407 /// that can be passed to setModemRegisters() if none of the choices in
davidr99 0:ab4e012489ef 408 /// ModemConfigChoice suit your need setModemRegisters() writes the
davidr99 0:ab4e012489ef 409 /// register values from this structure to the appropriate registers
davidr99 0:ab4e012489ef 410 /// to set the desired spreading factor, coding rate and bandwidth
davidr99 0:ab4e012489ef 411 typedef struct {
davidr99 0:ab4e012489ef 412 uint8_t reg_1d; ///< Value for register RH_RF95_REG_1D_MODEM_CONFIG1
davidr99 0:ab4e012489ef 413 uint8_t reg_1e; ///< Value for register RH_RF95_REG_1E_MODEM_CONFIG2
davidr99 0:ab4e012489ef 414 uint8_t reg_26; ///< Value for register RH_RF95_REG_26_MODEM_CONFIG3
davidr99 0:ab4e012489ef 415 } ModemConfig;
davidr99 0:ab4e012489ef 416
davidr99 0:ab4e012489ef 417 /// Choices for setModemConfig() for a selected subset of common
davidr99 0:ab4e012489ef 418 /// data rates. If you need another configuration,
davidr99 0:ab4e012489ef 419 /// determine the necessary settings and call setModemRegisters() with your
davidr99 0:ab4e012489ef 420 /// desired settings. It might be helpful to use the LoRa calculator mentioned in
davidr99 0:ab4e012489ef 421 /// http://www.semtech.com/images/datasheet/LoraDesignGuide_STD.pdf
davidr99 0:ab4e012489ef 422 /// These are indexes into MODEM_CONFIG_TABLE. We strongly recommend you use these symbolic
davidr99 0:ab4e012489ef 423 /// definitions and not their integer equivalents: its possible that new values will be
davidr99 0:ab4e012489ef 424 /// introduced in later versions (though we will try to avoid it).
davidr99 0:ab4e012489ef 425 typedef enum {
davidr99 0:ab4e012489ef 426 Bw125Cr45Sf128 = 0, ///< Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Default medium range
davidr99 0:ab4e012489ef 427 Bw500Cr45Sf128, ///< Bw = 500 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Fast+short range
davidr99 0:ab4e012489ef 428 Bw31_25Cr48Sf512, ///< Bw = 31.25 kHz, Cr = 4/8, Sf = 512chips/symbol, CRC on. Slow+long range
davidr99 0:ab4e012489ef 429 Bw125Cr48Sf4096, ///< Bw = 125 kHz, Cr = 4/8, Sf = 4096chips/symbol, CRC on. Slow+long range
davidr99 0:ab4e012489ef 430 } ModemConfigChoice;
davidr99 0:ab4e012489ef 431
davidr99 0:ab4e012489ef 432 /// Constructor. You can have multiple instances, but each instance must have its own
davidr99 0:ab4e012489ef 433 /// interrupt and slave select pin. After constructing, you must call init() to initialise the interface
davidr99 0:ab4e012489ef 434 /// and the radio module. A maximum of 3 instances can co-exist on one processor, provided there are sufficient
davidr99 0:ab4e012489ef 435 /// distinct interrupt lines, one for each instance.
davidr99 0:ab4e012489ef 436 /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RH_RF22 before
davidr99 0:ab4e012489ef 437 /// accessing it. Defaults to the normal SS pin for your Arduino (D10 for Diecimila, Uno etc, D53 for Mega, D10 for Maple)
davidr99 0:ab4e012489ef 438 /// \param[in] interruptPin The interrupt Pin number that is connected to the RFM DIO0 interrupt line.
davidr99 0:ab4e012489ef 439 /// Defaults to pin 2, as required by Anarduino MinWirelessLoRa module.
davidr99 0:ab4e012489ef 440 /// Caution: You must specify an interrupt capable pin.
davidr99 0:ab4e012489ef 441 /// On many Arduino boards, there are limitations as to which pins may be used as interrupts.
davidr99 0:ab4e012489ef 442 /// On Leonardo pins 0, 1, 2 or 3. On Mega2560 pins 2, 3, 18, 19, 20, 21. On Due and Teensy, any digital pin.
davidr99 0:ab4e012489ef 443 /// On other Arduinos pins 2 or 3.
davidr99 0:ab4e012489ef 444 /// See http://arduino.cc/en/Reference/attachInterrupt for more details.
davidr99 0:ab4e012489ef 445 /// On Chipkit Uno32, pins 38, 2, 7, 8, 35.
davidr99 0:ab4e012489ef 446 /// On other boards, any digital pin may be used.
davidr99 0:ab4e012489ef 447 /// \param[in] spi Pointer to the SPI interface object to use.
davidr99 0:ab4e012489ef 448 /// Defaults to the standard Arduino hardware SPI interface
davidr99 0:ab4e012489ef 449 RH_RF95(PINS slaveSelectPin, PINS interruptPin, RHGenericSPI& spi = hardware_spi);
davidr99 0:ab4e012489ef 450
davidr99 0:ab4e012489ef 451 /// Initialise the Driver transport hardware and software.
davidr99 0:ab4e012489ef 452 /// Make sure the Driver is properly configured before calling init().
davidr99 0:ab4e012489ef 453 /// \return true if initialisation succeeded.
davidr99 0:ab4e012489ef 454 virtual bool init();
davidr99 0:ab4e012489ef 455
davidr99 0:ab4e012489ef 456 /// Prints the value of all chip registers
davidr99 0:ab4e012489ef 457 /// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
davidr99 0:ab4e012489ef 458 /// For debugging purposes only.
davidr99 0:ab4e012489ef 459 /// \return true on success
davidr99 0:ab4e012489ef 460 bool printRegisters();
davidr99 0:ab4e012489ef 461
davidr99 0:ab4e012489ef 462 /// Sets all the registered required to configure the data modem in the RF95/96/97/98, including the bandwidth,
davidr99 0:ab4e012489ef 463 /// spreading factor etc. You can use this to configure the modem with custom configurations if none of the
davidr99 0:ab4e012489ef 464 /// canned configurations in ModemConfigChoice suit you.
davidr99 0:ab4e012489ef 465 /// \param[in] config A ModemConfig structure containing values for the modem configuration registers.
davidr99 0:ab4e012489ef 466 void setModemRegisters(const ModemConfig* config);
davidr99 0:ab4e012489ef 467
davidr99 0:ab4e012489ef 468 /// Select one of the predefined modem configurations. If you need a modem configuration not provided
davidr99 0:ab4e012489ef 469 /// here, use setModemRegisters() with your own ModemConfig.
davidr99 0:ab4e012489ef 470 /// \param[in] index The configuration choice.
davidr99 0:ab4e012489ef 471 /// \return true if index is a valid choice.
davidr99 0:ab4e012489ef 472 bool setModemConfig(ModemConfigChoice index);
davidr99 0:ab4e012489ef 473
davidr99 0:ab4e012489ef 474 /// Tests whether a new message is available
davidr99 0:ab4e012489ef 475 /// from the Driver.
davidr99 0:ab4e012489ef 476 /// On most drivers, this will also put the Driver into RHModeRx mode until
davidr99 0:ab4e012489ef 477 /// a message is actually received by the transport, when it wil be returned to RHModeIdle.
davidr99 0:ab4e012489ef 478 /// This can be called multiple times in a timeout loop
davidr99 0:ab4e012489ef 479 /// \return true if a new, complete, error-free uncollected message is available to be retreived by recv()
davidr99 0:ab4e012489ef 480 virtual bool available();
davidr99 0:ab4e012489ef 481
davidr99 0:ab4e012489ef 482 /// Turns the receiver on if it not already on.
davidr99 0:ab4e012489ef 483 /// If there is a valid message available, copy it to buf and return true
davidr99 0:ab4e012489ef 484 /// else return false.
davidr99 0:ab4e012489ef 485 /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
davidr99 0:ab4e012489ef 486 /// You should be sure to call this function frequently enough to not miss any messages
davidr99 0:ab4e012489ef 487 /// It is recommended that you call it in your main loop.
davidr99 0:ab4e012489ef 488 /// \param[in] buf Location to copy the received message
davidr99 0:ab4e012489ef 489 /// \param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied.
davidr99 0:ab4e012489ef 490 /// \return true if a valid message was copied to buf
davidr99 0:ab4e012489ef 491 virtual bool recv(uint8_t* buf, uint8_t* len);
davidr99 0:ab4e012489ef 492
davidr99 0:ab4e012489ef 493 /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
davidr99 0:ab4e012489ef 494 /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
davidr99 0:ab4e012489ef 495 /// of 0 is permitted.
davidr99 0:ab4e012489ef 496 /// \param[in] data Array of data to be sent
davidr99 0:ab4e012489ef 497 /// \param[in] len Number of bytes of data to send
davidr99 0:ab4e012489ef 498 /// \return true if the message length was valid and it was correctly queued for transmit
davidr99 0:ab4e012489ef 499 virtual bool send(const uint8_t* data, uint8_t len);
davidr99 0:ab4e012489ef 500
davidr99 0:ab4e012489ef 501 /// Sets the length of the preamble
davidr99 0:ab4e012489ef 502 /// in bytes.
davidr99 0:ab4e012489ef 503 /// Caution: this should be set to the same
davidr99 0:ab4e012489ef 504 /// value on all nodes in your network. Default is 8.
davidr99 0:ab4e012489ef 505 /// Sets the message preamble length in RH_RF95_REG_??_PREAMBLE_?SB
davidr99 0:ab4e012489ef 506 /// \param[in] bytes Preamble length in bytes.
davidr99 0:ab4e012489ef 507 void setPreambleLength(uint16_t bytes);
davidr99 0:ab4e012489ef 508
davidr99 0:ab4e012489ef 509 /// Returns the maximum message length
davidr99 0:ab4e012489ef 510 /// available in this Driver.
davidr99 0:ab4e012489ef 511 /// \return The maximum legal message length
davidr99 0:ab4e012489ef 512 virtual uint8_t maxMessageLength();
davidr99 0:ab4e012489ef 513
davidr99 0:ab4e012489ef 514 /// Sets the transmitter and receiver
davidr99 0:ab4e012489ef 515 /// centre frequency
davidr99 0:ab4e012489ef 516 /// \param[in] centre Frequency in MHz. 137.0 to 1020.0. Caution: RFM95/96/97/98 comes in several
davidr99 0:ab4e012489ef 517 /// different frequency ranges, and setting a frequency outside that range of your radio will probably not work
davidr99 0:ab4e012489ef 518 /// \return true if the selected frquency centre is within range
davidr99 0:ab4e012489ef 519 bool setFrequency(float centre);
davidr99 0:ab4e012489ef 520
davidr99 0:ab4e012489ef 521 /// If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running,
davidr99 0:ab4e012489ef 522 /// disables them.
davidr99 0:ab4e012489ef 523 void setModeIdle();
davidr99 0:ab4e012489ef 524
davidr99 0:ab4e012489ef 525 /// If current mode is Tx or Idle, changes it to Rx.
davidr99 0:ab4e012489ef 526 /// Starts the receiver in the RF95/96/97/98.
davidr99 0:ab4e012489ef 527 void setModeRx();
davidr99 0:ab4e012489ef 528
davidr99 0:ab4e012489ef 529 /// If current mode is Rx or Idle, changes it to Rx. F
davidr99 0:ab4e012489ef 530 /// Starts the transmitter in the RF95/96/97/98.
davidr99 0:ab4e012489ef 531 void setModeTx();
davidr99 0:ab4e012489ef 532
davidr99 0:ab4e012489ef 533 /// Sets the transmitter power output level.
davidr99 0:ab4e012489ef 534 /// Be a good neighbour and set the lowest power level you need.
davidr99 0:ab4e012489ef 535 /// Caution: legal power limits may apply in certain countries. At powers above 20dBm, PA_DAC is enabled.
davidr99 0:ab4e012489ef 536 /// After init(), the power will be set to 13dBm.
davidr99 0:ab4e012489ef 537 /// \param[in] power Transmitter power level in dBm. For RFM95/96/97/98 LORA, valid values are from +5 to +23
davidr99 0:ab4e012489ef 538 void setTxPower(int8_t power);
davidr99 0:ab4e012489ef 539
davidr99 0:ab4e012489ef 540 /// Sets the radio into low-power sleep mode.
davidr99 0:ab4e012489ef 541 /// If successful, the transport will stay in sleep mode until woken by
davidr99 0:ab4e012489ef 542 /// changing mode it idle, transmit or receive (eg by calling send(), recv(), available() etc)
davidr99 0:ab4e012489ef 543 /// Caution: there is a time penalty as the radio takes a finite time to wake from sleep mode.
davidr99 0:ab4e012489ef 544 /// \return true if sleep mode was successfully entered.
davidr99 0:ab4e012489ef 545 virtual bool sleep();
davidr99 0:ab4e012489ef 546
davidr99 0:ab4e012489ef 547 protected:
davidr99 0:ab4e012489ef 548 /// This is a low level function to handle the interrupts for one instance of RH_RF95.
davidr99 0:ab4e012489ef 549 /// Called automatically by isr*()
davidr99 0:ab4e012489ef 550 /// Should not need to be called by user code.
davidr99 0:ab4e012489ef 551 void handleInterrupt();
davidr99 0:ab4e012489ef 552
davidr99 0:ab4e012489ef 553 /// Examine the revceive buffer to determine whether the message is for this node
davidr99 0:ab4e012489ef 554 void validateRxBuf();
davidr99 0:ab4e012489ef 555
davidr99 0:ab4e012489ef 556 /// Clear our local receive buffer
davidr99 0:ab4e012489ef 557 void clearRxBuf();
davidr99 0:ab4e012489ef 558
davidr99 0:ab4e012489ef 559 private:
davidr99 0:ab4e012489ef 560 /// Low level interrupt service routine for device connected to interrupt 0
davidr99 0:ab4e012489ef 561 static void isr0();
davidr99 0:ab4e012489ef 562
davidr99 0:ab4e012489ef 563 /// Low level interrupt service routine for device connected to interrupt 1
davidr99 0:ab4e012489ef 564 static void isr1();
davidr99 0:ab4e012489ef 565
davidr99 0:ab4e012489ef 566 /// Low level interrupt service routine for device connected to interrupt 1
davidr99 0:ab4e012489ef 567 static void isr2();
davidr99 0:ab4e012489ef 568
davidr99 0:ab4e012489ef 569 /// Array of instances connected to interrupts 0 and 1
davidr99 0:ab4e012489ef 570 static RH_RF95* _deviceForInterrupt[];
davidr99 0:ab4e012489ef 571
davidr99 0:ab4e012489ef 572 /// Index of next interrupt number to use in _deviceForInterrupt
davidr99 0:ab4e012489ef 573 static uint8_t _interruptCount;
davidr99 0:ab4e012489ef 574
davidr99 0:ab4e012489ef 575 #if (RH_PLATFORM == RH_PLATFORM_MBED)
davidr99 0:ab4e012489ef 576 /// The configured interrupt pin connected to this instance
davidr99 0:ab4e012489ef 577 InterruptIn _interruptPin;
davidr99 0:ab4e012489ef 578 #else
davidr99 0:ab4e012489ef 579 /// The configured interrupt pin connected to this instance
davidr99 0:ab4e012489ef 580 uint8_t _interruptPin;
davidr99 0:ab4e012489ef 581 #endif
davidr99 0:ab4e012489ef 582
davidr99 0:ab4e012489ef 583 /// The index into _deviceForInterrupt[] for this device (if an interrupt is already allocated)
davidr99 0:ab4e012489ef 584 /// else 0xff
davidr99 0:ab4e012489ef 585 uint8_t _myInterruptIndex;
davidr99 0:ab4e012489ef 586
davidr99 0:ab4e012489ef 587 /// Number of octets in the buffer
davidr99 0:ab4e012489ef 588 volatile uint8_t _bufLen;
davidr99 0:ab4e012489ef 589
davidr99 0:ab4e012489ef 590 /// The receiver/transmitter buffer
davidr99 0:ab4e012489ef 591 uint8_t _buf[RH_RF95_MAX_PAYLOAD_LEN];
davidr99 0:ab4e012489ef 592
davidr99 0:ab4e012489ef 593 /// True when there is a valid message in the buffer
davidr99 0:ab4e012489ef 594 volatile bool _rxBufValid;
davidr99 0:ab4e012489ef 595 };
davidr99 0:ab4e012489ef 596
davidr99 0:ab4e012489ef 597 /// @example rf95_client.pde
davidr99 0:ab4e012489ef 598 /// @example rf95_server.pde
davidr99 0:ab4e012489ef 599 /// @example rf95_reliable_datagram_client.pde
davidr99 0:ab4e012489ef 600 /// @example rf95_reliable_datagram_server.pde
davidr99 0:ab4e012489ef 601
davidr99 0:ab4e012489ef 602 #endif
davidr99 0:ab4e012489ef 603