Driver library for SX1272/SX1276 transceivers

Fork of SX127x by wayne roberts

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 }