Driver library for SX1272/SX1276 transceivers
Dependents: LORA_RX LORA_TX WindConcentrator hid_test ... more
sx127x_lora.cpp
00001 #include "sx127x_lora.h" 00002 00003 /* SX127x driver 00004 * Copyright (c) 2013 Semtech 00005 * 00006 * Licensed under the Apache License, Version 2.0 (the "License"); 00007 * you may not use this file except in compliance with the License. 00008 * You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 00019 SX127x_lora::SX127x_lora(SX127x& r) : m_xcvr(r) 00020 { 00021 if (!m_xcvr.RegOpMode.bits.LongRangeMode) 00022 enable(); 00023 00024 RegModemConfig.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG); 00025 RegModemConfig2.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG2); 00026 RegTest33.octet = m_xcvr.read_reg(REG_LR_TEST33); // invert_i_q 00027 RegDriftInvert.octet = m_xcvr.read_reg(REG_LR_DRIFT_INVERT); 00028 RegGainDrift.octet = m_xcvr.read_reg(REG_LR_GAIN_DRIFT); 00029 00030 if (m_xcvr.type == SX1276) { 00031 RegAutoDrift.octet = m_xcvr.read_reg(REG_LR_SX1276_AUTO_DRIFT); 00032 } 00033 00034 00035 } 00036 00037 SX127x_lora::~SX127x_lora() 00038 { 00039 } 00040 00041 void SX127x_lora::write_fifo(uint8_t len) 00042 { 00043 int i; 00044 00045 m_xcvr.m_cs = 0; 00046 m_xcvr.m_spi.write(REG_FIFO | 0x80); // bit7 is high for writing to radio 00047 00048 for (i = 0; i < len; i++) { 00049 m_xcvr.m_spi.write(m_xcvr.tx_buf[i]); 00050 } 00051 m_xcvr.m_cs = 1; 00052 } 00053 00054 void SX127x_lora::read_fifo(uint8_t len) 00055 { 00056 int i; 00057 00058 m_xcvr.m_cs = 0; 00059 m_xcvr.m_spi.write(REG_FIFO); // bit7 is low for reading from radio 00060 for (i = 0; i < len; i++) { 00061 m_xcvr.rx_buf[i] = m_xcvr.m_spi.write(0); 00062 } 00063 m_xcvr.m_cs = 1; 00064 } 00065 00066 void SX127x_lora::enable() 00067 { 00068 m_xcvr.set_opmode(RF_OPMODE_SLEEP); 00069 00070 m_xcvr.RegOpMode.bits.LongRangeMode = 1; 00071 m_xcvr.write_reg(REG_OPMODE, m_xcvr.RegOpMode.octet); 00072 00073 m_xcvr.RegDioMapping1.bits.Dio0Mapping = 0; // DIO0 to RxDone 00074 m_xcvr.RegDioMapping1.bits.Dio1Mapping = 0; 00075 m_xcvr.write_reg(REG_DIOMAPPING1, m_xcvr.RegDioMapping1.octet); 00076 00077 RegTest31.octet = m_xcvr.read_reg(REG_LR_TEST31); 00078 RegTest31.bits.if_freq_auto = 0; // improved RX spurious rejection 00079 m_xcvr.write_reg(REG_LR_TEST31, RegTest31.octet); 00080 00081 m_xcvr.set_opmode(RF_OPMODE_STANDBY); 00082 } 00083 00084 uint8_t SX127x_lora::getCodingRate(bool from_rx) 00085 { 00086 if (from_rx) { 00087 // expected RegModemStatus was read on RxDone interrupt 00088 return RegModemStatus.bits.RxCodingRate; 00089 } else { // transmitted coding rate... 00090 if (m_xcvr.type == SX1276) 00091 return RegModemConfig.sx1276bits.CodingRate; 00092 else if (m_xcvr.type == SX1272) 00093 return RegModemConfig.sx1272bits.CodingRate; 00094 else 00095 return 0; 00096 } 00097 } 00098 00099 00100 00101 void SX127x_lora::setCodingRate(uint8_t cr) 00102 { 00103 if (!m_xcvr.RegOpMode.bits.LongRangeMode) 00104 return; 00105 00106 if (m_xcvr.type == SX1276) 00107 RegModemConfig.sx1276bits.CodingRate = cr; 00108 else if (m_xcvr.type == SX1272) 00109 RegModemConfig.sx1272bits.CodingRate = cr; 00110 else 00111 return; 00112 00113 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet); 00114 } 00115 00116 00117 00118 bool SX127x_lora::getHeaderMode(void) 00119 { 00120 if (m_xcvr.type == SX1276) { 00121 RegModemConfig.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG); 00122 return RegModemConfig.sx1276bits.ImplicitHeaderModeOn; 00123 } else if (m_xcvr.type == SX1272) { 00124 RegModemConfig.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG); 00125 return RegModemConfig.sx1272bits.ImplicitHeaderModeOn; 00126 } else 00127 return false; 00128 } 00129 00130 void SX127x_lora::setHeaderMode(bool hm) 00131 { 00132 if (m_xcvr.type == SX1276) 00133 RegModemConfig.sx1276bits.ImplicitHeaderModeOn = hm; 00134 else if (m_xcvr.type == SX1272) 00135 RegModemConfig.sx1272bits.ImplicitHeaderModeOn = hm; 00136 else 00137 return; 00138 00139 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet); 00140 } 00141 00142 00143 uint8_t SX127x_lora::getBw(void) 00144 { 00145 if (m_xcvr.type == SX1276) 00146 return RegModemConfig.sx1276bits.Bw; 00147 else if (m_xcvr.type == SX1272) 00148 return RegModemConfig.sx1272bits.Bw; 00149 else 00150 return 0; 00151 } 00152 00153 int SX127x_lora::get_freq_error_Hz() 00154 { 00155 int freq_error; 00156 float f, khz = 0; 00157 freq_error = m_xcvr.read_reg(REG_LR_TEST28); 00158 freq_error <<= 8; 00159 freq_error += m_xcvr.read_reg(REG_LR_TEST29); 00160 freq_error <<= 8; 00161 freq_error += m_xcvr.read_reg(REG_LR_TEST2A); 00162 if (freq_error & 0x80000) { // 20bit value is negative 00163 //signed 20bit to 32bit 00164 freq_error |= 0xfff00000; 00165 } 00166 f = freq_error / (float)XTAL_FREQ; 00167 f *= (float)0x1000000; // 2^24 00168 if (m_xcvr.type == SX1272) { 00169 switch (RegModemConfig.sx1272bits.Bw) { 00170 case 0: khz = 125; break; 00171 case 1: khz = 250; break; 00172 case 2: khz = 500; break; 00173 } 00174 } else if (m_xcvr.type == SX1276) { 00175 switch (RegModemConfig.sx1276bits.Bw) { 00176 case 0: khz = 7.8; break; 00177 case 1: khz = 10.4; break; 00178 case 2: khz = 15.6; break; 00179 case 3: khz = 20.8; break; 00180 case 4: khz = 31.25; break; 00181 case 5: khz = 41.7; break; 00182 case 6: khz = 62.5; break; 00183 case 7: khz = 125; break; 00184 case 8: khz = 250; break; 00185 case 9: khz = 500; break; 00186 } 00187 } 00188 f *= khz / 500; 00189 return (int)f; 00190 } 00191 00192 float SX127x_lora::get_symbol_period() 00193 { 00194 float khz = 0; 00195 00196 if (m_xcvr.type == SX1276) { 00197 switch (RegModemConfig.sx1276bits.Bw) { 00198 case 0: khz = 7.8; break; 00199 case 1: khz = 10.4; break; 00200 case 2: khz = 15.6; break; 00201 case 3: khz = 20.8; break; 00202 case 4: khz = 31.25; break; 00203 case 5: khz = 41.7; break; 00204 case 6: khz = 62.5; break; 00205 case 7: khz = 125; break; 00206 case 8: khz = 250; break; 00207 case 9: khz = 500; break; 00208 } 00209 } else if (m_xcvr.type == SX1272) { 00210 switch (RegModemConfig.sx1272bits.Bw) { 00211 case 0: khz = 125; break; 00212 case 1: khz = 250; break; 00213 case 2: khz = 500; break; 00214 } 00215 } 00216 00217 // return symbol duration in milliseconds 00218 return (1 << RegModemConfig2.sx1276bits.SpreadingFactor) / khz; 00219 } 00220 00221 void SX127x_lora::setBw_KHz(int khz) 00222 { 00223 uint8_t bw = 0; 00224 00225 if (m_xcvr.type == SX1276) { 00226 if (khz <= 8) bw = 0; 00227 else if (khz <= 11) bw = 1; 00228 else if (khz <= 16) bw = 2; 00229 else if (khz <= 21) bw = 3; 00230 else if (khz <= 32) bw = 4; 00231 else if (khz <= 42) bw = 5; 00232 else if (khz <= 63) bw = 6; 00233 else if (khz <= 125) bw = 7; 00234 else if (khz <= 250) bw = 8; 00235 else if (khz <= 500) bw = 9; 00236 } else if (m_xcvr.type == SX1272) { 00237 if (khz <= 125) bw = 0; 00238 else if (khz <= 250) bw = 1; 00239 else if (khz <= 500) bw = 2; 00240 } 00241 00242 setBw(bw); 00243 } 00244 00245 void SX127x_lora::setBw(uint8_t bw) 00246 { 00247 if (!m_xcvr.RegOpMode.bits.LongRangeMode) 00248 return; 00249 00250 if (m_xcvr.type == SX1276) { 00251 RegModemConfig.sx1276bits.Bw = bw; 00252 if (get_symbol_period() > 16) 00253 RegModemConfig3.sx1276bits.LowDataRateOptimize = 1; 00254 else 00255 RegModemConfig3.sx1276bits.LowDataRateOptimize = 0; 00256 m_xcvr.write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet); 00257 } else if (m_xcvr.type == SX1272) { 00258 RegModemConfig.sx1272bits.Bw = bw; 00259 if (get_symbol_period() > 16) 00260 RegModemConfig.sx1272bits.LowDataRateOptimize = 1; 00261 else 00262 RegModemConfig.sx1272bits.LowDataRateOptimize = 0; 00263 } else 00264 return; 00265 00266 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet); 00267 } 00268 00269 00270 00271 uint8_t SX127x_lora::getSf(void) 00272 { 00273 // spreading factor same between sx127[26] 00274 return RegModemConfig2.sx1276bits.SpreadingFactor; 00275 } 00276 00277 void SX127x_lora::set_nb_trig_peaks(int n) 00278 { 00279 /* TODO: different requirements for RX_CONTINUOUS vs RX_SINGLE */ 00280 RegTest31.bits.detect_trig_same_peaks_nb = n; 00281 m_xcvr.write_reg(REG_LR_TEST31, RegTest31.octet); 00282 } 00283 00284 00285 void SX127x_lora::setSf(uint8_t sf) 00286 { 00287 if (!m_xcvr.RegOpMode.bits.LongRangeMode) 00288 return; 00289 00290 // write register at 0x37 with value 0xc if at SF6 00291 if (sf < 7) 00292 m_xcvr.write_reg(REG_LR_DETECTION_THRESHOLD, 0x0c); 00293 else 00294 m_xcvr.write_reg(REG_LR_DETECTION_THRESHOLD, 0x0a); 00295 00296 RegModemConfig2.sx1276bits.SpreadingFactor = sf; // spreading factor same between sx127[26] 00297 m_xcvr.write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet); 00298 00299 if (m_xcvr.type == SX1272) { 00300 if (get_symbol_period() > 16) 00301 RegModemConfig.sx1272bits.LowDataRateOptimize = 1; 00302 else 00303 RegModemConfig.sx1272bits.LowDataRateOptimize = 0; 00304 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet); 00305 } else if (m_xcvr.type == SX1276) { 00306 if (get_symbol_period() > 16) 00307 RegModemConfig3.sx1276bits.LowDataRateOptimize = 1; 00308 else 00309 RegModemConfig3.sx1276bits.LowDataRateOptimize = 0; 00310 m_xcvr.write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet); 00311 } 00312 } 00313 00314 00315 00316 bool SX127x_lora::getRxPayloadCrcOn(void) 00317 { 00318 /* RxPayloadCrcOn enables CRC generation in transmitter */ 00319 /* in implicit mode, this bit also enables CRC in receiver */ 00320 if (m_xcvr.type == SX1276) { 00321 RegModemConfig2.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG2); 00322 return RegModemConfig2.sx1276bits.RxPayloadCrcOn; 00323 } else if (m_xcvr.type == SX1272) { 00324 RegModemConfig.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG); 00325 return RegModemConfig.sx1272bits.RxPayloadCrcOn; 00326 } else 00327 return 0; 00328 } 00329 00330 00331 void SX127x_lora::setRxPayloadCrcOn(bool on) 00332 { 00333 if (m_xcvr.type == SX1276) { 00334 RegModemConfig2.sx1276bits.RxPayloadCrcOn = on; 00335 m_xcvr.write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet); 00336 } else if (m_xcvr.type == SX1272) { 00337 RegModemConfig.sx1272bits.RxPayloadCrcOn = on; 00338 m_xcvr.write_reg(REG_LR_MODEMCONFIG, RegModemConfig.octet); 00339 } 00340 } 00341 00342 00343 00344 bool SX127x_lora::getAgcAutoOn(void) 00345 { 00346 if (m_xcvr.type == SX1276) { 00347 RegModemConfig3.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG3); 00348 return RegModemConfig3.sx1276bits.AgcAutoOn; 00349 } else if (m_xcvr.type == SX1272) { 00350 RegModemConfig2.octet = m_xcvr.read_reg(REG_LR_MODEMCONFIG2); 00351 return RegModemConfig2.sx1272bits.AgcAutoOn; 00352 } else 00353 return 0; 00354 } 00355 00356 void SX127x_lora::setAgcAutoOn(bool on) 00357 { 00358 if (m_xcvr.type == SX1276) { 00359 RegModemConfig3.sx1276bits.AgcAutoOn = on; 00360 m_xcvr.write_reg(REG_LR_MODEMCONFIG3, RegModemConfig3.octet); 00361 } else if (m_xcvr.type == SX1272) { 00362 RegModemConfig2.sx1272bits.AgcAutoOn = on; 00363 m_xcvr.write_reg(REG_LR_MODEMCONFIG2, RegModemConfig2.octet); 00364 } 00365 00366 } 00367 00368 void SX127x_lora::invert_tx(bool inv) 00369 { 00370 RegTest33.bits.chirp_invert_tx = !inv; 00371 m_xcvr.write_reg(REG_LR_TEST33, RegTest33.octet); 00372 } 00373 00374 void SX127x_lora::invert_rx(bool inv) 00375 { 00376 RegTest33.bits.invert_i_q = inv; 00377 m_xcvr.write_reg(REG_LR_TEST33, RegTest33.octet); 00378 /**/ 00379 RegDriftInvert.bits.invert_timing_error_per_symbol = !RegTest33.bits.invert_i_q; 00380 m_xcvr.write_reg(REG_LR_DRIFT_INVERT, RegDriftInvert.octet); 00381 } 00382 00383 void SX127x_lora::start_tx(uint8_t len) 00384 { 00385 // DIO0 to TxDone 00386 if (m_xcvr.RegDioMapping1.bits.Dio0Mapping != 1) { 00387 m_xcvr.RegDioMapping1.bits.Dio0Mapping = 1; 00388 m_xcvr.write_reg(REG_DIOMAPPING1, m_xcvr.RegDioMapping1.octet); 00389 } 00390 00391 // set FifoPtrAddr to FifoTxPtrBase 00392 m_xcvr.write_reg(REG_LR_FIFOADDRPTR, m_xcvr.read_reg(REG_LR_FIFOTXBASEADDR)); 00393 00394 // write PayloadLength bytes to fifo 00395 write_fifo(len); 00396 00397 m_xcvr.set_opmode(RF_OPMODE_TRANSMITTER); 00398 } 00399 00400 void SX127x_lora::start_rx(chip_mode_e mode) 00401 { 00402 if (!m_xcvr.RegOpMode.bits.LongRangeMode) 00403 return; // fsk mode 00404 if (m_xcvr.RegOpMode.sx1276LORAbits.AccessSharedReg) 00405 return; // fsk page 00406 00407 if (m_xcvr.type == SX1276) { 00408 if (RegModemConfig.sx1276bits.Bw == 9) { // if 500KHz bw: improved tolerance of reference frequency error 00409 if (RegAutoDrift.bits.freq_to_time_drift_auto) { 00410 RegAutoDrift.bits.freq_to_time_drift_auto = 0; 00411 m_xcvr.write_reg(REG_LR_SX1276_AUTO_DRIFT, RegAutoDrift.octet); 00412 } 00413 if (m_xcvr.HF) { 00414 // > 525MHz 00415 if (RegGainDrift.bits.freq_to_time_drift != 0x24) { 00416 RegGainDrift.bits.freq_to_time_drift = 0x24; 00417 m_xcvr.write_reg(REG_LR_GAIN_DRIFT, RegGainDrift.octet); 00418 } 00419 } else { 00420 // < 525MHz 00421 if (RegGainDrift.bits.freq_to_time_drift != 0x3f) { 00422 RegGainDrift.bits.freq_to_time_drift = 0x3f; 00423 m_xcvr.write_reg(REG_LR_GAIN_DRIFT, RegGainDrift.octet); 00424 } 00425 } 00426 00427 } else { 00428 if (!RegAutoDrift.bits.freq_to_time_drift_auto) { 00429 RegAutoDrift.bits.freq_to_time_drift_auto = 1; 00430 m_xcvr.write_reg(REG_LR_SX1276_AUTO_DRIFT, RegAutoDrift.octet); 00431 } 00432 } 00433 } // ... if (m_xcvr.type == SX1276) 00434 00435 // RX_CONTINUOUS: false detections vs missed detections tradeoff 00436 switch (RegModemConfig2.sx1276bits.SpreadingFactor) { 00437 case 6: 00438 set_nb_trig_peaks(3); 00439 break; 00440 case 7: 00441 set_nb_trig_peaks(4); 00442 break; 00443 default: 00444 set_nb_trig_peaks(5); 00445 break; 00446 } 00447 00448 m_xcvr.set_opmode(mode); 00449 00450 if (m_xcvr.RegDioMapping1.bits.Dio0Mapping != 0) { 00451 m_xcvr.RegDioMapping1.bits.Dio0Mapping = 0; // DIO0 to RxDone 00452 m_xcvr.write_reg(REG_DIOMAPPING1, m_xcvr.RegDioMapping1.octet); 00453 } 00454 00455 m_xcvr.write_reg(REG_LR_FIFOADDRPTR, m_xcvr.read_reg(REG_LR_FIFORXBASEADDR)); 00456 } 00457 00458 int SX127x_lora::get_pkt_rssi() 00459 { 00460 if (m_xcvr.type == SX1276) { 00461 if (m_xcvr.HF) 00462 return RegPktRssiValue - 157; 00463 else 00464 return RegPktRssiValue - 164; 00465 } else 00466 return RegPktRssiValue - 139; 00467 } 00468 00469 int SX127x_lora::get_current_rssi() 00470 { 00471 uint8_t v = m_xcvr.read_reg(REG_LR_RSSIVALUE); 00472 if (m_xcvr.type == SX1276) { 00473 if (m_xcvr.HF) 00474 return v - 157; 00475 else 00476 return v - 164; 00477 } else 00478 return v - 139; 00479 } 00480 00481 service_action_e SX127x_lora::service() 00482 { 00483 if (m_xcvr.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER) { 00484 if (poll_vh) { 00485 RegIrqFlags.octet = m_xcvr.read_reg(REG_LR_IRQFLAGS); 00486 if (RegIrqFlags.bits.ValidHeader) { 00487 RegIrqFlags.octet = 0; 00488 RegIrqFlags.bits.ValidHeader = 1; 00489 m_xcvr.write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet); 00490 printf("VH\r\n"); 00491 } 00492 } 00493 } 00494 00495 if (m_xcvr.dio0 == 0) 00496 return SERVICE_NONE; 00497 00498 switch (m_xcvr.RegDioMapping1.bits.Dio0Mapping) { 00499 case 0: // RxDone 00500 /* user checks for CRC error in IrqFlags */ 00501 RegIrqFlags.octet = m_xcvr.read_reg(REG_LR_IRQFLAGS); // save flags 00502 RegHopChannel.octet = m_xcvr.read_reg(REG_LR_HOPCHANNEL); 00503 //printf("[%02x]", RegIrqFlags.octet); 00504 m_xcvr.write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet); // clear flags in radio 00505 00506 /* any register of interest on received packet is read(saved) here */ 00507 RegModemStatus.octet = m_xcvr.read_reg(REG_LR_MODEMSTAT); 00508 RegPktSnrValue = m_xcvr.read_reg(REG_LR_PKTSNRVALUE); 00509 RegPktRssiValue = m_xcvr.read_reg(REG_LR_PKTRSSIVALUE); 00510 RegRxNbBytes = m_xcvr.read_reg(REG_LR_RXNBBYTES); 00511 00512 m_xcvr.write_reg(REG_LR_FIFOADDRPTR, m_xcvr.read_reg(REG_LR_FIFORXCURRENTADDR)); 00513 read_fifo(RegRxNbBytes); 00514 return SERVICE_READ_FIFO; 00515 case 1: // TxDone 00516 RegIrqFlags.octet = 0; 00517 RegIrqFlags.bits.TxDone = 1; 00518 m_xcvr.write_reg(REG_LR_IRQFLAGS, RegIrqFlags.octet); 00519 return SERVICE_TX_DONE; 00520 } // ...switch (RegDioMapping1.bits.Dio0Mapping) 00521 00522 return SERVICE_ERROR; 00523 } 00524
Generated on Tue Jul 12 2022 17:36:51 by 1.7.2