This driver is a stripped down version of the Radiohead 1.45 driver, and covers fewer radios. Threading and an event queue have been added to make the ISR's more stable across architectures. Specifically The STM32L4 parts

Dependents:   Threaded_LoRa_Modem

Committer:
rlanders73
Date:
Wed Jun 23 15:53:12 2021 +0000
Revision:
7:250d1c72df36
Parent:
3:6ffa8c82a713
explicitly not disabling interrupts for mbed

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
rlanders73 3:6ffa8c82a713 14 #include "PinNames.h"
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
rlanders73 1:dfeb5e8b199a 207 //#define RH_RF95_REG_40_DIO_MAPPING1 0x40
rlanders73 1:dfeb5e8b199a 208 #define RH_RF95_DIOMAPPING1_DIO0MAPPING_00 0x00
rlanders73 1:dfeb5e8b199a 209 #define RH_RF95_DIOMAPPING1_DIO0MAPPING_01 0x40
rlanders73 1:dfeb5e8b199a 210 #define RH_RF95_DIOMAPPING1_DIO0MAPPING_10 0x80
rlanders73 1:dfeb5e8b199a 211 #define RH_RF95_DIOMAPPING1_DIO0MAPPING_11 0xc0
rlanders73 1:dfeb5e8b199a 212
davidr99 0:ab4e012489ef 213 // RH_RF95_REG_4D_PA_DAC 0x4d
davidr99 0:ab4e012489ef 214 #define RH_RF95_PA_DAC_DISABLE 0x04
davidr99 0:ab4e012489ef 215 #define RH_RF95_PA_DAC_ENABLE 0x07
davidr99 0:ab4e012489ef 216
davidr99 0:ab4e012489ef 217 /////////////////////////////////////////////////////////////////////
davidr99 0:ab4e012489ef 218 /// \class RH_RF95 RH_RF95.h <RH_RF95.h>
davidr99 0:ab4e012489ef 219 /// \brief Driver to send and receive unaddressed, unreliable datagrams via a LoRa
davidr99 0:ab4e012489ef 220 /// capable radio transceiver.
davidr99 0:ab4e012489ef 221 ///
davidr99 0:ab4e012489ef 222 /// For Semtech SX1276/77/78 and HopeRF RFM95/96/97/98 and other similar LoRa capable radios.
davidr99 0:ab4e012489ef 223 /// Based on http://www.hoperf.com/upload/rf/RFM95_96_97_98W.pdf
davidr99 0:ab4e012489ef 224 /// and http://www.hoperf.cn/upload/rfchip/RF96_97_98.pdf
davidr99 0:ab4e012489ef 225 /// and http://www.semtech.com/images/datasheet/LoraDesignGuide_STD.pdf
davidr99 0:ab4e012489ef 226 /// and http://www.semtech.com/images/datasheet/sx1276.pdf
davidr99 0:ab4e012489ef 227 /// FSK/GFSK/OOK modes are not (yet) supported.
davidr99 0:ab4e012489ef 228 ///
davidr99 0:ab4e012489ef 229 /// Works with
davidr99 0:ab4e012489ef 230 /// - the excellent MiniWirelessLoRa from Anarduino http://www.anarduino.com/miniwireless
davidr99 0:ab4e012489ef 231 ///
davidr99 0:ab4e012489ef 232 /// \par Overview
davidr99 0:ab4e012489ef 233 ///
davidr99 0:ab4e012489ef 234 /// This class provides basic functions for sending and receiving unaddressed,
davidr99 0:ab4e012489ef 235 /// unreliable datagrams of arbitrary length to 251 octets per packet.
davidr99 0:ab4e012489ef 236 ///
davidr99 0:ab4e012489ef 237 /// Manager classes may use this class to implement reliable, addressed datagrams and streams,
davidr99 0:ab4e012489ef 238 /// mesh routers, repeaters, translators etc.
davidr99 0:ab4e012489ef 239 ///
davidr99 0:ab4e012489ef 240 /// Naturally, for any 2 radios to communicate that must be configured to use the same frequency and
davidr99 0:ab4e012489ef 241 /// modulation scheme.
davidr99 0:ab4e012489ef 242 ///
davidr99 0:ab4e012489ef 243 /// This Driver provides an object-oriented interface for sending and receiving data messages with Hope-RF
davidr99 0:ab4e012489ef 244 /// RFM95/96/97/98(W) and compatible radio modules in LoRa mode.
davidr99 0:ab4e012489ef 245 ///
davidr99 0:ab4e012489ef 246 /// The Hope-RF (http://www.hoperf.com) RFM95/96/97/98(W) is a low-cost ISM transceiver
davidr99 0:ab4e012489ef 247 /// chip. It supports FSK, GFSK, OOK over a wide range of frequencies and
davidr99 0:ab4e012489ef 248 /// programmable data rates, and it also supports the proprietary LoRA (Long Range) mode, which
davidr99 0:ab4e012489ef 249 /// is the only mode supported in this RadioHead driver.
davidr99 0:ab4e012489ef 250 ///
davidr99 0:ab4e012489ef 251 /// This Driver provides functions for sending and receiving messages of up
davidr99 0:ab4e012489ef 252 /// to 251 octets on any frequency supported by the radio, in a range of
davidr99 0:ab4e012489ef 253 /// predefined Bandwidths, Spreading Factors and Coding Rates. Frequency can be set with
davidr99 0:ab4e012489ef 254 /// 61Hz precision to any frequency from 240.0MHz to 960.0MHz. Caution: most modules only support a more limited
davidr99 0:ab4e012489ef 255 /// range of frequencies due to antenna tuning.
davidr99 0:ab4e012489ef 256 ///
davidr99 0:ab4e012489ef 257 /// Up to 2 RFM95/96/97/98(W) modules can be connected to an Arduino (3 on a Mega),
davidr99 0:ab4e012489ef 258 /// permitting the construction of translators and frequency changers, etc.
davidr99 0:ab4e012489ef 259 ///
davidr99 0:ab4e012489ef 260 /// Support for other features such as transmitter power control etc is
davidr99 0:ab4e012489ef 261 /// also provided.
davidr99 0:ab4e012489ef 262 ///
davidr99 0:ab4e012489ef 263 /// Tested on MinWirelessLoRa with arduino-1.0.5
davidr99 0:ab4e012489ef 264 /// on OpenSuSE 13.1
davidr99 0:ab4e012489ef 265 ///
davidr99 0:ab4e012489ef 266 /// \par Packet Format
davidr99 0:ab4e012489ef 267 ///
davidr99 0:ab4e012489ef 268 /// All messages sent and received by this RH_RF95 Driver conform to this packet format:
davidr99 0:ab4e012489ef 269 ///
davidr99 0:ab4e012489ef 270 /// - LoRa mode:
davidr99 0:ab4e012489ef 271 /// - 8 symbol PREAMBLE
davidr99 0:ab4e012489ef 272 /// - Explicit header with header CRC (handled internally by the radio)
davidr99 0:ab4e012489ef 273 /// - 4 octets HEADER: (TO, FROM, ID, FLAGS)
davidr99 0:ab4e012489ef 274 /// - 0 to 251 octets DATA
davidr99 0:ab4e012489ef 275 /// - CRC (handled internally by the radio)
davidr99 0:ab4e012489ef 276 ///
davidr99 0:ab4e012489ef 277 /// \par Connecting RFM95/96/97/98 to Arduino
davidr99 0:ab4e012489ef 278 ///
davidr99 0:ab4e012489ef 279 /// We tested with Anarduino MiniWirelessLoRA, which is an Arduino Duemilanove compatible with a RFM96W
davidr99 0:ab4e012489ef 280 /// module on-board. Therefore it needs no connections other than the USB
davidr99 0:ab4e012489ef 281 /// programming connection and an antenna to make it work.
davidr99 0:ab4e012489ef 282 ///
davidr99 0:ab4e012489ef 283 /// If you have a bare RFM95/96/97/98 that you want to connect to an Arduino, you
davidr99 0:ab4e012489ef 284 /// might use these connections (untested): CAUTION: you must use a 3.3V type
davidr99 0:ab4e012489ef 285 /// Arduino, otherwise you will also need voltage level shifters between the
davidr99 0:ab4e012489ef 286 /// Arduino and the RFM95. CAUTION, you must also ensure you connect an
davidr99 0:ab4e012489ef 287 /// antenna.
davidr99 0:ab4e012489ef 288 ///
davidr99 0:ab4e012489ef 289 /// \code
davidr99 0:ab4e012489ef 290 /// Arduino RFM95/96/97/98
davidr99 0:ab4e012489ef 291 /// GND----------GND (ground in)
davidr99 0:ab4e012489ef 292 /// 3V3----------3.3V (3.3V in)
davidr99 0:ab4e012489ef 293 /// interrupt 0 pin D2-----------DIO0 (interrupt request out)
davidr99 0:ab4e012489ef 294 /// SS pin D10----------NSS (chip select in)
davidr99 0:ab4e012489ef 295 /// SCK pin D13----------SCK (SPI clock in)
davidr99 0:ab4e012489ef 296 /// MOSI pin D11----------MOSI (SPI Data in)
davidr99 0:ab4e012489ef 297 /// MISO pin D12----------MISO (SPI Data out)
davidr99 0:ab4e012489ef 298 /// \endcode
davidr99 0:ab4e012489ef 299 ///
davidr99 0:ab4e012489ef 300 /// With these connections, you can then use the default constructor RH_RF95().
davidr99 0:ab4e012489ef 301 /// You can override the default settings for the SS pin and the interrupt in
davidr99 0:ab4e012489ef 302 /// the RH_RF95 constructor if you wish to connect the slave select SS to other
davidr99 0:ab4e012489ef 303 /// than the normal one for your Arduino (D10 for Diecimila, Uno etc and D53
davidr99 0:ab4e012489ef 304 /// for Mega) or the interrupt request to other than pin D2 (Caution,
davidr99 0:ab4e012489ef 305 /// different processors have different constraints as to the pins available
davidr99 0:ab4e012489ef 306 /// for interrupts).
davidr99 0:ab4e012489ef 307 ///
davidr99 0:ab4e012489ef 308 /// It is possible to have 2 or more radios connected to one Arduino, provided
davidr99 0:ab4e012489ef 309 /// each radio has its own SS and interrupt line (SCK, SDI and SDO are common
davidr99 0:ab4e012489ef 310 /// to all radios)
davidr99 0:ab4e012489ef 311 ///
davidr99 0:ab4e012489ef 312 /// Caution: on some Arduinos such as the Mega 2560, if you set the slave
davidr99 0:ab4e012489ef 313 /// select pin to be other than the usual SS pin (D53 on Mega 2560), you may
davidr99 0:ab4e012489ef 314 /// need to set the usual SS pin to be an output to force the Arduino into SPI
davidr99 0:ab4e012489ef 315 /// master mode.
davidr99 0:ab4e012489ef 316 ///
davidr99 0:ab4e012489ef 317 /// Caution: Power supply requirements of the RFM module may be relevant in some circumstances:
davidr99 0:ab4e012489ef 318 /// RFM95/96/97/98 modules are capable of pulling 120mA+ at full power, where Arduino's 3.3V line can
davidr99 0:ab4e012489ef 319 /// give 50mA. You may need to make provision for alternate power supply for
davidr99 0:ab4e012489ef 320 /// the RFM module, especially if you wish to use full transmit power, and/or you have
davidr99 0:ab4e012489ef 321 /// other shields demanding power. Inadequate power for the RFM is likely to cause symptoms such as:
davidr99 0:ab4e012489ef 322 /// - reset's/bootups terminate with "init failed" messages
davidr99 0:ab4e012489ef 323 /// - random termination of communication after 5-30 packets sent/received
davidr99 0:ab4e012489ef 324 /// - "fake ok" state, where initialization passes fluently, but communication doesn't happen
davidr99 0:ab4e012489ef 325 /// - shields hang Arduino boards, especially during the flashing
davidr99 0:ab4e012489ef 326 ///
davidr99 0:ab4e012489ef 327 /// \par Interrupts
davidr99 0:ab4e012489ef 328 ///
davidr99 0:ab4e012489ef 329 /// The RH_RF95 driver uses interrupts to react to events in the RFM module,
davidr99 0:ab4e012489ef 330 /// such as the reception of a new packet, or the completion of transmission
davidr99 0:ab4e012489ef 331 /// of a packet. The RH_RF95 driver interrupt service routine reads status from
davidr99 0:ab4e012489ef 332 /// and writes data to the the RFM module via the SPI interface. It is very
davidr99 0:ab4e012489ef 333 /// important therefore, that if you are using the RH_RF95 driver with another
davidr99 0:ab4e012489ef 334 /// SPI based deviced, that you disable interrupts while you transfer data to
davidr99 0:ab4e012489ef 335 /// and from that other device. Use cli() to disable interrupts and sei() to
davidr99 0:ab4e012489ef 336 /// reenable them.
davidr99 0:ab4e012489ef 337 ///
davidr99 0:ab4e012489ef 338 /// \par Memory
davidr99 0:ab4e012489ef 339 ///
davidr99 0:ab4e012489ef 340 /// The RH_RF95 driver requires non-trivial amounts of memory. The sample
davidr99 0:ab4e012489ef 341 /// programs all compile to about 8kbytes each, which will fit in the
davidr99 0:ab4e012489ef 342 /// flash proram memory of most Arduinos. However, the RAM requirements are
davidr99 0:ab4e012489ef 343 /// more critical. Therefore, you should be vary sparing with RAM use in
davidr99 0:ab4e012489ef 344 /// programs that use the RH_RF95 driver.
davidr99 0:ab4e012489ef 345 ///
davidr99 0:ab4e012489ef 346 /// It is often hard to accurately identify when you are hitting RAM limits on Arduino.
davidr99 0:ab4e012489ef 347 /// The symptoms can include:
davidr99 0:ab4e012489ef 348 /// - Mysterious crashes and restarts
davidr99 0:ab4e012489ef 349 /// - Changes in behaviour when seemingly unrelated changes are made (such as adding print() statements)
davidr99 0:ab4e012489ef 350 /// - Hanging
davidr99 0:ab4e012489ef 351 /// - Output from Serial.print() not appearing
davidr99 0:ab4e012489ef 352 ///
davidr99 0:ab4e012489ef 353 /// \par Range
davidr99 0:ab4e012489ef 354 ///
davidr99 0:ab4e012489ef 355 /// We have made some simple range tests under the following conditions:
davidr99 0:ab4e012489ef 356 /// - rf95_client base station connected to a VHF discone antenna at 8m height above ground
davidr99 0:ab4e012489ef 357 /// - rf95_server mobile connected to 17.3cm 1/4 wavelength antenna at 1m height, no ground plane.
davidr99 0:ab4e012489ef 358 /// - Both configured for 13dBm, 434MHz, Bw = 125 kHz, Cr = 4/8, Sf = 4096chips/symbol, CRC on. Slow+long range
davidr99 0:ab4e012489ef 359 /// - Minimum reported RSSI seen for successful comms was about -91
davidr99 0:ab4e012489ef 360 /// - Range over flat ground through heavy trees and vegetation approx 2km.
davidr99 0:ab4e012489ef 361 /// - At 20dBm (100mW) otherwise identical conditions approx 3km.
davidr99 0:ab4e012489ef 362 /// - At 20dBm, along salt water flat sandy beach, 3.2km.
davidr99 0:ab4e012489ef 363 ///
davidr99 0:ab4e012489ef 364 /// It should be noted that at this data rate, a 12 octet message takes 2 seconds to transmit.
davidr99 0:ab4e012489ef 365 ///
davidr99 0:ab4e012489ef 366 /// At 20dBm (100mW) with Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on.
davidr99 0:ab4e012489ef 367 /// (Default medium range) in the conditions described above.
davidr99 0:ab4e012489ef 368 /// - Range over flat ground through heavy trees and vegetation approx 2km.
davidr99 0:ab4e012489ef 369 ///
davidr99 0:ab4e012489ef 370 /// \par Transmitter Power
davidr99 0:ab4e012489ef 371 ///
davidr99 0:ab4e012489ef 372 /// You can control the transmitter power on the RF transceiver
davidr99 0:ab4e012489ef 373 /// with the RH_RF95::setTxPower() function. The argument can be any of
davidr99 0:ab4e012489ef 374 /// +5 to +23
davidr99 0:ab4e012489ef 375 /// The default is 13. Eg:
davidr99 0:ab4e012489ef 376 /// \code
davidr99 0:ab4e012489ef 377 /// driver.setTxPower(10);
davidr99 0:ab4e012489ef 378 /// \endcode
davidr99 0:ab4e012489ef 379 ///
davidr99 0:ab4e012489ef 380 /// We have made some actual power measurements against
davidr99 0:ab4e012489ef 381 /// programmed power for Anarduino MiniWirelessLoRa (which has RFM96W-433Mhz installed)
davidr99 0:ab4e012489ef 382 /// - MiniWirelessLoRa RFM96W-433Mhz, USB power
davidr99 0:ab4e012489ef 383 /// - 30cm RG316 soldered direct to RFM96W module ANT and GND
davidr99 0:ab4e012489ef 384 /// - SMA connector
davidr99 0:ab4e012489ef 385 /// - 12db attenuator
davidr99 0:ab4e012489ef 386 /// - SMA connector
davidr99 0:ab4e012489ef 387 /// - MiniKits AD8307 HF/VHF Power Head (calibrated against Rohde&Schwartz 806.2020 test set)
davidr99 0:ab4e012489ef 388 /// - Tektronix TDS220 scope to measure the Vout from power head
davidr99 0:ab4e012489ef 389 /// \code
davidr99 0:ab4e012489ef 390 /// Program power Measured Power
davidr99 0:ab4e012489ef 391 /// dBm dBm
davidr99 0:ab4e012489ef 392 /// 5 5
davidr99 0:ab4e012489ef 393 /// 7 7
davidr99 0:ab4e012489ef 394 /// 9 8
davidr99 0:ab4e012489ef 395 /// 11 11
davidr99 0:ab4e012489ef 396 /// 13 13
davidr99 0:ab4e012489ef 397 /// 15 15
davidr99 0:ab4e012489ef 398 /// 17 16
davidr99 0:ab4e012489ef 399 /// 19 18
davidr99 0:ab4e012489ef 400 /// 20 20
davidr99 0:ab4e012489ef 401 /// 21 21
davidr99 0:ab4e012489ef 402 /// 22 22
davidr99 0:ab4e012489ef 403 /// 23 23
davidr99 0:ab4e012489ef 404 /// \endcode
davidr99 0:ab4e012489ef 405 /// (Caution: we dont claim laboratory accuracy for these measurements)
davidr99 0:ab4e012489ef 406 /// You would not expect to get anywhere near these powers to air with a simple 1/4 wavelength wire antenna.
davidr99 0:ab4e012489ef 407 class RH_RF95 : public RHSPIDriver
davidr99 0:ab4e012489ef 408 {
davidr99 0:ab4e012489ef 409 public:
davidr99 0:ab4e012489ef 410 /// \brief Defines register values for a set of modem configuration registers
davidr99 0:ab4e012489ef 411 ///
davidr99 0:ab4e012489ef 412 /// Defines register values for a set of modem configuration registers
davidr99 0:ab4e012489ef 413 /// that can be passed to setModemRegisters() if none of the choices in
davidr99 0:ab4e012489ef 414 /// ModemConfigChoice suit your need setModemRegisters() writes the
davidr99 0:ab4e012489ef 415 /// register values from this structure to the appropriate registers
davidr99 0:ab4e012489ef 416 /// to set the desired spreading factor, coding rate and bandwidth
davidr99 0:ab4e012489ef 417 typedef struct {
davidr99 0:ab4e012489ef 418 uint8_t reg_1d; ///< Value for register RH_RF95_REG_1D_MODEM_CONFIG1
davidr99 0:ab4e012489ef 419 uint8_t reg_1e; ///< Value for register RH_RF95_REG_1E_MODEM_CONFIG2
davidr99 0:ab4e012489ef 420 uint8_t reg_26; ///< Value for register RH_RF95_REG_26_MODEM_CONFIG3
davidr99 0:ab4e012489ef 421 } ModemConfig;
davidr99 0:ab4e012489ef 422
davidr99 0:ab4e012489ef 423 /// Choices for setModemConfig() for a selected subset of common
davidr99 0:ab4e012489ef 424 /// data rates. If you need another configuration,
davidr99 0:ab4e012489ef 425 /// determine the necessary settings and call setModemRegisters() with your
davidr99 0:ab4e012489ef 426 /// desired settings. It might be helpful to use the LoRa calculator mentioned in
davidr99 0:ab4e012489ef 427 /// http://www.semtech.com/images/datasheet/LoraDesignGuide_STD.pdf
davidr99 0:ab4e012489ef 428 /// These are indexes into MODEM_CONFIG_TABLE. We strongly recommend you use these symbolic
davidr99 0:ab4e012489ef 429 /// definitions and not their integer equivalents: its possible that new values will be
davidr99 0:ab4e012489ef 430 /// introduced in later versions (though we will try to avoid it).
davidr99 0:ab4e012489ef 431 typedef enum {
davidr99 0:ab4e012489ef 432 Bw125Cr45Sf128 = 0, ///< Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Default medium range
davidr99 0:ab4e012489ef 433 Bw500Cr45Sf128, ///< Bw = 500 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Fast+short range
davidr99 0:ab4e012489ef 434 Bw31_25Cr48Sf512, ///< Bw = 31.25 kHz, Cr = 4/8, Sf = 512chips/symbol, CRC on. Slow+long range
davidr99 0:ab4e012489ef 435 Bw125Cr48Sf4096, ///< Bw = 125 kHz, Cr = 4/8, Sf = 4096chips/symbol, CRC on. Slow+long range
davidr99 0:ab4e012489ef 436 } ModemConfigChoice;
davidr99 0:ab4e012489ef 437
davidr99 0:ab4e012489ef 438 /// Constructor. You can have multiple instances, but each instance must have its own
davidr99 0:ab4e012489ef 439 /// interrupt and slave select pin. After constructing, you must call init() to initialise the interface
davidr99 0:ab4e012489ef 440 /// and the radio module. A maximum of 3 instances can co-exist on one processor, provided there are sufficient
davidr99 0:ab4e012489ef 441 /// distinct interrupt lines, one for each instance.
davidr99 0:ab4e012489ef 442 /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RH_RF22 before
davidr99 0:ab4e012489ef 443 /// 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 444 /// \param[in] interruptPin The interrupt Pin number that is connected to the RFM DIO0 interrupt line.
davidr99 0:ab4e012489ef 445 /// Defaults to pin 2, as required by Anarduino MinWirelessLoRa module.
davidr99 0:ab4e012489ef 446 /// Caution: You must specify an interrupt capable pin.
davidr99 0:ab4e012489ef 447 /// On many Arduino boards, there are limitations as to which pins may be used as interrupts.
davidr99 0:ab4e012489ef 448 /// 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 449 /// On other Arduinos pins 2 or 3.
davidr99 0:ab4e012489ef 450 /// See http://arduino.cc/en/Reference/attachInterrupt for more details.
davidr99 0:ab4e012489ef 451 /// On Chipkit Uno32, pins 38, 2, 7, 8, 35.
davidr99 0:ab4e012489ef 452 /// On other boards, any digital pin may be used.
davidr99 0:ab4e012489ef 453 /// \param[in] spi Pointer to the SPI interface object to use.
davidr99 0:ab4e012489ef 454 /// Defaults to the standard Arduino hardware SPI interface
davidr99 0:ab4e012489ef 455 RH_RF95(PINS slaveSelectPin, PINS interruptPin, RHGenericSPI& spi = hardware_spi);
davidr99 0:ab4e012489ef 456
davidr99 0:ab4e012489ef 457 /// Initialise the Driver transport hardware and software.
davidr99 0:ab4e012489ef 458 /// Make sure the Driver is properly configured before calling init().
davidr99 0:ab4e012489ef 459 /// \return true if initialisation succeeded.
davidr99 0:ab4e012489ef 460 virtual bool init();
davidr99 0:ab4e012489ef 461
davidr99 0:ab4e012489ef 462 /// Prints the value of all chip registers
davidr99 0:ab4e012489ef 463 /// to the Serial device if RH_HAVE_SERIAL is defined for the current platform
davidr99 0:ab4e012489ef 464 /// For debugging purposes only.
davidr99 0:ab4e012489ef 465 /// \return true on success
davidr99 0:ab4e012489ef 466 bool printRegisters();
davidr99 0:ab4e012489ef 467
davidr99 0:ab4e012489ef 468 /// Sets all the registered required to configure the data modem in the RF95/96/97/98, including the bandwidth,
davidr99 0:ab4e012489ef 469 /// spreading factor etc. You can use this to configure the modem with custom configurations if none of the
davidr99 0:ab4e012489ef 470 /// canned configurations in ModemConfigChoice suit you.
davidr99 0:ab4e012489ef 471 /// \param[in] config A ModemConfig structure containing values for the modem configuration registers.
davidr99 0:ab4e012489ef 472 void setModemRegisters(const ModemConfig* config);
davidr99 0:ab4e012489ef 473
davidr99 0:ab4e012489ef 474 /// Select one of the predefined modem configurations. If you need a modem configuration not provided
davidr99 0:ab4e012489ef 475 /// here, use setModemRegisters() with your own ModemConfig.
davidr99 0:ab4e012489ef 476 /// \param[in] index The configuration choice.
davidr99 0:ab4e012489ef 477 /// \return true if index is a valid choice.
davidr99 0:ab4e012489ef 478 bool setModemConfig(ModemConfigChoice index);
davidr99 0:ab4e012489ef 479
davidr99 0:ab4e012489ef 480 /// Tests whether a new message is available
davidr99 0:ab4e012489ef 481 /// from the Driver.
davidr99 0:ab4e012489ef 482 /// On most drivers, this will also put the Driver into RHModeRx mode until
davidr99 0:ab4e012489ef 483 /// a message is actually received by the transport, when it wil be returned to RHModeIdle.
davidr99 0:ab4e012489ef 484 /// This can be called multiple times in a timeout loop
davidr99 0:ab4e012489ef 485 /// \return true if a new, complete, error-free uncollected message is available to be retreived by recv()
davidr99 0:ab4e012489ef 486 virtual bool available();
davidr99 0:ab4e012489ef 487
davidr99 0:ab4e012489ef 488 /// Turns the receiver on if it not already on.
davidr99 0:ab4e012489ef 489 /// If there is a valid message available, copy it to buf and return true
davidr99 0:ab4e012489ef 490 /// else return false.
davidr99 0:ab4e012489ef 491 /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
davidr99 0:ab4e012489ef 492 /// You should be sure to call this function frequently enough to not miss any messages
davidr99 0:ab4e012489ef 493 /// It is recommended that you call it in your main loop.
davidr99 0:ab4e012489ef 494 /// \param[in] buf Location to copy the received message
davidr99 0:ab4e012489ef 495 /// \param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied.
davidr99 0:ab4e012489ef 496 /// \return true if a valid message was copied to buf
davidr99 0:ab4e012489ef 497 virtual bool recv(uint8_t* buf, uint8_t* len);
davidr99 0:ab4e012489ef 498
davidr99 0:ab4e012489ef 499 /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
davidr99 0:ab4e012489ef 500 /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
davidr99 0:ab4e012489ef 501 /// of 0 is permitted.
davidr99 0:ab4e012489ef 502 /// \param[in] data Array of data to be sent
davidr99 0:ab4e012489ef 503 /// \param[in] len Number of bytes of data to send
davidr99 0:ab4e012489ef 504 /// \return true if the message length was valid and it was correctly queued for transmit
davidr99 0:ab4e012489ef 505 virtual bool send(const uint8_t* data, uint8_t len);
davidr99 0:ab4e012489ef 506
davidr99 0:ab4e012489ef 507 /// Sets the length of the preamble
davidr99 0:ab4e012489ef 508 /// in bytes.
davidr99 0:ab4e012489ef 509 /// Caution: this should be set to the same
davidr99 0:ab4e012489ef 510 /// value on all nodes in your network. Default is 8.
davidr99 0:ab4e012489ef 511 /// Sets the message preamble length in RH_RF95_REG_??_PREAMBLE_?SB
davidr99 0:ab4e012489ef 512 /// \param[in] bytes Preamble length in bytes.
davidr99 0:ab4e012489ef 513 void setPreambleLength(uint16_t bytes);
davidr99 0:ab4e012489ef 514
davidr99 0:ab4e012489ef 515 /// Returns the maximum message length
davidr99 0:ab4e012489ef 516 /// available in this Driver.
davidr99 0:ab4e012489ef 517 /// \return The maximum legal message length
davidr99 0:ab4e012489ef 518 virtual uint8_t maxMessageLength();
davidr99 0:ab4e012489ef 519
davidr99 0:ab4e012489ef 520 /// Sets the transmitter and receiver
davidr99 0:ab4e012489ef 521 /// centre frequency
davidr99 0:ab4e012489ef 522 /// \param[in] centre Frequency in MHz. 137.0 to 1020.0. Caution: RFM95/96/97/98 comes in several
davidr99 0:ab4e012489ef 523 /// different frequency ranges, and setting a frequency outside that range of your radio will probably not work
davidr99 0:ab4e012489ef 524 /// \return true if the selected frquency centre is within range
davidr99 0:ab4e012489ef 525 bool setFrequency(float centre);
davidr99 0:ab4e012489ef 526
davidr99 0:ab4e012489ef 527 /// If current mode is Rx or Tx changes it to Idle. If the transmitter or receiver is running,
davidr99 0:ab4e012489ef 528 /// disables them.
davidr99 0:ab4e012489ef 529 void setModeIdle();
davidr99 0:ab4e012489ef 530
davidr99 0:ab4e012489ef 531 /// If current mode is Tx or Idle, changes it to Rx.
davidr99 0:ab4e012489ef 532 /// Starts the receiver in the RF95/96/97/98.
davidr99 0:ab4e012489ef 533 void setModeRx();
davidr99 0:ab4e012489ef 534
davidr99 0:ab4e012489ef 535 /// If current mode is Rx or Idle, changes it to Rx. F
davidr99 0:ab4e012489ef 536 /// Starts the transmitter in the RF95/96/97/98.
davidr99 0:ab4e012489ef 537 void setModeTx();
davidr99 0:ab4e012489ef 538
davidr99 0:ab4e012489ef 539 /// Sets the transmitter power output level.
davidr99 0:ab4e012489ef 540 /// Be a good neighbour and set the lowest power level you need.
davidr99 0:ab4e012489ef 541 /// Caution: legal power limits may apply in certain countries. At powers above 20dBm, PA_DAC is enabled.
davidr99 0:ab4e012489ef 542 /// After init(), the power will be set to 13dBm.
davidr99 0:ab4e012489ef 543 /// \param[in] power Transmitter power level in dBm. For RFM95/96/97/98 LORA, valid values are from +5 to +23
davidr99 0:ab4e012489ef 544 void setTxPower(int8_t power);
davidr99 0:ab4e012489ef 545
davidr99 0:ab4e012489ef 546 /// Sets the radio into low-power sleep mode.
davidr99 0:ab4e012489ef 547 /// If successful, the transport will stay in sleep mode until woken by
davidr99 0:ab4e012489ef 548 /// changing mode it idle, transmit or receive (eg by calling send(), recv(), available() etc)
davidr99 0:ab4e012489ef 549 /// Caution: there is a time penalty as the radio takes a finite time to wake from sleep mode.
davidr99 0:ab4e012489ef 550 /// \return true if sleep mode was successfully entered.
davidr99 0:ab4e012489ef 551 virtual bool sleep();
rlanders73 1:dfeb5e8b199a 552
rlanders73 3:6ffa8c82a713 553 void handleInterrupt();
davidr99 0:ab4e012489ef 554
davidr99 0:ab4e012489ef 555 protected:
davidr99 0:ab4e012489ef 556 /// This is a low level function to handle the interrupts for one instance of RH_RF95.
davidr99 0:ab4e012489ef 557 /// Called automatically by isr*()
davidr99 0:ab4e012489ef 558 /// Should not need to be called by user code.
rlanders73 1:dfeb5e8b199a 559
davidr99 0:ab4e012489ef 560
davidr99 0:ab4e012489ef 561 /// Examine the revceive buffer to determine whether the message is for this node
davidr99 0:ab4e012489ef 562 void validateRxBuf();
davidr99 0:ab4e012489ef 563
davidr99 0:ab4e012489ef 564 /// Clear our local receive buffer
davidr99 0:ab4e012489ef 565 void clearRxBuf();
davidr99 0:ab4e012489ef 566
davidr99 0:ab4e012489ef 567 private:
rlanders73 3:6ffa8c82a713 568 // static void startISR();
davidr99 0:ab4e012489ef 569 /// Low level interrupt service routine for device connected to interrupt 0
davidr99 0:ab4e012489ef 570 static void isr0();
davidr99 0:ab4e012489ef 571
davidr99 0:ab4e012489ef 572 /// Low level interrupt service routine for device connected to interrupt 1
davidr99 0:ab4e012489ef 573 static void isr1();
davidr99 0:ab4e012489ef 574
davidr99 0:ab4e012489ef 575 /// Low level interrupt service routine for device connected to interrupt 1
davidr99 0:ab4e012489ef 576 static void isr2();
davidr99 0:ab4e012489ef 577
davidr99 0:ab4e012489ef 578 /// Array of instances connected to interrupts 0 and 1
davidr99 0:ab4e012489ef 579 static RH_RF95* _deviceForInterrupt[];
davidr99 0:ab4e012489ef 580
davidr99 0:ab4e012489ef 581 /// Index of next interrupt number to use in _deviceForInterrupt
davidr99 0:ab4e012489ef 582 static uint8_t _interruptCount;
davidr99 0:ab4e012489ef 583
davidr99 0:ab4e012489ef 584 #if (RH_PLATFORM == RH_PLATFORM_MBED)
davidr99 0:ab4e012489ef 585 /// The configured interrupt pin connected to this instance
rlanders73 1:dfeb5e8b199a 586 InterruptIn _interruptPin;
rlanders73 3:6ffa8c82a713 587 Thread _isrThread;
rlanders73 3:6ffa8c82a713 588 static void manageISR();
rlanders73 3:6ffa8c82a713 589 // bool doISR;
davidr99 0:ab4e012489ef 590 #else
davidr99 0:ab4e012489ef 591 /// The configured interrupt pin connected to this instance
davidr99 0:ab4e012489ef 592 uint8_t _interruptPin;
davidr99 0:ab4e012489ef 593 #endif
davidr99 0:ab4e012489ef 594
davidr99 0:ab4e012489ef 595 /// The index into _deviceForInterrupt[] for this device (if an interrupt is already allocated)
davidr99 0:ab4e012489ef 596 /// else 0xff
davidr99 0:ab4e012489ef 597 uint8_t _myInterruptIndex;
davidr99 0:ab4e012489ef 598
davidr99 0:ab4e012489ef 599 /// Number of octets in the buffer
davidr99 0:ab4e012489ef 600 volatile uint8_t _bufLen;
davidr99 0:ab4e012489ef 601
davidr99 0:ab4e012489ef 602 /// The receiver/transmitter buffer
davidr99 0:ab4e012489ef 603 uint8_t _buf[RH_RF95_MAX_PAYLOAD_LEN];
davidr99 0:ab4e012489ef 604
davidr99 0:ab4e012489ef 605 /// True when there is a valid message in the buffer
davidr99 0:ab4e012489ef 606 volatile bool _rxBufValid;
davidr99 0:ab4e012489ef 607 };
davidr99 0:ab4e012489ef 608
davidr99 0:ab4e012489ef 609 /// @example rf95_client.pde
davidr99 0:ab4e012489ef 610 /// @example rf95_server.pde
davidr99 0:ab4e012489ef 611 /// @example rf95_reliable_datagram_client.pde
davidr99 0:ab4e012489ef 612 /// @example rf95_reliable_datagram_server.pde
davidr99 0:ab4e012489ef 613
davidr99 0:ab4e012489ef 614 #endif
davidr99 0:ab4e012489ef 615