Driver library for SX1272/SX1276 transceivers

Dependents:   LORA_RX LORA_TX WindConcentrator hid_test ... more

/media/uploads/dudmuck/lora.png

Driver library for SX1272 and SX1276 radio transceivers.

This device uses CSS modulation to provide much improved link budget. The RF hardware is same as in FSK devices, just with added LoRa spread-spectrum modem.

This library provides functions to configure radio chip and transmit & receive packets.

Using This Library

Library function service_radio() must be called continuously from main loop, to service interrupts from radio.

/media/uploads/dudmuck/sx1272rf1_connector_300.jpg

Board Specific implementation

FunctionPointer for rf_switch callback allows the program to implement control of RF switch unique to their board. Example options are:

  • SKY13373 for external power amplifier implementation. Requires two DigitalOut pins.
  • SKY13350 using PA_BOOST. requires two DigitalOut pins.
  • PE4259-63: controlled directly by radio chip, no software function needed. However, in the case of SX1276MB1xAS, the RXTX pin on IO2 should be driven by this callback function when R16 is installed (without R15) on this shield board.

Some configurations may need to force the use of RFO or PA_BOOST, or a board could offer both options. The rf_switch function pointer callback should support the implementation choice on the board.

further reading

Committer:
dudmuck
Date:
Fri Feb 27 22:50:18 2015 +0000
Revision:
10:7382c260c4b1
Parent:
9:ae1a71ccd730
Child:
12:bda42457c34a
added get_symbol_duration() to determine if LowDataRateOptimize should be used

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dudmuck 2:fdae76e1215e 1 #include "sx127x_lora.h"
dudmuck 2:fdae76e1215e 2
dudmuck 2:fdae76e1215e 3 /* SX127x driver
dudmuck 2:fdae76e1215e 4 * Copyright (c) 2013 Semtech
dudmuck 2:fdae76e1215e 5 *
dudmuck 2:fdae76e1215e 6 * Licensed under the Apache License, Version 2.0 (the "License");
dudmuck 2:fdae76e1215e 7 * you may not use this file except in compliance with the License.
dudmuck 2:fdae76e1215e 8 * You may obtain a copy of the License at
dudmuck 2:fdae76e1215e 9 *
dudmuck 2:fdae76e1215e 10 * http://www.apache.org/licenses/LICENSE-2.0
dudmuck 2:fdae76e1215e 11 *
dudmuck 2:fdae76e1215e 12 * Unless required by applicable law or agreed to in writing, software
dudmuck 2:fdae76e1215e 13 * distributed under the License is distributed on an "AS IS" BASIS,
dudmuck 2:fdae76e1215e 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dudmuck 2:fdae76e1215e 15 * See the License for the specific language governing permissions and
dudmuck 2:fdae76e1215e 16 * limitations under the License.
dudmuck 2:fdae76e1215e 17 */
dudmuck 2:fdae76e1215e 18
dudmuck 3:3bf2515b1eed 19 SX127x_lora::SX127x_lora(SX127x& r) : m_xcvr(r)
dudmuck 2:fdae76e1215e 20 {
dudmuck 2:fdae76e1215e 21 RegModemConfig.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG);
dudmuck 2:fdae76e1215e 22 RegModemConfig2.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG2);
dudmuck 2:fdae76e1215e 23 RegTest31.octet = m_xcvr.read_reg(REG_LR_TEST31);
dudmuck 2:fdae76e1215e 24
dudmuck 2:fdae76e1215e 25 // CRC for TX is disabled by default
dudmuck 2:fdae76e1215e 26 setRxPayloadCrcOn(true);
dudmuck 2:fdae76e1215e 27 }
dudmuck 2:fdae76e1215e 28
dudmuck 2:fdae76e1215e 29 SX127x_lora::~SX127x_lora()
dudmuck 2:fdae76e1215e 30 {
dudmuck 2:fdae76e1215e 31 }
dudmuck 2:fdae76e1215e 32
dudmuck 2:fdae76e1215e 33 void SX127x_lora::write_fifo(uint8_t len)
dudmuck 2:fdae76e1215e 34 {
dudmuck 2:fdae76e1215e 35 int i;
dudmuck 2:fdae76e1215e 36
dudmuck 2:fdae76e1215e 37 m_xcvr.m_cs = 0;
dudmuck 2:fdae76e1215e 38 m_xcvr.m_spi.write(REG_FIFO | 0x80); // bit7 is high for writing to radio
dudmuck 2:fdae76e1215e 39
dudmuck 2:fdae76e1215e 40 for (i = 0; i < len; i++) {
dudmuck 2:fdae76e1215e 41 m_xcvr.m_spi.write(m_xcvr.tx_buf[i]);
dudmuck 2:fdae76e1215e 42 }
dudmuck 2:fdae76e1215e 43 m_xcvr.m_cs = 1;
dudmuck 2:fdae76e1215e 44 }
dudmuck 2:fdae76e1215e 45
dudmuck 2:fdae76e1215e 46 void SX127x_lora::read_fifo(uint8_t len)
dudmuck 2:fdae76e1215e 47 {
dudmuck 2:fdae76e1215e 48 int i;
dudmuck 2:fdae76e1215e 49
dudmuck 2:fdae76e1215e 50 m_xcvr.m_cs = 0;
dudmuck 2:fdae76e1215e 51 m_xcvr.m_spi.write(REG_FIFO); // bit7 is low for reading from radio
dudmuck 2:fdae76e1215e 52 for (i = 0; i < len; i++) {
dudmuck 2:fdae76e1215e 53 m_xcvr.rx_buf[i] = m_xcvr.m_spi.write(0);
dudmuck 2:fdae76e1215e 54 }
dudmuck 2:fdae76e1215e 55 m_xcvr.m_cs = 1;
dudmuck 2:fdae76e1215e 56 }
dudmuck 2:fdae76e1215e 57
dudmuck 2:fdae76e1215e 58 void SX127x_lora::enable()
dudmuck 2:fdae76e1215e 59 {
dudmuck 2:fdae76e1215e 60 m_xcvr.set_opmode(RF_OPMODE_SLEEP);
dudmuck 2:fdae76e1215e 61
dudmuck 2:fdae76e1215e 62 m_xcvr.RegOpMode.bits.LongRangeMode = 1;
dudmuck 2:fdae76e1215e 63 m_xcvr.write_reg(REG_OPMODE, m_xcvr.RegOpMode.octet);
dudmuck 2:fdae76e1215e 64
dudmuck 2:fdae76e1215e 65 /*RegOpMode.octet = read_reg(REG_OPMODE);
dudmuck 2:fdae76e1215e 66 printf("setloraon:%02x\r\n", RegOpMode.octet);*/
dudmuck 2:fdae76e1215e 67
dudmuck 2:fdae76e1215e 68
dudmuck 2:fdae76e1215e 69 /* // RxDone RxTimeout FhssChangeChannel CadDone
dudmuck 2:fdae76e1215e 70 SX1272LR->RegDioMapping1 = RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO1_00 | RFLR_DIOMAPPING1_DIO2_00 | RFLR_DIOMAPPING1_DIO3_00;
dudmuck 2:fdae76e1215e 71 // CadDetected ModeReady
dudmuck 2:fdae76e1215e 72 SX1272LR->RegDioMapping2 = RFLR_DIOMAPPING2_DIO4_00 | RFLR_DIOMAPPING2_DIO5_00;
dudmuck 2:fdae76e1215e 73 SX1272WriteBuffer( REG_LR_DIOMAPPING1, &SX1272LR->RegDioMapping1, 2 );*/
dudmuck 2:fdae76e1215e 74 m_xcvr.RegDioMapping1.bits.Dio0Mapping = 0; // DIO0 to RxDone
dudmuck 2:fdae76e1215e 75 m_xcvr.RegDioMapping1.bits.Dio1Mapping = 0;
dudmuck 2:fdae76e1215e 76 m_xcvr.write_reg(REG_DIOMAPPING1, m_xcvr.RegDioMapping1.octet);
dudmuck 2:fdae76e1215e 77
dudmuck 2:fdae76e1215e 78 // todo: read LoRa regsiters
dudmuck 2:fdae76e1215e 79 //SX1272ReadBuffer( REG_LR_OPMODE, SX1272Regs + 1, 0x70 - 1 );
dudmuck 2:fdae76e1215e 80
dudmuck 2:fdae76e1215e 81 m_xcvr.set_opmode(RF_OPMODE_STANDBY);
dudmuck 2:fdae76e1215e 82 }
dudmuck 2:fdae76e1215e 83
dudmuck 2:fdae76e1215e 84 uint8_t SX127x_lora::getCodingRate(bool from_rx)
dudmuck 2:fdae76e1215e 85 {
dudmuck 2:fdae76e1215e 86 if (from_rx) {
dudmuck 2:fdae76e1215e 87 // expected RegModemStatus was read on RxDone interrupt
dudmuck 2:fdae76e1215e 88 return RegModemStatus.bits.RxCodingRate;
dudmuck 2:fdae76e1215e 89 } else { // transmitted coding rate...
dudmuck 2:fdae76e1215e 90 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 91 return RegModemConfig.sx1276bits.CodingRate;
dudmuck 2:fdae76e1215e 92 else if (m_xcvr.type == SX1272)
dudmuck 2:fdae76e1215e 93 return RegModemConfig.sx1272bits.CodingRate;
dudmuck 2:fdae76e1215e 94 else
dudmuck 2:fdae76e1215e 95 return 0;
dudmuck 2:fdae76e1215e 96 }
dudmuck 2:fdae76e1215e 97 }
dudmuck 2:fdae76e1215e 98
dudmuck 2:fdae76e1215e 99
dudmuck 2:fdae76e1215e 100
dudmuck 2:fdae76e1215e 101 void SX127x_lora::setCodingRate(uint8_t cr)
dudmuck 2:fdae76e1215e 102 {
dudmuck 2:fdae76e1215e 103 if (!m_xcvr.RegOpMode.bits.LongRangeMode)
dudmuck 2:fdae76e1215e 104 return;
dudmuck 2:fdae76e1215e 105
dudmuck 2:fdae76e1215e 106 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 107 RegModemConfig.sx1276bits.CodingRate = cr;
dudmuck 2:fdae76e1215e 108 else if (m_xcvr.type == SX1272)
dudmuck 2:fdae76e1215e 109 RegModemConfig.sx1272bits.CodingRate = cr;
dudmuck 2:fdae76e1215e 110 else
dudmuck 2:fdae76e1215e 111 return;
dudmuck 2:fdae76e1215e 112
dudmuck 2:fdae76e1215e 113 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 2:fdae76e1215e 114 }
dudmuck 2:fdae76e1215e 115
dudmuck 2:fdae76e1215e 116
dudmuck 2:fdae76e1215e 117
dudmuck 2:fdae76e1215e 118 bool SX127x_lora::getHeaderMode(void)
dudmuck 2:fdae76e1215e 119 {
dudmuck 2:fdae76e1215e 120 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 121 return RegModemConfig.sx1276bits.ImplicitHeaderModeOn;
dudmuck 2:fdae76e1215e 122 else if (m_xcvr.type == SX1272)
dudmuck 2:fdae76e1215e 123 return RegModemConfig.sx1272bits.ImplicitHeaderModeOn;
dudmuck 2:fdae76e1215e 124 else
dudmuck 2:fdae76e1215e 125 return false;
dudmuck 2:fdae76e1215e 126 }
dudmuck 2:fdae76e1215e 127
dudmuck 2:fdae76e1215e 128 void SX127x_lora::setHeaderMode(bool hm)
dudmuck 2:fdae76e1215e 129 {
dudmuck 2:fdae76e1215e 130 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 131 RegModemConfig.sx1276bits.ImplicitHeaderModeOn = hm;
dudmuck 2:fdae76e1215e 132 else if (m_xcvr.type == SX1272)
dudmuck 2:fdae76e1215e 133 RegModemConfig.sx1272bits.ImplicitHeaderModeOn = hm;
dudmuck 2:fdae76e1215e 134 else
dudmuck 2:fdae76e1215e 135 return;
dudmuck 2:fdae76e1215e 136
dudmuck 2:fdae76e1215e 137 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 2:fdae76e1215e 138 }
dudmuck 2:fdae76e1215e 139
dudmuck 2:fdae76e1215e 140
dudmuck 2:fdae76e1215e 141 uint8_t SX127x_lora::getBw(void)
dudmuck 2:fdae76e1215e 142 {
dudmuck 2:fdae76e1215e 143 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 144 return RegModemConfig.sx1276bits.Bw;
dudmuck 2:fdae76e1215e 145 else if (m_xcvr.type == SX1272)
dudmuck 2:fdae76e1215e 146 return RegModemConfig.sx1272bits.Bw;
dudmuck 2:fdae76e1215e 147 else
dudmuck 2:fdae76e1215e 148 return 0;
dudmuck 2:fdae76e1215e 149 }
dudmuck 10:7382c260c4b1 150 float SX127x_lora::get_symbol_period()
dudmuck 10:7382c260c4b1 151 {
dudmuck 10:7382c260c4b1 152 float khz = 0;
dudmuck 10:7382c260c4b1 153
dudmuck 10:7382c260c4b1 154 if (m_xcvr.type == SX1276) {
dudmuck 10:7382c260c4b1 155 switch (RegModemConfig.sx1276bits.Bw) {
dudmuck 10:7382c260c4b1 156 case 0: khz = 7.8; break;
dudmuck 10:7382c260c4b1 157 case 1: khz = 10.4; break;
dudmuck 10:7382c260c4b1 158 case 2: khz = 15.6; break;
dudmuck 10:7382c260c4b1 159 case 3: khz = 20.8; break;
dudmuck 10:7382c260c4b1 160 case 4: khz = 31.25; break;
dudmuck 10:7382c260c4b1 161 case 5: khz = 41.7; break;
dudmuck 10:7382c260c4b1 162 case 6: khz = 62.5; break;
dudmuck 10:7382c260c4b1 163 case 7: khz = 125; break;
dudmuck 10:7382c260c4b1 164 case 8: khz = 250; break;
dudmuck 10:7382c260c4b1 165 case 9: khz = 500; break;
dudmuck 10:7382c260c4b1 166 }
dudmuck 10:7382c260c4b1 167 } else if (m_xcvr.type == SX1272) {
dudmuck 10:7382c260c4b1 168 switch (RegModemConfig.sx1272bits.Bw) {
dudmuck 10:7382c260c4b1 169 case 0: khz = 125; break;
dudmuck 10:7382c260c4b1 170 case 1: khz = 250; break;
dudmuck 10:7382c260c4b1 171 case 2: khz = 500; break;
dudmuck 10:7382c260c4b1 172 }
dudmuck 10:7382c260c4b1 173 }
dudmuck 10:7382c260c4b1 174
dudmuck 10:7382c260c4b1 175 // return symbol duration in milliseconds
dudmuck 10:7382c260c4b1 176 return (1 << RegModemConfig2.sx1276bits.SpreadingFactor) / khz;
dudmuck 10:7382c260c4b1 177 }
dudmuck 2:fdae76e1215e 178
dudmuck 2:fdae76e1215e 179 void SX127x_lora::setBw(uint8_t bw)
dudmuck 2:fdae76e1215e 180 {
dudmuck 2:fdae76e1215e 181 if (!m_xcvr.RegOpMode.bits.LongRangeMode)
dudmuck 2:fdae76e1215e 182 return;
dudmuck 2:fdae76e1215e 183
dudmuck 10:7382c260c4b1 184 if (m_xcvr.type == SX1276) {
dudmuck 2:fdae76e1215e 185 RegModemConfig.sx1276bits.Bw = bw;
dudmuck 10:7382c260c4b1 186 if (get_symbol_period() > 16)
dudmuck 10:7382c260c4b1 187 RegModemConfig3.sx1276bits.LowDataRateOptimize = 1;
dudmuck 10:7382c260c4b1 188 else
dudmuck 10:7382c260c4b1 189 RegModemConfig3.sx1276bits.LowDataRateOptimize = 0;
dudmuck 10:7382c260c4b1 190 m_xcvr.write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet);
dudmuck 10:7382c260c4b1 191 } else if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 192 RegModemConfig.sx1272bits.Bw = bw;
dudmuck 10:7382c260c4b1 193 if (get_symbol_period() > 16)
dudmuck 2:fdae76e1215e 194 RegModemConfig.sx1272bits.LowDataRateOptimize = 1;
dudmuck 2:fdae76e1215e 195 else
dudmuck 2:fdae76e1215e 196 RegModemConfig.sx1272bits.LowDataRateOptimize = 0;
dudmuck 2:fdae76e1215e 197 } else
dudmuck 2:fdae76e1215e 198 return;
dudmuck 2:fdae76e1215e 199
dudmuck 2:fdae76e1215e 200 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 2:fdae76e1215e 201 }
dudmuck 2:fdae76e1215e 202
dudmuck 2:fdae76e1215e 203
dudmuck 2:fdae76e1215e 204
dudmuck 2:fdae76e1215e 205 uint8_t SX127x_lora::getSf(void)
dudmuck 2:fdae76e1215e 206 {
dudmuck 2:fdae76e1215e 207 // spreading factor same between sx127[26]
dudmuck 2:fdae76e1215e 208 return RegModemConfig2.sx1276bits.SpreadingFactor;
dudmuck 2:fdae76e1215e 209 }
dudmuck 2:fdae76e1215e 210
dudmuck 2:fdae76e1215e 211 void SX127x_lora::set_nb_trig_peaks(int n)
dudmuck 2:fdae76e1215e 212 {
dudmuck 2:fdae76e1215e 213 RegTest31.bits.detect_trig_same_peaks_nb = n;
dudmuck 2:fdae76e1215e 214 m_xcvr.write_reg(REG_LR_TEST31, RegTest31.octet);
dudmuck 2:fdae76e1215e 215 }
dudmuck 2:fdae76e1215e 216
dudmuck 2:fdae76e1215e 217
dudmuck 2:fdae76e1215e 218 void SX127x_lora::setSf(uint8_t sf)
dudmuck 2:fdae76e1215e 219 {
dudmuck 2:fdae76e1215e 220 if (!m_xcvr.RegOpMode.bits.LongRangeMode)
dudmuck 2:fdae76e1215e 221 return;
dudmuck 2:fdae76e1215e 222
dudmuck 2:fdae76e1215e 223 // false detections vs missed detections tradeoff
dudmuck 2:fdae76e1215e 224 switch (sf) {
dudmuck 2:fdae76e1215e 225 case 6:
dudmuck 2:fdae76e1215e 226 set_nb_trig_peaks(3);
dudmuck 2:fdae76e1215e 227 break;
dudmuck 2:fdae76e1215e 228 case 7:
dudmuck 2:fdae76e1215e 229 set_nb_trig_peaks(4);
dudmuck 2:fdae76e1215e 230 break;
dudmuck 2:fdae76e1215e 231 default:
dudmuck 2:fdae76e1215e 232 set_nb_trig_peaks(5);
dudmuck 2:fdae76e1215e 233 break;
dudmuck 2:fdae76e1215e 234 }
dudmuck 2:fdae76e1215e 235
dudmuck 2:fdae76e1215e 236 // write register at 0x37 with value 0xc if at SF6
dudmuck 2:fdae76e1215e 237 if (sf < 7)
dudmuck 2:fdae76e1215e 238 m_xcvr.write_reg(REG_LR_DETECTION_THRESHOLD, 0x0c);
dudmuck 2:fdae76e1215e 239 else
dudmuck 2:fdae76e1215e 240 m_xcvr.write_reg(REG_LR_DETECTION_THRESHOLD, 0x0a);
dudmuck 2:fdae76e1215e 241
dudmuck 2:fdae76e1215e 242 RegModemConfig2.sx1276bits.SpreadingFactor = sf; // spreading factor same between sx127[26]
dudmuck 2:fdae76e1215e 243 m_xcvr.write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 2:fdae76e1215e 244
dudmuck 2:fdae76e1215e 245 if (m_xcvr.type == SX1272) {
dudmuck 10:7382c260c4b1 246 if (get_symbol_period() > 16)
dudmuck 2:fdae76e1215e 247 RegModemConfig.sx1272bits.LowDataRateOptimize = 1;
dudmuck 2:fdae76e1215e 248 else
dudmuck 2:fdae76e1215e 249 RegModemConfig.sx1272bits.LowDataRateOptimize = 0;
dudmuck 2:fdae76e1215e 250 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 2:fdae76e1215e 251 } else if (m_xcvr.type == SX1276) {
dudmuck 10:7382c260c4b1 252 if (get_symbol_period() > 16)
dudmuck 2:fdae76e1215e 253 RegModemConfig3.sx1276bits.LowDataRateOptimize = 1;
dudmuck 2:fdae76e1215e 254 else
dudmuck 2:fdae76e1215e 255 RegModemConfig3.sx1276bits.LowDataRateOptimize = 0;
dudmuck 2:fdae76e1215e 256 m_xcvr.write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet);
dudmuck 2:fdae76e1215e 257 }
dudmuck 2:fdae76e1215e 258 }
dudmuck 2:fdae76e1215e 259
dudmuck 2:fdae76e1215e 260
dudmuck 2:fdae76e1215e 261
dudmuck 2:fdae76e1215e 262 bool SX127x_lora::getRxPayloadCrcOn(void)
dudmuck 2:fdae76e1215e 263 {
dudmuck 2:fdae76e1215e 264 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 265 return RegModemConfig2.sx1276bits.RxPayloadCrcOn;
dudmuck 2:fdae76e1215e 266 else if (m_xcvr.type == SX1272)
dudmuck 2:fdae76e1215e 267 return RegModemConfig.sx1272bits.RxPayloadCrcOn;
dudmuck 2:fdae76e1215e 268 else
dudmuck 2:fdae76e1215e 269 return 0;
dudmuck 2:fdae76e1215e 270 }
dudmuck 2:fdae76e1215e 271
dudmuck 2:fdae76e1215e 272
dudmuck 2:fdae76e1215e 273 void SX127x_lora::setRxPayloadCrcOn(bool on)
dudmuck 2:fdae76e1215e 274 {
dudmuck 2:fdae76e1215e 275 if (m_xcvr.type == SX1276) {
dudmuck 2:fdae76e1215e 276 RegModemConfig2.sx1276bits.RxPayloadCrcOn = on;
dudmuck 2:fdae76e1215e 277 m_xcvr.write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 2:fdae76e1215e 278 } else if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 279 RegModemConfig.sx1272bits.RxPayloadCrcOn = on;
dudmuck 2:fdae76e1215e 280 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 2:fdae76e1215e 281 }
dudmuck 2:fdae76e1215e 282 }
dudmuck 2:fdae76e1215e 283
dudmuck 2:fdae76e1215e 284
dudmuck 2:fdae76e1215e 285
dudmuck 2:fdae76e1215e 286 bool SX127x_lora::getAgcAutoOn(void)
dudmuck 2:fdae76e1215e 287 {
dudmuck 2:fdae76e1215e 288 if (m_xcvr.type == SX1276) {
dudmuck 2:fdae76e1215e 289 RegModemConfig3.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG3);
dudmuck 2:fdae76e1215e 290 return RegModemConfig3.sx1276bits.AgcAutoOn;
dudmuck 2:fdae76e1215e 291 } else if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 292 RegModemConfig2.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG2);
dudmuck 2:fdae76e1215e 293 return RegModemConfig2.sx1272bits.AgcAutoOn;
dudmuck 2:fdae76e1215e 294 } else
dudmuck 2:fdae76e1215e 295 return 0;
dudmuck 2:fdae76e1215e 296 }
dudmuck 2:fdae76e1215e 297
dudmuck 2:fdae76e1215e 298 void SX127x_lora::setAgcAutoOn(bool on)
dudmuck 2:fdae76e1215e 299 {
dudmuck 2:fdae76e1215e 300 if (m_xcvr.type == SX1276) {
dudmuck 2:fdae76e1215e 301 RegModemConfig3.sx1276bits.AgcAutoOn = on;
dudmuck 2:fdae76e1215e 302 m_xcvr.write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet);
dudmuck 2:fdae76e1215e 303 } else if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 304 RegModemConfig2.sx1272bits.AgcAutoOn = on;
dudmuck 2:fdae76e1215e 305 m_xcvr.write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 2:fdae76e1215e 306 }
dudmuck 2:fdae76e1215e 307
dudmuck 2:fdae76e1215e 308 }
dudmuck 2:fdae76e1215e 309
dudmuck 2:fdae76e1215e 310 void SX127x_lora::start_tx(uint8_t len)
dudmuck 7:927a05f84ede 311 {
dudmuck 2:fdae76e1215e 312 // DIO0 to TxDone
dudmuck 2:fdae76e1215e 313 if (m_xcvr.RegDioMapping1.bits.Dio0Mapping != 1) {
dudmuck 2:fdae76e1215e 314 m_xcvr.RegDioMapping1.bits.Dio0Mapping = 1;
dudmuck 2:fdae76e1215e 315 m_xcvr.write_reg(REG_DIOMAPPING1, m_xcvr.RegDioMapping1.octet);
dudmuck 2:fdae76e1215e 316 }
dudmuck 2:fdae76e1215e 317
dudmuck 2:fdae76e1215e 318 // set FifoPtrAddr to FifoTxPtrBase
dudmuck 2:fdae76e1215e 319 m_xcvr.write_reg(REG_LR_FIFOADDRPTR, m_xcvr.read_reg(REG_LR_FIFOTXBASEADDR));
dudmuck 2:fdae76e1215e 320
dudmuck 2:fdae76e1215e 321 // write PayloadLength bytes to fifo
dudmuck 2:fdae76e1215e 322 write_fifo(len);
dudmuck 7:927a05f84ede 323
dudmuck 2:fdae76e1215e 324 m_xcvr.set_opmode(RF_OPMODE_TRANSMITTER);
dudmuck 2:fdae76e1215e 325 }
dudmuck 2:fdae76e1215e 326
dudmuck 2:fdae76e1215e 327 void SX127x_lora::start_rx()
dudmuck 2:fdae76e1215e 328 {
dudmuck 2:fdae76e1215e 329 if (!m_xcvr.RegOpMode.bits.LongRangeMode)
dudmuck 2:fdae76e1215e 330 return;
dudmuck 2:fdae76e1215e 331
dudmuck 2:fdae76e1215e 332 if (m_xcvr.RegDioMapping1.bits.Dio0Mapping != 0) {
dudmuck 2:fdae76e1215e 333 m_xcvr.RegDioMapping1.bits.Dio0Mapping = 0; // DIO0 to RxDone
dudmuck 2:fdae76e1215e 334 m_xcvr.write_reg(REG_DIOMAPPING1, m_xcvr.RegDioMapping1.octet);
dudmuck 2:fdae76e1215e 335 }
dudmuck 2:fdae76e1215e 336
dudmuck 2:fdae76e1215e 337 m_xcvr.write_reg(REG_LR_FIFOADDRPTR, m_xcvr.read_reg(REG_LR_FIFORXBASEADDR));
dudmuck 7:927a05f84ede 338
dudmuck 2:fdae76e1215e 339 m_xcvr.set_opmode(RF_OPMODE_RECEIVER);
dudmuck 2:fdae76e1215e 340 }
dudmuck 2:fdae76e1215e 341
dudmuck 2:fdae76e1215e 342 float SX127x_lora::get_pkt_rssi()
dudmuck 2:fdae76e1215e 343 {
dudmuck 2:fdae76e1215e 344 /* TODO: calculating with pktSNR to give meaningful result below noise floor */
dudmuck 2:fdae76e1215e 345 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 346 return RegPktRssiValue - 137;
dudmuck 2:fdae76e1215e 347 else
dudmuck 2:fdae76e1215e 348 return RegPktRssiValue - 125;
dudmuck 2:fdae76e1215e 349 }
dudmuck 2:fdae76e1215e 350
dudmuck 2:fdae76e1215e 351 service_action_e SX127x_lora::service()
dudmuck 2:fdae76e1215e 352 {
dudmuck 2:fdae76e1215e 353 if (m_xcvr.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER) {
dudmuck 2:fdae76e1215e 354 if (poll_vh) {
dudmuck 2:fdae76e1215e 355 RegIrqFlags.octet = m_xcvr.read_reg(REG_LR_IRQFLAGS);
dudmuck 2:fdae76e1215e 356 if (RegIrqFlags.bits.ValidHeader) {
dudmuck 2:fdae76e1215e 357 RegIrqFlags.octet = 0;
dudmuck 2:fdae76e1215e 358 RegIrqFlags.bits.ValidHeader = 1;
dudmuck 2:fdae76e1215e 359 m_xcvr.write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet);
dudmuck 2:fdae76e1215e 360 printf("VH\r\n");
dudmuck 2:fdae76e1215e 361 }
dudmuck 2:fdae76e1215e 362 }
dudmuck 2:fdae76e1215e 363 }
dudmuck 7:927a05f84ede 364
dudmuck 2:fdae76e1215e 365 if (m_xcvr.dio0 == 0)
dudmuck 2:fdae76e1215e 366 return SERVICE_NONE;
dudmuck 2:fdae76e1215e 367
dudmuck 2:fdae76e1215e 368 switch (m_xcvr.RegDioMapping1.bits.Dio0Mapping) {
dudmuck 2:fdae76e1215e 369 case 0: // RxDone
dudmuck 2:fdae76e1215e 370 /* user checks for CRC error in IrqFlags */
dudmuck 2:fdae76e1215e 371 RegIrqFlags.octet = m_xcvr.read_reg(REG_LR_IRQFLAGS); // save flags
dudmuck 2:fdae76e1215e 372 RegHopChannel.octet = m_xcvr.read_reg(REG_LR_HOPCHANNEL);
dudmuck 2:fdae76e1215e 373 //printf("[%02x]", RegIrqFlags.octet);
dudmuck 2:fdae76e1215e 374 m_xcvr.write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet); // clear flags in radio
dudmuck 2:fdae76e1215e 375
dudmuck 2:fdae76e1215e 376 /* any register of interest on received packet is read(saved) here */
dudmuck 2:fdae76e1215e 377 RegModemStatus.octet = m_xcvr.read_reg(REG_LR_MODEMSTAT);
dudmuck 2:fdae76e1215e 378 RegPktSnrValue = m_xcvr.read_reg(REG_LR_PKTSNRVALUE);
dudmuck 2:fdae76e1215e 379 RegPktRssiValue = m_xcvr.read_reg(REG_LR_PKTRSSIVALUE);
dudmuck 2:fdae76e1215e 380 RegRxNbBytes = m_xcvr.read_reg(REG_LR_RXNBBYTES);
dudmuck 2:fdae76e1215e 381
dudmuck 2:fdae76e1215e 382 m_xcvr.write_reg(REG_LR_FIFOADDRPTR, m_xcvr.read_reg(REG_LR_FIFORXCURRENTADDR));
dudmuck 2:fdae76e1215e 383 read_fifo(RegRxNbBytes);
dudmuck 2:fdae76e1215e 384 return SERVICE_READ_FIFO;
dudmuck 2:fdae76e1215e 385 case 1: // TxDone
dudmuck 2:fdae76e1215e 386 RegIrqFlags.octet = 0;
dudmuck 2:fdae76e1215e 387 RegIrqFlags.bits.TxDone = 1;
dudmuck 2:fdae76e1215e 388 m_xcvr.write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet);
dudmuck 2:fdae76e1215e 389 return SERVICE_TX_DONE;
dudmuck 2:fdae76e1215e 390 } // ...switch (RegDioMapping1.bits.Dio0Mapping)
dudmuck 2:fdae76e1215e 391
dudmuck 2:fdae76e1215e 392 return SERVICE_ERROR;
dudmuck 2:fdae76e1215e 393 }