acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
SX1272.cpp (16074B)
1 #include "SX1272.h" 2 #if !defined(RADIOLIB_EXCLUDE_SX127X) 3 4 SX1272::SX1272(Module* mod) : SX127x(mod) { 5 6 } 7 8 int16_t SX1272::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, uint8_t gain) { 9 // execute common part 10 int16_t state = SX127x::begin(RADIOLIB_SX1272_CHIP_VERSION, syncWord, preambleLength); 11 RADIOLIB_ASSERT(state); 12 13 // configure publicly accessible settings 14 state = setBandwidth(bw); 15 RADIOLIB_ASSERT(state); 16 17 state = setFrequency(freq); 18 RADIOLIB_ASSERT(state); 19 20 state = setSpreadingFactor(sf); 21 RADIOLIB_ASSERT(state); 22 23 state = setCodingRate(cr); 24 RADIOLIB_ASSERT(state); 25 26 state = setOutputPower(power); 27 RADIOLIB_ASSERT(state); 28 29 state = setGain(gain); 30 RADIOLIB_ASSERT(state); 31 32 return(state); 33 } 34 35 int16_t SX1272::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, bool enableOOK) { 36 // execute common part 37 int16_t state = SX127x::beginFSK(RADIOLIB_SX1272_CHIP_VERSION, br, freqDev, rxBw, preambleLength, enableOOK); 38 RADIOLIB_ASSERT(state); 39 40 // configure settings not accessible by API 41 state = configFSK(); 42 RADIOLIB_ASSERT(state); 43 44 // configure publicly accessible settings 45 state = setFrequency(freq); 46 RADIOLIB_ASSERT(state); 47 48 state = setOutputPower(power); 49 RADIOLIB_ASSERT(state); 50 51 if(enableOOK) { 52 state = setDataShapingOOK(RADIOLIB_SHAPING_NONE); 53 RADIOLIB_ASSERT(state); 54 } else { 55 state = setDataShaping(RADIOLIB_SHAPING_NONE); 56 RADIOLIB_ASSERT(state); 57 } 58 59 return(state); 60 } 61 62 void SX1272::reset() { 63 _mod->pinMode(_mod->getRst(), OUTPUT); 64 _mod->digitalWrite(_mod->getRst(), HIGH); 65 _mod->delay(1); 66 _mod->digitalWrite(_mod->getRst(), LOW); 67 _mod->delay(5); 68 } 69 70 int16_t SX1272::setFrequency(float freq) { 71 RADIOLIB_CHECK_RANGE(freq, 860.0, 1020.0, RADIOLIB_ERR_INVALID_FREQUENCY); 72 73 // set frequency and if successful, save the new setting 74 int16_t state = SX127x::setFrequencyRaw(freq); 75 if(state == RADIOLIB_ERR_NONE) { 76 SX127x::_freq = freq; 77 } 78 return(state); 79 } 80 81 int16_t SX1272::setBandwidth(float bw) { 82 // check active modem 83 if(getActiveModem() != RADIOLIB_SX127X_LORA) { 84 return(RADIOLIB_ERR_WRONG_MODEM); 85 } 86 87 uint8_t newBandwidth; 88 89 // check allowed bandwidth values 90 if(fabs(bw - 125.0) <= 0.001) { 91 newBandwidth = RADIOLIB_SX1272_BW_125_00_KHZ; 92 } else if(fabs(bw - 250.0) <= 0.001) { 93 newBandwidth = RADIOLIB_SX1272_BW_250_00_KHZ; 94 } else if(fabs(bw - 500.0) <= 0.001) { 95 newBandwidth = RADIOLIB_SX1272_BW_500_00_KHZ; 96 } else { 97 return(RADIOLIB_ERR_INVALID_BANDWIDTH); 98 } 99 100 // set bandwidth and if successful, save the new setting 101 int16_t state = SX1272::setBandwidthRaw(newBandwidth); 102 if(state == RADIOLIB_ERR_NONE) { 103 SX127x::_bw = bw; 104 105 // calculate symbol length and set low data rate optimization, if auto-configuration is enabled 106 if(_ldroAuto) { 107 float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw; 108 RADIOLIB_DEBUG_PRINT("Symbol length: "); 109 RADIOLIB_DEBUG_PRINT(symbolLength); 110 RADIOLIB_DEBUG_PRINTLN(" ms"); 111 if(symbolLength >= 16.0) { 112 state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_LOW_DATA_RATE_OPT_ON, 0, 0); 113 } else { 114 state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_LOW_DATA_RATE_OPT_OFF, 0, 0); 115 } 116 } 117 } 118 return(state); 119 } 120 121 int16_t SX1272::setSpreadingFactor(uint8_t sf) { 122 // check active modem 123 if(getActiveModem() != RADIOLIB_SX127X_LORA) { 124 return(RADIOLIB_ERR_WRONG_MODEM); 125 } 126 127 uint8_t newSpreadingFactor; 128 129 // check allowed spreading factor values 130 switch(sf) { 131 case 6: 132 newSpreadingFactor = RADIOLIB_SX127X_SF_6; 133 break; 134 case 7: 135 newSpreadingFactor = RADIOLIB_SX127X_SF_7; 136 break; 137 case 8: 138 newSpreadingFactor = RADIOLIB_SX127X_SF_8; 139 break; 140 case 9: 141 newSpreadingFactor = RADIOLIB_SX127X_SF_9; 142 break; 143 case 10: 144 newSpreadingFactor = RADIOLIB_SX127X_SF_10; 145 break; 146 case 11: 147 newSpreadingFactor = RADIOLIB_SX127X_SF_11; 148 break; 149 case 12: 150 newSpreadingFactor = RADIOLIB_SX127X_SF_12; 151 break; 152 default: 153 return(RADIOLIB_ERR_INVALID_SPREADING_FACTOR); 154 } 155 156 // set spreading factor and if successful, save the new setting 157 int16_t state = SX1272::setSpreadingFactorRaw(newSpreadingFactor); 158 if(state == RADIOLIB_ERR_NONE) { 159 SX127x::_sf = sf; 160 161 // calculate symbol length and set low data rate optimization, if auto-configuration is enabled 162 if(_ldroAuto) { 163 float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw; 164 RADIOLIB_DEBUG_PRINT("Symbol length: "); 165 RADIOLIB_DEBUG_PRINT(symbolLength); 166 RADIOLIB_DEBUG_PRINTLN(" ms"); 167 if(symbolLength >= 16.0) { 168 state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_LOW_DATA_RATE_OPT_ON, 0, 0); 169 } else { 170 state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_LOW_DATA_RATE_OPT_OFF, 0, 0); 171 } 172 } 173 } 174 return(state); 175 } 176 177 int16_t SX1272::setCodingRate(uint8_t cr) { 178 // check active modem 179 if(getActiveModem() != RADIOLIB_SX127X_LORA) { 180 return(RADIOLIB_ERR_WRONG_MODEM); 181 } 182 183 uint8_t newCodingRate; 184 185 // check allowed coding rate values 186 switch(cr) { 187 case 5: 188 newCodingRate = RADIOLIB_SX1272_CR_4_5; 189 break; 190 case 6: 191 newCodingRate = RADIOLIB_SX1272_CR_4_6; 192 break; 193 case 7: 194 newCodingRate = RADIOLIB_SX1272_CR_4_7; 195 break; 196 case 8: 197 newCodingRate = RADIOLIB_SX1272_CR_4_8; 198 break; 199 default: 200 return(RADIOLIB_ERR_INVALID_CODING_RATE); 201 } 202 203 // set coding rate and if successful, save the new setting 204 int16_t state = SX1272::setCodingRateRaw(newCodingRate); 205 if(state == RADIOLIB_ERR_NONE) { 206 SX127x::_cr = cr; 207 } 208 return(state); 209 } 210 211 int16_t SX1272::setOutputPower(int8_t power, bool useRfo) { 212 // check allowed power range 213 if(useRfo) { 214 RADIOLIB_CHECK_RANGE(power, -1, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER); 215 } else { 216 RADIOLIB_CHECK_RANGE(power, 2, 20, RADIOLIB_ERR_INVALID_OUTPUT_POWER); 217 } 218 219 // set mode to standby 220 int16_t state = SX127x::standby(); 221 222 if(useRfo) { 223 // RFO output 224 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX127X_PA_SELECT_RFO, 7, 7); 225 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, (power + 1), 3, 0); 226 state |= _mod->SPIsetRegValue(RADIOLIB_SX1272_REG_PA_DAC, RADIOLIB_SX127X_PA_BOOST_OFF, 2, 0); 227 228 } else { 229 if(power <= 17) { 230 // power is 2 - 17 dBm, enable PA1 + PA2 on PA_BOOST 231 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX127X_PA_SELECT_BOOST, 7, 7); 232 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, (power - 2), 3, 0); 233 state |= _mod->SPIsetRegValue(RADIOLIB_SX1272_REG_PA_DAC, RADIOLIB_SX127X_PA_BOOST_OFF, 2, 0); 234 235 } else { 236 // power is 18 - 20 dBm, enable PA1 + PA2 on PA_BOOST and enable high power control 237 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX127X_PA_SELECT_BOOST, 7, 7); 238 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, (power - 5), 3, 0); 239 state |= _mod->SPIsetRegValue(RADIOLIB_SX1272_REG_PA_DAC, RADIOLIB_SX127X_PA_BOOST_ON, 2, 0); 240 241 } 242 243 } 244 245 return(state); 246 } 247 248 int16_t SX1272::setGain(uint8_t gain) { 249 // check allowed range 250 if(gain > 6) { 251 return(RADIOLIB_ERR_INVALID_GAIN); 252 } 253 254 // set mode to standby 255 int16_t state = SX127x::standby(); 256 257 // get modem 258 int16_t modem = getActiveModem(); 259 if(modem == RADIOLIB_SX127X_LORA){ 260 // set gain 261 if(gain == 0) { 262 // gain set to 0, enable AGC loop 263 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX1272_AGC_AUTO_ON, 2, 2); 264 } else { 265 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX1272_AGC_AUTO_OFF, 2, 2); 266 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_LNA, (gain << 5) | RADIOLIB_SX127X_LNA_BOOST_ON); 267 } 268 269 } else if(modem == RADIOLIB_SX127X_FSK_OOK) { 270 // set gain 271 if(gain == 0) { 272 // gain set to 0, enable AGC loop 273 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_RX_CONFIG, RADIOLIB_SX127X_AGC_AUTO_ON, 3, 3); 274 } else { 275 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_RX_CONFIG, RADIOLIB_SX127X_AGC_AUTO_ON, 3, 3); 276 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_LNA, (gain << 5) | RADIOLIB_SX127X_LNA_BOOST_ON); 277 } 278 279 } 280 281 return(state); 282 } 283 284 int16_t SX1272::setDataShaping(uint8_t sh) { 285 // check active modem 286 if(getActiveModem() != RADIOLIB_SX127X_FSK_OOK) { 287 return(RADIOLIB_ERR_WRONG_MODEM); 288 } 289 290 // check modulation 291 if(SX127x::_ook) { 292 return(RADIOLIB_ERR_INVALID_MODULATION); 293 } 294 295 // set mode to standby 296 int16_t state = SX127x::standby(); 297 RADIOLIB_ASSERT(state); 298 299 // set data shaping 300 switch(sh) { 301 case RADIOLIB_SHAPING_NONE: 302 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_OP_MODE, RADIOLIB_SX1272_NO_SHAPING, 4, 3)); 303 case RADIOLIB_SHAPING_0_3: 304 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_OP_MODE, RADIOLIB_SX1272_FSK_GAUSSIAN_0_3, 4, 3)); 305 case RADIOLIB_SHAPING_0_5: 306 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_OP_MODE, RADIOLIB_SX1272_FSK_GAUSSIAN_0_5, 4, 3)); 307 case RADIOLIB_SHAPING_1_0: 308 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_OP_MODE, RADIOLIB_SX1272_FSK_GAUSSIAN_1_0, 4, 3)); 309 default: 310 return(RADIOLIB_ERR_INVALID_DATA_SHAPING); 311 } 312 } 313 314 int16_t SX1272::setDataShapingOOK(uint8_t sh) { 315 // check active modem 316 if(getActiveModem() != RADIOLIB_SX127X_FSK_OOK) { 317 return(RADIOLIB_ERR_WRONG_MODEM); 318 } 319 320 // check modulation 321 if(!SX127x::_ook) { 322 return(RADIOLIB_ERR_INVALID_MODULATION); 323 } 324 325 // set mode to standby 326 int16_t state = SX127x::standby(); 327 328 // set data shaping 329 switch(sh) { 330 case 0: 331 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_OP_MODE, RADIOLIB_SX1272_NO_SHAPING, 4, 3); 332 break; 333 case 1: 334 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_OP_MODE, RADIOLIB_SX1272_OOK_FILTER_BR, 4, 3); 335 break; 336 case 2: 337 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_OP_MODE, RADIOLIB_SX1272_OOK_FILTER_2BR, 4, 3); 338 break; 339 default: 340 state = RADIOLIB_ERR_INVALID_DATA_SHAPING; 341 break; 342 } 343 344 return(state); 345 } 346 347 float SX1272::getRSSI(bool skipReceive) { 348 if(getActiveModem() == RADIOLIB_SX127X_LORA) { 349 // RSSI calculation uses different constant for low-frequency and high-frequency ports 350 float lastPacketRSSI = -139 + _mod->SPIgetRegValue(RADIOLIB_SX127X_REG_PKT_RSSI_VALUE); 351 352 // spread-spectrum modulation signal can be received below noise floor 353 // check last packet SNR and if it's less than 0, add it to reported RSSI to get the correct value 354 float lastPacketSNR = SX127x::getSNR(); 355 if(lastPacketSNR < 0.0) { 356 lastPacketRSSI += lastPacketSNR; 357 } 358 359 return(lastPacketRSSI); 360 361 } else { 362 // enable listen mode 363 if(!skipReceive) { 364 startReceive(); 365 } 366 367 // read the value for FSK 368 float rssi = (float)_mod->SPIgetRegValue(RADIOLIB_SX127X_REG_RSSI_VALUE_FSK) / -2.0; 369 370 // set mode back to standby 371 if(!skipReceive) { 372 standby(); 373 } 374 375 // return the value 376 return(rssi); 377 } 378 } 379 380 int16_t SX1272::setCRC(bool enable, bool mode) { 381 if(getActiveModem() == RADIOLIB_SX127X_LORA) { 382 // set LoRa CRC 383 SX127x::_crcEnabled = enable; 384 if(enable) { 385 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX1272_RX_CRC_MODE_ON, 2, 2)); 386 } else { 387 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX1272_RX_CRC_MODE_OFF, 2, 2)); 388 } 389 } else { 390 // set FSK CRC 391 int16_t state = RADIOLIB_ERR_NONE; 392 if(enable) { 393 state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_ON, 4, 4); 394 } else { 395 state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_OFF, 4, 4); 396 } 397 RADIOLIB_ASSERT(state); 398 399 // set FSK CRC mode 400 if(mode) { 401 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_WHITENING_TYPE_IBM, 0, 0)); 402 } else { 403 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_WHITENING_TYPE_CCITT, 0, 0)); 404 } 405 } 406 } 407 408 int16_t SX1272::forceLDRO(bool enable) { 409 if(getActiveModem() != RADIOLIB_SX127X_LORA) { 410 return(RADIOLIB_ERR_WRONG_MODEM); 411 } 412 413 _ldroAuto = false; 414 if(enable) { 415 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_LOW_DATA_RATE_OPT_ON, 0, 0)); 416 } else { 417 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_LOW_DATA_RATE_OPT_OFF, 0, 0)); 418 } 419 } 420 421 int16_t SX1272::autoLDRO() { 422 if(getActiveModem() != RADIOLIB_SX127X_LORA) { 423 return(RADIOLIB_ERR_WRONG_MODEM); 424 } 425 426 _ldroAuto = true; 427 return(RADIOLIB_ERR_NONE); 428 } 429 430 int16_t SX1272::implicitHeader(size_t len) { 431 return(setHeaderType(RADIOLIB_SX1272_HEADER_IMPL_MODE, len)); 432 } 433 434 int16_t SX1272::explicitHeader() { 435 return(setHeaderType(RADIOLIB_SX1272_HEADER_EXPL_MODE)); 436 } 437 438 int16_t SX1272::setBandwidthRaw(uint8_t newBandwidth) { 439 // set mode to standby 440 int16_t state = SX127x::standby(); 441 442 // write register 443 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, newBandwidth, 7, 6); 444 return(state); 445 } 446 447 int16_t SX1272::setSpreadingFactorRaw(uint8_t newSpreadingFactor) { 448 // set mode to standby 449 int16_t state = SX127x::standby(); 450 451 // write registers 452 if(newSpreadingFactor == RADIOLIB_SX127X_SF_6) { 453 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_HEADER_IMPL_MODE | (SX127x::_crcEnabled ? RADIOLIB_SX1272_RX_CRC_MODE_ON : RADIOLIB_SX1272_RX_CRC_MODE_OFF), 2, 1); 454 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX127X_SF_6 | RADIOLIB_SX127X_TX_MODE_SINGLE, 7, 3); 455 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECT_OPTIMIZE, RADIOLIB_SX127X_DETECT_OPTIMIZE_SF_6, 2, 0); 456 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECTION_THRESHOLD, RADIOLIB_SX127X_DETECTION_THRESHOLD_SF_6); 457 } else { 458 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_HEADER_EXPL_MODE | (SX127x::_crcEnabled ? RADIOLIB_SX1272_RX_CRC_MODE_ON : RADIOLIB_SX1272_RX_CRC_MODE_OFF), 2, 1); 459 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, newSpreadingFactor | RADIOLIB_SX127X_TX_MODE_SINGLE, 7, 3); 460 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECT_OPTIMIZE, RADIOLIB_SX127X_DETECT_OPTIMIZE_SF_7_12, 2, 0); 461 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECTION_THRESHOLD, RADIOLIB_SX127X_DETECTION_THRESHOLD_SF_7_12); 462 } 463 return(state); 464 } 465 466 int16_t SX1272::setCodingRateRaw(uint8_t newCodingRate) { 467 // set mode to standby 468 int16_t state = SX127x::standby(); 469 470 // write register 471 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, newCodingRate, 5, 3); 472 return(state); 473 } 474 475 int16_t SX1272::setHeaderType(uint8_t headerType, size_t len) { 476 // check active modem 477 if(getActiveModem() != RADIOLIB_SX127X_LORA) { 478 return(RADIOLIB_ERR_WRONG_MODEM); 479 } 480 481 // set requested packet mode 482 int16_t state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, headerType, 2, 2); 483 RADIOLIB_ASSERT(state); 484 485 // set length to register 486 state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len); 487 RADIOLIB_ASSERT(state); 488 489 // update cached value 490 _packetLength = len; 491 492 return(state); 493 } 494 495 int16_t SX1272::configFSK() { 496 // configure common registers 497 int16_t state = SX127x::configFSK(); 498 RADIOLIB_ASSERT(state); 499 500 // set fast PLL hop 501 state = _mod->SPIsetRegValue(RADIOLIB_SX1272_REG_PLL_HOP, RADIOLIB_SX127X_FAST_HOP_ON, 7, 7); 502 return(state); 503 } 504 505 void SX1272::errataFix(bool rx) { 506 (void)rx; 507 508 // mitigation of receiver spurious response 509 // see SX1272/73 Errata, section 2.2 for details 510 _mod->SPIsetRegValue(0x31, 0b10000000, 7, 7); 511 } 512 513 #endif