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:
Wed Mar 26 00:56:09 2014 +0000
Revision:
0:27aa8733f85d
Child:
1:7dc60eb4c7ec
initial commit of library driver for SX1272/SX1276

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dudmuck 0:27aa8733f85d 1 #include "sx127x.h"
dudmuck 0:27aa8733f85d 2
dudmuck 0:27aa8733f85d 3 /* SX127x driver
dudmuck 0:27aa8733f85d 4 * Copyright (c) 2013 Semtech
dudmuck 0:27aa8733f85d 5 *
dudmuck 0:27aa8733f85d 6 * Licensed under the Apache License, Version 2.0 (the "License");
dudmuck 0:27aa8733f85d 7 * you may not use this file except in compliance with the License.
dudmuck 0:27aa8733f85d 8 * You may obtain a copy of the License at
dudmuck 0:27aa8733f85d 9 *
dudmuck 0:27aa8733f85d 10 * http://www.apache.org/licenses/LICENSE-2.0
dudmuck 0:27aa8733f85d 11 *
dudmuck 0:27aa8733f85d 12 * Unless required by applicable law or agreed to in writing, software
dudmuck 0:27aa8733f85d 13 * distributed under the License is distributed on an "AS IS" BASIS,
dudmuck 0:27aa8733f85d 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dudmuck 0:27aa8733f85d 15 * See the License for the specific language governing permissions and
dudmuck 0:27aa8733f85d 16 * limitations under the License.
dudmuck 0:27aa8733f85d 17 */
dudmuck 0:27aa8733f85d 18
dudmuck 0:27aa8733f85d 19 SX127x::SX127x(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rst, PinName dio_0, PinName dio_1, PinName fem_ctx, PinName fem_cps) :
dudmuck 0:27aa8733f85d 20 m_spi(mosi, miso, sclk), m_cs(cs), reset_pin(rst), dio0(dio_0), dio1(dio_1), femctx(fem_ctx), femcps(fem_cps)
dudmuck 0:27aa8733f85d 21 {
dudmuck 0:27aa8733f85d 22 reset_pin.input();
dudmuck 0:27aa8733f85d 23 m_cs = 1;
dudmuck 0:27aa8733f85d 24 m_spi.format(8, 0);
dudmuck 0:27aa8733f85d 25 m_spi.frequency(1000000);
dudmuck 0:27aa8733f85d 26
dudmuck 0:27aa8733f85d 27 init();
dudmuck 0:27aa8733f85d 28 }
dudmuck 0:27aa8733f85d 29
dudmuck 0:27aa8733f85d 30 SX127x::~SX127x()
dudmuck 0:27aa8733f85d 31 {
dudmuck 0:27aa8733f85d 32 set_opmode(RF_OPMODE_SLEEP);
dudmuck 0:27aa8733f85d 33 }
dudmuck 0:27aa8733f85d 34
dudmuck 0:27aa8733f85d 35 void SX127x::init()
dudmuck 0:27aa8733f85d 36 {
dudmuck 0:27aa8733f85d 37 type = SX_NONE;
dudmuck 0:27aa8733f85d 38
dudmuck 0:27aa8733f85d 39 RegOpMode.octet = read_reg(REG_OPMODE);
dudmuck 0:27aa8733f85d 40 RegPaConfig.octet = read_reg(REG_PACONFIG);
dudmuck 0:27aa8733f85d 41 RegLna.octet = read_reg(REG_LNA);
dudmuck 0:27aa8733f85d 42 RegDioMapping1.octet = read_reg(REG_DIOMAPPING1);
dudmuck 0:27aa8733f85d 43 RegDioMapping2.octet = read_reg(REG_DIOMAPPING2);
dudmuck 0:27aa8733f85d 44
dudmuck 0:27aa8733f85d 45 if (!RegOpMode.bits.LongRangeMode) {
dudmuck 0:27aa8733f85d 46 if (RegOpMode.bits.Mode != RF_OPMODE_SLEEP)
dudmuck 0:27aa8733f85d 47 set_opmode(RF_OPMODE_SLEEP);
dudmuck 0:27aa8733f85d 48 RegOpMode.bits.LongRangeMode = 1;
dudmuck 0:27aa8733f85d 49 write_reg(REG_OPMODE, RegOpMode.octet);
dudmuck 0:27aa8733f85d 50 }
dudmuck 0:27aa8733f85d 51
dudmuck 0:27aa8733f85d 52 RegModemConfig.octet = read_reg(REG_LR_MODEMCONFIG);
dudmuck 0:27aa8733f85d 53 RegModemConfig2.octet = read_reg(REG_LR_MODEMCONFIG2);
dudmuck 0:27aa8733f85d 54 RegTest31.octet = read_reg(REG_LR_TEST31);
dudmuck 0:27aa8733f85d 55
dudmuck 0:27aa8733f85d 56 get_type();
dudmuck 0:27aa8733f85d 57
dudmuck 0:27aa8733f85d 58 // turn on PA BOOST, eval boards are wired for this connection
dudmuck 0:27aa8733f85d 59 RegPaConfig.bits.PaSelect = 1;
dudmuck 0:27aa8733f85d 60 write_reg(REG_PACONFIG, RegPaConfig.octet);
dudmuck 0:27aa8733f85d 61
dudmuck 0:27aa8733f85d 62 // CRC for TX is disabled by default
dudmuck 0:27aa8733f85d 63 setRxPayloadCrcOn(true);
dudmuck 0:27aa8733f85d 64 }
dudmuck 0:27aa8733f85d 65
dudmuck 0:27aa8733f85d 66 void SX127x::get_type()
dudmuck 0:27aa8733f85d 67 {
dudmuck 0:27aa8733f85d 68 RegOpMode.octet = read_reg(REG_OPMODE);
dudmuck 0:27aa8733f85d 69 if (RegOpMode.sx1276LORAbits.LowFrequencyModeOn)
dudmuck 0:27aa8733f85d 70 type = SX1276;
dudmuck 0:27aa8733f85d 71 else {
dudmuck 0:27aa8733f85d 72 RegOpMode.sx1276LORAbits.LowFrequencyModeOn = 1;
dudmuck 0:27aa8733f85d 73 write_reg(REG_OPMODE, RegOpMode.octet);
dudmuck 0:27aa8733f85d 74 RegOpMode.octet = read_reg(REG_OPMODE);
dudmuck 0:27aa8733f85d 75 if (RegOpMode.sx1276LORAbits.LowFrequencyModeOn)
dudmuck 0:27aa8733f85d 76 type = SX1276;
dudmuck 0:27aa8733f85d 77 else
dudmuck 0:27aa8733f85d 78 type = SX1272;
dudmuck 0:27aa8733f85d 79 }
dudmuck 0:27aa8733f85d 80 }
dudmuck 0:27aa8733f85d 81 uint8_t SX127x::read_reg(uint8_t addr)
dudmuck 0:27aa8733f85d 82 {
dudmuck 0:27aa8733f85d 83 uint8_t ret;
dudmuck 0:27aa8733f85d 84 // Select the device by seting chip select low
dudmuck 0:27aa8733f85d 85 m_cs = 0;
dudmuck 0:27aa8733f85d 86
dudmuck 0:27aa8733f85d 87 m_spi.write(addr); // bit7 is low for reading from radio
dudmuck 0:27aa8733f85d 88
dudmuck 0:27aa8733f85d 89 // Send a dummy byte to receive the contents of register
dudmuck 0:27aa8733f85d 90 ret = m_spi.write(0x00);
dudmuck 0:27aa8733f85d 91
dudmuck 0:27aa8733f85d 92 // Deselect the device
dudmuck 0:27aa8733f85d 93 m_cs = 1;
dudmuck 0:27aa8733f85d 94
dudmuck 0:27aa8733f85d 95 return ret;
dudmuck 0:27aa8733f85d 96 }
dudmuck 0:27aa8733f85d 97
dudmuck 0:27aa8733f85d 98 uint16_t SX127x::read_u16(uint8_t addr)
dudmuck 0:27aa8733f85d 99 {
dudmuck 0:27aa8733f85d 100 uint16_t ret;
dudmuck 0:27aa8733f85d 101 // Select the device by seting chip select low
dudmuck 0:27aa8733f85d 102 m_cs = 0;
dudmuck 0:27aa8733f85d 103
dudmuck 0:27aa8733f85d 104 m_spi.write(addr); // bit7 is low for reading from radio
dudmuck 0:27aa8733f85d 105
dudmuck 0:27aa8733f85d 106 // Send a dummy byte to receive the contents of register
dudmuck 0:27aa8733f85d 107 ret = m_spi.write(0x00);
dudmuck 0:27aa8733f85d 108 ret <<= 8;
dudmuck 0:27aa8733f85d 109 ret += m_spi.write(0x00);
dudmuck 0:27aa8733f85d 110
dudmuck 0:27aa8733f85d 111 // Deselect the device
dudmuck 0:27aa8733f85d 112 m_cs = 1;
dudmuck 0:27aa8733f85d 113
dudmuck 0:27aa8733f85d 114 return ret;
dudmuck 0:27aa8733f85d 115 }
dudmuck 0:27aa8733f85d 116
dudmuck 0:27aa8733f85d 117 void SX127x::write_reg_u24(uint8_t addr, uint32_t data)
dudmuck 0:27aa8733f85d 118 {
dudmuck 0:27aa8733f85d 119 m_cs = 0; // Select the device by seting chip select low
dudmuck 0:27aa8733f85d 120
dudmuck 0:27aa8733f85d 121 m_spi.write(addr | 0x80); // bit7 is high for writing to radio
dudmuck 0:27aa8733f85d 122 m_spi.write((data >> 16) & 0xff);
dudmuck 0:27aa8733f85d 123 m_spi.write((data >> 8) & 0xff);
dudmuck 0:27aa8733f85d 124 m_spi.write(data & 0xff);
dudmuck 0:27aa8733f85d 125
dudmuck 0:27aa8733f85d 126 m_cs = 1; // Deselect the device
dudmuck 0:27aa8733f85d 127
dudmuck 0:27aa8733f85d 128 if (addr == REG_FRFMSB) {
dudmuck 0:27aa8733f85d 129 if (data < 0x8340000) // < 525MHz
dudmuck 0:27aa8733f85d 130 HF = false;
dudmuck 0:27aa8733f85d 131 else
dudmuck 0:27aa8733f85d 132 HF = true;
dudmuck 0:27aa8733f85d 133 }
dudmuck 0:27aa8733f85d 134 }
dudmuck 0:27aa8733f85d 135
dudmuck 0:27aa8733f85d 136 void SX127x::write_reg(uint8_t addr, uint8_t data)
dudmuck 0:27aa8733f85d 137 {
dudmuck 0:27aa8733f85d 138 m_cs = 0; // Select the device by seting chip select low
dudmuck 0:27aa8733f85d 139
dudmuck 0:27aa8733f85d 140 m_spi.write(addr | 0x80); // bit7 is high for writing to radio
dudmuck 0:27aa8733f85d 141 m_spi.write(data);
dudmuck 0:27aa8733f85d 142
dudmuck 0:27aa8733f85d 143 m_cs = 1; // Deselect the device
dudmuck 0:27aa8733f85d 144 }
dudmuck 0:27aa8733f85d 145
dudmuck 0:27aa8733f85d 146 void SX127x::lora_write_fifo(uint8_t len)
dudmuck 0:27aa8733f85d 147 {
dudmuck 0:27aa8733f85d 148 int i;
dudmuck 0:27aa8733f85d 149
dudmuck 0:27aa8733f85d 150 m_cs = 0;
dudmuck 0:27aa8733f85d 151 m_spi.write(REG_FIFO | 0x80); // bit7 is high for writing to radio
dudmuck 0:27aa8733f85d 152 for (i = 0; i < len; i++) {
dudmuck 0:27aa8733f85d 153 m_spi.write(tx_buf[i]);
dudmuck 0:27aa8733f85d 154 }
dudmuck 0:27aa8733f85d 155 m_cs = 1;
dudmuck 0:27aa8733f85d 156 }
dudmuck 0:27aa8733f85d 157
dudmuck 0:27aa8733f85d 158 void SX127x::lora_read_fifo(uint8_t len)
dudmuck 0:27aa8733f85d 159 {
dudmuck 0:27aa8733f85d 160 int i;
dudmuck 0:27aa8733f85d 161
dudmuck 0:27aa8733f85d 162 m_cs = 0;
dudmuck 0:27aa8733f85d 163 m_spi.write(REG_FIFO); // bit7 is low for reading from radio
dudmuck 0:27aa8733f85d 164 for (i = 0; i < len; i++) {
dudmuck 0:27aa8733f85d 165 rx_buf[i] = m_spi.write(0);
dudmuck 0:27aa8733f85d 166 }
dudmuck 0:27aa8733f85d 167 m_cs = 1;
dudmuck 0:27aa8733f85d 168 }
dudmuck 0:27aa8733f85d 169
dudmuck 0:27aa8733f85d 170 void SX127x::set_opmode(chip_mode_e mode)
dudmuck 0:27aa8733f85d 171 {
dudmuck 0:27aa8733f85d 172 RegOpMode.bits.Mode = mode;
dudmuck 0:27aa8733f85d 173 write_reg(REG_OPMODE, RegOpMode.octet);
dudmuck 0:27aa8733f85d 174 }
dudmuck 0:27aa8733f85d 175
dudmuck 0:27aa8733f85d 176 void SX127x::set_frf_MHz( float MHz )
dudmuck 0:27aa8733f85d 177 {
dudmuck 0:27aa8733f85d 178 uint32_t frf;
dudmuck 0:27aa8733f85d 179
dudmuck 0:27aa8733f85d 180 frf = MHz / FREQ_STEP_MHZ;
dudmuck 0:27aa8733f85d 181 write_reg_u24(REG_FRFMSB, frf);
dudmuck 0:27aa8733f85d 182
dudmuck 0:27aa8733f85d 183 if (MHz < 525)
dudmuck 0:27aa8733f85d 184 HF = false;
dudmuck 0:27aa8733f85d 185 else
dudmuck 0:27aa8733f85d 186 HF = true;
dudmuck 0:27aa8733f85d 187 }
dudmuck 0:27aa8733f85d 188
dudmuck 0:27aa8733f85d 189 float SX127x::get_frf_MHz(void)
dudmuck 0:27aa8733f85d 190 {
dudmuck 0:27aa8733f85d 191 uint32_t frf;
dudmuck 0:27aa8733f85d 192 uint8_t lsb, mid, msb;
dudmuck 0:27aa8733f85d 193 float MHz;
dudmuck 0:27aa8733f85d 194
dudmuck 0:27aa8733f85d 195 msb = read_reg(REG_FRFMSB);
dudmuck 0:27aa8733f85d 196 mid = read_reg(REG_FRFMID);
dudmuck 0:27aa8733f85d 197 lsb = read_reg(REG_FRFLSB);
dudmuck 0:27aa8733f85d 198 frf = msb;
dudmuck 0:27aa8733f85d 199 frf <<= 8;
dudmuck 0:27aa8733f85d 200 frf += mid;
dudmuck 0:27aa8733f85d 201 frf <<= 8;
dudmuck 0:27aa8733f85d 202 frf += lsb;
dudmuck 0:27aa8733f85d 203
dudmuck 0:27aa8733f85d 204 MHz = frf * FREQ_STEP_MHZ;
dudmuck 0:27aa8733f85d 205
dudmuck 0:27aa8733f85d 206 if (MHz < 525)
dudmuck 0:27aa8733f85d 207 HF = false;
dudmuck 0:27aa8733f85d 208 else
dudmuck 0:27aa8733f85d 209 HF = true;
dudmuck 0:27aa8733f85d 210
dudmuck 0:27aa8733f85d 211 return MHz;
dudmuck 0:27aa8733f85d 212 }
dudmuck 0:27aa8733f85d 213
dudmuck 0:27aa8733f85d 214 uint8_t SX127x::getCodingRate(bool from_rx)
dudmuck 0:27aa8733f85d 215 {
dudmuck 0:27aa8733f85d 216 if (from_rx) {
dudmuck 0:27aa8733f85d 217 // expected RegModemStatus was read on RxDone interrupt
dudmuck 0:27aa8733f85d 218 return RegModemStatus.bits.RxCodingRate;
dudmuck 0:27aa8733f85d 219 } else { // transmitted coding rate...
dudmuck 0:27aa8733f85d 220 if (type == SX1276)
dudmuck 0:27aa8733f85d 221 return RegModemConfig.sx1276bits.CodingRate;
dudmuck 0:27aa8733f85d 222 else if (type == SX1272)
dudmuck 0:27aa8733f85d 223 return RegModemConfig.sx1272bits.CodingRate;
dudmuck 0:27aa8733f85d 224 else
dudmuck 0:27aa8733f85d 225 return 0;
dudmuck 0:27aa8733f85d 226 }
dudmuck 0:27aa8733f85d 227 }
dudmuck 0:27aa8733f85d 228
dudmuck 0:27aa8733f85d 229 void SX127x::setCodingRate(uint8_t cr)
dudmuck 0:27aa8733f85d 230 {
dudmuck 0:27aa8733f85d 231 if (type == SX1276)
dudmuck 0:27aa8733f85d 232 RegModemConfig.sx1276bits.CodingRate = cr;
dudmuck 0:27aa8733f85d 233 else if (type == SX1272)
dudmuck 0:27aa8733f85d 234 RegModemConfig.sx1272bits.CodingRate = cr;
dudmuck 0:27aa8733f85d 235 else
dudmuck 0:27aa8733f85d 236 return;
dudmuck 0:27aa8733f85d 237
dudmuck 0:27aa8733f85d 238 write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 0:27aa8733f85d 239 }
dudmuck 0:27aa8733f85d 240
dudmuck 0:27aa8733f85d 241 bool SX127x::getHeaderMode(void)
dudmuck 0:27aa8733f85d 242 {
dudmuck 0:27aa8733f85d 243 if (type == SX1276)
dudmuck 0:27aa8733f85d 244 return RegModemConfig.sx1276bits.ImplicitHeaderModeOn;
dudmuck 0:27aa8733f85d 245 else if (type == SX1272)
dudmuck 0:27aa8733f85d 246 return RegModemConfig.sx1272bits.ImplicitHeaderModeOn;
dudmuck 0:27aa8733f85d 247 else
dudmuck 0:27aa8733f85d 248 return false;
dudmuck 0:27aa8733f85d 249 }
dudmuck 0:27aa8733f85d 250
dudmuck 0:27aa8733f85d 251 void SX127x::setHeaderMode(bool hm)
dudmuck 0:27aa8733f85d 252 {
dudmuck 0:27aa8733f85d 253 if (type == SX1276)
dudmuck 0:27aa8733f85d 254 RegModemConfig.sx1276bits.ImplicitHeaderModeOn = hm;
dudmuck 0:27aa8733f85d 255 else if (type == SX1272)
dudmuck 0:27aa8733f85d 256 RegModemConfig.sx1272bits.ImplicitHeaderModeOn = hm;
dudmuck 0:27aa8733f85d 257 else
dudmuck 0:27aa8733f85d 258 return;
dudmuck 0:27aa8733f85d 259
dudmuck 0:27aa8733f85d 260 write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 0:27aa8733f85d 261 }
dudmuck 0:27aa8733f85d 262
dudmuck 0:27aa8733f85d 263 uint8_t SX127x::getBw(void)
dudmuck 0:27aa8733f85d 264 {
dudmuck 0:27aa8733f85d 265 if (type == SX1276)
dudmuck 0:27aa8733f85d 266 return RegModemConfig.sx1276bits.Bw;
dudmuck 0:27aa8733f85d 267 else if (type == SX1272)
dudmuck 0:27aa8733f85d 268 return RegModemConfig.sx1272bits.Bw;
dudmuck 0:27aa8733f85d 269 else
dudmuck 0:27aa8733f85d 270 return 0;
dudmuck 0:27aa8733f85d 271 }
dudmuck 0:27aa8733f85d 272
dudmuck 0:27aa8733f85d 273 void SX127x::setBw(uint8_t bw)
dudmuck 0:27aa8733f85d 274 {
dudmuck 0:27aa8733f85d 275 if (type == SX1276)
dudmuck 0:27aa8733f85d 276 RegModemConfig.sx1276bits.Bw = bw;
dudmuck 0:27aa8733f85d 277 else if (type == SX1272) {
dudmuck 0:27aa8733f85d 278 RegModemConfig.sx1272bits.Bw = bw;
dudmuck 0:27aa8733f85d 279 if (RegModemConfig2.sx1272bits.SpreadingFactor > 10)
dudmuck 0:27aa8733f85d 280 RegModemConfig.sx1272bits.LowDataRateOptimize = 1;
dudmuck 0:27aa8733f85d 281 else
dudmuck 0:27aa8733f85d 282 RegModemConfig.sx1272bits.LowDataRateOptimize = 0;
dudmuck 0:27aa8733f85d 283 } else
dudmuck 0:27aa8733f85d 284 return;
dudmuck 0:27aa8733f85d 285
dudmuck 0:27aa8733f85d 286 write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 0:27aa8733f85d 287 }
dudmuck 0:27aa8733f85d 288
dudmuck 0:27aa8733f85d 289 uint8_t SX127x::getSf(void)
dudmuck 0:27aa8733f85d 290 {
dudmuck 0:27aa8733f85d 291 // spreading factor same between sx127[26]
dudmuck 0:27aa8733f85d 292 return RegModemConfig2.sx1276bits.SpreadingFactor;
dudmuck 0:27aa8733f85d 293 }
dudmuck 0:27aa8733f85d 294
dudmuck 0:27aa8733f85d 295 void SX127x::set_nb_trig_peaks(int n)
dudmuck 0:27aa8733f85d 296 {
dudmuck 0:27aa8733f85d 297 RegTest31.bits.detect_trig_same_peaks_nb = n;
dudmuck 0:27aa8733f85d 298 write_reg(REG_LR_TEST31, RegTest31.octet);
dudmuck 0:27aa8733f85d 299 }
dudmuck 0:27aa8733f85d 300
dudmuck 0:27aa8733f85d 301 void SX127x::setSf(uint8_t sf)
dudmuck 0:27aa8733f85d 302 {
dudmuck 0:27aa8733f85d 303 // false detections vs missed detections tradeoff
dudmuck 0:27aa8733f85d 304 switch (sf) {
dudmuck 0:27aa8733f85d 305 case 6:
dudmuck 0:27aa8733f85d 306 set_nb_trig_peaks(3);
dudmuck 0:27aa8733f85d 307 break;
dudmuck 0:27aa8733f85d 308 case 7:
dudmuck 0:27aa8733f85d 309 set_nb_trig_peaks(4);
dudmuck 0:27aa8733f85d 310 break;
dudmuck 0:27aa8733f85d 311 default:
dudmuck 0:27aa8733f85d 312 set_nb_trig_peaks(5);
dudmuck 0:27aa8733f85d 313 break;
dudmuck 0:27aa8733f85d 314 }
dudmuck 0:27aa8733f85d 315
dudmuck 0:27aa8733f85d 316 // write register at 0x37 with value 0xc if at SF6
dudmuck 0:27aa8733f85d 317 if (sf < 7)
dudmuck 0:27aa8733f85d 318 write_reg(REG_LR_DETECTION_THRESHOLD, 0x0c);
dudmuck 0:27aa8733f85d 319 else
dudmuck 0:27aa8733f85d 320 write_reg(REG_LR_DETECTION_THRESHOLD, 0x0a);
dudmuck 0:27aa8733f85d 321
dudmuck 0:27aa8733f85d 322 RegModemConfig2.sx1276bits.SpreadingFactor = sf; // spreading factor same between sx127[26]
dudmuck 0:27aa8733f85d 323 write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 0:27aa8733f85d 324
dudmuck 0:27aa8733f85d 325 if (type == SX1272) {
dudmuck 0:27aa8733f85d 326 if (sf > 10 && RegModemConfig.sx1272bits.Bw == 0) // if bw=125KHz and sf11 or sf12
dudmuck 0:27aa8733f85d 327 RegModemConfig.sx1272bits.LowDataRateOptimize = 1;
dudmuck 0:27aa8733f85d 328 else
dudmuck 0:27aa8733f85d 329 RegModemConfig.sx1272bits.LowDataRateOptimize = 0;
dudmuck 0:27aa8733f85d 330 write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 0:27aa8733f85d 331 } else if (type == SX1276) {
dudmuck 0:27aa8733f85d 332 if (sf > 10 && RegModemConfig.sx1272bits.Bw == 0) // if bw=125KHz and sf11 or sf12
dudmuck 0:27aa8733f85d 333 RegModemConfig3.sx1276bits.LowDataRateOptimize = 1;
dudmuck 0:27aa8733f85d 334 else
dudmuck 0:27aa8733f85d 335 RegModemConfig3.sx1276bits.LowDataRateOptimize = 0;
dudmuck 0:27aa8733f85d 336 write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet);
dudmuck 0:27aa8733f85d 337 }
dudmuck 0:27aa8733f85d 338 }
dudmuck 0:27aa8733f85d 339
dudmuck 0:27aa8733f85d 340 bool SX127x::getRxPayloadCrcOn(void)
dudmuck 0:27aa8733f85d 341 {
dudmuck 0:27aa8733f85d 342 if (type == SX1276)
dudmuck 0:27aa8733f85d 343 return RegModemConfig2.sx1276bits.RxPayloadCrcOn;
dudmuck 0:27aa8733f85d 344 else if (type == SX1272)
dudmuck 0:27aa8733f85d 345 return RegModemConfig.sx1272bits.RxPayloadCrcOn;
dudmuck 0:27aa8733f85d 346 else
dudmuck 0:27aa8733f85d 347 return 0;
dudmuck 0:27aa8733f85d 348 }
dudmuck 0:27aa8733f85d 349
dudmuck 0:27aa8733f85d 350 void SX127x::setRxPayloadCrcOn(bool on)
dudmuck 0:27aa8733f85d 351 {
dudmuck 0:27aa8733f85d 352 if (type == SX1276) {
dudmuck 0:27aa8733f85d 353 RegModemConfig2.sx1276bits.RxPayloadCrcOn = on;
dudmuck 0:27aa8733f85d 354 write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 0:27aa8733f85d 355 } else if (type == SX1272) {
dudmuck 0:27aa8733f85d 356 RegModemConfig.sx1272bits.RxPayloadCrcOn = on;
dudmuck 0:27aa8733f85d 357 write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 0:27aa8733f85d 358 }
dudmuck 0:27aa8733f85d 359 }
dudmuck 0:27aa8733f85d 360
dudmuck 0:27aa8733f85d 361 bool SX127x::getAgcAutoOn(void)
dudmuck 0:27aa8733f85d 362 {
dudmuck 0:27aa8733f85d 363 if (type == SX1276) {
dudmuck 0:27aa8733f85d 364 RegModemConfig3.octet = read_reg(REG_LR_MODEMCONFIG3);
dudmuck 0:27aa8733f85d 365 return RegModemConfig3.sx1276bits.AgcAutoOn;
dudmuck 0:27aa8733f85d 366 } else if (type == SX1272) {
dudmuck 0:27aa8733f85d 367 RegModemConfig2.octet = read_reg(REG_LR_MODEMCONFIG2);
dudmuck 0:27aa8733f85d 368 return RegModemConfig2.sx1272bits.AgcAutoOn;
dudmuck 0:27aa8733f85d 369 } else
dudmuck 0:27aa8733f85d 370 return 0;
dudmuck 0:27aa8733f85d 371 }
dudmuck 0:27aa8733f85d 372
dudmuck 0:27aa8733f85d 373 void SX127x::setAgcAutoOn(bool on)
dudmuck 0:27aa8733f85d 374 {
dudmuck 0:27aa8733f85d 375 if (type == SX1276) {
dudmuck 0:27aa8733f85d 376 RegModemConfig3.sx1276bits.AgcAutoOn = on;
dudmuck 0:27aa8733f85d 377 write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet);
dudmuck 0:27aa8733f85d 378 } else if (type == SX1272) {
dudmuck 0:27aa8733f85d 379 RegModemConfig2.sx1272bits.AgcAutoOn = on;
dudmuck 0:27aa8733f85d 380 write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 0:27aa8733f85d 381 }
dudmuck 0:27aa8733f85d 382
dudmuck 0:27aa8733f85d 383 }
dudmuck 0:27aa8733f85d 384
dudmuck 0:27aa8733f85d 385 void SX127x::lora_start_tx(uint8_t len)
dudmuck 0:27aa8733f85d 386 {
dudmuck 0:27aa8733f85d 387 if (type == SX1276) {
dudmuck 0:27aa8733f85d 388 // PA_BOOST on LF, RFO on HF
dudmuck 0:27aa8733f85d 389 if (HF) {
dudmuck 0:27aa8733f85d 390 if (RegPaConfig.bits.PaSelect) {
dudmuck 0:27aa8733f85d 391 RegPaConfig.bits.PaSelect = 0;
dudmuck 0:27aa8733f85d 392 write_reg(REG_PACONFIG, RegPaConfig.octet);
dudmuck 0:27aa8733f85d 393 }
dudmuck 0:27aa8733f85d 394 } else { // LF...
dudmuck 0:27aa8733f85d 395 if (!RegPaConfig.bits.PaSelect) {
dudmuck 0:27aa8733f85d 396 RegPaConfig.bits.PaSelect = 1;
dudmuck 0:27aa8733f85d 397 write_reg(REG_PACONFIG, RegPaConfig.octet);
dudmuck 0:27aa8733f85d 398 }
dudmuck 0:27aa8733f85d 399 }
dudmuck 0:27aa8733f85d 400 } else if (type == SX1272) {
dudmuck 0:27aa8733f85d 401 // always PA_BOOST
dudmuck 0:27aa8733f85d 402 if (!RegPaConfig.bits.PaSelect) {
dudmuck 0:27aa8733f85d 403 RegPaConfig.bits.PaSelect = 1;
dudmuck 0:27aa8733f85d 404 write_reg(REG_PACONFIG, RegPaConfig.octet);
dudmuck 0:27aa8733f85d 405 }
dudmuck 0:27aa8733f85d 406 }
dudmuck 0:27aa8733f85d 407
dudmuck 0:27aa8733f85d 408
dudmuck 0:27aa8733f85d 409 // DIO0 to TxDone
dudmuck 0:27aa8733f85d 410 if (RegDioMapping1.bits.Dio0Mapping != 1) {
dudmuck 0:27aa8733f85d 411 RegDioMapping1.bits.Dio0Mapping = 1;
dudmuck 0:27aa8733f85d 412 write_reg(REG_DIOMAPPING1, RegDioMapping1.octet);
dudmuck 0:27aa8733f85d 413 }
dudmuck 0:27aa8733f85d 414
dudmuck 0:27aa8733f85d 415 // set FifoPtrAddr to FifoTxPtrBase
dudmuck 0:27aa8733f85d 416 write_reg(REG_LR_FIFOADDRPTR, read_reg(REG_LR_FIFOTXBASEADDR));
dudmuck 0:27aa8733f85d 417
dudmuck 0:27aa8733f85d 418 // write PayloadLength bytes to fifo
dudmuck 0:27aa8733f85d 419 lora_write_fifo(len);
dudmuck 0:27aa8733f85d 420
dudmuck 0:27aa8733f85d 421 if (HF)
dudmuck 0:27aa8733f85d 422 femctx = 1;
dudmuck 0:27aa8733f85d 423 else
dudmuck 0:27aa8733f85d 424 femcps = 0;
dudmuck 0:27aa8733f85d 425
dudmuck 0:27aa8733f85d 426 // radio doesnt provide FhssChangeChannel with channel=0 for TX
dudmuck 0:27aa8733f85d 427 if (RegHopPeriod > 0)
dudmuck 0:27aa8733f85d 428 write_reg_u24(REG_FRFMSB, frfs[0]);
dudmuck 0:27aa8733f85d 429
dudmuck 0:27aa8733f85d 430 set_opmode(RF_OPMODE_TRANSMITTER);
dudmuck 0:27aa8733f85d 431 }
dudmuck 0:27aa8733f85d 432
dudmuck 0:27aa8733f85d 433
dudmuck 0:27aa8733f85d 434
dudmuck 0:27aa8733f85d 435 void SX127x::lora_start_rx()
dudmuck 0:27aa8733f85d 436 {
dudmuck 0:27aa8733f85d 437 if (HF)
dudmuck 0:27aa8733f85d 438 femctx = 0;
dudmuck 0:27aa8733f85d 439 else
dudmuck 0:27aa8733f85d 440 femcps = 1;
dudmuck 0:27aa8733f85d 441
dudmuck 0:27aa8733f85d 442 if (RegDioMapping1.bits.Dio0Mapping != 0) {
dudmuck 0:27aa8733f85d 443 RegDioMapping1.bits.Dio0Mapping = 0; // DIO0 to RxDone
dudmuck 0:27aa8733f85d 444 write_reg(REG_DIOMAPPING1, RegDioMapping1.octet);
dudmuck 0:27aa8733f85d 445 }
dudmuck 0:27aa8733f85d 446
dudmuck 0:27aa8733f85d 447 write_reg(REG_LR_FIFOADDRPTR, read_reg(REG_LR_FIFORXBASEADDR));
dudmuck 0:27aa8733f85d 448
dudmuck 0:27aa8733f85d 449 // shouldn't be necessary, radio should provide FhssChangeChannel with channel=0 for RX
dudmuck 0:27aa8733f85d 450 if (RegHopPeriod > 0)
dudmuck 0:27aa8733f85d 451 write_reg_u24(REG_FRFMSB, frfs[0]);
dudmuck 0:27aa8733f85d 452
dudmuck 0:27aa8733f85d 453 set_opmode(RF_OPMODE_RECEIVER);
dudmuck 0:27aa8733f85d 454 }
dudmuck 0:27aa8733f85d 455
dudmuck 0:27aa8733f85d 456
dudmuck 0:27aa8733f85d 457 void SX127x::hw_reset()
dudmuck 0:27aa8733f85d 458 {
dudmuck 0:27aa8733f85d 459 /* only a french-swiss design would have hi-Z deassert */
dudmuck 0:27aa8733f85d 460 reset_pin.output();
dudmuck 0:27aa8733f85d 461 reset_pin.write(1);
dudmuck 0:27aa8733f85d 462 wait(0.05);
dudmuck 0:27aa8733f85d 463 reset_pin.input();
dudmuck 0:27aa8733f85d 464 wait(0.05);
dudmuck 0:27aa8733f85d 465 }
dudmuck 0:27aa8733f85d 466
dudmuck 0:27aa8733f85d 467 service_action_e SX127x::service()
dudmuck 0:27aa8733f85d 468 {
dudmuck 0:27aa8733f85d 469
dudmuck 0:27aa8733f85d 470 if (RegOpMode.bits.Mode == RF_OPMODE_RECEIVER) {
dudmuck 0:27aa8733f85d 471 if (poll_vh) {
dudmuck 0:27aa8733f85d 472 RegIrqFlags.octet = read_reg(REG_LR_IRQFLAGS);
dudmuck 0:27aa8733f85d 473 if (RegIrqFlags.bits.ValidHeader) {
dudmuck 0:27aa8733f85d 474 RegIrqFlags.octet = 0;
dudmuck 0:27aa8733f85d 475 RegIrqFlags.bits.ValidHeader = 1;
dudmuck 0:27aa8733f85d 476 write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet);
dudmuck 0:27aa8733f85d 477 printf("VH\r\n");
dudmuck 0:27aa8733f85d 478 }
dudmuck 0:27aa8733f85d 479 }
dudmuck 0:27aa8733f85d 480 }
dudmuck 0:27aa8733f85d 481
dudmuck 0:27aa8733f85d 482 // FhssChangeChannel
dudmuck 0:27aa8733f85d 483 if (RegDioMapping1.bits.Dio1Mapping == 1) {
dudmuck 0:27aa8733f85d 484 if (dio1) {
dudmuck 0:27aa8733f85d 485 RegHopChannel.octet = read_reg(REG_LR_HOPCHANNEL);
dudmuck 0:27aa8733f85d 486 write_reg_u24(REG_FRFMSB, frfs[RegHopChannel.bits.FhssPresentChannel]);
dudmuck 0:27aa8733f85d 487 printf("hopch:%d\r\n", RegHopChannel.bits.FhssPresentChannel);
dudmuck 0:27aa8733f85d 488 RegIrqFlags.octet = 0;
dudmuck 0:27aa8733f85d 489 RegIrqFlags.bits.FhssChangeChannel = 1;
dudmuck 0:27aa8733f85d 490 write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet);
dudmuck 0:27aa8733f85d 491
dudmuck 0:27aa8733f85d 492 }
dudmuck 0:27aa8733f85d 493 }
dudmuck 0:27aa8733f85d 494
dudmuck 0:27aa8733f85d 495 if (dio0 == 0)
dudmuck 0:27aa8733f85d 496 return SERVICE_NONE;
dudmuck 0:27aa8733f85d 497
dudmuck 0:27aa8733f85d 498 switch (RegDioMapping1.bits.Dio0Mapping) {
dudmuck 0:27aa8733f85d 499 case 0: // RxDone
dudmuck 0:27aa8733f85d 500 /* user checks for CRC error in IrqFlags */
dudmuck 0:27aa8733f85d 501 RegIrqFlags.octet = read_reg(REG_LR_IRQFLAGS); // save flags
dudmuck 0:27aa8733f85d 502 RegHopChannel.octet = read_reg(REG_LR_HOPCHANNEL);
dudmuck 0:27aa8733f85d 503 if (RegIrqFlags.bits.FhssChangeChannel) {
dudmuck 0:27aa8733f85d 504 write_reg_u24(REG_FRFMSB, frfs[RegHopChannel.bits.FhssPresentChannel]);
dudmuck 0:27aa8733f85d 505 }
dudmuck 0:27aa8733f85d 506 //printf("[%02x]", RegIrqFlags.octet);
dudmuck 0:27aa8733f85d 507 write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet); // clear flags in radio
dudmuck 0:27aa8733f85d 508
dudmuck 0:27aa8733f85d 509 /* any register of interest on received packet is read(saved) here */
dudmuck 0:27aa8733f85d 510 RegModemStatus.octet = read_reg(REG_LR_MODEMSTAT);
dudmuck 0:27aa8733f85d 511 RegPktSnrValue = read_reg(REG_LR_PKTSNRVALUE);
dudmuck 0:27aa8733f85d 512 RegPktRssiValue = read_reg(REG_LR_PKTRSSIVALUE);
dudmuck 0:27aa8733f85d 513 RegRxNbBytes = read_reg(REG_LR_RXNBBYTES);
dudmuck 0:27aa8733f85d 514
dudmuck 0:27aa8733f85d 515 write_reg(REG_LR_FIFOADDRPTR, read_reg(REG_LR_FIFORXCURRENTADDR));
dudmuck 0:27aa8733f85d 516 lora_read_fifo(RegRxNbBytes);
dudmuck 0:27aa8733f85d 517 return SERVICE_READ_FIFO;
dudmuck 0:27aa8733f85d 518 case 1: // TxDone
dudmuck 0:27aa8733f85d 519 if (HF)
dudmuck 0:27aa8733f85d 520 femctx = 0;
dudmuck 0:27aa8733f85d 521 else
dudmuck 0:27aa8733f85d 522 femcps = 1;
dudmuck 0:27aa8733f85d 523
dudmuck 0:27aa8733f85d 524 RegIrqFlags.octet = 0;
dudmuck 0:27aa8733f85d 525 RegIrqFlags.bits.TxDone = 1;
dudmuck 0:27aa8733f85d 526 write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet);
dudmuck 0:27aa8733f85d 527 return SERVICE_TX_DONE;
dudmuck 0:27aa8733f85d 528 } // ...switch (RegDioMapping1.bits.Dio0Mapping)
dudmuck 0:27aa8733f85d 529
dudmuck 0:27aa8733f85d 530 return SERVICE_ERROR;
dudmuck 0:27aa8733f85d 531 }