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:
Thu May 21 18:24:04 2015 +0000
Revision:
16:3de8e1c465eb
Parent:
15:3f3fc6792f97
Child:
17:59279bc8cdab
added lora function to set bandwidth in KHz

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 15:3f3fc6792f97 150
dudmuck 15:3f3fc6792f97 151 int SX127x_lora::get_freq_error_Hz()
dudmuck 15:3f3fc6792f97 152 {
dudmuck 15:3f3fc6792f97 153 int freq_error;
dudmuck 15:3f3fc6792f97 154 float f, khz = 0;
dudmuck 15:3f3fc6792f97 155 freq_error = m_xcvr.read_reg(REG_LR_TEST28);
dudmuck 15:3f3fc6792f97 156 freq_error <<= 8;
dudmuck 15:3f3fc6792f97 157 freq_error += m_xcvr.read_reg(REG_LR_TEST29);
dudmuck 15:3f3fc6792f97 158 freq_error <<= 8;
dudmuck 15:3f3fc6792f97 159 freq_error += m_xcvr.read_reg(REG_LR_TEST2A);
dudmuck 15:3f3fc6792f97 160 if (freq_error & 0x80000) { // 20bit value is negative
dudmuck 15:3f3fc6792f97 161 //signed 20bit to 32bit
dudmuck 15:3f3fc6792f97 162 freq_error |= 0xfff00000;
dudmuck 15:3f3fc6792f97 163 }
dudmuck 15:3f3fc6792f97 164 f = freq_error / (float)XTAL_FREQ;
dudmuck 15:3f3fc6792f97 165 f *= (float)0x1000000; // 2^24
dudmuck 15:3f3fc6792f97 166 if (m_xcvr.type == SX1272) {
dudmuck 15:3f3fc6792f97 167 switch (RegModemConfig.sx1272bits.Bw) {
dudmuck 15:3f3fc6792f97 168 case 0: khz = 125; break;
dudmuck 15:3f3fc6792f97 169 case 1: khz = 250; break;
dudmuck 15:3f3fc6792f97 170 case 2: khz = 500; break;
dudmuck 15:3f3fc6792f97 171 }
dudmuck 15:3f3fc6792f97 172 } else if (m_xcvr.type == SX1276) {
dudmuck 15:3f3fc6792f97 173 switch (RegModemConfig.sx1276bits.Bw) {
dudmuck 15:3f3fc6792f97 174 case 0: khz = 7.8; break;
dudmuck 15:3f3fc6792f97 175 case 1: khz = 10.4; break;
dudmuck 15:3f3fc6792f97 176 case 2: khz = 15.6; break;
dudmuck 15:3f3fc6792f97 177 case 3: khz = 20.8; break;
dudmuck 15:3f3fc6792f97 178 case 4: khz = 31.25; break;
dudmuck 15:3f3fc6792f97 179 case 5: khz = 41.7; break;
dudmuck 15:3f3fc6792f97 180 case 6: khz = 62.5; break;
dudmuck 15:3f3fc6792f97 181 case 7: khz = 125; break;
dudmuck 15:3f3fc6792f97 182 case 8: khz = 250; break;
dudmuck 15:3f3fc6792f97 183 case 9: khz = 500; break;
dudmuck 15:3f3fc6792f97 184 }
dudmuck 15:3f3fc6792f97 185 }
dudmuck 15:3f3fc6792f97 186 f *= khz / 500;
dudmuck 15:3f3fc6792f97 187 return (int)f;
dudmuck 15:3f3fc6792f97 188 }
dudmuck 15:3f3fc6792f97 189
dudmuck 10:7382c260c4b1 190 float SX127x_lora::get_symbol_period()
dudmuck 10:7382c260c4b1 191 {
dudmuck 10:7382c260c4b1 192 float khz = 0;
dudmuck 10:7382c260c4b1 193
dudmuck 10:7382c260c4b1 194 if (m_xcvr.type == SX1276) {
dudmuck 10:7382c260c4b1 195 switch (RegModemConfig.sx1276bits.Bw) {
dudmuck 10:7382c260c4b1 196 case 0: khz = 7.8; break;
dudmuck 10:7382c260c4b1 197 case 1: khz = 10.4; break;
dudmuck 10:7382c260c4b1 198 case 2: khz = 15.6; break;
dudmuck 10:7382c260c4b1 199 case 3: khz = 20.8; break;
dudmuck 10:7382c260c4b1 200 case 4: khz = 31.25; break;
dudmuck 10:7382c260c4b1 201 case 5: khz = 41.7; break;
dudmuck 10:7382c260c4b1 202 case 6: khz = 62.5; break;
dudmuck 10:7382c260c4b1 203 case 7: khz = 125; break;
dudmuck 10:7382c260c4b1 204 case 8: khz = 250; break;
dudmuck 10:7382c260c4b1 205 case 9: khz = 500; break;
dudmuck 10:7382c260c4b1 206 }
dudmuck 10:7382c260c4b1 207 } else if (m_xcvr.type == SX1272) {
dudmuck 10:7382c260c4b1 208 switch (RegModemConfig.sx1272bits.Bw) {
dudmuck 10:7382c260c4b1 209 case 0: khz = 125; break;
dudmuck 10:7382c260c4b1 210 case 1: khz = 250; break;
dudmuck 10:7382c260c4b1 211 case 2: khz = 500; break;
dudmuck 10:7382c260c4b1 212 }
dudmuck 10:7382c260c4b1 213 }
dudmuck 10:7382c260c4b1 214
dudmuck 10:7382c260c4b1 215 // return symbol duration in milliseconds
dudmuck 10:7382c260c4b1 216 return (1 << RegModemConfig2.sx1276bits.SpreadingFactor) / khz;
dudmuck 10:7382c260c4b1 217 }
dudmuck 2:fdae76e1215e 218
dudmuck 16:3de8e1c465eb 219 void SX127x_lora::setBw_KHz(int khz)
dudmuck 16:3de8e1c465eb 220 {
dudmuck 16:3de8e1c465eb 221 uint8_t bw = 0;
dudmuck 16:3de8e1c465eb 222
dudmuck 16:3de8e1c465eb 223 if (m_xcvr.type == SX1276) {
dudmuck 16:3de8e1c465eb 224 if (khz <= 8) bw = 0;
dudmuck 16:3de8e1c465eb 225 else if (khz <= 11) bw = 1;
dudmuck 16:3de8e1c465eb 226 else if (khz <= 16) bw = 2;
dudmuck 16:3de8e1c465eb 227 else if (khz <= 21) bw = 3;
dudmuck 16:3de8e1c465eb 228 else if (khz <= 32) bw = 4;
dudmuck 16:3de8e1c465eb 229 else if (khz <= 42) bw = 5;
dudmuck 16:3de8e1c465eb 230 else if (khz <= 63) bw = 6;
dudmuck 16:3de8e1c465eb 231 else if (khz <= 125) bw = 7;
dudmuck 16:3de8e1c465eb 232 else if (khz <= 250) bw = 8;
dudmuck 16:3de8e1c465eb 233 else if (khz <= 500) bw = 9;
dudmuck 16:3de8e1c465eb 234 } else if (m_xcvr.type == SX1272) {
dudmuck 16:3de8e1c465eb 235 if (khz <= 125) bw = 0;
dudmuck 16:3de8e1c465eb 236 else if (khz <= 250) bw = 1;
dudmuck 16:3de8e1c465eb 237 else if (khz <= 500) bw = 2;
dudmuck 16:3de8e1c465eb 238 }
dudmuck 16:3de8e1c465eb 239
dudmuck 16:3de8e1c465eb 240 setBw(bw);
dudmuck 16:3de8e1c465eb 241 }
dudmuck 16:3de8e1c465eb 242
dudmuck 2:fdae76e1215e 243 void SX127x_lora::setBw(uint8_t bw)
dudmuck 2:fdae76e1215e 244 {
dudmuck 2:fdae76e1215e 245 if (!m_xcvr.RegOpMode.bits.LongRangeMode)
dudmuck 2:fdae76e1215e 246 return;
dudmuck 2:fdae76e1215e 247
dudmuck 10:7382c260c4b1 248 if (m_xcvr.type == SX1276) {
dudmuck 2:fdae76e1215e 249 RegModemConfig.sx1276bits.Bw = bw;
dudmuck 10:7382c260c4b1 250 if (get_symbol_period() > 16)
dudmuck 10:7382c260c4b1 251 RegModemConfig3.sx1276bits.LowDataRateOptimize = 1;
dudmuck 10:7382c260c4b1 252 else
dudmuck 10:7382c260c4b1 253 RegModemConfig3.sx1276bits.LowDataRateOptimize = 0;
dudmuck 10:7382c260c4b1 254 m_xcvr.write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet);
dudmuck 10:7382c260c4b1 255 } else if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 256 RegModemConfig.sx1272bits.Bw = bw;
dudmuck 10:7382c260c4b1 257 if (get_symbol_period() > 16)
dudmuck 2:fdae76e1215e 258 RegModemConfig.sx1272bits.LowDataRateOptimize = 1;
dudmuck 2:fdae76e1215e 259 else
dudmuck 2:fdae76e1215e 260 RegModemConfig.sx1272bits.LowDataRateOptimize = 0;
dudmuck 2:fdae76e1215e 261 } else
dudmuck 2:fdae76e1215e 262 return;
dudmuck 2:fdae76e1215e 263
dudmuck 2:fdae76e1215e 264 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 2:fdae76e1215e 265 }
dudmuck 2:fdae76e1215e 266
dudmuck 2:fdae76e1215e 267
dudmuck 2:fdae76e1215e 268
dudmuck 2:fdae76e1215e 269 uint8_t SX127x_lora::getSf(void)
dudmuck 2:fdae76e1215e 270 {
dudmuck 2:fdae76e1215e 271 // spreading factor same between sx127[26]
dudmuck 2:fdae76e1215e 272 return RegModemConfig2.sx1276bits.SpreadingFactor;
dudmuck 2:fdae76e1215e 273 }
dudmuck 2:fdae76e1215e 274
dudmuck 2:fdae76e1215e 275 void SX127x_lora::set_nb_trig_peaks(int n)
dudmuck 2:fdae76e1215e 276 {
dudmuck 13:1953e70522aa 277 /* TODO: different requirements for RX_CONTINUOUS vs RX_SINGLE */
dudmuck 2:fdae76e1215e 278 RegTest31.bits.detect_trig_same_peaks_nb = n;
dudmuck 2:fdae76e1215e 279 m_xcvr.write_reg(REG_LR_TEST31, RegTest31.octet);
dudmuck 2:fdae76e1215e 280 }
dudmuck 2:fdae76e1215e 281
dudmuck 2:fdae76e1215e 282
dudmuck 2:fdae76e1215e 283 void SX127x_lora::setSf(uint8_t sf)
dudmuck 2:fdae76e1215e 284 {
dudmuck 2:fdae76e1215e 285 if (!m_xcvr.RegOpMode.bits.LongRangeMode)
dudmuck 2:fdae76e1215e 286 return;
dudmuck 2:fdae76e1215e 287
dudmuck 2:fdae76e1215e 288 // false detections vs missed detections tradeoff
dudmuck 2:fdae76e1215e 289 switch (sf) {
dudmuck 2:fdae76e1215e 290 case 6:
dudmuck 2:fdae76e1215e 291 set_nb_trig_peaks(3);
dudmuck 2:fdae76e1215e 292 break;
dudmuck 2:fdae76e1215e 293 case 7:
dudmuck 2:fdae76e1215e 294 set_nb_trig_peaks(4);
dudmuck 2:fdae76e1215e 295 break;
dudmuck 2:fdae76e1215e 296 default:
dudmuck 2:fdae76e1215e 297 set_nb_trig_peaks(5);
dudmuck 2:fdae76e1215e 298 break;
dudmuck 2:fdae76e1215e 299 }
dudmuck 2:fdae76e1215e 300
dudmuck 2:fdae76e1215e 301 // write register at 0x37 with value 0xc if at SF6
dudmuck 2:fdae76e1215e 302 if (sf < 7)
dudmuck 2:fdae76e1215e 303 m_xcvr.write_reg(REG_LR_DETECTION_THRESHOLD, 0x0c);
dudmuck 2:fdae76e1215e 304 else
dudmuck 2:fdae76e1215e 305 m_xcvr.write_reg(REG_LR_DETECTION_THRESHOLD, 0x0a);
dudmuck 2:fdae76e1215e 306
dudmuck 2:fdae76e1215e 307 RegModemConfig2.sx1276bits.SpreadingFactor = sf; // spreading factor same between sx127[26]
dudmuck 2:fdae76e1215e 308 m_xcvr.write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 2:fdae76e1215e 309
dudmuck 2:fdae76e1215e 310 if (m_xcvr.type == SX1272) {
dudmuck 10:7382c260c4b1 311 if (get_symbol_period() > 16)
dudmuck 2:fdae76e1215e 312 RegModemConfig.sx1272bits.LowDataRateOptimize = 1;
dudmuck 2:fdae76e1215e 313 else
dudmuck 2:fdae76e1215e 314 RegModemConfig.sx1272bits.LowDataRateOptimize = 0;
dudmuck 2:fdae76e1215e 315 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 2:fdae76e1215e 316 } else if (m_xcvr.type == SX1276) {
dudmuck 10:7382c260c4b1 317 if (get_symbol_period() > 16)
dudmuck 2:fdae76e1215e 318 RegModemConfig3.sx1276bits.LowDataRateOptimize = 1;
dudmuck 2:fdae76e1215e 319 else
dudmuck 2:fdae76e1215e 320 RegModemConfig3.sx1276bits.LowDataRateOptimize = 0;
dudmuck 2:fdae76e1215e 321 m_xcvr.write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet);
dudmuck 2:fdae76e1215e 322 }
dudmuck 2:fdae76e1215e 323 }
dudmuck 2:fdae76e1215e 324
dudmuck 2:fdae76e1215e 325
dudmuck 2:fdae76e1215e 326
dudmuck 2:fdae76e1215e 327 bool SX127x_lora::getRxPayloadCrcOn(void)
dudmuck 2:fdae76e1215e 328 {
dudmuck 2:fdae76e1215e 329 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 330 return RegModemConfig2.sx1276bits.RxPayloadCrcOn;
dudmuck 2:fdae76e1215e 331 else if (m_xcvr.type == SX1272)
dudmuck 2:fdae76e1215e 332 return RegModemConfig.sx1272bits.RxPayloadCrcOn;
dudmuck 2:fdae76e1215e 333 else
dudmuck 2:fdae76e1215e 334 return 0;
dudmuck 2:fdae76e1215e 335 }
dudmuck 2:fdae76e1215e 336
dudmuck 2:fdae76e1215e 337
dudmuck 2:fdae76e1215e 338 void SX127x_lora::setRxPayloadCrcOn(bool on)
dudmuck 2:fdae76e1215e 339 {
dudmuck 2:fdae76e1215e 340 if (m_xcvr.type == SX1276) {
dudmuck 2:fdae76e1215e 341 RegModemConfig2.sx1276bits.RxPayloadCrcOn = on;
dudmuck 2:fdae76e1215e 342 m_xcvr.write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 2:fdae76e1215e 343 } else if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 344 RegModemConfig.sx1272bits.RxPayloadCrcOn = on;
dudmuck 2:fdae76e1215e 345 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet);
dudmuck 2:fdae76e1215e 346 }
dudmuck 2:fdae76e1215e 347 }
dudmuck 2:fdae76e1215e 348
dudmuck 2:fdae76e1215e 349
dudmuck 2:fdae76e1215e 350
dudmuck 2:fdae76e1215e 351 bool SX127x_lora::getAgcAutoOn(void)
dudmuck 2:fdae76e1215e 352 {
dudmuck 2:fdae76e1215e 353 if (m_xcvr.type == SX1276) {
dudmuck 2:fdae76e1215e 354 RegModemConfig3.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG3);
dudmuck 2:fdae76e1215e 355 return RegModemConfig3.sx1276bits.AgcAutoOn;
dudmuck 2:fdae76e1215e 356 } else if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 357 RegModemConfig2.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG2);
dudmuck 2:fdae76e1215e 358 return RegModemConfig2.sx1272bits.AgcAutoOn;
dudmuck 2:fdae76e1215e 359 } else
dudmuck 2:fdae76e1215e 360 return 0;
dudmuck 2:fdae76e1215e 361 }
dudmuck 2:fdae76e1215e 362
dudmuck 2:fdae76e1215e 363 void SX127x_lora::setAgcAutoOn(bool on)
dudmuck 2:fdae76e1215e 364 {
dudmuck 2:fdae76e1215e 365 if (m_xcvr.type == SX1276) {
dudmuck 2:fdae76e1215e 366 RegModemConfig3.sx1276bits.AgcAutoOn = on;
dudmuck 2:fdae76e1215e 367 m_xcvr.write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet);
dudmuck 2:fdae76e1215e 368 } else if (m_xcvr.type == SX1272) {
dudmuck 2:fdae76e1215e 369 RegModemConfig2.sx1272bits.AgcAutoOn = on;
dudmuck 2:fdae76e1215e 370 m_xcvr.write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet);
dudmuck 2:fdae76e1215e 371 }
dudmuck 2:fdae76e1215e 372
dudmuck 2:fdae76e1215e 373 }
dudmuck 2:fdae76e1215e 374
dudmuck 2:fdae76e1215e 375 void SX127x_lora::start_tx(uint8_t len)
dudmuck 7:927a05f84ede 376 {
dudmuck 2:fdae76e1215e 377 // DIO0 to TxDone
dudmuck 2:fdae76e1215e 378 if (m_xcvr.RegDioMapping1.bits.Dio0Mapping != 1) {
dudmuck 2:fdae76e1215e 379 m_xcvr.RegDioMapping1.bits.Dio0Mapping = 1;
dudmuck 2:fdae76e1215e 380 m_xcvr.write_reg(REG_DIOMAPPING1, m_xcvr.RegDioMapping1.octet);
dudmuck 2:fdae76e1215e 381 }
dudmuck 2:fdae76e1215e 382
dudmuck 2:fdae76e1215e 383 // set FifoPtrAddr to FifoTxPtrBase
dudmuck 2:fdae76e1215e 384 m_xcvr.write_reg(REG_LR_FIFOADDRPTR, m_xcvr.read_reg(REG_LR_FIFOTXBASEADDR));
dudmuck 2:fdae76e1215e 385
dudmuck 2:fdae76e1215e 386 // write PayloadLength bytes to fifo
dudmuck 2:fdae76e1215e 387 write_fifo(len);
dudmuck 7:927a05f84ede 388
dudmuck 2:fdae76e1215e 389 m_xcvr.set_opmode(RF_OPMODE_TRANSMITTER);
dudmuck 2:fdae76e1215e 390 }
dudmuck 2:fdae76e1215e 391
dudmuck 2:fdae76e1215e 392 void SX127x_lora::start_rx()
dudmuck 2:fdae76e1215e 393 {
dudmuck 2:fdae76e1215e 394 if (!m_xcvr.RegOpMode.bits.LongRangeMode)
dudmuck 12:bda42457c34a 395 return; // fsk mode
dudmuck 12:bda42457c34a 396 if (m_xcvr.RegOpMode.sx1276LORAbits.AccessSharedReg)
dudmuck 12:bda42457c34a 397 return; // fsk page
dudmuck 13:1953e70522aa 398
dudmuck 13:1953e70522aa 399 m_xcvr.set_opmode(RF_OPMODE_RECEIVER);
dudmuck 2:fdae76e1215e 400
dudmuck 2:fdae76e1215e 401 if (m_xcvr.RegDioMapping1.bits.Dio0Mapping != 0) {
dudmuck 2:fdae76e1215e 402 m_xcvr.RegDioMapping1.bits.Dio0Mapping = 0; // DIO0 to RxDone
dudmuck 2:fdae76e1215e 403 m_xcvr.write_reg(REG_DIOMAPPING1, m_xcvr.RegDioMapping1.octet);
dudmuck 2:fdae76e1215e 404 }
dudmuck 2:fdae76e1215e 405
dudmuck 2:fdae76e1215e 406 m_xcvr.write_reg(REG_LR_FIFOADDRPTR, m_xcvr.read_reg(REG_LR_FIFORXBASEADDR));
dudmuck 2:fdae76e1215e 407 }
dudmuck 2:fdae76e1215e 408
dudmuck 2:fdae76e1215e 409 float SX127x_lora::get_pkt_rssi()
dudmuck 2:fdae76e1215e 410 {
dudmuck 2:fdae76e1215e 411 /* TODO: calculating with pktSNR to give meaningful result below noise floor */
dudmuck 2:fdae76e1215e 412 if (m_xcvr.type == SX1276)
dudmuck 2:fdae76e1215e 413 return RegPktRssiValue - 137;
dudmuck 2:fdae76e1215e 414 else
dudmuck 2:fdae76e1215e 415 return RegPktRssiValue - 125;
dudmuck 2:fdae76e1215e 416 }
dudmuck 2:fdae76e1215e 417
dudmuck 2:fdae76e1215e 418 service_action_e SX127x_lora::service()
dudmuck 2:fdae76e1215e 419 {
dudmuck 2:fdae76e1215e 420 if (m_xcvr.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER) {
dudmuck 2:fdae76e1215e 421 if (poll_vh) {
dudmuck 2:fdae76e1215e 422 RegIrqFlags.octet = m_xcvr.read_reg(REG_LR_IRQFLAGS);
dudmuck 2:fdae76e1215e 423 if (RegIrqFlags.bits.ValidHeader) {
dudmuck 2:fdae76e1215e 424 RegIrqFlags.octet = 0;
dudmuck 2:fdae76e1215e 425 RegIrqFlags.bits.ValidHeader = 1;
dudmuck 2:fdae76e1215e 426 m_xcvr.write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet);
dudmuck 2:fdae76e1215e 427 printf("VH\r\n");
dudmuck 2:fdae76e1215e 428 }
dudmuck 2:fdae76e1215e 429 }
dudmuck 2:fdae76e1215e 430 }
dudmuck 7:927a05f84ede 431
dudmuck 2:fdae76e1215e 432 if (m_xcvr.dio0 == 0)
dudmuck 2:fdae76e1215e 433 return SERVICE_NONE;
dudmuck 2:fdae76e1215e 434
dudmuck 2:fdae76e1215e 435 switch (m_xcvr.RegDioMapping1.bits.Dio0Mapping) {
dudmuck 2:fdae76e1215e 436 case 0: // RxDone
dudmuck 2:fdae76e1215e 437 /* user checks for CRC error in IrqFlags */
dudmuck 2:fdae76e1215e 438 RegIrqFlags.octet = m_xcvr.read_reg(REG_LR_IRQFLAGS); // save flags
dudmuck 2:fdae76e1215e 439 RegHopChannel.octet = m_xcvr.read_reg(REG_LR_HOPCHANNEL);
dudmuck 2:fdae76e1215e 440 //printf("[%02x]", RegIrqFlags.octet);
dudmuck 2:fdae76e1215e 441 m_xcvr.write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet); // clear flags in radio
dudmuck 2:fdae76e1215e 442
dudmuck 2:fdae76e1215e 443 /* any register of interest on received packet is read(saved) here */
dudmuck 2:fdae76e1215e 444 RegModemStatus.octet = m_xcvr.read_reg(REG_LR_MODEMSTAT);
dudmuck 2:fdae76e1215e 445 RegPktSnrValue = m_xcvr.read_reg(REG_LR_PKTSNRVALUE);
dudmuck 2:fdae76e1215e 446 RegPktRssiValue = m_xcvr.read_reg(REG_LR_PKTRSSIVALUE);
dudmuck 2:fdae76e1215e 447 RegRxNbBytes = m_xcvr.read_reg(REG_LR_RXNBBYTES);
dudmuck 2:fdae76e1215e 448
dudmuck 2:fdae76e1215e 449 m_xcvr.write_reg(REG_LR_FIFOADDRPTR, m_xcvr.read_reg(REG_LR_FIFORXCURRENTADDR));
dudmuck 2:fdae76e1215e 450 read_fifo(RegRxNbBytes);
dudmuck 2:fdae76e1215e 451 return SERVICE_READ_FIFO;
dudmuck 2:fdae76e1215e 452 case 1: // TxDone
dudmuck 2:fdae76e1215e 453 RegIrqFlags.octet = 0;
dudmuck 2:fdae76e1215e 454 RegIrqFlags.bits.TxDone = 1;
dudmuck 2:fdae76e1215e 455 m_xcvr.write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet);
dudmuck 2:fdae76e1215e 456 return SERVICE_TX_DONE;
dudmuck 2:fdae76e1215e 457 } // ...switch (RegDioMapping1.bits.Dio0Mapping)
dudmuck 2:fdae76e1215e 458
dudmuck 2:fdae76e1215e 459 return SERVICE_ERROR;
dudmuck 12:bda42457c34a 460 }
dudmuck 12:bda42457c34a 461