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 |
SX126x.cpp (56526B)
1 #include "SX126x.h" 2 #if !defined(RADIOLIB_EXCLUDE_SX126X) 3 4 SX126x::SX126x(Module* mod) : PhysicalLayer(RADIOLIB_SX126X_FREQUENCY_STEP_SIZE, RADIOLIB_SX126X_MAX_PACKET_LENGTH) { 5 _mod = mod; 6 } 7 8 Module* SX126x::getMod() { 9 return(_mod); 10 } 11 12 int16_t SX126x::begin(uint8_t cr, uint8_t syncWord, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) { 13 // set module properties 14 _mod->init(); 15 _mod->pinMode(_mod->getIrq(), INPUT); 16 _mod->pinMode(_mod->getGpio(), INPUT); 17 RADIOLIB_DEBUG_PRINTLN(F("M\tSX126x")); 18 19 // BW in kHz and SF are required in order to calculate LDRO for setModulationParams 20 // set the defaults, this will get overwritten later anyway 21 _bwKhz = 500.0; 22 _sf = 9; 23 24 // initialize configuration variables (will be overwritten during public settings configuration) 25 _bw = RADIOLIB_SX126X_LORA_BW_500_0; // initialized to 500 kHz, since lower valeus will interfere with LLCC68 26 _cr = RADIOLIB_SX126X_LORA_CR_4_7; 27 _ldro = 0x00; 28 _crcType = RADIOLIB_SX126X_LORA_CRC_ON; 29 _preambleLength = preambleLength; 30 _tcxoDelay = 0; 31 _headerType = RADIOLIB_SX126X_LORA_HEADER_EXPLICIT; 32 _implicitLen = 0xFF; 33 34 // reset the module and verify startup 35 int16_t state = reset(); 36 RADIOLIB_ASSERT(state); 37 38 // set mode to standby 39 state = standby(); 40 RADIOLIB_ASSERT(state); 41 42 // configure settings not accessible by API 43 state = config(RADIOLIB_SX126X_PACKET_TYPE_LORA); 44 RADIOLIB_ASSERT(state); 45 46 // set TCXO control, if requested 47 if(tcxoVoltage > 0.0) { 48 state = setTCXO(tcxoVoltage); 49 RADIOLIB_ASSERT(state); 50 } 51 52 // configure publicly accessible settings 53 state = setCodingRate(cr); 54 RADIOLIB_ASSERT(state); 55 56 state = setSyncWord(syncWord); 57 RADIOLIB_ASSERT(state); 58 59 state = setPreambleLength(preambleLength); 60 RADIOLIB_ASSERT(state); 61 62 // set publicly accessible settings that are not a part of begin method 63 state = setCurrentLimit(60.0); 64 RADIOLIB_ASSERT(state); 65 66 state = setDio2AsRfSwitch(true); 67 RADIOLIB_ASSERT(state); 68 69 if (useRegulatorLDO) { 70 state = setRegulatorLDO(); 71 } else { 72 state = setRegulatorDCDC(); 73 } 74 75 return(state); 76 } 77 78 int16_t SX126x::beginFSK(float br, float freqDev, float rxBw, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) { 79 // set module properties 80 _mod->init(); 81 _mod->pinMode(_mod->getIrq(), INPUT); 82 _mod->pinMode(_mod->getGpio(), INPUT); 83 RADIOLIB_DEBUG_PRINTLN(F("M\tSX126x")); 84 85 // initialize configuration variables (will be overwritten during public settings configuration) 86 _br = 21333; // 48.0 kbps 87 _freqDev = 52428; // 50.0 kHz 88 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_156_2; 89 _rxBwKhz = 156.2; 90 _pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_5; 91 _crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_2_BYTE_INV; // CCIT CRC configuration 92 _preambleLengthFSK = preambleLength; 93 _addrComp = RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF; 94 95 // reset the module and verify startup 96 int16_t state = reset(); 97 RADIOLIB_ASSERT(state); 98 99 // set mode to standby 100 state = standby(); 101 RADIOLIB_ASSERT(state); 102 103 // configure settings not accessible by API 104 state = config(RADIOLIB_SX126X_PACKET_TYPE_GFSK); 105 RADIOLIB_ASSERT(state); 106 107 // set TCXO control, if requested 108 if(tcxoVoltage > 0.0) { 109 state = setTCXO(tcxoVoltage); 110 RADIOLIB_ASSERT(state); 111 } 112 113 // configure publicly accessible settings 114 state = setBitRate(br); 115 RADIOLIB_ASSERT(state); 116 117 state = setFrequencyDeviation(freqDev); 118 RADIOLIB_ASSERT(state); 119 120 state = setRxBandwidth(rxBw); 121 RADIOLIB_ASSERT(state); 122 123 state = setCurrentLimit(60.0); 124 RADIOLIB_ASSERT(state); 125 126 state = setPreambleLength(preambleLength); 127 RADIOLIB_ASSERT(state); 128 129 if(useRegulatorLDO) { 130 state = setRegulatorLDO(); 131 } else { 132 state = setRegulatorDCDC(); 133 } 134 RADIOLIB_ASSERT(state); 135 136 // set publicly accessible settings that are not a part of begin method 137 uint8_t sync[] = {0x12, 0xAD}; 138 state = setSyncWord(sync, 2); 139 RADIOLIB_ASSERT(state); 140 141 state = setDataShaping(RADIOLIB_SHAPING_NONE); 142 RADIOLIB_ASSERT(state); 143 144 state = setEncoding(RADIOLIB_ENCODING_NRZ); 145 RADIOLIB_ASSERT(state); 146 147 state = variablePacketLengthMode(RADIOLIB_SX126X_MAX_PACKET_LENGTH); 148 RADIOLIB_ASSERT(state); 149 150 state = setCRC(2); 151 RADIOLIB_ASSERT(state); 152 153 state = setDio2AsRfSwitch(false); 154 RADIOLIB_ASSERT(state); 155 156 return(state); 157 } 158 159 int16_t SX126x::reset(bool verify) { 160 // run the reset sequence 161 _mod->pinMode(_mod->getRst(), OUTPUT); 162 _mod->digitalWrite(_mod->getRst(), LOW); 163 _mod->delay(1); 164 _mod->digitalWrite(_mod->getRst(), HIGH); 165 166 // return immediately when verification is disabled 167 if(!verify) { 168 return(RADIOLIB_ERR_NONE); 169 } 170 171 // set mode to standby - SX126x often refuses first few commands after reset 172 uint32_t start = _mod->millis(); 173 while(true) { 174 // try to set mode to standby 175 int16_t state = standby(); 176 if(state == RADIOLIB_ERR_NONE) { 177 // standby command successful 178 return(RADIOLIB_ERR_NONE); 179 } 180 181 // standby command failed, check timeout and try again 182 if(_mod->millis() - start >= 3000) { 183 // timed out, possibly incorrect wiring 184 return(state); 185 } 186 187 // wait a bit to not spam the module 188 _mod->delay(10); 189 } 190 } 191 192 int16_t SX126x::transmit(uint8_t* data, size_t len, uint8_t addr) { 193 // set mode to standby 194 int16_t state = standby(); 195 RADIOLIB_ASSERT(state); 196 197 // check packet length 198 if(len > RADIOLIB_SX126X_MAX_PACKET_LENGTH) { 199 return(RADIOLIB_ERR_PACKET_TOO_LONG); 200 } 201 202 uint32_t timeout = 0; 203 204 // get currently active modem 205 uint8_t modem = getPacketType(); 206 if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) { 207 // calculate timeout (150% of expected time-on-air) 208 timeout = (getTimeOnAir(len) * 3) / 2; 209 210 } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 211 // calculate timeout (500% of expected time-on-air) 212 timeout = getTimeOnAir(len) * 5; 213 214 } else { 215 return(RADIOLIB_ERR_UNKNOWN); 216 } 217 218 RADIOLIB_DEBUG_PRINT(F("Timeout in ")); 219 RADIOLIB_DEBUG_PRINT(timeout); 220 RADIOLIB_DEBUG_PRINTLN(F(" us")); 221 222 // start transmission 223 state = startTransmit(data, len, addr); 224 RADIOLIB_ASSERT(state); 225 226 // wait for packet transmission or timeout 227 uint32_t start = _mod->micros(); 228 while(!_mod->digitalRead(_mod->getIrq())) { 229 _mod->yield(); 230 if(_mod->micros() - start > timeout) { 231 clearIrqStatus(); 232 standby(); 233 return(RADIOLIB_ERR_TX_TIMEOUT); 234 } 235 } 236 uint32_t elapsed = _mod->micros() - start; 237 238 // update data rate 239 _dataRate = (len*8.0)/((float)elapsed/1000000.0); 240 241 // clear interrupt flags 242 state = clearIrqStatus(); 243 RADIOLIB_ASSERT(state); 244 245 // set mode to standby to disable transmitter 246 state = standby(); 247 248 return(state); 249 } 250 251 int16_t SX126x::receive(uint8_t* data, size_t len) { 252 // set mode to standby 253 int16_t state = standby(); 254 RADIOLIB_ASSERT(state); 255 256 uint32_t timeout = 0; 257 258 // get currently active modem 259 uint8_t modem = getPacketType(); 260 if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) { 261 // calculate timeout (100 LoRa symbols, the default for SX127x series) 262 float symbolLength = (float)(uint32_t(1) << _sf) / (float)_bwKhz; 263 timeout = (uint32_t)(symbolLength * 100.0 * 1000.0); 264 } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 265 // calculate timeout (500 % of expected time-one-air) 266 size_t maxLen = len; 267 if(len == 0) { 268 maxLen = 0xFF; 269 } 270 float brBps = ((float)(RADIOLIB_SX126X_CRYSTAL_FREQ) * 1000000.0 * 32.0) / (float)_br; 271 timeout = (uint32_t)(((maxLen * 8.0) / brBps) * 1000000.0 * 5.0); 272 273 } else { 274 return(RADIOLIB_ERR_UNKNOWN); 275 } 276 277 RADIOLIB_DEBUG_PRINT(F("Timeout in ")); 278 RADIOLIB_DEBUG_PRINT(timeout); 279 RADIOLIB_DEBUG_PRINTLN(F(" us")); 280 281 // start reception 282 uint32_t timeoutValue = (uint32_t)((float)timeout / 15.625); 283 state = startReceive(timeoutValue); 284 RADIOLIB_ASSERT(state); 285 286 // wait for packet reception or timeout 287 uint32_t start = _mod->micros(); 288 while(!_mod->digitalRead(_mod->getIrq())) { 289 _mod->yield(); 290 if(_mod->micros() - start > timeout) { 291 fixImplicitTimeout(); 292 clearIrqStatus(); 293 standby(); 294 return(RADIOLIB_ERR_RX_TIMEOUT); 295 } 296 } 297 298 // fix timeout in implicit LoRa mode 299 if(((_headerType == RADIOLIB_SX126X_LORA_HEADER_IMPLICIT) && (getPacketType() == RADIOLIB_SX126X_PACKET_TYPE_LORA))) { 300 state = fixImplicitTimeout(); 301 RADIOLIB_ASSERT(state); 302 } 303 304 // read the received data 305 return(readData(data, len)); 306 } 307 308 int16_t SX126x::transmitDirect(uint32_t frf) { 309 // set RF switch (if present) 310 _mod->setRfSwitchState(LOW, HIGH); 311 312 // user requested to start transmitting immediately (required for RTTY) 313 int16_t state = RADIOLIB_ERR_NONE; 314 if(frf != 0) { 315 state = setRfFrequency(frf); 316 } 317 RADIOLIB_ASSERT(state); 318 319 // start transmitting 320 uint8_t data[] = {RADIOLIB_SX126X_CMD_NOP}; 321 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_TX_CONTINUOUS_WAVE, data, 1)); 322 } 323 324 int16_t SX126x::receiveDirect() { 325 // set RF switch (if present) 326 _mod->setRfSwitchState(HIGH, LOW); 327 328 // SX126x is unable to output received data directly 329 return(RADIOLIB_ERR_UNKNOWN); 330 } 331 332 int16_t SX126x::scanChannel() { 333 // set mode to CAD 334 int state = startChannelScan(); 335 RADIOLIB_ASSERT(state); 336 337 // wait for channel activity detected or timeout 338 while(!_mod->digitalRead(_mod->getIrq())) { 339 _mod->yield(); 340 } 341 342 // check CAD result 343 return(getChannelScanResult()); 344 } 345 346 int16_t SX126x::sleep(bool retainConfig) { 347 // set RF switch (if present) 348 _mod->setRfSwitchState(LOW, LOW); 349 350 uint8_t sleepMode = RADIOLIB_SX126X_SLEEP_START_WARM | RADIOLIB_SX126X_SLEEP_RTC_OFF; 351 if(!retainConfig) { 352 sleepMode = RADIOLIB_SX126X_SLEEP_START_COLD | RADIOLIB_SX126X_SLEEP_RTC_OFF; 353 } 354 int16_t state = SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_SLEEP, &sleepMode, 1, false); 355 356 // wait for SX126x to safely enter sleep mode 357 _mod->delay(1); 358 359 return(state); 360 } 361 362 int16_t SX126x::standby() { 363 return(SX126x::standby(RADIOLIB_SX126X_STANDBY_RC)); 364 } 365 366 int16_t SX126x::standby(uint8_t mode) { 367 // set RF switch (if present) 368 _mod->setRfSwitchState(LOW, LOW); 369 370 uint8_t data[] = {mode}; 371 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_STANDBY, data, 1)); 372 } 373 374 void SX126x::setDio1Action(void (*func)(void)) { 375 _mod->attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, RISING); 376 } 377 378 void SX126x::clearDio1Action() { 379 _mod->detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq())); 380 } 381 382 int16_t SX126x::startTransmit(uint8_t* data, size_t len, uint8_t addr) { 383 // suppress unused variable warning 384 (void)addr; 385 386 // check packet length 387 if(len > RADIOLIB_SX126X_MAX_PACKET_LENGTH) { 388 return(RADIOLIB_ERR_PACKET_TOO_LONG); 389 } 390 391 // maximum packet length is decreased by 1 when address filtering is active 392 if((_addrComp != RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF) && (len > RADIOLIB_SX126X_MAX_PACKET_LENGTH - 1)) { 393 return(RADIOLIB_ERR_PACKET_TOO_LONG); 394 } 395 396 // set packet Length 397 int16_t state = RADIOLIB_ERR_NONE; 398 uint8_t modem = getPacketType(); 399 if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) { 400 state = setPacketParams(_preambleLength, _crcType, len, _headerType); 401 } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 402 state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType, len); 403 } else { 404 return(RADIOLIB_ERR_UNKNOWN); 405 } 406 RADIOLIB_ASSERT(state); 407 408 // set DIO mapping 409 state = setDioIrqParams(RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_TIMEOUT, RADIOLIB_SX126X_IRQ_TX_DONE); 410 RADIOLIB_ASSERT(state); 411 412 // set buffer pointers 413 state = setBufferBaseAddress(); 414 RADIOLIB_ASSERT(state); 415 416 // write packet to buffer 417 state = writeBuffer(data, len); 418 RADIOLIB_ASSERT(state); 419 420 // clear interrupt flags 421 state = clearIrqStatus(); 422 RADIOLIB_ASSERT(state); 423 424 // fix sensitivity 425 state = fixSensitivity(); 426 RADIOLIB_ASSERT(state); 427 428 // set RF switch (if present) 429 _mod->setRfSwitchState(LOW, HIGH); 430 431 // start transmission 432 state = setTx(RADIOLIB_SX126X_TX_TIMEOUT_NONE); 433 RADIOLIB_ASSERT(state); 434 435 // wait for BUSY to go low (= PA ramp up done) 436 while(_mod->digitalRead(_mod->getGpio())) { 437 _mod->yield(); 438 } 439 440 return(state); 441 } 442 443 int16_t SX126x::startReceive(uint32_t timeout) { 444 int16_t state = startReceiveCommon(timeout); 445 RADIOLIB_ASSERT(state); 446 447 // set RF switch (if present) 448 _mod->setRfSwitchState(HIGH, LOW); 449 450 // set mode to receive 451 state = setRx(timeout); 452 453 return(state); 454 } 455 456 int16_t SX126x::startReceiveDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod) { 457 // datasheet claims time to go to sleep is ~500us, same to wake up, compensate for that with 1 ms + TCXO delay 458 uint32_t transitionTime = _tcxoDelay + 1000; 459 sleepPeriod -= transitionTime; 460 461 // divide by 15.625 462 uint32_t rxPeriodRaw = (rxPeriod * 8) / 125; 463 uint32_t sleepPeriodRaw = (sleepPeriod * 8) / 125; 464 465 // check 24 bit limit and zero value (likely not intended) 466 if((rxPeriodRaw & 0xFF000000) || (rxPeriodRaw == 0)) { 467 return(RADIOLIB_ERR_INVALID_RX_PERIOD); 468 } 469 470 // this check of the high byte also catches underflow when we subtracted transitionTime 471 if((sleepPeriodRaw & 0xFF000000) || (sleepPeriodRaw == 0)) { 472 return(RADIOLIB_ERR_INVALID_SLEEP_PERIOD); 473 } 474 475 int16_t state = startReceiveCommon(); 476 RADIOLIB_ASSERT(state); 477 478 uint8_t data[6] = {(uint8_t)((rxPeriodRaw >> 16) & 0xFF), (uint8_t)((rxPeriodRaw >> 8) & 0xFF), (uint8_t)(rxPeriodRaw & 0xFF), 479 (uint8_t)((sleepPeriodRaw >> 16) & 0xFF), (uint8_t)((sleepPeriodRaw >> 8) & 0xFF), (uint8_t)(sleepPeriodRaw & 0xFF)}; 480 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_RX_DUTY_CYCLE, data, 6)); 481 } 482 483 int16_t SX126x::startReceiveDutyCycleAuto(uint16_t senderPreambleLength, uint16_t minSymbols) { 484 if(senderPreambleLength == 0) { 485 senderPreambleLength = _preambleLength; 486 } 487 488 // worst case is that the sender starts transmitting when we're just less than minSymbols from going back to sleep. 489 // in this case, we don't catch minSymbols before going to sleep, 490 // so we must be awake for at least that long before the sender stops transmitting. 491 uint16_t sleepSymbols = senderPreambleLength - 2 * minSymbols; 492 493 // if we're not to sleep at all, just use the standard startReceive. 494 if(2 * minSymbols > senderPreambleLength) { 495 return(startReceive()); 496 } 497 498 uint32_t symbolLength = ((uint32_t)(10 * 1000) << _sf) / (10 * _bwKhz); 499 uint32_t sleepPeriod = symbolLength * sleepSymbols; 500 RADIOLIB_DEBUG_PRINT(F("Auto sleep period: ")); 501 RADIOLIB_DEBUG_PRINTLN(sleepPeriod); 502 503 // when the unit detects a preamble, it starts a timer that will timeout if it doesn't receive a header in time. 504 // the duration is sleepPeriod + 2 * wakePeriod. 505 // The sleepPeriod doesn't take into account shutdown and startup time for the unit (~1ms) 506 // We need to ensure that the timeout is longer than senderPreambleLength. 507 // So we must satisfy: wakePeriod > (preamblePeriod - (sleepPeriod - 1000)) / 2. (A) 508 // we also need to ensure the unit is awake to see at least minSymbols. (B) 509 uint32_t wakePeriod = max( 510 (symbolLength * (senderPreambleLength + 1) - (sleepPeriod - 1000)) / 2, // (A) 511 symbolLength * (minSymbols + 1)); //(B) 512 RADIOLIB_DEBUG_PRINT(F("Auto wake period: ")); 513 RADIOLIB_DEBUG_PRINTLN(wakePeriod); 514 515 // If our sleep period is shorter than our transition time, just use the standard startReceive 516 if(sleepPeriod < _tcxoDelay + 1016) { 517 return(startReceive()); 518 } 519 520 return(startReceiveDutyCycle(wakePeriod, sleepPeriod)); 521 } 522 523 int16_t SX126x::startReceiveCommon(uint32_t timeout) { 524 // set DIO mapping 525 uint16_t mask = RADIOLIB_SX126X_IRQ_RX_DONE; 526 if(timeout != RADIOLIB_SX126X_RX_TIMEOUT_INF) { 527 mask |= RADIOLIB_SX126X_IRQ_TIMEOUT; 528 } 529 int16_t state = setDioIrqParams(RADIOLIB_SX126X_IRQ_RX_DONE | RADIOLIB_SX126X_IRQ_TIMEOUT | RADIOLIB_SX126X_IRQ_CRC_ERR | RADIOLIB_SX126X_IRQ_HEADER_ERR, mask); 530 RADIOLIB_ASSERT(state); 531 532 // set buffer pointers 533 state = setBufferBaseAddress(); 534 RADIOLIB_ASSERT(state); 535 536 // clear interrupt flags 537 state = clearIrqStatus(); 538 539 // restore original packet length 540 uint8_t modem = getPacketType(); 541 if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) { 542 state = setPacketParams(_preambleLength, _crcType, _implicitLen, _headerType); 543 } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 544 state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType); 545 } else { 546 return(RADIOLIB_ERR_UNKNOWN); 547 } 548 549 return(state); 550 } 551 552 int16_t SX126x::readData(uint8_t* data, size_t len) { 553 // set mode to standby 554 int16_t state = standby(); 555 RADIOLIB_ASSERT(state); 556 557 // check integrity CRC 558 uint16_t irq = getIrqStatus(); 559 int16_t crcState = RADIOLIB_ERR_NONE; 560 if((irq & RADIOLIB_SX126X_IRQ_CRC_ERR) || (irq & RADIOLIB_SX126X_IRQ_HEADER_ERR)) { 561 crcState = RADIOLIB_ERR_CRC_MISMATCH; 562 } 563 564 // get packet length 565 size_t length = getPacketLength(); 566 if((len != 0) && (len < length)) { 567 // user requested less data than we got, only return what was requested 568 length = len; 569 } 570 571 // read packet data 572 state = readBuffer(data, length); 573 RADIOLIB_ASSERT(state); 574 575 // clear interrupt flags 576 state = clearIrqStatus(); 577 578 // check if CRC failed - this is done after reading data to give user the option to keep them 579 RADIOLIB_ASSERT(crcState); 580 581 return(state); 582 } 583 584 int16_t SX126x::startChannelScan() { 585 // check active modem 586 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) { 587 return(RADIOLIB_ERR_WRONG_MODEM); 588 } 589 590 // set mode to standby 591 int16_t state = standby(); 592 RADIOLIB_ASSERT(state); 593 594 // set RF switch (if present) 595 _mod->setRfSwitchState(HIGH, LOW); 596 597 // set DIO pin mapping 598 state = setDioIrqParams(RADIOLIB_SX126X_IRQ_CAD_DETECTED | RADIOLIB_SX126X_IRQ_CAD_DONE, RADIOLIB_SX126X_IRQ_CAD_DETECTED | RADIOLIB_SX126X_IRQ_CAD_DONE); 599 RADIOLIB_ASSERT(state); 600 601 // clear interrupt flags 602 state = clearIrqStatus(); 603 RADIOLIB_ASSERT(state); 604 605 // set mode to CAD 606 state = setCad(); 607 return(state); 608 } 609 610 int16_t SX126x::getChannelScanResult() { 611 // check active modem 612 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) { 613 return(RADIOLIB_ERR_WRONG_MODEM); 614 } 615 616 // check CAD result 617 uint16_t cadResult = getIrqStatus(); 618 if(cadResult & RADIOLIB_SX126X_IRQ_CAD_DETECTED) { 619 // detected some LoRa activity 620 clearIrqStatus(); 621 return(RADIOLIB_LORA_DETECTED); 622 } else if(cadResult & RADIOLIB_SX126X_IRQ_CAD_DONE) { 623 // channel is free 624 clearIrqStatus(); 625 return(RADIOLIB_CHANNEL_FREE); 626 } 627 628 return(RADIOLIB_ERR_UNKNOWN); 629 } 630 631 int16_t SX126x::setBandwidth(float bw) { 632 // check active modem 633 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) { 634 return(RADIOLIB_ERR_WRONG_MODEM); 635 } 636 637 // ensure byte conversion doesn't overflow 638 RADIOLIB_CHECK_RANGE(bw, 0.0, 510.0, RADIOLIB_ERR_INVALID_BANDWIDTH); 639 640 // check allowed bandwidth values 641 uint8_t bw_div2 = bw / 2 + 0.01; 642 switch (bw_div2) { 643 case 3: // 7.8: 644 _bw = RADIOLIB_SX126X_LORA_BW_7_8; 645 break; 646 case 5: // 10.4: 647 _bw = RADIOLIB_SX126X_LORA_BW_10_4; 648 break; 649 case 7: // 15.6: 650 _bw = RADIOLIB_SX126X_LORA_BW_15_6; 651 break; 652 case 10: // 20.8: 653 _bw = RADIOLIB_SX126X_LORA_BW_20_8; 654 break; 655 case 15: // 31.25: 656 _bw = RADIOLIB_SX126X_LORA_BW_31_25; 657 break; 658 case 20: // 41.7: 659 _bw = RADIOLIB_SX126X_LORA_BW_41_7; 660 break; 661 case 31: // 62.5: 662 _bw = RADIOLIB_SX126X_LORA_BW_62_5; 663 break; 664 case 62: // 125.0: 665 _bw = RADIOLIB_SX126X_LORA_BW_125_0; 666 break; 667 case 125: // 250.0 668 _bw = RADIOLIB_SX126X_LORA_BW_250_0; 669 break; 670 case 250: // 500.0 671 _bw = RADIOLIB_SX126X_LORA_BW_500_0; 672 break; 673 default: 674 return(RADIOLIB_ERR_INVALID_BANDWIDTH); 675 } 676 677 // update modulation parameters 678 _bwKhz = bw; 679 return(setModulationParams(_sf, _bw, _cr, _ldro)); 680 } 681 682 int16_t SX126x::setSpreadingFactor(uint8_t sf) { 683 // check active modem 684 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) { 685 return(RADIOLIB_ERR_WRONG_MODEM); 686 } 687 688 RADIOLIB_CHECK_RANGE(sf, 5, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR); 689 690 // update modulation parameters 691 _sf = sf; 692 return(setModulationParams(_sf, _bw, _cr, _ldro)); 693 } 694 695 int16_t SX126x::setCodingRate(uint8_t cr) { 696 // check active modem 697 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) { 698 return(RADIOLIB_ERR_WRONG_MODEM); 699 } 700 701 RADIOLIB_CHECK_RANGE(cr, 5, 8, RADIOLIB_ERR_INVALID_CODING_RATE); 702 703 // update modulation parameters 704 _cr = cr - 4; 705 return(setModulationParams(_sf, _bw, _cr, _ldro)); 706 } 707 708 int16_t SX126x::setSyncWord(uint8_t syncWord, uint8_t controlBits) { 709 // check active modem 710 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) { 711 return(RADIOLIB_ERR_WRONG_MODEM); 712 } 713 714 // update register 715 uint8_t data[2] = {(uint8_t)((syncWord & 0xF0) | ((controlBits & 0xF0) >> 4)), (uint8_t)(((syncWord & 0x0F) << 4) | (controlBits & 0x0F))}; 716 return(writeRegister(RADIOLIB_SX126X_REG_LORA_SYNC_WORD_MSB, data, 2)); 717 } 718 719 int16_t SX126x::setCurrentLimit(float currentLimit) { 720 // check allowed range 721 if(!((currentLimit >= 0) && (currentLimit <= 140))) { 722 return(RADIOLIB_ERR_INVALID_CURRENT_LIMIT); 723 } 724 725 // calculate raw value 726 uint8_t rawLimit = (uint8_t)(currentLimit / 2.5); 727 728 // update register 729 return(writeRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &rawLimit, 1)); 730 } 731 732 float SX126x::getCurrentLimit() { 733 // get the raw value 734 uint8_t ocp = 0; 735 readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1); 736 737 // return the actual value 738 return((float)ocp * 2.5); 739 } 740 741 int16_t SX126x::setPreambleLength(uint16_t preambleLength) { 742 uint8_t modem = getPacketType(); 743 if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) { 744 _preambleLength = preambleLength; 745 return(setPacketParams(_preambleLength, _crcType, _implicitLen, _headerType)); 746 } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 747 _preambleLengthFSK = preambleLength; 748 return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType)); 749 } 750 751 return(RADIOLIB_ERR_UNKNOWN); 752 } 753 754 int16_t SX126x::setFrequencyDeviation(float freqDev) { 755 // check active modem 756 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 757 return(RADIOLIB_ERR_WRONG_MODEM); 758 } 759 760 // set frequency deviation to lowest available setting (required for digimodes) 761 float newFreqDev = freqDev; 762 if(freqDev < 0.0) { 763 newFreqDev = 0.6; 764 } 765 766 RADIOLIB_CHECK_RANGE(newFreqDev, 0.6, 200.0, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION); 767 768 // calculate raw frequency deviation value 769 uint32_t freqDevRaw = (uint32_t)(((newFreqDev * 1000.0) * (float)((uint32_t)(1) << 25)) / (RADIOLIB_SX126X_CRYSTAL_FREQ * 1000000.0)); 770 771 // check modulation parameters 772 /*if(2 * freqDevRaw + _br > _rxBwKhz * 1000.0) { 773 return(RADIOLIB_ERR_INVALID_MODULATION_PARAMETERS); 774 }*/ 775 _freqDev = freqDevRaw; 776 777 // update modulation parameters 778 return(setModulationParamsFSK(_br, _pulseShape, _rxBw, _freqDev)); 779 } 780 781 int16_t SX126x::setBitRate(float br) { 782 // check active modem 783 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 784 return(RADIOLIB_ERR_WRONG_MODEM); 785 } 786 787 RADIOLIB_CHECK_RANGE(br, 0.6, 300.0, RADIOLIB_ERR_INVALID_BIT_RATE); 788 789 // calculate raw bit rate value 790 uint32_t brRaw = (uint32_t)((RADIOLIB_SX126X_CRYSTAL_FREQ * 1000000.0 * 32.0) / (br * 1000.0)); 791 792 // check modulation parameters 793 /*if(2 * _freqDev + brRaw > _rxBwKhz * 1000.0) { 794 return(RADIOLIB_ERR_INVALID_MODULATION_PARAMETERS); 795 }*/ 796 _br = brRaw; 797 798 // update modulation parameters 799 return(setModulationParamsFSK(_br, _pulseShape, _rxBw, _freqDev)); 800 } 801 802 int16_t SX126x::setRxBandwidth(float rxBw) { 803 // check active modem 804 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 805 return(RADIOLIB_ERR_WRONG_MODEM); 806 } 807 808 // check modulation parameters 809 /*if(2 * _freqDev + _br > rxBw * 1000.0) { 810 return(RADIOLIB_ERR_INVALID_MODULATION_PARAMETERS); 811 }*/ 812 _rxBwKhz = rxBw; 813 814 // check allowed receiver bandwidth values 815 if(fabs(rxBw - 4.8) <= 0.001) { 816 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_4_8; 817 } else if(fabs(rxBw - 5.8) <= 0.001) { 818 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_5_8; 819 } else if(fabs(rxBw - 7.3) <= 0.001) { 820 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_7_3; 821 } else if(fabs(rxBw - 9.7) <= 0.001) { 822 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_9_7; 823 } else if(fabs(rxBw - 11.7) <= 0.001) { 824 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_11_7; 825 } else if(fabs(rxBw - 14.6) <= 0.001) { 826 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_14_6; 827 } else if(fabs(rxBw - 19.5) <= 0.001) { 828 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_19_5; 829 } else if(fabs(rxBw - 23.4) <= 0.001) { 830 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_23_4; 831 } else if(fabs(rxBw - 29.3) <= 0.001) { 832 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_29_3; 833 } else if(fabs(rxBw - 39.0) <= 0.001) { 834 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_39_0; 835 } else if(fabs(rxBw - 46.9) <= 0.001) { 836 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_46_9; 837 } else if(fabs(rxBw - 58.6) <= 0.001) { 838 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_58_6; 839 } else if(fabs(rxBw - 78.2) <= 0.001) { 840 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_78_2; 841 } else if(fabs(rxBw - 93.8) <= 0.001) { 842 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_93_8; 843 } else if(fabs(rxBw - 117.3) <= 0.001) { 844 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_117_3; 845 } else if(fabs(rxBw - 156.2) <= 0.001) { 846 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_156_2; 847 } else if(fabs(rxBw - 187.2) <= 0.001) { 848 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_187_2; 849 } else if(fabs(rxBw - 234.3) <= 0.001) { 850 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_234_3; 851 } else if(fabs(rxBw - 312.0) <= 0.001) { 852 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_312_0; 853 } else if(fabs(rxBw - 373.6) <= 0.001) { 854 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_373_6; 855 } else if(fabs(rxBw - 467.0) <= 0.001) { 856 _rxBw = RADIOLIB_SX126X_GFSK_RX_BW_467_0; 857 } else { 858 return(RADIOLIB_ERR_INVALID_RX_BANDWIDTH); 859 } 860 861 // update modulation parameters 862 return(setModulationParamsFSK(_br, _pulseShape, _rxBw, _freqDev)); 863 } 864 865 int16_t SX126x::setDataShaping(uint8_t sh) { 866 // check active modem 867 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 868 return(RADIOLIB_ERR_WRONG_MODEM); 869 } 870 871 // set data shaping 872 switch(sh) { 873 case RADIOLIB_SHAPING_NONE: 874 _pulseShape = RADIOLIB_SX126X_GFSK_FILTER_NONE; 875 break; 876 case RADIOLIB_SHAPING_0_3: 877 _pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_3; 878 break; 879 case RADIOLIB_SHAPING_0_5: 880 _pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_5; 881 break; 882 case RADIOLIB_SHAPING_0_7: 883 _pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_7; 884 break; 885 case RADIOLIB_SHAPING_1_0: 886 _pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_1; 887 break; 888 default: 889 return(RADIOLIB_ERR_INVALID_DATA_SHAPING); 890 } 891 892 // update modulation parameters 893 return(setModulationParamsFSK(_br, _pulseShape, _rxBw, _freqDev)); 894 } 895 896 int16_t SX126x::setSyncWord(uint8_t* syncWord, uint8_t len) { 897 // check active modem 898 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 899 return(RADIOLIB_ERR_WRONG_MODEM); 900 } 901 902 // check sync word Length 903 if(len > 8) { 904 return(RADIOLIB_ERR_INVALID_SYNC_WORD); 905 } 906 907 // write sync word 908 int16_t state = writeRegister(RADIOLIB_SX126X_REG_SYNC_WORD_0, syncWord, len); 909 RADIOLIB_ASSERT(state); 910 911 // update packet parameters 912 _syncWordLength = len * 8; 913 state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType); 914 915 return(state); 916 } 917 918 int16_t SX126x::setSyncBits(uint8_t *syncWord, uint8_t bitsLen) { 919 // check active modem 920 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 921 return(RADIOLIB_ERR_WRONG_MODEM); 922 } 923 924 // check sync word Length 925 if(bitsLen > 0x40) { 926 return(RADIOLIB_ERR_INVALID_SYNC_WORD); 927 } 928 929 uint8_t bytesLen = bitsLen / 8; 930 if ((bitsLen % 8) != 0) { 931 bytesLen++; 932 } 933 934 // write sync word 935 int16_t state = writeRegister(RADIOLIB_SX126X_REG_SYNC_WORD_0, syncWord, bytesLen); 936 RADIOLIB_ASSERT(state); 937 938 // update packet parameters 939 _syncWordLength = bitsLen; 940 state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType); 941 942 return(state); 943 } 944 945 int16_t SX126x::setNodeAddress(uint8_t nodeAddr) { 946 // check active modem 947 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 948 return(RADIOLIB_ERR_WRONG_MODEM); 949 } 950 951 // enable address filtering (node only) 952 _addrComp = RADIOLIB_SX126X_GFSK_ADDRESS_FILT_NODE; 953 int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType); 954 RADIOLIB_ASSERT(state); 955 956 // set node address 957 state = writeRegister(RADIOLIB_SX126X_REG_NODE_ADDRESS, &nodeAddr, 1); 958 959 return(state); 960 } 961 962 int16_t SX126x::setBroadcastAddress(uint8_t broadAddr) { 963 // check active modem 964 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 965 return(RADIOLIB_ERR_WRONG_MODEM); 966 } 967 968 // enable address filtering (node and broadcast) 969 _addrComp = RADIOLIB_SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST; 970 int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType); 971 RADIOLIB_ASSERT(state); 972 973 // set broadcast address 974 state = writeRegister(RADIOLIB_SX126X_REG_BROADCAST_ADDRESS, &broadAddr, 1); 975 976 return(state); 977 } 978 979 int16_t SX126x::disableAddressFiltering() { 980 // check active modem 981 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 982 return(RADIOLIB_ERR_WRONG_MODEM); 983 } 984 985 // disable address filtering 986 _addrComp = RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF; 987 return(setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening)); 988 } 989 990 int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool inverted) { 991 // check active modem 992 uint8_t modem = getPacketType(); 993 994 if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 995 // update packet parameters 996 switch(len) { 997 case 0: 998 _crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_OFF; 999 break; 1000 case 1: 1001 if(inverted) { 1002 _crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_1_BYTE_INV; 1003 } else { 1004 _crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_1_BYTE; 1005 } 1006 break; 1007 case 2: 1008 if(inverted) { 1009 _crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_2_BYTE_INV; 1010 } else { 1011 _crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_2_BYTE; 1012 } 1013 break; 1014 default: 1015 return(RADIOLIB_ERR_INVALID_CRC_CONFIGURATION); 1016 } 1017 1018 int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType); 1019 RADIOLIB_ASSERT(state); 1020 1021 // write initial CRC value 1022 uint8_t data[2] = {(uint8_t)((initial >> 8) & 0xFF), (uint8_t)(initial & 0xFF)}; 1023 state = writeRegister(RADIOLIB_SX126X_REG_CRC_INITIAL_MSB, data, 2); 1024 RADIOLIB_ASSERT(state); 1025 1026 // write CRC polynomial value 1027 data[0] = (uint8_t)((polynomial >> 8) & 0xFF); 1028 data[1] = (uint8_t)(polynomial & 0xFF); 1029 state = writeRegister(RADIOLIB_SX126X_REG_CRC_POLYNOMIAL_MSB, data, 2); 1030 1031 return(state); 1032 1033 } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) { 1034 // LoRa CRC doesn't allow to set CRC polynomial, initial value, or inversion 1035 1036 // update packet parameters 1037 if(len) { 1038 _crcType = RADIOLIB_SX126X_LORA_CRC_ON; 1039 } else { 1040 _crcType = RADIOLIB_SX126X_LORA_CRC_OFF; 1041 } 1042 1043 return(setPacketParams(_preambleLength, _crcType, _implicitLen, _headerType)); 1044 } 1045 1046 return(RADIOLIB_ERR_UNKNOWN); 1047 } 1048 1049 int16_t SX126x::setWhitening(bool enabled, uint16_t initial) { 1050 // check active modem 1051 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 1052 return(RADIOLIB_ERR_WRONG_MODEM); 1053 } 1054 1055 int16_t state = RADIOLIB_ERR_NONE; 1056 if(!enabled) { 1057 // disable whitening 1058 _whitening = RADIOLIB_SX126X_GFSK_WHITENING_OFF; 1059 1060 state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType); 1061 RADIOLIB_ASSERT(state); 1062 1063 } else { 1064 // enable whitening 1065 _whitening = RADIOLIB_SX126X_GFSK_WHITENING_ON; 1066 1067 // write initial whitening value 1068 // as per note on pg. 65 of datasheet v1.2: "The user should not change the value of the 7 MSB's of this register" 1069 uint8_t data[2]; 1070 // first read the actual value and mask 7 MSB which we can not change 1071 // if different value is written in 7 MSB, the Rx won't even work (tested on HW) 1072 state = readRegister(RADIOLIB_SX126X_REG_WHITENING_INITIAL_MSB, data, 1); 1073 RADIOLIB_ASSERT(state); 1074 1075 data[0] = (data[0] & 0xFE) | (uint8_t)((initial >> 8) & 0x01); 1076 data[1] = (uint8_t)(initial & 0xFF); 1077 state = writeRegister(RADIOLIB_SX126X_REG_WHITENING_INITIAL_MSB, data, 2); 1078 RADIOLIB_ASSERT(state); 1079 1080 state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, _packetType); 1081 RADIOLIB_ASSERT(state); 1082 } 1083 return(state); 1084 } 1085 1086 float SX126x::getDataRate() const { 1087 return(_dataRate); 1088 } 1089 1090 float SX126x::getRSSI() { 1091 // get last packet RSSI from packet status 1092 uint32_t packetStatus = getPacketStatus(); 1093 uint8_t rssiPkt = packetStatus & 0xFF; 1094 return(-1.0 * rssiPkt/2.0); 1095 } 1096 1097 float SX126x::getSNR() { 1098 // check active modem 1099 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) { 1100 return(RADIOLIB_ERR_WRONG_MODEM); 1101 } 1102 1103 // get last packet SNR from packet status 1104 uint32_t packetStatus = getPacketStatus(); 1105 uint8_t snrPkt = (packetStatus >> 8) & 0xFF; 1106 if(snrPkt < 128) { 1107 return(snrPkt/4.0); 1108 } else { 1109 return((snrPkt - 256)/4.0); 1110 } 1111 } 1112 1113 size_t SX126x::getPacketLength(bool update) { 1114 (void)update; 1115 uint8_t rxBufStatus[2] = {0, 0}; 1116 SPIreadCommand(RADIOLIB_SX126X_CMD_GET_RX_BUFFER_STATUS, rxBufStatus, 2); 1117 return((size_t)rxBufStatus[0]); 1118 } 1119 1120 int16_t SX126x::fixedPacketLengthMode(uint8_t len) { 1121 return(setPacketMode(RADIOLIB_SX126X_GFSK_PACKET_FIXED, len)); 1122 } 1123 1124 int16_t SX126x::variablePacketLengthMode(uint8_t maxLen) { 1125 return(setPacketMode(RADIOLIB_SX126X_GFSK_PACKET_VARIABLE, maxLen)); 1126 } 1127 1128 uint32_t SX126x::getTimeOnAir(size_t len) { 1129 // everything is in microseconds to allow integer arithmetic 1130 // some constants have .25, these are multiplied by 4, and have _x4 postfix to indicate that fact 1131 if(getPacketType() == RADIOLIB_SX126X_PACKET_TYPE_LORA) { 1132 uint32_t symbolLength_us = ((uint32_t)(1000 * 10) << _sf) / (_bwKhz * 10) ; 1133 uint8_t sfCoeff1_x4 = 17; // (4.25 * 4) 1134 uint8_t sfCoeff2 = 8; 1135 if(_sf == 5 || _sf == 6) { 1136 sfCoeff1_x4 = 25; // 6.25 * 4 1137 sfCoeff2 = 0; 1138 } 1139 uint8_t sfDivisor = 4*_sf; 1140 if(symbolLength_us >= 16000) { 1141 sfDivisor = 4*(_sf - 2); 1142 } 1143 const int8_t bitsPerCrc = 16; 1144 const int8_t N_symbol_header = _headerType == RADIOLIB_SX126X_LORA_HEADER_EXPLICIT ? 20 : 0; 1145 1146 // numerator of equation in section 6.1.4 of SX1268 datasheet v1.1 (might not actually be bitcount, but it has len * 8) 1147 int16_t bitCount = (int16_t) 8 * len + _crcType * bitsPerCrc - 4 * _sf + sfCoeff2 + N_symbol_header; 1148 if(bitCount < 0) { 1149 bitCount = 0; 1150 } 1151 // add (sfDivisor) - 1 to the numerator to give integer CEIL(...) 1152 uint16_t nPreCodedSymbols = (bitCount + (sfDivisor - 1)) / (sfDivisor); 1153 1154 // preamble can be 65k, therefore nSymbol_x4 needs to be 32 bit 1155 uint32_t nSymbol_x4 = (_preambleLength + 8) * 4 + sfCoeff1_x4 + nPreCodedSymbols * (_cr + 4) * 4; 1156 1157 return((symbolLength_us * nSymbol_x4) / 4); 1158 } else { 1159 return((len * 8 * _br) / (RADIOLIB_SX126X_CRYSTAL_FREQ * 32)); 1160 } 1161 } 1162 1163 float SX126x::getRSSIInst() { 1164 uint8_t data[3] = {0, 0, 0}; // RssiInst, Status, RFU 1165 SPIreadCommand(RADIOLIB_SX126X_CMD_GET_RSSI_INST, data, 3); 1166 1167 return (float)data[0] / (-2.0); 1168 } 1169 1170 int16_t SX126x::implicitHeader(size_t len) { 1171 return(setHeaderType(RADIOLIB_SX126X_LORA_HEADER_IMPLICIT, len)); 1172 } 1173 1174 int16_t SX126x::explicitHeader() { 1175 return(setHeaderType(RADIOLIB_SX126X_LORA_HEADER_EXPLICIT)); 1176 } 1177 1178 int16_t SX126x::setRegulatorLDO() { 1179 return(setRegulatorMode(RADIOLIB_SX126X_REGULATOR_LDO)); 1180 } 1181 1182 int16_t SX126x::setRegulatorDCDC() { 1183 return(setRegulatorMode(RADIOLIB_SX126X_REGULATOR_DC_DC)); 1184 } 1185 1186 int16_t SX126x::setEncoding(uint8_t encoding) { 1187 return(setWhitening(encoding)); 1188 } 1189 1190 void SX126x::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) { 1191 _mod->setRfSwitchPins(rxEn, txEn); 1192 } 1193 1194 int16_t SX126x::forceLDRO(bool enable) { 1195 // check active modem 1196 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) { 1197 return(RADIOLIB_ERR_WRONG_MODEM); 1198 } 1199 1200 // update modulation parameters 1201 _ldroAuto = false; 1202 _ldro = (uint8_t)enable; 1203 return(setModulationParams(_sf, _bw, _cr, _ldro)); 1204 } 1205 1206 int16_t SX126x::autoLDRO() { 1207 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) { 1208 return(RADIOLIB_ERR_WRONG_MODEM); 1209 } 1210 1211 _ldroAuto = true; 1212 return(RADIOLIB_ERR_NONE); 1213 } 1214 1215 uint8_t SX126x::randomByte() { 1216 // set mode to Rx 1217 setRx(RADIOLIB_SX126X_RX_TIMEOUT_INF); 1218 1219 // wait a bit for the RSSI reading to stabilise 1220 _mod->delay(10); 1221 1222 // read RSSI value 8 times, always keep just the least significant bit 1223 uint8_t randByte = 0x00; 1224 for(uint8_t i = 0; i < 8; i++) { 1225 uint8_t val = 0x00; 1226 readRegister(RADIOLIB_SX126X_REG_RANDOM_NUMBER_0, &val, sizeof(uint8_t)); 1227 randByte |= ((val & 0x01) << i); 1228 } 1229 1230 // set mode to standby 1231 standby(); 1232 1233 return(randByte); 1234 } 1235 1236 #if !defined(RADIOLIB_EXCLUDE_DIRECT_RECEIVE) 1237 void SX126x::setDirectAction(void (*func)(void)) { 1238 // SX126x is unable to perform direct mode reception 1239 // this method is implemented only for PhysicalLayer compatibility 1240 (void)func; 1241 } 1242 1243 void SX126x::readBit(RADIOLIB_PIN_TYPE pin) { 1244 // SX126x is unable to perform direct mode reception 1245 // this method is implemented only for PhysicalLayer compatibility 1246 (void)pin; 1247 } 1248 #endif 1249 1250 int16_t SX126x::setTCXO(float voltage, uint32_t delay) { 1251 // set mode to standby 1252 standby(); 1253 1254 // check RADIOLIB_SX126X_XOSC_START_ERR flag and clear it 1255 if(getDeviceErrors() & RADIOLIB_SX126X_XOSC_START_ERR) { 1256 clearDeviceErrors(); 1257 } 1258 1259 // check 0 V disable 1260 if(fabs(voltage - 0.0) <= 0.001) { 1261 return(reset(true)); 1262 } 1263 1264 // check alowed voltage values 1265 uint8_t data[4]; 1266 if(fabs(voltage - 1.6) <= 0.001) { 1267 data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_1_6; 1268 } else if(fabs(voltage - 1.7) <= 0.001) { 1269 data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_1_7; 1270 } else if(fabs(voltage - 1.8) <= 0.001) { 1271 data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_1_8; 1272 } else if(fabs(voltage - 2.2) <= 0.001) { 1273 data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_2_2; 1274 } else if(fabs(voltage - 2.4) <= 0.001) { 1275 data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_2_4; 1276 } else if(fabs(voltage - 2.7) <= 0.001) { 1277 data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_2_7; 1278 } else if(fabs(voltage - 3.0) <= 0.001) { 1279 data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_3_0; 1280 } else if(fabs(voltage - 3.3) <= 0.001) { 1281 data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_3_3; 1282 } else { 1283 return(RADIOLIB_ERR_INVALID_TCXO_VOLTAGE); 1284 } 1285 1286 // calculate delay 1287 uint32_t delayValue = (float)delay / 15.625; 1288 data[1] = (uint8_t)((delayValue >> 16) & 0xFF); 1289 data[2] = (uint8_t)((delayValue >> 8) & 0xFF); 1290 data[3] = (uint8_t)(delayValue & 0xFF); 1291 1292 _tcxoDelay = delay; 1293 1294 // enable TCXO control on DIO3 1295 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_DIO3_AS_TCXO_CTRL, data, 4)); 1296 } 1297 1298 int16_t SX126x::setDio2AsRfSwitch(bool enable) { 1299 uint8_t data = 0; 1300 if(enable) { 1301 data = RADIOLIB_SX126X_DIO2_AS_RF_SWITCH; 1302 } else { 1303 data = RADIOLIB_SX126X_DIO2_AS_IRQ; 1304 } 1305 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL, &data, 1)); 1306 } 1307 1308 int16_t SX126x::setTx(uint32_t timeout) { 1309 uint8_t data[] = { (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF)} ; 1310 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_TX, data, 3)); 1311 } 1312 1313 int16_t SX126x::setRx(uint32_t timeout) { 1314 uint8_t data[] = { (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF) }; 1315 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_RX, data, 3)); 1316 } 1317 1318 int16_t SX126x::setCad() { 1319 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_CAD, NULL, 0)); 1320 } 1321 1322 int16_t SX126x::setPaConfig(uint8_t paDutyCycle, uint8_t deviceSel, uint8_t hpMax, uint8_t paLut) { 1323 uint8_t data[] = { paDutyCycle, hpMax, deviceSel, paLut }; 1324 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_PA_CONFIG, data, 4)); 1325 } 1326 1327 int16_t SX126x::writeRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) { 1328 uint8_t cmd[] = { RADIOLIB_SX126X_CMD_WRITE_REGISTER, (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) }; 1329 return(SPIwriteCommand(cmd, 3, data, numBytes)); 1330 } 1331 1332 int16_t SX126x::readRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) { 1333 uint8_t cmd[] = { RADIOLIB_SX126X_CMD_READ_REGISTER, (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) }; 1334 return(SX126x::SPItransfer(cmd, 3, false, NULL, data, numBytes, true)); 1335 } 1336 1337 int16_t SX126x::writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset) { 1338 uint8_t cmd[] = { RADIOLIB_SX126X_CMD_WRITE_BUFFER, offset }; 1339 return(SPIwriteCommand(cmd, 2, data, numBytes)); 1340 } 1341 1342 int16_t SX126x::readBuffer(uint8_t* data, uint8_t numBytes) { 1343 uint8_t cmd[] = { RADIOLIB_SX126X_CMD_READ_BUFFER, RADIOLIB_SX126X_CMD_NOP }; 1344 return(SPIreadCommand(cmd, 2, data, numBytes)); 1345 } 1346 1347 int16_t SX126x::setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask) { 1348 uint8_t data[8] = {(uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)(irqMask & 0xFF), 1349 (uint8_t)((dio1Mask >> 8) & 0xFF), (uint8_t)(dio1Mask & 0xFF), 1350 (uint8_t)((dio2Mask >> 8) & 0xFF), (uint8_t)(dio2Mask & 0xFF), 1351 (uint8_t)((dio3Mask >> 8) & 0xFF), (uint8_t)(dio3Mask & 0xFF)}; 1352 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_DIO_IRQ_PARAMS, data, 8)); 1353 } 1354 1355 uint16_t SX126x::getIrqStatus() { 1356 uint8_t data[] = { 0x00, 0x00 }; 1357 SPIreadCommand(RADIOLIB_SX126X_CMD_GET_IRQ_STATUS, data, 2); 1358 return(((uint16_t)(data[0]) << 8) | data[1]); 1359 } 1360 1361 int16_t SX126x::clearIrqStatus(uint16_t clearIrqParams) { 1362 uint8_t data[] = { (uint8_t)((clearIrqParams >> 8) & 0xFF), (uint8_t)(clearIrqParams & 0xFF) }; 1363 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_CLEAR_IRQ_STATUS, data, 2)); 1364 } 1365 1366 int16_t SX126x::setRfFrequency(uint32_t frf) { 1367 uint8_t data[] = { (uint8_t)((frf >> 24) & 0xFF), (uint8_t)((frf >> 16) & 0xFF), (uint8_t)((frf >> 8) & 0xFF), (uint8_t)(frf & 0xFF) }; 1368 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_RF_FREQUENCY, data, 4)); 1369 } 1370 1371 int16_t SX126x::calibrateImage(uint8_t* data) { 1372 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_CALIBRATE_IMAGE, data, 2)); 1373 } 1374 1375 uint8_t SX126x::getPacketType() { 1376 uint8_t data = 0xFF; 1377 SPIreadCommand(RADIOLIB_SX126X_CMD_GET_PACKET_TYPE, &data, 1); 1378 return(data); 1379 } 1380 1381 int16_t SX126x::setTxParams(uint8_t power, uint8_t rampTime) { 1382 uint8_t data[] = { power, rampTime }; 1383 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_TX_PARAMS, data, 2)); 1384 } 1385 1386 int16_t SX126x::setPacketMode(uint8_t mode, uint8_t len) { 1387 // check active modem 1388 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) { 1389 return(RADIOLIB_ERR_WRONG_MODEM); 1390 } 1391 1392 // set requested packet mode 1393 int16_t state = setPacketParamsFSK(_preambleLengthFSK, _crcTypeFSK, _syncWordLength, _addrComp, _whitening, mode, len); 1394 RADIOLIB_ASSERT(state); 1395 1396 // update cached value 1397 _packetType = mode; 1398 return(state); 1399 } 1400 1401 int16_t SX126x::setHeaderType(uint8_t headerType, size_t len) { 1402 // check active modem 1403 if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) { 1404 return(RADIOLIB_ERR_WRONG_MODEM); 1405 } 1406 1407 // set requested packet mode 1408 int16_t state = setPacketParams(_preambleLength, _crcType, len, headerType); 1409 RADIOLIB_ASSERT(state); 1410 1411 // update cached value 1412 _headerType = headerType; 1413 _implicitLen = len; 1414 1415 return(state); 1416 } 1417 1418 int16_t SX126x::setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t ldro) { 1419 // calculate symbol length and enable low data rate optimization, if auto-configuration is enabled 1420 if(_ldroAuto) { 1421 float symbolLength = (float)(uint32_t(1) << _sf) / (float)_bwKhz; 1422 RADIOLIB_DEBUG_PRINT("Symbol length: "); 1423 RADIOLIB_DEBUG_PRINT(symbolLength); 1424 RADIOLIB_DEBUG_PRINTLN(" ms"); 1425 if(symbolLength >= 16.0) { 1426 _ldro = RADIOLIB_SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON; 1427 } else { 1428 _ldro = RADIOLIB_SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF; 1429 } 1430 } else { 1431 _ldro = ldro; 1432 } 1433 // 500/9/8 - 0x09 0x04 0x03 0x00 - SF9, BW125, 4/8 1434 // 500/11/8 - 0x0B 0x04 0x03 0x00 - SF11 BW125, 4/7 1435 uint8_t data[4] = {sf, bw, cr, _ldro}; 1436 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_MODULATION_PARAMS, data, 4)); 1437 } 1438 1439 int16_t SX126x::setModulationParamsFSK(uint32_t br, uint8_t pulseShape, uint8_t rxBw, uint32_t freqDev) { 1440 uint8_t data[8] = {(uint8_t)((br >> 16) & 0xFF), (uint8_t)((br >> 8) & 0xFF), (uint8_t)(br & 0xFF), 1441 pulseShape, rxBw, 1442 (uint8_t)((freqDev >> 16) & 0xFF), (uint8_t)((freqDev >> 8) & 0xFF), (uint8_t)(freqDev & 0xFF)}; 1443 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_MODULATION_PARAMS, data, 8)); 1444 } 1445 1446 int16_t SX126x::setPacketParams(uint16_t preambleLength, uint8_t crcType, uint8_t payloadLength, uint8_t headerType, uint8_t invertIQ) { 1447 int16_t state = fixInvertedIQ(invertIQ); 1448 RADIOLIB_ASSERT(state); 1449 uint8_t data[6] = {(uint8_t)((preambleLength >> 8) & 0xFF), (uint8_t)(preambleLength & 0xFF), headerType, payloadLength, crcType, invertIQ}; 1450 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_PACKET_PARAMS, data, 6)); 1451 } 1452 1453 int16_t SX126x::setPacketParamsFSK(uint16_t preambleLength, uint8_t crcType, uint8_t syncWordLength, uint8_t addrComp, uint8_t whitening, uint8_t packetType, uint8_t payloadLength, uint8_t preambleDetectorLength) { 1454 uint8_t data[9] = {(uint8_t)((preambleLength >> 8) & 0xFF), (uint8_t)(preambleLength & 0xFF), 1455 preambleDetectorLength, syncWordLength, addrComp, 1456 packetType, payloadLength, crcType, whitening}; 1457 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_PACKET_PARAMS, data, 9)); 1458 } 1459 1460 int16_t SX126x::setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress) { 1461 uint8_t data[2] = {txBaseAddress, rxBaseAddress}; 1462 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_BUFFER_BASE_ADDRESS, data, 2)); 1463 } 1464 1465 int16_t SX126x::setRegulatorMode(uint8_t mode) { 1466 uint8_t data[1] = {mode}; 1467 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_REGULATOR_MODE, data, 1)); 1468 } 1469 1470 uint8_t SX126x::getStatus() { 1471 uint8_t data = 0; 1472 SPIreadCommand(RADIOLIB_SX126X_CMD_GET_STATUS, &data, 1); 1473 return(data); 1474 } 1475 1476 uint32_t SX126x::getPacketStatus() { 1477 uint8_t data[3] = {0, 0, 0}; 1478 SPIreadCommand(RADIOLIB_SX126X_CMD_GET_PACKET_STATUS, data, 3); 1479 return((((uint32_t)data[0]) << 16) | (((uint32_t)data[1]) << 8) | (uint32_t)data[2]); 1480 } 1481 1482 uint16_t SX126x::getDeviceErrors() { 1483 uint8_t data[2] = {0, 0}; 1484 SPIreadCommand(RADIOLIB_SX126X_CMD_GET_DEVICE_ERRORS, data, 2); 1485 uint16_t opError = (((uint16_t)data[0] & 0xFF) << 8) & ((uint16_t)data[1]); 1486 return(opError); 1487 } 1488 1489 int16_t SX126x::clearDeviceErrors() { 1490 uint8_t data[2] = {RADIOLIB_SX126X_CMD_NOP, RADIOLIB_SX126X_CMD_NOP}; 1491 return(SPIwriteCommand(RADIOLIB_SX126X_CMD_CLEAR_DEVICE_ERRORS, data, 2)); 1492 } 1493 1494 int16_t SX126x::setFrequencyRaw(float freq) { 1495 // calculate raw value 1496 uint32_t frf = (freq * (uint32_t(1) << RADIOLIB_SX126X_DIV_EXPONENT)) / RADIOLIB_SX126X_CRYSTAL_FREQ; 1497 return(setRfFrequency(frf)); 1498 } 1499 1500 int16_t SX126x::fixSensitivity() { 1501 // fix receiver sensitivity for 500 kHz LoRa 1502 // see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.1 for details 1503 1504 // read current sensitivity configuration 1505 uint8_t sensitivityConfig = 0; 1506 int16_t state = readRegister(RADIOLIB_SX126X_REG_SENSITIVITY_CONFIG, &sensitivityConfig, 1); 1507 RADIOLIB_ASSERT(state); 1508 1509 // fix the value for LoRa with 500 kHz bandwidth 1510 if((getPacketType() == RADIOLIB_SX126X_PACKET_TYPE_LORA) && (fabs(_bwKhz - 500.0) <= 0.001)) { 1511 sensitivityConfig &= 0xFB; 1512 } else { 1513 sensitivityConfig |= 0x04; 1514 } 1515 return(writeRegister(RADIOLIB_SX126X_REG_SENSITIVITY_CONFIG, &sensitivityConfig, 1)); 1516 } 1517 1518 int16_t SX126x::fixPaClamping() { 1519 // fixes overly eager PA clamping 1520 // see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.2 for details 1521 1522 // read current clamping configuration 1523 uint8_t clampConfig = 0; 1524 int16_t state = readRegister(RADIOLIB_SX126X_REG_TX_CLAMP_CONFIG, &clampConfig, 1); 1525 RADIOLIB_ASSERT(state); 1526 1527 // update with the new value 1528 clampConfig |= 0x1E; 1529 return(writeRegister(RADIOLIB_SX126X_REG_TX_CLAMP_CONFIG, &clampConfig, 1)); 1530 } 1531 1532 int16_t SX126x::fixImplicitTimeout() { 1533 // fixes timeout in implicit header mode 1534 // see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.3 for details 1535 1536 //check if we're in implicit LoRa mode 1537 if(!((_headerType == RADIOLIB_SX126X_LORA_HEADER_IMPLICIT) && (getPacketType() == RADIOLIB_SX126X_PACKET_TYPE_LORA))) { 1538 return(RADIOLIB_ERR_WRONG_MODEM); 1539 } 1540 1541 // stop RTC counter 1542 uint8_t rtcStop = 0x00; 1543 int16_t state = writeRegister(RADIOLIB_SX126X_REG_DIO3_OUT_VOLTAGE_CTRL, &rtcStop, 1); 1544 RADIOLIB_ASSERT(state); 1545 1546 // read currently active event 1547 uint8_t rtcEvent = 0; 1548 state = readRegister(RADIOLIB_SX126X_REG_EVENT_MASK, &rtcEvent, 1); 1549 RADIOLIB_ASSERT(state); 1550 1551 // clear events 1552 rtcEvent |= 0x02; 1553 return(writeRegister(RADIOLIB_SX126X_REG_EVENT_MASK, &rtcEvent, 1)); 1554 } 1555 1556 int16_t SX126x::fixInvertedIQ(uint8_t iqConfig) { 1557 // fixes IQ configuration for inverted IQ 1558 // see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.4 for details 1559 1560 // read current IQ configuration 1561 uint8_t iqConfigCurrent = 0; 1562 int16_t state = readRegister(RADIOLIB_SX126X_REG_IQ_CONFIG, &iqConfigCurrent, 1); 1563 RADIOLIB_ASSERT(state); 1564 1565 // set correct IQ configuration 1566 if(iqConfig == RADIOLIB_SX126X_LORA_IQ_INVERTED) { 1567 iqConfigCurrent &= 0xFB; 1568 } else { 1569 iqConfigCurrent |= 0x04; 1570 } 1571 1572 // update with the new value 1573 return(writeRegister(RADIOLIB_SX126X_REG_IQ_CONFIG, &iqConfigCurrent, 1)); 1574 } 1575 1576 int16_t SX126x::config(uint8_t modem) { 1577 // reset buffer base address 1578 int16_t state = setBufferBaseAddress(); 1579 RADIOLIB_ASSERT(state); 1580 1581 // set modem 1582 uint8_t data[7]; 1583 data[0] = modem; 1584 state = SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_PACKET_TYPE, data, 1); 1585 RADIOLIB_ASSERT(state); 1586 1587 // set Rx/Tx fallback mode to STDBY_RC 1588 data[0] = RADIOLIB_SX126X_RX_TX_FALLBACK_MODE_STDBY_RC; 1589 state = SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_RX_TX_FALLBACK_MODE, data, 1); 1590 RADIOLIB_ASSERT(state); 1591 1592 // set CAD parameters 1593 data[0] = RADIOLIB_SX126X_CAD_ON_8_SYMB; 1594 data[1] = _sf + 13; 1595 data[2] = 10; 1596 data[3] = RADIOLIB_SX126X_CAD_GOTO_STDBY; 1597 data[4] = 0x00; 1598 data[5] = 0x00; 1599 data[6] = 0x00; 1600 state = SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_CAD_PARAMS, data, 7); 1601 RADIOLIB_ASSERT(state); 1602 1603 // clear IRQ 1604 state = clearIrqStatus(); 1605 state |= setDioIrqParams(RADIOLIB_SX126X_IRQ_NONE, RADIOLIB_SX126X_IRQ_NONE); 1606 RADIOLIB_ASSERT(state); 1607 1608 // calibrate all blocks 1609 data[0] = RADIOLIB_SX126X_CALIBRATE_ALL; 1610 state = SPIwriteCommand(RADIOLIB_SX126X_CMD_CALIBRATE, data, 1); 1611 RADIOLIB_ASSERT(state); 1612 1613 // wait for calibration completion 1614 _mod->delay(5); 1615 while(_mod->digitalRead(_mod->getGpio())) { 1616 _mod->yield(); 1617 } 1618 1619 return(RADIOLIB_ERR_NONE); 1620 } 1621 1622 int16_t SX126x::SPIwriteCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy) { 1623 return(SX126x::SPItransfer(cmd, cmdLen, true, data, NULL, numBytes, waitForBusy)); 1624 } 1625 1626 int16_t SX126x::SPIwriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy) { 1627 return(SX126x::SPItransfer(&cmd, 1, true, data, NULL, numBytes, waitForBusy)); 1628 } 1629 1630 int16_t SX126x::SPIreadCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy) { 1631 return(SX126x::SPItransfer(cmd, cmdLen, false, NULL, data, numBytes, waitForBusy)); 1632 } 1633 1634 int16_t SX126x::SPIreadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy) { 1635 return(SX126x::SPItransfer(&cmd, 1, false, NULL, data, numBytes, waitForBusy)); 1636 } 1637 1638 int16_t SX126x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy, uint32_t timeout) { 1639 #if defined(RADIOLIB_VERBOSE) 1640 uint8_t debugBuff[256]; 1641 #endif 1642 1643 // pull NSS low 1644 _mod->digitalWrite(_mod->getCs(), LOW); 1645 1646 // ensure BUSY is low (state machine ready) 1647 uint32_t start = _mod->millis(); 1648 while(_mod->digitalRead(_mod->getGpio())) { 1649 _mod->yield(); 1650 if(_mod->millis() - start >= timeout) { 1651 _mod->digitalWrite(_mod->getCs(), HIGH); 1652 return(RADIOLIB_ERR_SPI_CMD_TIMEOUT); 1653 } 1654 } 1655 1656 // start transfer 1657 _mod->SPIbeginTransaction(); 1658 1659 // send command byte(s) 1660 for(uint8_t n = 0; n < cmdLen; n++) { 1661 _mod->SPItransfer(cmd[n]); 1662 } 1663 1664 // variable to save error during SPI transfer 1665 uint8_t status = 0; 1666 1667 // send/receive all bytes 1668 if(write) { 1669 for(uint8_t n = 0; n < numBytes; n++) { 1670 // send byte 1671 uint8_t in = _mod->SPItransfer(dataOut[n]); 1672 #if defined(RADIOLIB_VERBOSE) 1673 debugBuff[n] = in; 1674 #endif 1675 1676 // check status 1677 if(((in & 0b00001110) == RADIOLIB_SX126X_STATUS_CMD_TIMEOUT) || 1678 ((in & 0b00001110) == RADIOLIB_SX126X_STATUS_CMD_INVALID) || 1679 ((in & 0b00001110) == RADIOLIB_SX126X_STATUS_CMD_FAILED)) { 1680 status = in & 0b00001110; 1681 break; 1682 } else if(in == 0x00 || in == 0xFF) { 1683 status = RADIOLIB_SX126X_STATUS_SPI_FAILED; 1684 break; 1685 } 1686 } 1687 1688 } else { 1689 // skip the first byte for read-type commands (status-only) 1690 uint8_t in = _mod->SPItransfer(RADIOLIB_SX126X_CMD_NOP); 1691 #if defined(RADIOLIB_VERBOSE) 1692 debugBuff[0] = in; 1693 #endif 1694 1695 // check status 1696 if(((in & 0b00001110) == RADIOLIB_SX126X_STATUS_CMD_TIMEOUT) || 1697 ((in & 0b00001110) == RADIOLIB_SX126X_STATUS_CMD_INVALID) || 1698 ((in & 0b00001110) == RADIOLIB_SX126X_STATUS_CMD_FAILED)) { 1699 status = in & 0b00001110; 1700 } else if(in == 0x00 || in == 0xFF) { 1701 status = RADIOLIB_SX126X_STATUS_SPI_FAILED; 1702 } else { 1703 for(uint8_t n = 0; n < numBytes; n++) { 1704 dataIn[n] = _mod->SPItransfer(RADIOLIB_SX126X_CMD_NOP); 1705 } 1706 } 1707 } 1708 1709 // stop transfer 1710 _mod->SPIendTransaction(); 1711 _mod->digitalWrite(_mod->getCs(), HIGH); 1712 1713 // wait for BUSY to go high and then low 1714 if(waitForBusy) { 1715 _mod->delayMicroseconds(1); 1716 start = _mod->millis(); 1717 while(_mod->digitalRead(_mod->getGpio())) { 1718 _mod->yield(); 1719 if(_mod->millis() - start >= timeout) { 1720 status = RADIOLIB_SX126X_STATUS_CMD_TIMEOUT; 1721 break; 1722 } 1723 } 1724 } 1725 1726 // print debug output 1727 #if defined(RADIOLIB_VERBOSE) 1728 // print command byte(s) 1729 RADIOLIB_VERBOSE_PRINT("CMD\t"); 1730 for(uint8_t n = 0; n < cmdLen; n++) { 1731 RADIOLIB_VERBOSE_PRINT(cmd[n], HEX); 1732 RADIOLIB_VERBOSE_PRINT('\t'); 1733 } 1734 RADIOLIB_VERBOSE_PRINTLN(); 1735 1736 // print data bytes 1737 RADIOLIB_VERBOSE_PRINT("DAT"); 1738 if(write) { 1739 RADIOLIB_VERBOSE_PRINT("W\t"); 1740 for(uint8_t n = 0; n < numBytes; n++) { 1741 RADIOLIB_VERBOSE_PRINT(dataOut[n], HEX); 1742 RADIOLIB_VERBOSE_PRINT('\t'); 1743 RADIOLIB_VERBOSE_PRINT(debugBuff[n], HEX); 1744 RADIOLIB_VERBOSE_PRINT('\t'); 1745 } 1746 RADIOLIB_VERBOSE_PRINTLN(); 1747 } else { 1748 RADIOLIB_VERBOSE_PRINT("R\t"); 1749 // skip the first byte for read-type commands (status-only) 1750 RADIOLIB_VERBOSE_PRINT(RADIOLIB_SX126X_CMD_NOP, HEX); 1751 RADIOLIB_VERBOSE_PRINT('\t'); 1752 RADIOLIB_VERBOSE_PRINT(debugBuff[0], HEX); 1753 RADIOLIB_VERBOSE_PRINT('\t') 1754 1755 for(uint8_t n = 0; n < numBytes; n++) { 1756 RADIOLIB_VERBOSE_PRINT(RADIOLIB_SX126X_CMD_NOP, HEX); 1757 RADIOLIB_VERBOSE_PRINT('\t'); 1758 RADIOLIB_VERBOSE_PRINT(dataIn[n], HEX); 1759 RADIOLIB_VERBOSE_PRINT('\t'); 1760 } 1761 RADIOLIB_VERBOSE_PRINTLN(); 1762 } 1763 RADIOLIB_VERBOSE_PRINTLN(); 1764 #else 1765 // some faster platforms require a short delay here 1766 // not sure why, but it seems that long enough SPI transaction 1767 // (e.g. setPacketParams for GFSK) will fail without it 1768 #if defined(RADIOLIB_SPI_SLOWDOWN) 1769 _mod->delay(1); 1770 #endif 1771 #endif 1772 1773 // parse status 1774 switch(status) { 1775 case RADIOLIB_SX126X_STATUS_CMD_TIMEOUT: 1776 return(RADIOLIB_ERR_SPI_CMD_TIMEOUT); 1777 case RADIOLIB_SX126X_STATUS_CMD_INVALID: 1778 return(RADIOLIB_ERR_SPI_CMD_INVALID); 1779 case RADIOLIB_SX126X_STATUS_CMD_FAILED: 1780 return(RADIOLIB_ERR_SPI_CMD_FAILED); 1781 case RADIOLIB_SX126X_STATUS_SPI_FAILED: 1782 return(RADIOLIB_ERR_CHIP_NOT_FOUND); 1783 default: 1784 return(RADIOLIB_ERR_NONE); 1785 } 1786 } 1787 1788 #endif