V148
Fork of RadioHead-148 by
RH_RF95.h@1:b7641da2b203, 2017-10-25 (annotated)
- Committer:
- ilkaykozak
- Date:
- Wed Oct 25 05:14:09 2017 +0000
- Revision:
- 1:b7641da2b203
- Parent:
- 0:ab4e012489ef
V148
Who changed what in which revision?
User | Revision | Line number | New 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 |