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 |
SX1278.cpp (19762B)
1 #include "SX1278.h" 2 #if !defined(RADIOLIB_EXCLUDE_SX127X) 3 4 SX1278::SX1278(Module* mod) : SX127x(mod) { 5 6 } 7 8 int16_t SX1278::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_SX1278_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 SX1278::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_SX1278_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 SX1278::reset() { 63 _mod->pinMode(_mod->getRst(), OUTPUT); 64 _mod->digitalWrite(_mod->getRst(), LOW); 65 _mod->delay(1); 66 _mod->digitalWrite(_mod->getRst(), HIGH); 67 _mod->delay(5); 68 } 69 70 int16_t SX1278::setFrequency(float freq) { 71 RADIOLIB_CHECK_RANGE(freq, 137.0, 525.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 SX1278::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 - 7.8) <= 0.001) { 91 newBandwidth = RADIOLIB_SX1278_BW_7_80_KHZ; 92 } else if(fabs(bw - 10.4) <= 0.001) { 93 newBandwidth = RADIOLIB_SX1278_BW_10_40_KHZ; 94 } else if(fabs(bw - 15.6) <= 0.001) { 95 newBandwidth = RADIOLIB_SX1278_BW_15_60_KHZ; 96 } else if(fabs(bw - 20.8) <= 0.001) { 97 newBandwidth = RADIOLIB_SX1278_BW_20_80_KHZ; 98 } else if(fabs(bw - 31.25) <= 0.001) { 99 newBandwidth = RADIOLIB_SX1278_BW_31_25_KHZ; 100 } else if(fabs(bw - 41.7) <= 0.001) { 101 newBandwidth = RADIOLIB_SX1278_BW_41_70_KHZ; 102 } else if(fabs(bw - 62.5) <= 0.001) { 103 newBandwidth = RADIOLIB_SX1278_BW_62_50_KHZ; 104 } else if(fabs(bw - 125.0) <= 0.001) { 105 newBandwidth = RADIOLIB_SX1278_BW_125_00_KHZ; 106 } else if(fabs(bw - 250.0) <= 0.001) { 107 newBandwidth = RADIOLIB_SX1278_BW_250_00_KHZ; 108 } else if(fabs(bw - 500.0) <= 0.001) { 109 newBandwidth = RADIOLIB_SX1278_BW_500_00_KHZ; 110 } else { 111 return(RADIOLIB_ERR_INVALID_BANDWIDTH); 112 } 113 114 // set bandwidth and if successful, save the new setting 115 int16_t state = SX1278::setBandwidthRaw(newBandwidth); 116 if(state == RADIOLIB_ERR_NONE) { 117 SX127x::_bw = bw; 118 119 // calculate symbol length and set low data rate optimization, if auto-configuration is enabled 120 if(_ldroAuto) { 121 float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw; 122 RADIOLIB_DEBUG_PRINT("Symbol length: "); 123 RADIOLIB_DEBUG_PRINT(symbolLength); 124 RADIOLIB_DEBUG_PRINTLN(" ms"); 125 if(symbolLength >= 16.0) { 126 state = _mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_ON, 3, 3); 127 } else { 128 state = _mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_OFF, 3, 3); 129 } 130 } 131 } 132 return(state); 133 } 134 135 int16_t SX1278::setSpreadingFactor(uint8_t sf) { 136 // check active modem 137 if(getActiveModem() != RADIOLIB_SX127X_LORA) { 138 return(RADIOLIB_ERR_WRONG_MODEM); 139 } 140 141 uint8_t newSpreadingFactor; 142 143 // check allowed spreading factor values 144 switch(sf) { 145 case 6: 146 newSpreadingFactor = RADIOLIB_SX127X_SF_6; 147 break; 148 case 7: 149 newSpreadingFactor = RADIOLIB_SX127X_SF_7; 150 break; 151 case 8: 152 newSpreadingFactor = RADIOLIB_SX127X_SF_8; 153 break; 154 case 9: 155 newSpreadingFactor = RADIOLIB_SX127X_SF_9; 156 break; 157 case 10: 158 newSpreadingFactor = RADIOLIB_SX127X_SF_10; 159 break; 160 case 11: 161 newSpreadingFactor = RADIOLIB_SX127X_SF_11; 162 break; 163 case 12: 164 newSpreadingFactor = RADIOLIB_SX127X_SF_12; 165 break; 166 default: 167 return(RADIOLIB_ERR_INVALID_SPREADING_FACTOR); 168 } 169 170 // set spreading factor and if successful, save the new setting 171 int16_t state = SX1278::setSpreadingFactorRaw(newSpreadingFactor); 172 if(state == RADIOLIB_ERR_NONE) { 173 SX127x::_sf = sf; 174 175 // calculate symbol length and set low data rate optimization, if auto-configuration is enabled 176 if(_ldroAuto) { 177 float symbolLength = (float)(uint32_t(1) << SX127x::_sf) / (float)SX127x::_bw; 178 RADIOLIB_DEBUG_PRINT("Symbol length: "); 179 RADIOLIB_DEBUG_PRINT(symbolLength); 180 RADIOLIB_DEBUG_PRINTLN(" ms"); 181 if(symbolLength >= 16.0) { 182 state = _mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_ON, 3, 3); 183 } else { 184 state = _mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_OFF, 3, 3); 185 } 186 } 187 } 188 return(state); 189 } 190 191 int16_t SX1278::setCodingRate(uint8_t cr) { 192 // check active modem 193 if(getActiveModem() != RADIOLIB_SX127X_LORA) { 194 return(RADIOLIB_ERR_WRONG_MODEM); 195 } 196 197 uint8_t newCodingRate; 198 199 // check allowed coding rate values 200 switch(cr) { 201 case 5: 202 newCodingRate = RADIOLIB_SX1278_CR_4_5; 203 break; 204 case 6: 205 newCodingRate = RADIOLIB_SX1278_CR_4_6; 206 break; 207 case 7: 208 newCodingRate = RADIOLIB_SX1278_CR_4_7; 209 break; 210 case 8: 211 newCodingRate = RADIOLIB_SX1278_CR_4_8; 212 break; 213 default: 214 return(RADIOLIB_ERR_INVALID_CODING_RATE); 215 } 216 217 // set coding rate and if successful, save the new setting 218 int16_t state = SX1278::setCodingRateRaw(newCodingRate); 219 if(state == RADIOLIB_ERR_NONE) { 220 SX127x::_cr = cr; 221 } 222 return(state); 223 } 224 225 int16_t SX1278::setOutputPower(int8_t power, bool useRfo) { 226 // check allowed power range 227 if(useRfo) { 228 // RFO output 229 RADIOLIB_CHECK_RANGE(power, -3, 15, RADIOLIB_ERR_INVALID_OUTPUT_POWER); 230 } else { 231 // PA_BOOST output, check high-power operation 232 if(power != 20) { 233 RADIOLIB_CHECK_RANGE(power, 2, 17, RADIOLIB_ERR_INVALID_OUTPUT_POWER); 234 } 235 } 236 237 // set mode to standby 238 int16_t state = SX127x::standby(); 239 240 if(useRfo) { 241 uint8_t paCfg = 0; 242 if(power < 0) { 243 // low power mode RFO output 244 paCfg = RADIOLIB_SX1278_LOW_POWER | (power + 3); 245 } else { 246 // high power mode RFO output 247 paCfg = RADIOLIB_SX1278_MAX_POWER | power; 248 } 249 250 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX127X_PA_SELECT_RFO, 7, 7); 251 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, paCfg, 6, 0); 252 state |= _mod->SPIsetRegValue(RADIOLIB_SX1278_REG_PA_DAC, RADIOLIB_SX127X_PA_BOOST_OFF, 2, 0); 253 254 } else { 255 if(power != 20) { 256 // power is 2 - 17 dBm, enable PA1 + PA2 on PA_BOOST 257 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX127X_PA_SELECT_BOOST, 7, 7); 258 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX1278_MAX_POWER | (power - 2), 6, 0); 259 state |= _mod->SPIsetRegValue(RADIOLIB_SX1278_REG_PA_DAC, RADIOLIB_SX127X_PA_BOOST_OFF, 2, 0); 260 261 } else { 262 // power is 20 dBm, enable PA1 + PA2 on PA_BOOST and enable high power control 263 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX127X_PA_SELECT_BOOST, 7, 7); 264 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX1278_MAX_POWER | 0x0F, 6, 0); 265 state |= _mod->SPIsetRegValue(RADIOLIB_SX1278_REG_PA_DAC, RADIOLIB_SX127X_PA_BOOST_ON, 2, 0); 266 267 } 268 } 269 270 return(state); 271 } 272 273 int16_t SX1278::setGain(uint8_t gain) { 274 // check allowed range 275 if(gain > 6) { 276 return(RADIOLIB_ERR_INVALID_GAIN); 277 } 278 279 // set mode to standby 280 int16_t state = SX127x::standby(); 281 282 // get modem 283 int16_t modem = getActiveModem(); 284 if(modem == RADIOLIB_SX127X_LORA){ 285 // set gain 286 if(gain == 0) { 287 // gain set to 0, enable AGC loop 288 state |= _mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_AGC_AUTO_ON, 2, 2); 289 } else { 290 state |= _mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_AGC_AUTO_OFF, 2, 2); 291 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_LNA, (gain << 5) | RADIOLIB_SX127X_LNA_BOOST_ON); 292 } 293 294 } else if(modem == RADIOLIB_SX127X_FSK_OOK) { 295 // set gain 296 if(gain == 0) { 297 // gain set to 0, enable AGC loop 298 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_RX_CONFIG, RADIOLIB_SX127X_AGC_AUTO_ON, 3, 3); 299 } else { 300 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_RX_CONFIG, RADIOLIB_SX1278_AGC_AUTO_OFF, 3, 3); 301 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_LNA, (gain << 5) | RADIOLIB_SX127X_LNA_BOOST_ON); 302 } 303 304 } 305 306 return(state); 307 } 308 309 int16_t SX1278::setDataShaping(uint8_t sh) { 310 // check active modem 311 if(getActiveModem() != RADIOLIB_SX127X_FSK_OOK) { 312 return(RADIOLIB_ERR_WRONG_MODEM); 313 } 314 315 // check modulation 316 if(SX127x::_ook) { 317 // we're in OOK mode, the only thing we can do is disable 318 if(sh == RADIOLIB_SHAPING_NONE) { 319 return(setDataShapingOOK(0)); 320 } 321 322 return(RADIOLIB_ERR_INVALID_MODULATION); 323 } 324 325 // set mode to standby 326 int16_t state = SX127x::standby(); 327 RADIOLIB_ASSERT(state); 328 329 // set data shaping 330 switch(sh) { 331 case RADIOLIB_SHAPING_NONE: 332 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_NO_SHAPING, 6, 5)); 333 case RADIOLIB_SHAPING_0_3: 334 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_FSK_GAUSSIAN_0_3, 6, 5)); 335 case RADIOLIB_SHAPING_0_5: 336 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_FSK_GAUSSIAN_0_5, 6, 5)); 337 case RADIOLIB_SHAPING_1_0: 338 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_FSK_GAUSSIAN_1_0, 6, 5)); 339 default: 340 return(RADIOLIB_ERR_INVALID_DATA_SHAPING); 341 } 342 } 343 344 int16_t SX1278::setDataShapingOOK(uint8_t sh) { 345 // check active modem 346 if(getActiveModem() != RADIOLIB_SX127X_FSK_OOK) { 347 return(RADIOLIB_ERR_WRONG_MODEM); 348 } 349 350 // check modulation 351 if(!SX127x::_ook) { 352 return(RADIOLIB_ERR_INVALID_MODULATION); 353 } 354 355 // set mode to standby 356 int16_t state = SX127x::standby(); 357 358 // set data shaping 359 switch(sh) { 360 case 0: 361 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_NO_SHAPING, 6, 5); 362 break; 363 case 1: 364 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_OOK_FILTER_BR, 6, 5); 365 break; 366 case 2: 367 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_OOK_FILTER_2BR, 6, 5); 368 break; 369 default: 370 return(RADIOLIB_ERR_INVALID_DATA_SHAPING); 371 } 372 373 return(state); 374 } 375 376 float SX1278::getRSSI(bool skipReceive) { 377 if(getActiveModem() == RADIOLIB_SX127X_LORA) { 378 // for LoRa, get RSSI of the last packet 379 float lastPacketRSSI; 380 381 // RSSI calculation uses different constant for low-frequency and high-frequency ports 382 if(_freq < 868.0) { 383 lastPacketRSSI = -164 + _mod->SPIgetRegValue(RADIOLIB_SX127X_REG_PKT_RSSI_VALUE); 384 } else { 385 lastPacketRSSI = -157 + _mod->SPIgetRegValue(RADIOLIB_SX127X_REG_PKT_RSSI_VALUE); 386 } 387 388 // spread-spectrum modulation signal can be received below noise floor 389 // check last packet SNR and if it's less than 0, add it to reported RSSI to get the correct value 390 float lastPacketSNR = SX127x::getSNR(); 391 if(lastPacketSNR < 0.0) { 392 lastPacketRSSI += lastPacketSNR; 393 } 394 395 return(lastPacketRSSI); 396 397 } else { 398 // enable listen mode 399 if(!skipReceive) { 400 startReceive(); 401 } 402 403 // read the value for FSK 404 float rssi = (float)_mod->SPIgetRegValue(RADIOLIB_SX127X_REG_RSSI_VALUE_FSK) / -2.0; 405 406 // set mode back to standby 407 if(!skipReceive) { 408 standby(); 409 } 410 411 // return the value 412 return(rssi); 413 } 414 } 415 416 int16_t SX1278::setCRC(bool enable, bool mode) { 417 if(getActiveModem() == RADIOLIB_SX127X_LORA) { 418 // set LoRa CRC 419 SX127x::_crcEnabled = enable; 420 if(enable) { 421 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX1278_RX_CRC_MODE_ON, 2, 2)); 422 } else { 423 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX1278_RX_CRC_MODE_OFF, 2, 2)); 424 } 425 } else { 426 // set FSK CRC 427 int16_t state = RADIOLIB_ERR_NONE; 428 if(enable) { 429 state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_ON, 4, 4); 430 } else { 431 state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_OFF, 4, 4); 432 } 433 RADIOLIB_ASSERT(state); 434 435 // set FSK CRC mode 436 if(mode) { 437 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_WHITENING_TYPE_IBM, 0, 0)); 438 } else { 439 return(_mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_WHITENING_TYPE_CCITT, 0, 0)); 440 } 441 } 442 } 443 444 int16_t SX1278::forceLDRO(bool enable) { 445 if(getActiveModem() != RADIOLIB_SX127X_LORA) { 446 return(RADIOLIB_ERR_WRONG_MODEM); 447 } 448 449 _ldroAuto = false; 450 if(enable) { 451 return(_mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_ON, 3, 3)); 452 } else { 453 return(_mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_OFF, 3, 3)); 454 } 455 } 456 457 int16_t SX1278::autoLDRO() { 458 if(getActiveModem() != RADIOLIB_SX127X_LORA) { 459 return(RADIOLIB_ERR_WRONG_MODEM); 460 } 461 462 _ldroAuto = true; 463 return(RADIOLIB_ERR_NONE); 464 } 465 466 int16_t SX1278::implicitHeader(size_t len) { 467 return(setHeaderType(RADIOLIB_SX1278_HEADER_IMPL_MODE, len)); 468 } 469 470 int16_t SX1278::explicitHeader() { 471 return(setHeaderType(RADIOLIB_SX1278_HEADER_EXPL_MODE)); 472 } 473 474 int16_t SX1278::setBandwidthRaw(uint8_t newBandwidth) { 475 // set mode to standby 476 int16_t state = SX127x::standby(); 477 478 // write register 479 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, newBandwidth, 7, 4); 480 return(state); 481 } 482 483 int16_t SX1278::setSpreadingFactorRaw(uint8_t newSpreadingFactor) { 484 // set mode to standby 485 int16_t state = SX127x::standby(); 486 487 // write registers 488 if(newSpreadingFactor == RADIOLIB_SX127X_SF_6) { 489 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1278_HEADER_IMPL_MODE, 0, 0); 490 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX127X_SF_6 | RADIOLIB_SX127X_TX_MODE_SINGLE | (SX127x::_crcEnabled ? RADIOLIB_SX1278_RX_CRC_MODE_ON : RADIOLIB_SX1278_RX_CRC_MODE_OFF), 7, 2); 491 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECT_OPTIMIZE, RADIOLIB_SX127X_DETECT_OPTIMIZE_SF_6, 2, 0); 492 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECTION_THRESHOLD, RADIOLIB_SX127X_DETECTION_THRESHOLD_SF_6); 493 } else { 494 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1278_HEADER_EXPL_MODE, 0, 0); 495 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, newSpreadingFactor | RADIOLIB_SX127X_TX_MODE_SINGLE | (SX127x::_crcEnabled ? RADIOLIB_SX1278_RX_CRC_MODE_ON : RADIOLIB_SX1278_RX_CRC_MODE_OFF), 7, 2); 496 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECT_OPTIMIZE, RADIOLIB_SX127X_DETECT_OPTIMIZE_SF_7_12, 2, 0); 497 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECTION_THRESHOLD, RADIOLIB_SX127X_DETECTION_THRESHOLD_SF_7_12); 498 } 499 return(state); 500 } 501 502 int16_t SX1278::setCodingRateRaw(uint8_t newCodingRate) { 503 // set mode to standby 504 int16_t state = SX127x::standby(); 505 506 // write register 507 state |= _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, newCodingRate, 3, 1); 508 return(state); 509 } 510 511 int16_t SX1278::setHeaderType(uint8_t headerType, size_t len) { 512 // check active modem 513 if(getActiveModem() != RADIOLIB_SX127X_LORA) { 514 return(RADIOLIB_ERR_WRONG_MODEM); 515 } 516 517 // set requested packet mode 518 int16_t state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, headerType, 0, 0); 519 RADIOLIB_ASSERT(state); 520 521 // set length to register 522 state = _mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len); 523 RADIOLIB_ASSERT(state); 524 525 // update cached value 526 _packetLength = len; 527 528 return(state); 529 } 530 531 int16_t SX1278::configFSK() { 532 // configure common registers 533 int16_t state = SX127x::configFSK(); 534 RADIOLIB_ASSERT(state); 535 536 // set fast PLL hop 537 state = _mod->SPIsetRegValue(RADIOLIB_SX1278_REG_PLL_HOP, RADIOLIB_SX127X_FAST_HOP_ON, 7, 7); 538 return(state); 539 } 540 541 void SX1278::errataFix(bool rx) { 542 // only apply in LoRa mode 543 if(getActiveModem() != RADIOLIB_SX127X_LORA) { 544 return; 545 } 546 547 // sensitivity optimization for 500kHz bandwidth 548 // see SX1276/77/78 Errata, section 2.1 for details 549 if(fabs(_bw - 500.0) <= 0.001) { 550 if((_freq >= 862.0) && (_freq <= 1020.0)) { 551 _mod->SPIwriteRegister(0x36, 0x02); 552 _mod->SPIwriteRegister(0x3a, 0x64); 553 } else if((_freq >= 410.0) && (_freq <= 525.0)) { 554 _mod->SPIwriteRegister(0x36, 0x02); 555 _mod->SPIwriteRegister(0x3a, 0x7F); 556 } 557 } 558 559 // mitigation of receiver spurious response 560 // see SX1276/77/78 Errata, section 2.3 for details 561 562 // figure out what we need to set 563 uint8_t fixedRegs[3] = { 0x00, 0x00, 0x00 }; 564 float rxFreq = _freq; 565 if(fabs(_bw - 7.8) <= 0.001) { 566 fixedRegs[0] = 0b0000000; 567 fixedRegs[1] = 0x48; 568 fixedRegs[2] = 0x00; 569 rxFreq += 0.00781; 570 } else if(fabs(_bw - 10.4) <= 0.001) { 571 fixedRegs[0] = 0b0000000; 572 fixedRegs[1] = 0x44; 573 fixedRegs[2] = 0x00; 574 rxFreq += 0.01042; 575 } else if(fabs(_bw - 15.6) <= 0.001) { 576 fixedRegs[0] = 0b0000000; 577 fixedRegs[1] = 0x44; 578 fixedRegs[2] = 0x00; 579 rxFreq += 0.01562; 580 } else if(fabs(_bw - 20.8) <= 0.001) { 581 fixedRegs[0] = 0b0000000; 582 fixedRegs[1] = 0x44; 583 fixedRegs[2] = 0x00; 584 rxFreq += 0.02083; 585 } else if(fabs(_bw - 31.25) <= 0.001) { 586 fixedRegs[0] = 0b0000000; 587 fixedRegs[1] = 0x44; 588 fixedRegs[2] = 0x00; 589 rxFreq += 0.03125; 590 } else if(fabs(_bw - 41.7) <= 0.001) { 591 fixedRegs[0] = 0b0000000; 592 fixedRegs[1] = 0x44; 593 fixedRegs[2] = 0x00; 594 rxFreq += 0.04167; 595 } else if(fabs(_bw - 62.5) <= 0.001) { 596 fixedRegs[0] = 0b0000000; 597 fixedRegs[1] = 0x40; 598 fixedRegs[2] = 0x00; 599 } else if(fabs(_bw - 125.0) <= 0.001) { 600 fixedRegs[0] = 0b0000000; 601 fixedRegs[1] = 0x40; 602 fixedRegs[2] = 0x00; 603 } else if(fabs(_bw - 250.0) <= 0.001) { 604 fixedRegs[0] = 0b0000000; 605 fixedRegs[1] = 0x40; 606 fixedRegs[2] = 0x00; 607 } else if(fabs(_bw - 500.0) <= 0.001) { 608 fixedRegs[0] = 0b1000000; 609 fixedRegs[1] = _mod->SPIreadRegister(0x2F); 610 fixedRegs[2] = _mod->SPIreadRegister(0x30); 611 } else { 612 return; 613 } 614 615 // first, go to standby 616 standby(); 617 618 // shift the freqency up when receiving, or restore the original when transmitting 619 if(rx) { 620 SX127x::setFrequencyRaw(rxFreq); 621 } else { 622 SX127x::setFrequencyRaw(_freq); 623 } 624 625 // finally, apply errata fixes 626 _mod->SPIsetRegValue(0x31, fixedRegs[0], 7, 7); 627 _mod->SPIsetRegValue(0x2F, fixedRegs[1]); 628 _mod->SPIsetRegValue(0x30, fixedRegs[2]); 629 } 630 631 #endif