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:
Mon Apr 14 21:57:41 2014 +0000
Revision:
1:7dc60eb4c7ec
Parent:
0:27aa8733f85d
Child:
2:fdae76e1215e
added read/write functions for USB HID application

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 1:7dc60eb4c7ec 25 m_spi.frequency(3000000);
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 1:7dc60eb4c7ec 81
dudmuck 1:7dc60eb4c7ec 82 void
dudmuck 1:7dc60eb4c7ec 83 SX127x::ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
dudmuck 1:7dc60eb4c7ec 84 {
dudmuck 1:7dc60eb4c7ec 85 uint8_t i;
dudmuck 1:7dc60eb4c7ec 86
dudmuck 1:7dc60eb4c7ec 87 m_cs = 0;
dudmuck 1:7dc60eb4c7ec 88
dudmuck 1:7dc60eb4c7ec 89 m_spi.write(addr); // bit7 is low for reading from radio
dudmuck 1:7dc60eb4c7ec 90
dudmuck 1:7dc60eb4c7ec 91 for( i = 0; i < size; i++ )
dudmuck 1:7dc60eb4c7ec 92 {
dudmuck 1:7dc60eb4c7ec 93 buffer[i] = m_spi.write(0x00);
dudmuck 1:7dc60eb4c7ec 94 }
dudmuck 1:7dc60eb4c7ec 95
dudmuck 1:7dc60eb4c7ec 96 m_cs = 1;
dudmuck 1:7dc60eb4c7ec 97 }
dudmuck 1:7dc60eb4c7ec 98
dudmuck 0:27aa8733f85d 99 uint8_t SX127x::read_reg(uint8_t addr)
dudmuck 0:27aa8733f85d 100 {
dudmuck 0:27aa8733f85d 101 uint8_t ret;
dudmuck 0:27aa8733f85d 102 // Select the device by seting chip select low
dudmuck 0:27aa8733f85d 103 m_cs = 0;
dudmuck 0:27aa8733f85d 104
dudmuck 0:27aa8733f85d 105 m_spi.write(addr); // bit7 is low for reading from radio
dudmuck 0:27aa8733f85d 106
dudmuck 0:27aa8733f85d 107 // Send a dummy byte to receive the contents of register
dudmuck 0:27aa8733f85d 108 ret = m_spi.write(0x00);
dudmuck 0:27aa8733f85d 109
dudmuck 0:27aa8733f85d 110 // Deselect the device
dudmuck 0:27aa8733f85d 111 m_cs = 1;
dudmuck 0:27aa8733f85d 112
dudmuck 0:27aa8733f85d 113 return ret;
dudmuck 0:27aa8733f85d 114 }
dudmuck 0:27aa8733f85d 115
dudmuck 0:27aa8733f85d 116 uint16_t SX127x::read_u16(uint8_t addr)
dudmuck 0:27aa8733f85d 117 {
dudmuck 0:27aa8733f85d 118 uint16_t ret;
dudmuck 0:27aa8733f85d 119 // Select the device by seting chip select low
dudmuck 0:27aa8733f85d 120 m_cs = 0;
dudmuck 0:27aa8733f85d 121
dudmuck 0:27aa8733f85d 122 m_spi.write(addr); // bit7 is low for reading from radio
dudmuck 0:27aa8733f85d 123
dudmuck 0:27aa8733f85d 124 // Send a dummy byte to receive the contents of register
dudmuck 0:27aa8733f85d 125 ret = m_spi.write(0x00);
dudmuck 0:27aa8733f85d 126 ret <<= 8;
dudmuck 0:27aa8733f85d 127 ret += m_spi.write(0x00);
dudmuck 0:27aa8733f85d 128
dudmuck 0:27aa8733f85d 129 // Deselect the device
dudmuck 0:27aa8733f85d 130 m_cs = 1;
dudmuck 0:27aa8733f85d 131
dudmuck 0:27aa8733f85d 132 return ret;
dudmuck 0:27aa8733f85d 133 }
dudmuck 0:27aa8733f85d 134
dudmuck 0:27aa8733f85d 135 void SX127x::write_reg_u24(uint8_t addr, uint32_t data)
dudmuck 0:27aa8733f85d 136 {
dudmuck 0:27aa8733f85d 137 m_cs = 0; // Select the device by seting chip select low
dudmuck 0:27aa8733f85d 138
dudmuck 0:27aa8733f85d 139 m_spi.write(addr | 0x80); // bit7 is high for writing to radio
dudmuck 0:27aa8733f85d 140 m_spi.write((data >> 16) & 0xff);
dudmuck 0:27aa8733f85d 141 m_spi.write((data >> 8) & 0xff);
dudmuck 0:27aa8733f85d 142 m_spi.write(data & 0xff);
dudmuck 0:27aa8733f85d 143
dudmuck 0:27aa8733f85d 144 m_cs = 1; // Deselect the device
dudmuck 0:27aa8733f85d 145
dudmuck 0:27aa8733f85d 146 if (addr == REG_FRFMSB) {
dudmuck 0:27aa8733f85d 147 if (data < 0x8340000) // < 525MHz
dudmuck 0:27aa8733f85d 148 HF = false;
dudmuck 0:27aa8733f85d 149 else
dudmuck 0:27aa8733f85d 150 HF = true;
dudmuck 0:27aa8733f85d 151 }
dudmuck 0:27aa8733f85d 152 }
dudmuck 0:27aa8733f85d 153
dudmuck 0:27aa8733f85d 154 void SX127x::write_reg(uint8_t addr, uint8_t data)
dudmuck 0:27aa8733f85d 155 {
dudmuck 0:27aa8733f85d 156 m_cs = 0; // Select the device by seting chip select low
dudmuck 0:27aa8733f85d 157
dudmuck 0:27aa8733f85d 158 m_spi.write(addr | 0x80); // bit7 is high for writing to radio
dudmuck 0:27aa8733f85d 159 m_spi.write(data);
dudmuck 0:27aa8733f85d 160
dudmuck 0:27aa8733f85d 161 m_cs = 1; // Deselect the device
dudmuck 0:27aa8733f85d 162 }
dudmuck 0:27aa8733f85d 163
dudmuck 1:7dc60eb4c7ec 164 void SX127x::WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
dudmuck 1:7dc60eb4c7ec 165 {
dudmuck 1:7dc60eb4c7ec 166 uint8_t i;
dudmuck 1:7dc60eb4c7ec 167
dudmuck 1:7dc60eb4c7ec 168 m_cs = 0; // Select the device by seting chip select low
dudmuck 1:7dc60eb4c7ec 169
dudmuck 1:7dc60eb4c7ec 170 m_spi.write(addr | 0x80); // bit7 is high for writing to radio
dudmuck 1:7dc60eb4c7ec 171 for( i = 0; i < size; i++ )
dudmuck 1:7dc60eb4c7ec 172 {
dudmuck 1:7dc60eb4c7ec 173 m_spi.write(buffer[i]);
dudmuck 1:7dc60eb4c7ec 174 }
dudmuck 1:7dc60eb4c7ec 175
dudmuck 1:7dc60eb4c7ec 176 m_cs = 1; // Deselect the device
dudmuck 1:7dc60eb4c7ec 177 }
dudmuck 1:7dc60eb4c7ec 178
dudmuck 0:27aa8733f85d 179 void SX127x::lora_write_fifo(uint8_t len)
dudmuck 0:27aa8733f85d 180 {
dudmuck 0:27aa8733f85d 181 int i;
dudmuck 0:27aa8733f85d 182
dudmuck 0:27aa8733f85d 183 m_cs = 0;
dudmuck 0:27aa8733f85d 184 m_spi.write(REG_FIFO | 0x80); // bit7 is high for writing to radio
dudmuck 0:27aa8733f85d 185 for (i = 0; i < len; i++) {
dudmuck 0:27aa8733f85d 186 m_spi.write(tx_buf[i]);
dudmuck 0:27aa8733f85d 187 }
dudmuck 0:27aa8733f85d 188 m_cs = 1;
dudmuck 0:27aa8733f85d 189 }
dudmuck 0:27aa8733f85d 190
dudmuck 0:27aa8733f85d 191 void SX127x::lora_read_fifo(uint8_t len)
dudmuck 0:27aa8733f85d 192 {
dudmuck 0:27aa8733f85d 193 int i;
dudmuck 0:27aa8733f85d 194
dudmuck 0:27aa8733f85d 195 m_cs = 0;
dudmuck 0:27aa8733f85d 196 m_spi.write(REG_FIFO); // bit7 is low for reading from radio
dudmuck 0:27aa8733f85d 197 for (i = 0; i < len; i++) {
dudmuck 0:27aa8733f85d 198 rx_buf[i] = m_spi.write(0);
dudmuck 0:27aa8733f85d 199 }
dudmuck 0:27aa8733f85d 200 m_cs = 1;
dudmuck 0:27aa8733f85d 201 }
dudmuck 0:27aa8733f85d 202
dudmuck 1:7dc60eb4c7ec 203 void
dudmuck 1:7dc60eb4c7ec 204 SX127x::SetLoRaOn( bool enable )
dudmuck 1:7dc60eb4c7ec 205 {
dudmuck 1:7dc60eb4c7ec 206 set_opmode(RF_OPMODE_SLEEP);
dudmuck 1:7dc60eb4c7ec 207
dudmuck 1:7dc60eb4c7ec 208 if (enable)
dudmuck 1:7dc60eb4c7ec 209 {
dudmuck 1:7dc60eb4c7ec 210 RegOpMode.bits.LongRangeMode = 1;
dudmuck 1:7dc60eb4c7ec 211 write_reg(REG_OPMODE, RegOpMode.octet);
dudmuck 1:7dc60eb4c7ec 212
dudmuck 1:7dc60eb4c7ec 213 /*RegOpMode.octet = read_reg(REG_OPMODE);
dudmuck 1:7dc60eb4c7ec 214 printf("setloraon:%02x\r\n", RegOpMode.octet);*/
dudmuck 1:7dc60eb4c7ec 215
dudmuck 1:7dc60eb4c7ec 216
dudmuck 1:7dc60eb4c7ec 217 /* // RxDone RxTimeout FhssChangeChannel CadDone
dudmuck 1:7dc60eb4c7ec 218 SX1272LR->RegDioMapping1 = RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO1_00 | RFLR_DIOMAPPING1_DIO2_00 | RFLR_DIOMAPPING1_DIO3_00;
dudmuck 1:7dc60eb4c7ec 219 // CadDetected ModeReady
dudmuck 1:7dc60eb4c7ec 220 SX1272LR->RegDioMapping2 = RFLR_DIOMAPPING2_DIO4_00 | RFLR_DIOMAPPING2_DIO5_00;
dudmuck 1:7dc60eb4c7ec 221 SX1272WriteBuffer( REG_LR_DIOMAPPING1, &SX1272LR->RegDioMapping1, 2 );*/
dudmuck 1:7dc60eb4c7ec 222 RegDioMapping1.bits.Dio0Mapping = 0; // DIO0 to RxDone
dudmuck 1:7dc60eb4c7ec 223 RegDioMapping1.bits.Dio1Mapping = 0;
dudmuck 1:7dc60eb4c7ec 224 write_reg(REG_DIOMAPPING1, RegDioMapping1.octet);
dudmuck 1:7dc60eb4c7ec 225
dudmuck 1:7dc60eb4c7ec 226 // todo: read LoRa regsiters
dudmuck 1:7dc60eb4c7ec 227 //SX1272ReadBuffer( REG_LR_OPMODE, SX1272Regs + 1, 0x70 - 1 );
dudmuck 1:7dc60eb4c7ec 228 }
dudmuck 1:7dc60eb4c7ec 229 else
dudmuck 1:7dc60eb4c7ec 230 {
dudmuck 1:7dc60eb4c7ec 231 RegOpMode.bits.LongRangeMode = 0;
dudmuck 1:7dc60eb4c7ec 232 write_reg(REG_OPMODE, RegOpMode.octet);
dudmuck 1:7dc60eb4c7ec 233
dudmuck 1:7dc60eb4c7ec 234 /*RegOpMode.octet = read_reg(REG_OPMODE);
dudmuck 1:7dc60eb4c7ec 235 printf("setloraoff:%02x\r\n", RegOpMode.octet);*/
dudmuck 1:7dc60eb4c7ec 236
dudmuck 1:7dc60eb4c7ec 237 // todo: read FSK regsiters
dudmuck 1:7dc60eb4c7ec 238 //SX1272ReadBuffer( REG_OPMODE, SX1272Regs + 1, 0x70 - 1 );
dudmuck 1:7dc60eb4c7ec 239 }
dudmuck 1:7dc60eb4c7ec 240
dudmuck 1:7dc60eb4c7ec 241 set_opmode(RF_OPMODE_STANDBY);
dudmuck 1:7dc60eb4c7ec 242 }
dudmuck 1:7dc60eb4c7ec 243
dudmuck 1:7dc60eb4c7ec 244
dudmuck 0:27aa8733f85d 245 void SX127x::set_opmode(chip_mode_e mode)
dudmuck 0:27aa8733f85d 246 {
dudmuck 0:27aa8733f85d 247 RegOpMode.bits.Mode = mode;
dudmuck 0:27aa8733f85d 248 write_reg(REG_OPMODE, RegOpMode.octet);
dudmuck 0:27aa8733f85d 249 }
dudmuck 0:27aa8733f85d 250
dudmuck 0:27aa8733f85d 251 void SX127x::set_frf_MHz( float MHz )
dudmuck 0:27aa8733f85d 252 {
dudmuck 0:27aa8733f85d 253 uint32_t frf;
dudmuck 0:27aa8733f85d 254
dudmuck 0:27aa8733f85d 255 frf = MHz / FREQ_STEP_MHZ;
dudmuck 0:27aa8733f85d 256 write_reg_u24(REG_FRFMSB, frf);
dudmuck 0:27aa8733f85d 257
dudmuck 0:27aa8733f85d 258 if (MHz < 525)
dudmuck 0:27aa8733f85d 259 HF = false;
dudmuck 0:27aa8733f85d 260 else
dudmuck 0:27aa8733f85d 261 HF = true;
dudmuck 0:27aa8733f85d 262 }
dudmuck 0:27aa8733f85d 263
dudmuck 0:27aa8733f85d 264 float SX127x::get_frf_MHz(void)
dudmuck 0:27aa8733f85d 265 {
dudmuck 0:27aa8733f85d 266 uint32_t frf;
dudmuck 0:27aa8733f85d 267 uint8_t lsb, mid, msb;
dudmuck 0:27aa8733f85d 268 float MHz;
dudmuck 0:27aa8733f85d 269
dudmuck 0:27aa8733f85d 270 msb = read_reg(REG_FRFMSB);
dudmuck 0:27aa8733f85d 271 mid = read_reg(REG_FRFMID);
dudmuck 0:27aa8733f85d 272 lsb = read_reg(REG_FRFLSB);
dudmuck 0:27aa8733f85d 273 frf = msb;
dudmuck 0:27aa8733f85d 274 frf <<= 8;
dudmuck 0:27aa8733f85d 275 frf += mid;
dudmuck 0:27aa8733f85d 276 frf <<= 8;
dudmuck 0:27aa8733f85d 277 frf += lsb;
dudmuck 0:27aa8733f85d 278
dudmuck 0:27aa8733f85d 279 MHz = frf * FREQ_STEP_MHZ;
dudmuck 0:27aa8733f85d 280
dudmuck 0:27aa8733f85d 281 if (MHz < 525)
dudmuck 0:27aa8733f85d 282 HF = false;
dudmuck 0:27aa8733f85d 283 else
dudmuck 0:27aa8733f85d 284 HF = true;
dudmuck 0:27aa8733f85d 285
dudmuck 0:27aa8733f85d 286 return MHz;
dudmuck 0:27aa8733f85d 287 }
dudmuck 0:27aa8733f85d 288
dudmuck 0:27aa8733f85d 289 uint8_t SX127x::getCodingRate(bool from_rx)
dudmuck 0:27aa8733f85d 290 {
dudmuck 0:27aa8733f85d 291 if (from_rx) {
dudmuck 0:27aa8733f85d 292 // expected RegModemStatus was read on RxDone interrupt
dudmuck 0:27aa8733f85d 293 return RegModemStatus.bits.RxCodingRate;
dudmuck 0:27aa8733f85d 294 } else { // transmitted coding rate...
dudmuck 0:27aa8733f85d 295 if (type == SX1276)
dudmuck 0:27aa8733f85d 296 return RegModemConfig.sx1276bits.CodingRate;
dudmuck 0:27aa8733f85d 297 else if (type == SX1272)
dudmuck 0:27aa8733f85d 298 return RegModemConfig.sx1272bits.CodingRate;
dudmuck 0:27aa8733f85d 299 else
dudmuck 0:27aa8733f85d 300 return 0;
dudmuck 0:27aa8733f85d 301 }
dudmuck 0:27aa8733f85d 302 }
dudmuck 0:27aa8733f85d 303
dudmuck 0:27aa8733f85d 304 void SX127x::setCodingRate(uint8_t cr)
dudmuck 0:27aa8733f85d 305 {
dudmuck 0:27aa8733f85d 306 if (type == SX1276)
dudmuck 0:27aa8733f85d 307 RegModemConfig.sx1276bits.CodingRate = cr;
dudmuck 0:27aa8733f85d 308 else if (type == SX1272)
dudmuck 0:27aa8733f85d 309 RegModemConfig.sx1272bits.CodingRate = cr;
dudmuck 0:27aa8733f85d 310 else
dudmuck 0:27aa8733f85d 311 return;
dudmuck 0:27aa8733f85d 312
dudmuck 0:27aa8733f85d 313 write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 0:27aa8733f85d 314 }
dudmuck 0:27aa8733f85d 315
dudmuck 0:27aa8733f85d 316 bool SX127x::getHeaderMode(void)
dudmuck 0:27aa8733f85d 317 {
dudmuck 0:27aa8733f85d 318 if (type == SX1276)
dudmuck 0:27aa8733f85d 319 return RegModemConfig.sx1276bits.ImplicitHeaderModeOn;
dudmuck 0:27aa8733f85d 320 else if (type == SX1272)
dudmuck 0:27aa8733f85d 321 return RegModemConfig.sx1272bits.ImplicitHeaderModeOn;
dudmuck 0:27aa8733f85d 322 else
dudmuck 0:27aa8733f85d 323 return false;
dudmuck 0:27aa8733f85d 324 }
dudmuck 0:27aa8733f85d 325
dudmuck 0:27aa8733f85d 326 void SX127x::setHeaderMode(bool hm)
dudmuck 0:27aa8733f85d 327 {
dudmuck 0:27aa8733f85d 328 if (type == SX1276)
dudmuck 0:27aa8733f85d 329 RegModemConfig.sx1276bits.ImplicitHeaderModeOn = hm;
dudmuck 0:27aa8733f85d 330 else if (type == SX1272)
dudmuck 0:27aa8733f85d 331 RegModemConfig.sx1272bits.ImplicitHeaderModeOn = hm;
dudmuck 0:27aa8733f85d 332 else
dudmuck 0:27aa8733f85d 333 return;
dudmuck 0:27aa8733f85d 334
dudmuck 0:27aa8733f85d 335 write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 0:27aa8733f85d 336 }
dudmuck 0:27aa8733f85d 337
dudmuck 0:27aa8733f85d 338 uint8_t SX127x::getBw(void)
dudmuck 0:27aa8733f85d 339 {
dudmuck 0:27aa8733f85d 340 if (type == SX1276)
dudmuck 0:27aa8733f85d 341 return RegModemConfig.sx1276bits.Bw;
dudmuck 0:27aa8733f85d 342 else if (type == SX1272)
dudmuck 0:27aa8733f85d 343 return RegModemConfig.sx1272bits.Bw;
dudmuck 0:27aa8733f85d 344 else
dudmuck 0:27aa8733f85d 345 return 0;
dudmuck 0:27aa8733f85d 346 }
dudmuck 0:27aa8733f85d 347
dudmuck 0:27aa8733f85d 348 void SX127x::setBw(uint8_t bw)
dudmuck 0:27aa8733f85d 349 {
dudmuck 0:27aa8733f85d 350 if (type == SX1276)
dudmuck 0:27aa8733f85d 351 RegModemConfig.sx1276bits.Bw = bw;
dudmuck 0:27aa8733f85d 352 else if (type == SX1272) {
dudmuck 0:27aa8733f85d 353 RegModemConfig.sx1272bits.Bw = bw;
dudmuck 0:27aa8733f85d 354 if (RegModemConfig2.sx1272bits.SpreadingFactor > 10)
dudmuck 0:27aa8733f85d 355 RegModemConfig.sx1272bits.LowDataRateOptimize = 1;
dudmuck 0:27aa8733f85d 356 else
dudmuck 0:27aa8733f85d 357 RegModemConfig.sx1272bits.LowDataRateOptimize = 0;
dudmuck 0:27aa8733f85d 358 } else
dudmuck 0:27aa8733f85d 359 return;
dudmuck 0:27aa8733f85d 360
dudmuck 0:27aa8733f85d 361 write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 0:27aa8733f85d 362 }
dudmuck 0:27aa8733f85d 363
dudmuck 0:27aa8733f85d 364 uint8_t SX127x::getSf(void)
dudmuck 0:27aa8733f85d 365 {
dudmuck 0:27aa8733f85d 366 // spreading factor same between sx127[26]
dudmuck 0:27aa8733f85d 367 return RegModemConfig2.sx1276bits.SpreadingFactor;
dudmuck 0:27aa8733f85d 368 }
dudmuck 0:27aa8733f85d 369
dudmuck 0:27aa8733f85d 370 void SX127x::set_nb_trig_peaks(int n)
dudmuck 0:27aa8733f85d 371 {
dudmuck 0:27aa8733f85d 372 RegTest31.bits.detect_trig_same_peaks_nb = n;
dudmuck 0:27aa8733f85d 373 write_reg(REG_LR_TEST31, RegTest31.octet);
dudmuck 0:27aa8733f85d 374 }
dudmuck 0:27aa8733f85d 375
dudmuck 0:27aa8733f85d 376 void SX127x::setSf(uint8_t sf)
dudmuck 0:27aa8733f85d 377 {
dudmuck 0:27aa8733f85d 378 // false detections vs missed detections tradeoff
dudmuck 0:27aa8733f85d 379 switch (sf) {
dudmuck 0:27aa8733f85d 380 case 6:
dudmuck 0:27aa8733f85d 381 set_nb_trig_peaks(3);
dudmuck 0:27aa8733f85d 382 break;
dudmuck 0:27aa8733f85d 383 case 7:
dudmuck 0:27aa8733f85d 384 set_nb_trig_peaks(4);
dudmuck 0:27aa8733f85d 385 break;
dudmuck 0:27aa8733f85d 386 default:
dudmuck 0:27aa8733f85d 387 set_nb_trig_peaks(5);
dudmuck 0:27aa8733f85d 388 break;
dudmuck 0:27aa8733f85d 389 }
dudmuck 0:27aa8733f85d 390
dudmuck 0:27aa8733f85d 391 // write register at 0x37 with value 0xc if at SF6
dudmuck 0:27aa8733f85d 392 if (sf < 7)
dudmuck 0:27aa8733f85d 393 write_reg(REG_LR_DETECTION_THRESHOLD, 0x0c);
dudmuck 0:27aa8733f85d 394 else
dudmuck 0:27aa8733f85d 395 write_reg(REG_LR_DETECTION_THRESHOLD, 0x0a);
dudmuck 0:27aa8733f85d 396
dudmuck 0:27aa8733f85d 397 RegModemConfig2.sx1276bits.SpreadingFactor = sf; // spreading factor same between sx127[26]
dudmuck 0:27aa8733f85d 398 write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 0:27aa8733f85d 399
dudmuck 0:27aa8733f85d 400 if (type == SX1272) {
dudmuck 0:27aa8733f85d 401 if (sf > 10 && RegModemConfig.sx1272bits.Bw == 0) // if bw=125KHz and sf11 or sf12
dudmuck 0:27aa8733f85d 402 RegModemConfig.sx1272bits.LowDataRateOptimize = 1;
dudmuck 0:27aa8733f85d 403 else
dudmuck 0:27aa8733f85d 404 RegModemConfig.sx1272bits.LowDataRateOptimize = 0;
dudmuck 0:27aa8733f85d 405 write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 0:27aa8733f85d 406 } else if (type == SX1276) {
dudmuck 0:27aa8733f85d 407 if (sf > 10 && RegModemConfig.sx1272bits.Bw == 0) // if bw=125KHz and sf11 or sf12
dudmuck 0:27aa8733f85d 408 RegModemConfig3.sx1276bits.LowDataRateOptimize = 1;
dudmuck 0:27aa8733f85d 409 else
dudmuck 0:27aa8733f85d 410 RegModemConfig3.sx1276bits.LowDataRateOptimize = 0;
dudmuck 0:27aa8733f85d 411 write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet);
dudmuck 0:27aa8733f85d 412 }
dudmuck 0:27aa8733f85d 413 }
dudmuck 0:27aa8733f85d 414
dudmuck 0:27aa8733f85d 415 bool SX127x::getRxPayloadCrcOn(void)
dudmuck 0:27aa8733f85d 416 {
dudmuck 0:27aa8733f85d 417 if (type == SX1276)
dudmuck 0:27aa8733f85d 418 return RegModemConfig2.sx1276bits.RxPayloadCrcOn;
dudmuck 0:27aa8733f85d 419 else if (type == SX1272)
dudmuck 0:27aa8733f85d 420 return RegModemConfig.sx1272bits.RxPayloadCrcOn;
dudmuck 0:27aa8733f85d 421 else
dudmuck 0:27aa8733f85d 422 return 0;
dudmuck 0:27aa8733f85d 423 }
dudmuck 0:27aa8733f85d 424
dudmuck 0:27aa8733f85d 425 void SX127x::setRxPayloadCrcOn(bool on)
dudmuck 0:27aa8733f85d 426 {
dudmuck 0:27aa8733f85d 427 if (type == SX1276) {
dudmuck 0:27aa8733f85d 428 RegModemConfig2.sx1276bits.RxPayloadCrcOn = on;
dudmuck 0:27aa8733f85d 429 write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 0:27aa8733f85d 430 } else if (type == SX1272) {
dudmuck 0:27aa8733f85d 431 RegModemConfig.sx1272bits.RxPayloadCrcOn = on;
dudmuck 0:27aa8733f85d 432 write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 0:27aa8733f85d 433 }
dudmuck 0:27aa8733f85d 434 }
dudmuck 0:27aa8733f85d 435
dudmuck 0:27aa8733f85d 436 bool SX127x::getAgcAutoOn(void)
dudmuck 0:27aa8733f85d 437 {
dudmuck 0:27aa8733f85d 438 if (type == SX1276) {
dudmuck 0:27aa8733f85d 439 RegModemConfig3.octet = read_reg(REG_LR_MODEMCONFIG3);
dudmuck 0:27aa8733f85d 440 return RegModemConfig3.sx1276bits.AgcAutoOn;
dudmuck 0:27aa8733f85d 441 } else if (type == SX1272) {
dudmuck 0:27aa8733f85d 442 RegModemConfig2.octet = read_reg(REG_LR_MODEMCONFIG2);
dudmuck 0:27aa8733f85d 443 return RegModemConfig2.sx1272bits.AgcAutoOn;
dudmuck 0:27aa8733f85d 444 } else
dudmuck 0:27aa8733f85d 445 return 0;
dudmuck 0:27aa8733f85d 446 }
dudmuck 0:27aa8733f85d 447
dudmuck 0:27aa8733f85d 448 void SX127x::setAgcAutoOn(bool on)
dudmuck 0:27aa8733f85d 449 {
dudmuck 0:27aa8733f85d 450 if (type == SX1276) {
dudmuck 0:27aa8733f85d 451 RegModemConfig3.sx1276bits.AgcAutoOn = on;
dudmuck 0:27aa8733f85d 452 write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet);
dudmuck 0:27aa8733f85d 453 } else if (type == SX1272) {
dudmuck 0:27aa8733f85d 454 RegModemConfig2.sx1272bits.AgcAutoOn = on;
dudmuck 0:27aa8733f85d 455 write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 0:27aa8733f85d 456 }
dudmuck 0:27aa8733f85d 457
dudmuck 0:27aa8733f85d 458 }
dudmuck 0:27aa8733f85d 459
dudmuck 0:27aa8733f85d 460 void SX127x::lora_start_tx(uint8_t len)
dudmuck 0:27aa8733f85d 461 {
dudmuck 0:27aa8733f85d 462 if (type == SX1276) {
dudmuck 0:27aa8733f85d 463 // PA_BOOST on LF, RFO on HF
dudmuck 0:27aa8733f85d 464 if (HF) {
dudmuck 0:27aa8733f85d 465 if (RegPaConfig.bits.PaSelect) {
dudmuck 0:27aa8733f85d 466 RegPaConfig.bits.PaSelect = 0;
dudmuck 0:27aa8733f85d 467 write_reg(REG_PACONFIG, RegPaConfig.octet);
dudmuck 0:27aa8733f85d 468 }
dudmuck 0:27aa8733f85d 469 } else { // LF...
dudmuck 0:27aa8733f85d 470 if (!RegPaConfig.bits.PaSelect) {
dudmuck 0:27aa8733f85d 471 RegPaConfig.bits.PaSelect = 1;
dudmuck 0:27aa8733f85d 472 write_reg(REG_PACONFIG, RegPaConfig.octet);
dudmuck 0:27aa8733f85d 473 }
dudmuck 0:27aa8733f85d 474 }
dudmuck 0:27aa8733f85d 475 } else if (type == SX1272) {
dudmuck 0:27aa8733f85d 476 // always PA_BOOST
dudmuck 0:27aa8733f85d 477 if (!RegPaConfig.bits.PaSelect) {
dudmuck 0:27aa8733f85d 478 RegPaConfig.bits.PaSelect = 1;
dudmuck 0:27aa8733f85d 479 write_reg(REG_PACONFIG, RegPaConfig.octet);
dudmuck 0:27aa8733f85d 480 }
dudmuck 0:27aa8733f85d 481 }
dudmuck 0:27aa8733f85d 482
dudmuck 0:27aa8733f85d 483
dudmuck 0:27aa8733f85d 484 // DIO0 to TxDone
dudmuck 0:27aa8733f85d 485 if (RegDioMapping1.bits.Dio0Mapping != 1) {
dudmuck 0:27aa8733f85d 486 RegDioMapping1.bits.Dio0Mapping = 1;
dudmuck 0:27aa8733f85d 487 write_reg(REG_DIOMAPPING1, RegDioMapping1.octet);
dudmuck 0:27aa8733f85d 488 }
dudmuck 0:27aa8733f85d 489
dudmuck 0:27aa8733f85d 490 // set FifoPtrAddr to FifoTxPtrBase
dudmuck 0:27aa8733f85d 491 write_reg(REG_LR_FIFOADDRPTR, read_reg(REG_LR_FIFOTXBASEADDR));
dudmuck 0:27aa8733f85d 492
dudmuck 0:27aa8733f85d 493 // write PayloadLength bytes to fifo
dudmuck 0:27aa8733f85d 494 lora_write_fifo(len);
dudmuck 0:27aa8733f85d 495
dudmuck 0:27aa8733f85d 496 if (HF)
dudmuck 0:27aa8733f85d 497 femctx = 1;
dudmuck 0:27aa8733f85d 498 else
dudmuck 0:27aa8733f85d 499 femcps = 0;
dudmuck 0:27aa8733f85d 500
dudmuck 0:27aa8733f85d 501 // radio doesnt provide FhssChangeChannel with channel=0 for TX
dudmuck 0:27aa8733f85d 502 if (RegHopPeriod > 0)
dudmuck 0:27aa8733f85d 503 write_reg_u24(REG_FRFMSB, frfs[0]);
dudmuck 0:27aa8733f85d 504
dudmuck 0:27aa8733f85d 505 set_opmode(RF_OPMODE_TRANSMITTER);
dudmuck 0:27aa8733f85d 506 }
dudmuck 0:27aa8733f85d 507
dudmuck 0:27aa8733f85d 508
dudmuck 0:27aa8733f85d 509
dudmuck 0:27aa8733f85d 510 void SX127x::lora_start_rx()
dudmuck 0:27aa8733f85d 511 {
dudmuck 0:27aa8733f85d 512 if (HF)
dudmuck 0:27aa8733f85d 513 femctx = 0;
dudmuck 0:27aa8733f85d 514 else
dudmuck 0:27aa8733f85d 515 femcps = 1;
dudmuck 0:27aa8733f85d 516
dudmuck 0:27aa8733f85d 517 if (RegDioMapping1.bits.Dio0Mapping != 0) {
dudmuck 0:27aa8733f85d 518 RegDioMapping1.bits.Dio0Mapping = 0; // DIO0 to RxDone
dudmuck 0:27aa8733f85d 519 write_reg(REG_DIOMAPPING1, RegDioMapping1.octet);
dudmuck 0:27aa8733f85d 520 }
dudmuck 0:27aa8733f85d 521
dudmuck 0:27aa8733f85d 522 write_reg(REG_LR_FIFOADDRPTR, read_reg(REG_LR_FIFORXBASEADDR));
dudmuck 0:27aa8733f85d 523
dudmuck 0:27aa8733f85d 524 // shouldn't be necessary, radio should provide FhssChangeChannel with channel=0 for RX
dudmuck 0:27aa8733f85d 525 if (RegHopPeriod > 0)
dudmuck 0:27aa8733f85d 526 write_reg_u24(REG_FRFMSB, frfs[0]);
dudmuck 0:27aa8733f85d 527
dudmuck 0:27aa8733f85d 528 set_opmode(RF_OPMODE_RECEIVER);
dudmuck 0:27aa8733f85d 529 }
dudmuck 0:27aa8733f85d 530
dudmuck 0:27aa8733f85d 531
dudmuck 0:27aa8733f85d 532 void SX127x::hw_reset()
dudmuck 0:27aa8733f85d 533 {
dudmuck 0:27aa8733f85d 534 /* only a french-swiss design would have hi-Z deassert */
dudmuck 0:27aa8733f85d 535 reset_pin.output();
dudmuck 0:27aa8733f85d 536 reset_pin.write(1);
dudmuck 0:27aa8733f85d 537 wait(0.05);
dudmuck 0:27aa8733f85d 538 reset_pin.input();
dudmuck 0:27aa8733f85d 539 wait(0.05);
dudmuck 0:27aa8733f85d 540 }
dudmuck 0:27aa8733f85d 541
dudmuck 0:27aa8733f85d 542 service_action_e SX127x::service()
dudmuck 0:27aa8733f85d 543 {
dudmuck 0:27aa8733f85d 544
dudmuck 0:27aa8733f85d 545 if (RegOpMode.bits.Mode == RF_OPMODE_RECEIVER) {
dudmuck 0:27aa8733f85d 546 if (poll_vh) {
dudmuck 0:27aa8733f85d 547 RegIrqFlags.octet = read_reg(REG_LR_IRQFLAGS);
dudmuck 0:27aa8733f85d 548 if (RegIrqFlags.bits.ValidHeader) {
dudmuck 0:27aa8733f85d 549 RegIrqFlags.octet = 0;
dudmuck 0:27aa8733f85d 550 RegIrqFlags.bits.ValidHeader = 1;
dudmuck 0:27aa8733f85d 551 write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet);
dudmuck 0:27aa8733f85d 552 printf("VH\r\n");
dudmuck 0:27aa8733f85d 553 }
dudmuck 0:27aa8733f85d 554 }
dudmuck 0:27aa8733f85d 555 }
dudmuck 0:27aa8733f85d 556
dudmuck 0:27aa8733f85d 557 // FhssChangeChannel
dudmuck 0:27aa8733f85d 558 if (RegDioMapping1.bits.Dio1Mapping == 1) {
dudmuck 0:27aa8733f85d 559 if (dio1) {
dudmuck 0:27aa8733f85d 560 RegHopChannel.octet = read_reg(REG_LR_HOPCHANNEL);
dudmuck 0:27aa8733f85d 561 write_reg_u24(REG_FRFMSB, frfs[RegHopChannel.bits.FhssPresentChannel]);
dudmuck 0:27aa8733f85d 562 printf("hopch:%d\r\n", RegHopChannel.bits.FhssPresentChannel);
dudmuck 0:27aa8733f85d 563 RegIrqFlags.octet = 0;
dudmuck 0:27aa8733f85d 564 RegIrqFlags.bits.FhssChangeChannel = 1;
dudmuck 0:27aa8733f85d 565 write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet);
dudmuck 0:27aa8733f85d 566
dudmuck 0:27aa8733f85d 567 }
dudmuck 0:27aa8733f85d 568 }
dudmuck 0:27aa8733f85d 569
dudmuck 0:27aa8733f85d 570 if (dio0 == 0)
dudmuck 0:27aa8733f85d 571 return SERVICE_NONE;
dudmuck 0:27aa8733f85d 572
dudmuck 0:27aa8733f85d 573 switch (RegDioMapping1.bits.Dio0Mapping) {
dudmuck 0:27aa8733f85d 574 case 0: // RxDone
dudmuck 0:27aa8733f85d 575 /* user checks for CRC error in IrqFlags */
dudmuck 0:27aa8733f85d 576 RegIrqFlags.octet = read_reg(REG_LR_IRQFLAGS); // save flags
dudmuck 0:27aa8733f85d 577 RegHopChannel.octet = read_reg(REG_LR_HOPCHANNEL);
dudmuck 0:27aa8733f85d 578 if (RegIrqFlags.bits.FhssChangeChannel) {
dudmuck 0:27aa8733f85d 579 write_reg_u24(REG_FRFMSB, frfs[RegHopChannel.bits.FhssPresentChannel]);
dudmuck 0:27aa8733f85d 580 }
dudmuck 0:27aa8733f85d 581 //printf("[%02x]", RegIrqFlags.octet);
dudmuck 0:27aa8733f85d 582 write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet); // clear flags in radio
dudmuck 0:27aa8733f85d 583
dudmuck 0:27aa8733f85d 584 /* any register of interest on received packet is read(saved) here */
dudmuck 0:27aa8733f85d 585 RegModemStatus.octet = read_reg(REG_LR_MODEMSTAT);
dudmuck 0:27aa8733f85d 586 RegPktSnrValue = read_reg(REG_LR_PKTSNRVALUE);
dudmuck 0:27aa8733f85d 587 RegPktRssiValue = read_reg(REG_LR_PKTRSSIVALUE);
dudmuck 0:27aa8733f85d 588 RegRxNbBytes = read_reg(REG_LR_RXNBBYTES);
dudmuck 0:27aa8733f85d 589
dudmuck 0:27aa8733f85d 590 write_reg(REG_LR_FIFOADDRPTR, read_reg(REG_LR_FIFORXCURRENTADDR));
dudmuck 0:27aa8733f85d 591 lora_read_fifo(RegRxNbBytes);
dudmuck 0:27aa8733f85d 592 return SERVICE_READ_FIFO;
dudmuck 0:27aa8733f85d 593 case 1: // TxDone
dudmuck 0:27aa8733f85d 594 if (HF)
dudmuck 0:27aa8733f85d 595 femctx = 0;
dudmuck 0:27aa8733f85d 596 else
dudmuck 0:27aa8733f85d 597 femcps = 1;
dudmuck 0:27aa8733f85d 598
dudmuck 0:27aa8733f85d 599 RegIrqFlags.octet = 0;
dudmuck 0:27aa8733f85d 600 RegIrqFlags.bits.TxDone = 1;
dudmuck 0:27aa8733f85d 601 write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet);
dudmuck 0:27aa8733f85d 602 return SERVICE_TX_DONE;
dudmuck 0:27aa8733f85d 603 } // ...switch (RegDioMapping1.bits.Dio0Mapping)
dudmuck 0:27aa8733f85d 604
dudmuck 0:27aa8733f85d 605 return SERVICE_ERROR;
dudmuck 0:27aa8733f85d 606 }