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 |
SX128x.cpp (48832B)
1 #include "SX128x.h" 2 #if !defined(RADIOLIB_EXCLUDE_SX128X) 3 4 SX128x::SX128x(Module* mod) : PhysicalLayer(RADIOLIB_SX128X_FREQUENCY_STEP_SIZE, RADIOLIB_SX128X_MAX_PACKET_LENGTH) { 5 _mod = mod; 6 } 7 8 Module* SX128x::getMod() { 9 return(_mod); 10 } 11 12 int16_t SX128x::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength) { 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\tSX128x")); 18 19 // initialize LoRa modulation variables 20 _bwKhz = bw; 21 _sf = RADIOLIB_SX128X_LORA_SF_9; 22 _cr = RADIOLIB_SX128X_LORA_CR_4_7; 23 24 // initialize LoRa packet variables 25 _preambleLengthLoRa = preambleLength; 26 _headerType = RADIOLIB_SX128X_LORA_HEADER_EXPLICIT; 27 _payloadLen = 0xFF; 28 _crcLoRa = RADIOLIB_SX128X_LORA_CRC_ON; 29 30 // reset the module and verify startup 31 int16_t state = reset(); 32 RADIOLIB_ASSERT(state); 33 34 // set mode to standby 35 state = standby(); 36 RADIOLIB_ASSERT(state); 37 38 // configure settings not accessible by API 39 state = config(RADIOLIB_SX128X_PACKET_TYPE_LORA); 40 RADIOLIB_ASSERT(state); 41 42 // configure publicly accessible settings 43 state = setFrequency(freq); 44 RADIOLIB_ASSERT(state); 45 46 state = setBandwidth(bw); 47 RADIOLIB_ASSERT(state); 48 49 state = setSpreadingFactor(sf); 50 RADIOLIB_ASSERT(state); 51 52 state = setCodingRate(cr); 53 RADIOLIB_ASSERT(state); 54 55 state = setSyncWord(syncWord); 56 RADIOLIB_ASSERT(state); 57 58 state = setPreambleLength(preambleLength); 59 RADIOLIB_ASSERT(state); 60 61 state = setOutputPower(power); 62 RADIOLIB_ASSERT(state); 63 64 return(state); 65 } 66 67 int16_t SX128x::beginGFSK(float freq, uint16_t br, float freqDev, int8_t power, uint16_t preambleLength) { 68 // set module properties 69 _mod->init(); 70 _mod->pinMode(_mod->getIrq(), INPUT); 71 _mod->pinMode(_mod->getGpio(), INPUT); 72 RADIOLIB_DEBUG_PRINTLN(F("M\tSX128x")); 73 74 // initialize GFSK modulation variables 75 _brKbps = br; 76 _br = RADIOLIB_SX128X_BLE_GFSK_BR_0_800_BW_2_4; 77 _modIndexReal = 1.0; 78 _modIndex = RADIOLIB_SX128X_BLE_GFSK_MOD_IND_1_00; 79 _shaping = RADIOLIB_SX128X_BLE_GFSK_BT_0_5; 80 81 // initialize GFSK packet variables 82 _preambleLengthGFSK = preambleLength; 83 _syncWordLen = 2; 84 _syncWordMatch = RADIOLIB_SX128X_GFSK_FLRC_SYNC_WORD_1; 85 _crcGFSK = RADIOLIB_SX128X_GFSK_FLRC_CRC_2_BYTE; 86 _whitening = RADIOLIB_SX128X_GFSK_BLE_WHITENING_ON; 87 88 // reset the module and verify startup 89 int16_t state = reset(); 90 RADIOLIB_ASSERT(state); 91 92 // set mode to standby 93 state = standby(); 94 RADIOLIB_ASSERT(state); 95 96 // configure settings not accessible by API 97 state = config(RADIOLIB_SX128X_PACKET_TYPE_GFSK); 98 RADIOLIB_ASSERT(state); 99 100 // configure publicly accessible settings 101 state = setFrequency(freq); 102 RADIOLIB_ASSERT(state); 103 104 state = setBitRate(br); 105 RADIOLIB_ASSERT(state); 106 107 state = setFrequencyDeviation(freqDev); 108 RADIOLIB_ASSERT(state); 109 110 state = setOutputPower(power); 111 RADIOLIB_ASSERT(state); 112 113 state = setPreambleLength(preambleLength); 114 RADIOLIB_ASSERT(state); 115 116 state = setDataShaping(RADIOLIB_SHAPING_0_5); 117 RADIOLIB_ASSERT(state); 118 119 // set publicly accessible settings that are not a part of begin method 120 uint8_t sync[] = { 0x12, 0xAD }; 121 state = setSyncWord(sync, 2); 122 RADIOLIB_ASSERT(state); 123 124 state = setEncoding(RADIOLIB_ENCODING_NRZ); 125 RADIOLIB_ASSERT(state); 126 127 return(state); 128 } 129 130 int16_t SX128x::beginBLE(float freq, uint16_t br, float freqDev, int8_t power, uint8_t dataShaping) { 131 // set module properties 132 _mod->init(); 133 _mod->pinMode(_mod->getIrq(), INPUT); 134 _mod->pinMode(_mod->getGpio(), INPUT); 135 RADIOLIB_DEBUG_PRINTLN(F("M\tSX128x")); 136 137 // initialize BLE modulation variables 138 _brKbps = br; 139 _br = RADIOLIB_SX128X_BLE_GFSK_BR_0_800_BW_2_4; 140 _modIndexReal = 1.0; 141 _modIndex = RADIOLIB_SX128X_BLE_GFSK_MOD_IND_1_00; 142 _shaping = RADIOLIB_SX128X_BLE_GFSK_BT_0_5; 143 144 // initialize BLE packet variables 145 _crcGFSK = RADIOLIB_SX128X_BLE_CRC_3_BYTE; 146 _whitening = RADIOLIB_SX128X_GFSK_BLE_WHITENING_ON; 147 148 // reset the module and verify startup 149 int16_t state = reset(); 150 RADIOLIB_ASSERT(state); 151 152 // set mode to standby 153 state = standby(); 154 RADIOLIB_ASSERT(state); 155 156 // configure settings not accessible by API 157 state = config(RADIOLIB_SX128X_PACKET_TYPE_BLE); 158 RADIOLIB_ASSERT(state); 159 160 // configure publicly accessible settings 161 state = setFrequency(freq); 162 RADIOLIB_ASSERT(state); 163 164 state = setBitRate(br); 165 RADIOLIB_ASSERT(state); 166 167 state = setFrequencyDeviation(freqDev); 168 RADIOLIB_ASSERT(state); 169 170 state = setOutputPower(power); 171 RADIOLIB_ASSERT(state); 172 173 state = setDataShaping(dataShaping); 174 RADIOLIB_ASSERT(state); 175 176 return(state); 177 } 178 179 int16_t SX128x::beginFLRC(float freq, uint16_t br, uint8_t cr, int8_t power, uint16_t preambleLength, uint8_t dataShaping) { 180 // set module properties 181 _mod->init(); 182 _mod->pinMode(_mod->getIrq(), INPUT); 183 _mod->pinMode(_mod->getGpio(), INPUT); 184 RADIOLIB_DEBUG_PRINTLN(F("M\tSX128x")); 185 186 // initialize FLRC modulation variables 187 _brKbps = br; 188 _br = RADIOLIB_SX128X_FLRC_BR_0_650_BW_0_6; 189 _crFLRC = RADIOLIB_SX128X_FLRC_CR_3_4; 190 _shaping = RADIOLIB_SX128X_FLRC_BT_0_5; 191 192 // initialize FLRC packet variables 193 _preambleLengthGFSK = preambleLength; 194 _syncWordLen = 2; 195 _syncWordMatch = RADIOLIB_SX128X_GFSK_FLRC_SYNC_WORD_1; 196 _crcGFSK = RADIOLIB_SX128X_GFSK_FLRC_CRC_2_BYTE; 197 _whitening = RADIOLIB_SX128X_GFSK_BLE_WHITENING_OFF; 198 199 // reset the module and verify startup 200 int16_t state = reset(); 201 RADIOLIB_ASSERT(state); 202 203 // set mode to standby 204 state = standby(); 205 RADIOLIB_ASSERT(state); 206 207 // configure settings not accessible by API 208 state = config(RADIOLIB_SX128X_PACKET_TYPE_FLRC); 209 RADIOLIB_ASSERT(state); 210 211 // configure publicly accessible settings 212 state = setFrequency(freq); 213 RADIOLIB_ASSERT(state); 214 215 state = setBitRate(br); 216 RADIOLIB_ASSERT(state); 217 218 state = setCodingRate(cr); 219 RADIOLIB_ASSERT(state); 220 221 state = setOutputPower(power); 222 RADIOLIB_ASSERT(state); 223 224 state = setPreambleLength(preambleLength); 225 RADIOLIB_ASSERT(state); 226 227 state = setDataShaping(dataShaping); 228 RADIOLIB_ASSERT(state); 229 230 // set publicly accessible settings that are not a part of begin method 231 uint8_t sync[] = { 0x2D, 0x01, 0x4B, 0x1D}; 232 state = setSyncWord(sync, 4); 233 RADIOLIB_ASSERT(state); 234 235 return(state); 236 } 237 238 int16_t SX128x::reset(bool verify) { 239 // run the reset sequence - same as SX126x, as SX128x docs don't seem to mention this 240 _mod->pinMode(_mod->getRst(), OUTPUT); 241 _mod->digitalWrite(_mod->getRst(), LOW); 242 _mod->delay(1); 243 _mod->digitalWrite(_mod->getRst(), HIGH); 244 245 // return immediately when verification is disabled 246 if(!verify) { 247 return(RADIOLIB_ERR_NONE); 248 } 249 250 // set mode to standby 251 uint32_t start = _mod->millis(); 252 while(true) { 253 // try to set mode to standby 254 int16_t state = standby(); 255 if(state == RADIOLIB_ERR_NONE) { 256 // standby command successful 257 return(RADIOLIB_ERR_NONE); 258 } 259 260 // standby command failed, check timeout and try again 261 if(_mod->millis() - start >= 3000) { 262 // timed out, possibly incorrect wiring 263 return(state); 264 } 265 266 // wait a bit to not spam the module 267 _mod->delay(10); 268 } 269 } 270 271 int16_t SX128x::transmit(uint8_t* data, size_t len, uint8_t addr) { 272 // check packet length 273 if(len > RADIOLIB_SX128X_MAX_PACKET_LENGTH) { 274 return(RADIOLIB_ERR_PACKET_TOO_LONG); 275 } 276 277 // check active modem 278 uint8_t modem = getPacketType(); 279 if(modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING) { 280 return(RADIOLIB_ERR_WRONG_MODEM); 281 } 282 283 // set mode to standby 284 int16_t state = standby(); 285 RADIOLIB_ASSERT(state); 286 287 // calculate timeout (500% of expected time-on-air) 288 uint32_t timeout = getTimeOnAir(len) * 5; 289 290 RADIOLIB_DEBUG_PRINT(F("Timeout in ")); 291 RADIOLIB_DEBUG_PRINT(timeout); 292 RADIOLIB_DEBUG_PRINTLN(F(" us")); 293 294 // start transmission 295 state = startTransmit(data, len, addr); 296 RADIOLIB_ASSERT(state); 297 298 // wait for packet transmission or timeout 299 uint32_t start = _mod->micros(); 300 while(!_mod->digitalRead(_mod->getIrq())) { 301 _mod->yield(); 302 if(_mod->micros() - start > timeout) { 303 clearIrqStatus(); 304 standby(); 305 return(RADIOLIB_ERR_TX_TIMEOUT); 306 } 307 } 308 309 // clear interrupt flags 310 state = clearIrqStatus(); 311 RADIOLIB_ASSERT(state); 312 313 // set mode to standby to disable transmitter 314 state = standby(); 315 316 return(state); 317 } 318 319 int16_t SX128x::receive(uint8_t* data, size_t len) { 320 // check active modem 321 uint8_t modem = getPacketType(); 322 if(modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING) { 323 return(RADIOLIB_ERR_WRONG_MODEM); 324 } 325 326 // set mode to standby 327 int16_t state = standby(); 328 RADIOLIB_ASSERT(state); 329 330 // calculate timeout (1000% of expected time-on-air) 331 uint32_t timeout = getTimeOnAir(len) * 10; 332 333 RADIOLIB_DEBUG_PRINT(F("Timeout in ")); 334 RADIOLIB_DEBUG_PRINT(timeout); 335 RADIOLIB_DEBUG_PRINTLN(F(" us")); 336 337 // start reception 338 uint32_t timeoutValue = (uint32_t)((float)timeout / 15.625); 339 state = startReceive(timeoutValue); 340 RADIOLIB_ASSERT(state); 341 342 // wait for packet reception or timeout 343 uint32_t start = _mod->micros(); 344 while(!_mod->digitalRead(_mod->getIrq())) { 345 _mod->yield(); 346 if(_mod->micros() - start > timeout) { 347 clearIrqStatus(); 348 standby(); 349 return(RADIOLIB_ERR_RX_TIMEOUT); 350 } 351 } 352 353 // read the received data 354 return(readData(data, len)); 355 } 356 357 int16_t SX128x::transmitDirect(uint32_t frf) { 358 // set RF switch (if present) 359 _mod->setRfSwitchState(LOW, HIGH); 360 361 // user requested to start transmitting immediately (required for RTTY) 362 int16_t state = RADIOLIB_ERR_NONE; 363 if(frf != 0) { 364 state = setRfFrequency(frf); 365 } 366 RADIOLIB_ASSERT(state); 367 368 // start transmitting 369 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_TX_CONTINUOUS_WAVE, NULL, 0)); 370 } 371 372 int16_t SX128x::receiveDirect() { 373 // set RF switch (if present) 374 _mod->setRfSwitchState(HIGH, LOW); 375 376 // SX128x is unable to output received data directly 377 return(RADIOLIB_ERR_UNKNOWN); 378 } 379 380 int16_t SX128x::scanChannel() { 381 // check active modem 382 if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_LORA) { 383 return(RADIOLIB_ERR_WRONG_MODEM); 384 } 385 386 // set mode to standby 387 int16_t state = standby(); 388 RADIOLIB_ASSERT(state); 389 390 // set DIO pin mapping 391 state = setDioIrqParams(RADIOLIB_SX128X_IRQ_CAD_DETECTED | RADIOLIB_SX128X_IRQ_CAD_DONE, RADIOLIB_SX128X_IRQ_CAD_DETECTED | RADIOLIB_SX128X_IRQ_CAD_DONE); 392 RADIOLIB_ASSERT(state); 393 394 // clear interrupt flags 395 state = clearIrqStatus(); 396 RADIOLIB_ASSERT(state); 397 398 // set RF switch (if present) 399 _mod->setRfSwitchState(HIGH, LOW); 400 401 // set mode to CAD 402 state = setCad(); 403 RADIOLIB_ASSERT(state); 404 405 // wait for channel activity detected or timeout 406 while(!_mod->digitalRead(_mod->getIrq())) { 407 _mod->yield(); 408 } 409 410 // check CAD result 411 uint16_t cadResult = getIrqStatus(); 412 if(cadResult & RADIOLIB_SX128X_IRQ_CAD_DETECTED) { 413 // detected some LoRa activity 414 clearIrqStatus(); 415 return(RADIOLIB_LORA_DETECTED); 416 } else if(cadResult & RADIOLIB_SX128X_IRQ_CAD_DONE) { 417 // channel is free 418 clearIrqStatus(); 419 return(RADIOLIB_CHANNEL_FREE); 420 } 421 422 return(RADIOLIB_ERR_UNKNOWN); 423 } 424 425 int16_t SX128x::sleep(bool retainConfig) { 426 // set RF switch (if present) 427 _mod->setRfSwitchState(LOW, LOW); 428 429 uint8_t sleepConfig = RADIOLIB_SX128X_SLEEP_DATA_BUFFER_RETAIN | RADIOLIB_SX128X_SLEEP_DATA_RAM_RETAIN; 430 if(!retainConfig) { 431 sleepConfig = RADIOLIB_SX128X_SLEEP_DATA_BUFFER_FLUSH | RADIOLIB_SX128X_SLEEP_DATA_RAM_FLUSH; 432 } 433 int16_t state = SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_SLEEP, &sleepConfig, 1, false); 434 435 // wait for SX128x to safely enter sleep mode 436 _mod->delay(1); 437 438 return(state); 439 } 440 441 int16_t SX128x::standby() { 442 return(SX128x::standby(RADIOLIB_SX128X_STANDBY_RC)); 443 } 444 445 int16_t SX128x::standby(uint8_t mode) { 446 // set RF switch (if present) 447 _mod->setRfSwitchState(LOW, LOW); 448 449 uint8_t data[] = { mode }; 450 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_STANDBY, data, 1)); 451 } 452 453 void SX128x::setDio1Action(void (*func)(void)) { 454 _mod->attachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq()), func, RISING); 455 } 456 457 void SX128x::clearDio1Action() { 458 _mod->detachInterrupt(RADIOLIB_DIGITAL_PIN_TO_INTERRUPT(_mod->getIrq())); 459 } 460 461 int16_t SX128x::startTransmit(uint8_t* data, size_t len, uint8_t addr) { 462 // suppress unused variable warning 463 (void)addr; 464 465 // check packet length 466 if(len > RADIOLIB_SX128X_MAX_PACKET_LENGTH) { 467 return(RADIOLIB_ERR_PACKET_TOO_LONG); 468 } 469 470 // set packet Length 471 int16_t state = RADIOLIB_ERR_NONE; 472 uint8_t modem = getPacketType(); 473 if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) { 474 state = setPacketParamsLoRa(_preambleLengthLoRa, _headerType, len, _crcLoRa); 475 } else if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC)) { 476 state = setPacketParamsGFSK(_preambleLengthGFSK, _syncWordLen, _syncWordMatch, _crcGFSK, _whitening, len); 477 } else if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) { 478 state = setPacketParamsBLE(_connectionState, _crcBLE, _bleTestPayload, _whitening); 479 } else { 480 return(RADIOLIB_ERR_WRONG_MODEM); 481 } 482 RADIOLIB_ASSERT(state); 483 484 // update output power 485 state = setTxParams(_pwr); 486 RADIOLIB_ASSERT(state); 487 488 // set buffer pointers 489 state = setBufferBaseAddress(); 490 RADIOLIB_ASSERT(state); 491 492 // write packet to buffer 493 if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) { 494 // first 2 bytes of BLE payload are PDU header 495 state = writeBuffer(data, len, 2); 496 RADIOLIB_ASSERT(state); 497 } else { 498 state = writeBuffer(data, len); 499 RADIOLIB_ASSERT(state); 500 } 501 502 // set DIO mapping 503 state = setDioIrqParams(RADIOLIB_SX128X_IRQ_TX_DONE | RADIOLIB_SX128X_IRQ_RX_TX_TIMEOUT, RADIOLIB_SX128X_IRQ_TX_DONE); 504 RADIOLIB_ASSERT(state); 505 506 // clear interrupt flags 507 state = clearIrqStatus(); 508 RADIOLIB_ASSERT(state); 509 510 // set RF switch (if present) 511 _mod->setRfSwitchState(LOW, HIGH); 512 513 // start transmission 514 state = setTx(RADIOLIB_SX128X_TX_TIMEOUT_NONE); 515 RADIOLIB_ASSERT(state); 516 517 // wait for BUSY to go low (= PA ramp up done) 518 while(_mod->digitalRead(_mod->getGpio())) { 519 _mod->yield(); 520 } 521 522 return(state); 523 } 524 525 int16_t SX128x::startReceive(uint16_t timeout) { 526 // check active modem 527 if(getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_RANGING) { 528 return(RADIOLIB_ERR_WRONG_MODEM); 529 } 530 531 // set DIO mapping 532 int16_t state = setDioIrqParams(RADIOLIB_SX128X_IRQ_RX_DONE | RADIOLIB_SX128X_IRQ_RX_TX_TIMEOUT | RADIOLIB_SX128X_IRQ_CRC_ERROR | RADIOLIB_SX128X_IRQ_HEADER_ERROR, RADIOLIB_SX128X_IRQ_RX_DONE); 533 RADIOLIB_ASSERT(state); 534 535 // set buffer pointers 536 state = setBufferBaseAddress(); 537 RADIOLIB_ASSERT(state); 538 539 // clear interrupt flags 540 state = clearIrqStatus(); 541 RADIOLIB_ASSERT(state); 542 543 // set implicit mode and expected len if applicable 544 if((_headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) && (getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_LORA)) { 545 state = setPacketParamsLoRa(_preambleLengthLoRa, _headerType, _payloadLen, _crcLoRa); 546 RADIOLIB_ASSERT(state); 547 } 548 549 // set RF switch (if present) 550 _mod->setRfSwitchState(HIGH, LOW); 551 552 // set mode to receive 553 state = setRx(timeout); 554 555 return(state); 556 } 557 558 int16_t SX128x::readData(uint8_t* data, size_t len) { 559 // check active modem 560 if(getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_RANGING) { 561 return(RADIOLIB_ERR_WRONG_MODEM); 562 } 563 564 // set mode to standby 565 int16_t state = standby(); 566 RADIOLIB_ASSERT(state); 567 568 // check integrity CRC 569 uint16_t irq = getIrqStatus(); 570 int16_t crcState = RADIOLIB_ERR_NONE; 571 if((irq & RADIOLIB_SX128X_IRQ_CRC_ERROR) || (irq & RADIOLIB_SX128X_IRQ_HEADER_ERROR)) { 572 crcState = RADIOLIB_ERR_CRC_MISMATCH; 573 } 574 575 // get packet length 576 size_t length = getPacketLength(); 577 if((len != 0) && (len < length)) { 578 // user requested less data than we got, only return what was requested 579 length = len; 580 } 581 582 // read packet data 583 state = readBuffer(data, length); 584 RADIOLIB_ASSERT(state); 585 586 // clear interrupt flags 587 state = clearIrqStatus(); 588 589 // check if CRC failed - this is done after reading data to give user the option to keep them 590 RADIOLIB_ASSERT(crcState); 591 592 return(state); 593 } 594 595 int16_t SX128x::setFrequency(float freq) { 596 RADIOLIB_CHECK_RANGE(freq, 2400.0, 2500.0, RADIOLIB_ERR_INVALID_FREQUENCY); 597 598 // calculate raw value 599 uint32_t frf = (freq * (uint32_t(1) << RADIOLIB_SX128X_DIV_EXPONENT)) / RADIOLIB_SX128X_CRYSTAL_FREQ; 600 return(setRfFrequency(frf)); 601 } 602 603 int16_t SX128x::setBandwidth(float bw) { 604 // check active modem 605 uint8_t modem = getPacketType(); 606 if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) { 607 // check range for LoRa 608 RADIOLIB_CHECK_RANGE(bw, 203.125, 1625.0, RADIOLIB_ERR_INVALID_BANDWIDTH); 609 } else if(modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING) { 610 // check range for ranging 611 RADIOLIB_CHECK_RANGE(bw, 406.25, 1625.0, RADIOLIB_ERR_INVALID_BANDWIDTH); 612 } else { 613 return(RADIOLIB_ERR_WRONG_MODEM); 614 } 615 616 if(fabs(bw - 203.125) <= 0.001) { 617 _bw = RADIOLIB_SX128X_LORA_BW_203_125; 618 } else if(fabs(bw - 406.25) <= 0.001) { 619 _bw = RADIOLIB_SX128X_LORA_BW_406_25; 620 } else if(fabs(bw - 812.5) <= 0.001) { 621 _bw = RADIOLIB_SX128X_LORA_BW_812_50; 622 } else if(fabs(bw - 1625.0) <= 0.001) { 623 _bw = RADIOLIB_SX128X_LORA_BW_1625_00; 624 } else { 625 return(RADIOLIB_ERR_INVALID_BANDWIDTH); 626 } 627 628 // update modulation parameters 629 _bwKhz = bw; 630 return(setModulationParams(_sf, _bw, _cr)); 631 } 632 633 int16_t SX128x::setSpreadingFactor(uint8_t sf) { 634 // check active modem 635 uint8_t modem = getPacketType(); 636 if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) { 637 // check range for LoRa 638 RADIOLIB_CHECK_RANGE(sf, 5, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR); 639 } else if(modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING) { 640 // check range for ranging 641 RADIOLIB_CHECK_RANGE(sf, 5, 10, RADIOLIB_ERR_INVALID_SPREADING_FACTOR); 642 } else { 643 return(RADIOLIB_ERR_WRONG_MODEM); 644 } 645 646 // update modulation parameters 647 _sf = sf << 4; 648 int16_t state = setModulationParams(_sf, _bw, _cr); 649 RADIOLIB_ASSERT(state); 650 651 // update mystery register in LoRa mode - SX1280 datasheet v3.0 section 13.4.1 652 if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) { 653 uint8_t data = 0; 654 if((_sf == RADIOLIB_SX128X_LORA_SF_5) || (_sf == RADIOLIB_SX128X_LORA_SF_6)) { 655 data = 0x1E; 656 } else if((_sf == RADIOLIB_SX128X_LORA_SF_7) || (_sf == RADIOLIB_SX128X_LORA_SF_8)) { 657 data = 0x37; 658 } else { 659 data = 0x32; 660 } 661 state = SX128x::writeRegister(RADIOLIB_SX128X_REG_LORA_SF_CONFIG, &data, 1); 662 } 663 664 return(state); 665 } 666 667 int16_t SX128x::setCodingRate(uint8_t cr, bool longInterleaving) { 668 // check active modem 669 uint8_t modem = getPacketType(); 670 671 // LoRa/ranging 672 if((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING)) { 673 RADIOLIB_CHECK_RANGE(cr, 5, 8, RADIOLIB_ERR_INVALID_CODING_RATE); 674 675 // update modulation parameters 676 if(longInterleaving && (modem == RADIOLIB_SX128X_PACKET_TYPE_LORA)) { 677 _cr = cr; 678 } else { 679 _cr = cr - 4; 680 } 681 return(setModulationParams(_sf, _bw, _cr)); 682 683 // FLRC 684 } else if(modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC) { 685 RADIOLIB_CHECK_RANGE(cr, 2, 4, RADIOLIB_ERR_INVALID_CODING_RATE); 686 687 // update modulation parameters 688 _crFLRC = (cr - 2) * 2; 689 return(setModulationParams(_br, _crFLRC, _shaping)); 690 } 691 692 return(RADIOLIB_ERR_WRONG_MODEM); 693 } 694 695 int16_t SX128x::setOutputPower(int8_t power) { 696 RADIOLIB_CHECK_RANGE(power, -18, 13, RADIOLIB_ERR_INVALID_OUTPUT_POWER); 697 _pwr = power + 18; 698 return(setTxParams(_pwr)); 699 } 700 701 int16_t SX128x::setPreambleLength(uint32_t preambleLength) { 702 uint8_t modem = getPacketType(); 703 if((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING)) { 704 // LoRa or ranging 705 RADIOLIB_CHECK_RANGE(preambleLength, 2, 491520, RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH); 706 707 // check preamble length is even - no point even trying odd numbers 708 if(preambleLength % 2 != 0) { 709 return(RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH); 710 } 711 712 // calculate exponent and mantissa values (use the next longer preamble if there's no exact match) 713 uint8_t e = 1; 714 uint8_t m = 1; 715 uint32_t len = 0; 716 for(; e <= 15; e++) { 717 for(; m <= 15; m++) { 718 len = m * (uint32_t(1) << e); 719 if(len >= preambleLength) { 720 break; 721 } 722 } 723 if(len >= preambleLength) { 724 break; 725 } 726 } 727 728 // update packet parameters 729 _preambleLengthLoRa = (e << 4) | m; 730 return(setPacketParamsLoRa(_preambleLengthLoRa, _headerType, _payloadLen, _crcLoRa)); 731 732 } else if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC)) { 733 // GFSK or FLRC 734 RADIOLIB_CHECK_RANGE(preambleLength, 4, 32, RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH); 735 736 // check preamble length is multiple of 4 737 if(preambleLength % 4 != 0) { 738 return(RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH); 739 } 740 741 // update packet parameters 742 _preambleLengthGFSK = ((preambleLength / 4) - 1) << 4; 743 return(setPacketParamsGFSK(_preambleLengthGFSK, _syncWordLen, _syncWordMatch, _crcGFSK, _whitening)); 744 } 745 746 return(RADIOLIB_ERR_WRONG_MODEM); 747 } 748 749 int16_t SX128x::setBitRate(uint16_t br) { 750 // check active modem 751 uint8_t modem = getPacketType(); 752 753 // GFSK/BLE 754 if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_BLE)) { 755 if(br == 125) { 756 _br = RADIOLIB_SX128X_BLE_GFSK_BR_0_125_BW_0_3; 757 } else if(br == 250) { 758 _br = RADIOLIB_SX128X_BLE_GFSK_BR_0_250_BW_0_6; 759 } else if(br == 400) { 760 _br = RADIOLIB_SX128X_BLE_GFSK_BR_0_400_BW_1_2; 761 } else if(br == 500) { 762 _br = RADIOLIB_SX128X_BLE_GFSK_BR_0_500_BW_1_2; 763 } else if(br == 800) { 764 _br = RADIOLIB_SX128X_BLE_GFSK_BR_0_800_BW_2_4; 765 } else if(br == 1000) { 766 _br = RADIOLIB_SX128X_BLE_GFSK_BR_1_000_BW_2_4; 767 } else if(br == 1600) { 768 _br = RADIOLIB_SX128X_BLE_GFSK_BR_1_600_BW_2_4; 769 } else if(br == 2000) { 770 _br = RADIOLIB_SX128X_BLE_GFSK_BR_2_000_BW_2_4; 771 } else { 772 return(RADIOLIB_ERR_INVALID_BIT_RATE); 773 } 774 775 // update modulation parameters 776 _brKbps = br; 777 return(setModulationParams(_br, _modIndex, _shaping)); 778 779 // FLRC 780 } else if(modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC) { 781 if(br == 260) { 782 _br = RADIOLIB_SX128X_FLRC_BR_0_260_BW_0_3; 783 } else if(br == 325) { 784 _br = RADIOLIB_SX128X_FLRC_BR_0_325_BW_0_3; 785 } else if(br == 520) { 786 _br = RADIOLIB_SX128X_FLRC_BR_0_520_BW_0_6; 787 } else if(br == 650) { 788 _br = RADIOLIB_SX128X_FLRC_BR_0_650_BW_0_6; 789 } else if(br == 1000) { 790 _br = RADIOLIB_SX128X_FLRC_BR_1_000_BW_1_2; 791 } else if(br == 1300) { 792 _br = RADIOLIB_SX128X_FLRC_BR_1_300_BW_1_2; 793 } else { 794 return(RADIOLIB_ERR_INVALID_BIT_RATE); 795 } 796 797 // update modulation parameters 798 _brKbps = br; 799 return(setModulationParams(_br, _crFLRC, _shaping)); 800 801 } 802 803 return(RADIOLIB_ERR_WRONG_MODEM); 804 } 805 806 int16_t SX128x::setFrequencyDeviation(float freqDev) { 807 // check active modem 808 uint8_t modem = getPacketType(); 809 if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_BLE))) { 810 return(RADIOLIB_ERR_WRONG_MODEM); 811 } 812 813 // set frequency deviation to lowest available setting (required for digimodes) 814 float newFreqDev = freqDev; 815 if(freqDev < 0.0) { 816 newFreqDev = 62.5; 817 } 818 819 RADIOLIB_CHECK_RANGE(newFreqDev, 62.5, 1000.0, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION); 820 821 // override for the lowest possible frequency deviation - required for some PhysicalLayer protocols 822 if(newFreqDev == 0.0) { 823 _modIndex = RADIOLIB_SX128X_BLE_GFSK_MOD_IND_0_35; 824 _br = RADIOLIB_SX128X_BLE_GFSK_BR_0_125_BW_0_3; 825 return(setModulationParams(_br, _modIndex, _shaping)); 826 } 827 828 // update modulation parameters 829 uint8_t modIndex = (uint8_t)((8.0 * (newFreqDev / (float)_brKbps)) - 1.0); 830 if(modIndex > RADIOLIB_SX128X_BLE_GFSK_MOD_IND_4_00) { 831 return(RADIOLIB_ERR_INVALID_MODULATION_PARAMETERS); 832 } 833 834 // update modulation parameters 835 _modIndex = modIndex; 836 return(setModulationParams(_br, _modIndex, _shaping)); 837 } 838 839 int16_t SX128x::setDataShaping(uint8_t sh) { 840 // check active modem 841 uint8_t modem = getPacketType(); 842 if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC))) { 843 return(RADIOLIB_ERR_WRONG_MODEM); 844 } 845 846 // set data shaping 847 switch(sh) { 848 case RADIOLIB_SHAPING_NONE: 849 _shaping = RADIOLIB_SX128X_BLE_GFSK_BT_OFF; 850 break; 851 case RADIOLIB_SHAPING_0_5: 852 _shaping = RADIOLIB_SX128X_BLE_GFSK_BT_0_5; 853 break; 854 case RADIOLIB_SHAPING_1_0: 855 _shaping = RADIOLIB_SX128X_BLE_GFSK_BT_1_0; 856 break; 857 default: 858 return(RADIOLIB_ERR_INVALID_DATA_SHAPING); 859 } 860 861 // update modulation parameters 862 if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_BLE)) { 863 return(setModulationParams(_br, _modIndex, _shaping)); 864 } else { 865 return(setModulationParams(_br, _crFLRC, _shaping)); 866 } 867 } 868 869 int16_t SX128x::setSyncWord(uint8_t* syncWord, uint8_t len) { 870 // check active modem 871 uint8_t modem = getPacketType(); 872 if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC))) { 873 return(RADIOLIB_ERR_WRONG_MODEM); 874 } 875 876 if(modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) { 877 // GFSK can use up to 5 bytes as sync word 878 if(len > 5) { 879 return(RADIOLIB_ERR_INVALID_SYNC_WORD); 880 } 881 882 // calculate sync word length parameter value 883 if(len > 0) { 884 _syncWordLen = (len - 1)*2; 885 } 886 887 } else { 888 // FLRC requires 32-bit sync word 889 if(!((len == 0) || (len == 4))) { 890 return(RADIOLIB_ERR_INVALID_SYNC_WORD); 891 } 892 893 // save sync word length parameter value 894 _syncWordLen = len; 895 } 896 897 // reverse sync word byte order 898 uint8_t syncWordBuff[] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; 899 for(uint8_t i = 0; i < len; i++) { 900 syncWordBuff[4 - i] = syncWord[i]; 901 } 902 903 // update sync word 904 int16_t state = SX128x::writeRegister(RADIOLIB_SX128X_REG_SYNC_WORD_1_BYTE_4, syncWordBuff, 5); 905 RADIOLIB_ASSERT(state); 906 907 // update packet parameters 908 if(_syncWordLen == 0) { 909 _syncWordMatch = RADIOLIB_SX128X_GFSK_FLRC_SYNC_WORD_OFF; 910 } else { 911 /// \todo add support for multiple sync words 912 _syncWordMatch = RADIOLIB_SX128X_GFSK_FLRC_SYNC_WORD_1; 913 } 914 return(setPacketParamsGFSK(_preambleLengthGFSK, _syncWordLen, _syncWordMatch, _crcGFSK, _whitening)); 915 } 916 917 int16_t SX128x::setSyncWord(uint8_t syncWord, uint8_t controlBits) { 918 // check active modem 919 if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_LORA) { 920 return(RADIOLIB_ERR_WRONG_MODEM); 921 } 922 923 // update register 924 uint8_t data[2] = {(uint8_t)((syncWord & 0xF0) | ((controlBits & 0xF0) >> 4)), (uint8_t)(((syncWord & 0x0F) << 4) | (controlBits & 0x0F))}; 925 return(writeRegister(RADIOLIB_SX128X_REG_LORA_SYNC_WORD_MSB, data, 2)); 926 } 927 928 int16_t SX128x::setCRC(uint8_t len, uint32_t initial, uint16_t polynomial) { 929 // check active modem 930 uint8_t modem = getPacketType(); 931 932 int16_t state; 933 if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC)) { 934 // update packet parameters 935 if(modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) { 936 if(len > 2) { 937 return(RADIOLIB_ERR_INVALID_CRC_CONFIGURATION); 938 } 939 } else { 940 if(len > 3) { 941 return(RADIOLIB_ERR_INVALID_CRC_CONFIGURATION); 942 } 943 } 944 _crcGFSK = len << 4; 945 state = setPacketParamsGFSK(_preambleLengthGFSK, _syncWordLen, _syncWordMatch, _crcGFSK, _whitening); 946 RADIOLIB_ASSERT(state); 947 948 // set initial CRC value 949 uint8_t data[] = { (uint8_t)((initial >> 8) & 0xFF), (uint8_t)(initial & 0xFF) }; 950 state = writeRegister(RADIOLIB_SX128X_REG_CRC_INITIAL_MSB, data, 2); 951 RADIOLIB_ASSERT(state); 952 953 // set CRC polynomial 954 data[0] = (uint8_t)((polynomial >> 8) & 0xFF); 955 data[1] = (uint8_t)(polynomial & 0xFF); 956 state = writeRegister(RADIOLIB_SX128X_REG_CRC_POLYNOMIAL_MSB, data, 2); 957 return(state); 958 959 } else if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) { 960 // update packet parameters 961 if(len == 0) { 962 _crcBLE = RADIOLIB_SX128X_BLE_CRC_OFF; 963 } else if(len == 3) { 964 _crcBLE = RADIOLIB_SX128X_BLE_CRC_3_BYTE; 965 } else { 966 return(RADIOLIB_ERR_INVALID_CRC_CONFIGURATION); 967 } 968 state = setPacketParamsBLE(_connectionState, _crcBLE, _bleTestPayload, _whitening); 969 RADIOLIB_ASSERT(state); 970 971 // set initial CRC value 972 uint8_t data[] = { (uint8_t)((initial >> 16) & 0xFF), (uint8_t)((initial >> 8) & 0xFF), (uint8_t)(initial & 0xFF) }; 973 state = writeRegister(RADIOLIB_SX128X_REG_BLE_CRC_INITIAL_MSB, data, 3); 974 return(state); 975 976 } else if((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING)) { 977 // update packet parameters 978 if(len == 0) { 979 _crcLoRa = RADIOLIB_SX128X_LORA_CRC_OFF; 980 } else if(len == 2) { 981 _crcLoRa = RADIOLIB_SX128X_LORA_CRC_ON; 982 } else { 983 return(RADIOLIB_ERR_INVALID_CRC_CONFIGURATION); 984 } 985 state = setPacketParamsLoRa(_preambleLengthLoRa, _headerType, _payloadLen, _crcLoRa); 986 return(state); 987 } 988 989 return(RADIOLIB_ERR_UNKNOWN); 990 } 991 992 int16_t SX128x::setWhitening(bool enabled) { 993 // check active modem 994 uint8_t modem = getPacketType(); 995 if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_BLE))) { 996 return(RADIOLIB_ERR_WRONG_MODEM); 997 } 998 999 // update packet parameters 1000 if(enabled) { 1001 _whitening = RADIOLIB_SX128X_GFSK_BLE_WHITENING_ON; 1002 } else { 1003 _whitening = RADIOLIB_SX128X_GFSK_BLE_WHITENING_OFF; 1004 } 1005 1006 if(modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) { 1007 return(setPacketParamsGFSK(_preambleLengthGFSK, _syncWordLen, _syncWordMatch, _crcGFSK, _whitening)); 1008 } 1009 return(setPacketParamsBLE(_connectionState, _crcBLE, _bleTestPayload, _whitening)); 1010 } 1011 1012 int16_t SX128x::setAccessAddress(uint32_t addr) { 1013 // check active modem 1014 if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_BLE) { 1015 return(RADIOLIB_ERR_WRONG_MODEM); 1016 } 1017 1018 // set the address 1019 uint8_t addrBuff[] = { (uint8_t)((addr >> 24) & 0xFF), (uint8_t)((addr >> 16) & 0xFF), (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) }; 1020 return(SX128x::writeRegister(RADIOLIB_SX128X_REG_ACCESS_ADDRESS_BYTE_3, addrBuff, 4)); 1021 } 1022 1023 int16_t SX128x::setHighSensitivityMode(bool hsm) { 1024 // read the current registers 1025 uint8_t RxGain = 0; 1026 int16_t state = readRegister(RADIOLIB_SX128X_REG_GAIN_MODE, &RxGain, 1); 1027 RADIOLIB_ASSERT(state); 1028 1029 if(hsm) { 1030 RxGain |= 0xC0; // Set bits 6 and 7 1031 } else { 1032 RxGain &= ~0xC0; // Unset bits 6 and 7 1033 } 1034 1035 // update all values 1036 state = writeRegister(RADIOLIB_SX128X_REG_GAIN_MODE, &RxGain, 1); 1037 return(state); 1038 } 1039 1040 int16_t SX128x::setGainControl(uint8_t gain) { 1041 // read the current registers 1042 uint8_t ManualGainSetting = 0; 1043 int16_t state = readRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_CONTROL_ENABLE_2, &ManualGainSetting, 1); 1044 RADIOLIB_ASSERT(state); 1045 uint8_t LNAGainValue = 0; 1046 state = readRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_SETTING, &LNAGainValue, 1); 1047 RADIOLIB_ASSERT(state); 1048 uint8_t LNAGainControl = 0; 1049 state = readRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_CONTROL_ENABLE_1, &LNAGainControl, 1); 1050 RADIOLIB_ASSERT(state); 1051 1052 // set the gain 1053 if (gain > 0 && gain < 14) { 1054 // Set manual gain 1055 ManualGainSetting &= ~0x01; // Set bit 0 to 0 (Enable Manual Gain Control) 1056 LNAGainValue &= 0xF0; // Bits 0, 1, 2 and 3 to 0 1057 LNAGainValue |= gain; // Set bits 0, 1, 2 and 3 to Manual Gain Setting (1-13) 1058 LNAGainControl |= 0x80; // Set bit 7 to 1 (Enable Manual Gain Control) 1059 } else { 1060 // Set automatic gain if 0 or out of range 1061 ManualGainSetting |= 0x01; // Set bit 0 to 1 (Enable Automatic Gain Control) 1062 LNAGainValue &= 0xF0; // Bits 0, 1, 2 and 3 to 0 1063 LNAGainValue |= 0x0A; // Set bits 0, 1, 2 and 3 to Manual Gain Setting (1-13) 1064 LNAGainControl &= ~0x80; // Set bit 7 to 0 (Enable Automatic Gain Control) 1065 } 1066 1067 // update all values 1068 state = writeRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_CONTROL_ENABLE_2, &ManualGainSetting, 1); 1069 RADIOLIB_ASSERT(state); 1070 state = writeRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_SETTING, &LNAGainValue, 1); 1071 RADIOLIB_ASSERT(state); 1072 state = writeRegister(RADIOLIB_SX128X_REG_MANUAL_GAIN_CONTROL_ENABLE_1, &LNAGainControl, 1); 1073 return(state); 1074 } 1075 1076 float SX128x::getRSSI() { 1077 // get packet status 1078 uint8_t packetStatus[5]; 1079 SPIreadCommand(RADIOLIB_SX128X_CMD_GET_PACKET_STATUS, packetStatus, 5); 1080 1081 // check active modem 1082 uint8_t modem = getPacketType(); 1083 if((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING)) { 1084 // LoRa or ranging 1085 uint8_t rssiSync = packetStatus[0]; 1086 float rssiMeasured = -1.0 * rssiSync/2.0; 1087 float snr = getSNR(); 1088 if(snr <= 0.0) { 1089 return(rssiMeasured - snr); 1090 } else { 1091 return(rssiMeasured); 1092 } 1093 } else { 1094 // GFSK, BLE or FLRC 1095 uint8_t rssiSync = packetStatus[1]; 1096 return(-1.0 * rssiSync/2.0); 1097 } 1098 } 1099 1100 float SX128x::getSNR() { 1101 // check active modem 1102 uint8_t modem = getPacketType(); 1103 if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING))) { 1104 return(0.0); 1105 } 1106 1107 // get packet status 1108 uint8_t packetStatus[5]; 1109 SPIreadCommand(RADIOLIB_SX128X_CMD_GET_PACKET_STATUS, packetStatus, 5); 1110 1111 // calculate real SNR 1112 uint8_t snr = packetStatus[1]; 1113 if(snr < 128) { 1114 return(snr/4.0); 1115 } else { 1116 return((snr - 256)/4.0); 1117 } 1118 } 1119 1120 float SX128x::getFrequencyError() { 1121 // check active modem 1122 uint8_t modem = getPacketType(); 1123 if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING))) { 1124 return(0.0); 1125 } 1126 1127 // read the raw frequency error register values 1128 uint8_t efeRaw[3] = {0}; 1129 int16_t state = readRegister(RADIOLIB_SX128X_REG_FEI_MSB, &efeRaw[0], 1); 1130 RADIOLIB_ASSERT(state); 1131 state = readRegister(RADIOLIB_SX128X_REG_FEI_MID, &efeRaw[1], 1); 1132 RADIOLIB_ASSERT(state); 1133 state = readRegister(RADIOLIB_SX128X_REG_FEI_LSB, &efeRaw[2], 1); 1134 RADIOLIB_ASSERT(state); 1135 uint32_t efe = ((uint32_t) efeRaw[0] << 16) | ((uint32_t) efeRaw[1] << 8) | efeRaw[2]; 1136 efe &= 0x0FFFFF; 1137 1138 float error = 0; 1139 1140 // check the first bit 1141 if (efe & 0x80000) { 1142 // frequency error is negative 1143 efe |= (uint32_t) 0xFFF00000; 1144 efe = ~efe + 1; 1145 error = 1.55 * (float) efe / (1600.0 / (float) _bwKhz) * -1.0; 1146 } else { 1147 error = 1.55 * (float) efe / (1600.0 / (float) _bwKhz); 1148 } 1149 1150 return(error); 1151 } 1152 1153 size_t SX128x::getPacketLength(bool update) { 1154 (void)update; 1155 uint8_t rxBufStatus[2] = {0, 0}; 1156 SPIreadCommand(RADIOLIB_SX128X_CMD_GET_RX_BUFFER_STATUS, rxBufStatus, 2); 1157 return((size_t)rxBufStatus[0]); 1158 } 1159 1160 uint32_t SX128x::getTimeOnAir(size_t len) { 1161 // check active modem 1162 uint8_t modem = getPacketType(); 1163 if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) { 1164 // calculate number of symbols 1165 float N_symbol = 0; 1166 uint8_t sf = _sf >> 4; 1167 if(_cr <= RADIOLIB_SX128X_LORA_CR_4_8) { 1168 // legacy coding rate - nice and simple 1169 1170 // get SF coefficients 1171 float coeff1 = 0; 1172 int16_t coeff2 = 0; 1173 int16_t coeff3 = 0; 1174 if(sf < 7) { 1175 // SF5, SF6 1176 coeff1 = 6.25; 1177 coeff2 = 4*sf; 1178 coeff3 = 4*sf; 1179 } else if(sf < 11) { 1180 // SF7. SF8, SF9, SF10 1181 coeff1 = 4.25; 1182 coeff2 = 4*sf + 8; 1183 coeff3 = 4*sf; 1184 } else { 1185 // SF11, SF12 1186 coeff1 = 4.25; 1187 coeff2 = 4*sf + 8; 1188 coeff3 = 4*(sf - 2); 1189 } 1190 1191 // get CRC length 1192 int16_t N_bitCRC = 16; 1193 if(_crcLoRa == RADIOLIB_SX128X_LORA_CRC_OFF) { 1194 N_bitCRC = 0; 1195 } 1196 1197 // get header length 1198 int16_t N_symbolHeader = 20; 1199 if(_headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) { 1200 N_symbolHeader = 0; 1201 } 1202 1203 // calculate number of LoRa preamble symbols 1204 uint32_t N_symbolPreamble = (_preambleLengthLoRa & 0x0F) * (uint32_t(1) << ((_preambleLengthLoRa & 0xF0) >> 4)); 1205 1206 // calculate the number of symbols 1207 N_symbol = (float)N_symbolPreamble + coeff1 + 8.0 + ceil(max((int16_t)(8 * len + N_bitCRC - coeff2 + N_symbolHeader), (int16_t)0) / (float)coeff3) * (float)(_cr + 4); 1208 1209 } else { 1210 // long interleaving - abandon hope all ye who enter here 1211 /// \todo implement this mess - SX1280 datasheet v3.0 section 7.4.4.2 1212 1213 } 1214 1215 // get time-on-air in us 1216 return(((uint32_t(1) << sf) / _bwKhz) * N_symbol * 1000.0); 1217 1218 } else { 1219 return(((uint32_t)len * 8 * 1000) / _brKbps); 1220 } 1221 1222 } 1223 1224 int16_t SX128x::implicitHeader(size_t len) { 1225 return(setHeaderType(RADIOLIB_SX128X_LORA_HEADER_IMPLICIT, len)); 1226 } 1227 1228 int16_t SX128x::explicitHeader() { 1229 return(setHeaderType(RADIOLIB_SX128X_LORA_HEADER_EXPLICIT)); 1230 } 1231 1232 int16_t SX128x::setEncoding(uint8_t encoding) { 1233 return(setWhitening(encoding)); 1234 } 1235 1236 void SX128x::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) { 1237 _mod->setRfSwitchPins(rxEn, txEn); 1238 } 1239 1240 uint8_t SX128x::randomByte() { 1241 // it's unclear whether SX128x can measure RSSI while not receiving a packet 1242 // this method is implemented only for PhysicalLayer compatibility 1243 return(0); 1244 } 1245 1246 #if !defined(RADIOLIB_EXCLUDE_DIRECT_RECEIVE) 1247 void SX128x::setDirectAction(void (*func)(void)) { 1248 // SX128x is unable to perform direct mode reception 1249 // this method is implemented only for PhysicalLayer compatibility 1250 (void)func; 1251 } 1252 1253 void SX128x::readBit(RADIOLIB_PIN_TYPE pin) { 1254 // SX128x is unable to perform direct mode reception 1255 // this method is implemented only for PhysicalLayer compatibility 1256 (void)pin; 1257 } 1258 #endif 1259 1260 uint8_t SX128x::getStatus() { 1261 uint8_t data = 0; 1262 SPIreadCommand(RADIOLIB_SX128X_CMD_GET_STATUS, &data, 1); 1263 return(data); 1264 } 1265 1266 int16_t SX128x::writeRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) { 1267 uint8_t cmd[] = { RADIOLIB_SX128X_CMD_WRITE_REGISTER, (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) }; 1268 return(SPIwriteCommand(cmd, 3, data, numBytes)); 1269 } 1270 1271 int16_t SX128x::readRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) { 1272 uint8_t cmd[] = { RADIOLIB_SX128X_CMD_READ_REGISTER, (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) }; 1273 return(SX128x::SPItransfer(cmd, 3, false, NULL, data, numBytes, true)); 1274 } 1275 1276 int16_t SX128x::writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset) { 1277 uint8_t cmd[] = { RADIOLIB_SX128X_CMD_WRITE_BUFFER, offset }; 1278 return(SPIwriteCommand(cmd, 2, data, numBytes)); 1279 } 1280 1281 int16_t SX128x::readBuffer(uint8_t* data, uint8_t numBytes) { 1282 uint8_t cmd[] = { RADIOLIB_SX128X_CMD_READ_BUFFER, RADIOLIB_SX128X_CMD_NOP }; 1283 return(SPIreadCommand(cmd, 2, data, numBytes)); 1284 } 1285 1286 int16_t SX128x::setTx(uint16_t periodBaseCount, uint8_t periodBase) { 1287 uint8_t data[] = { periodBase, (uint8_t)((periodBaseCount >> 8) & 0xFF), (uint8_t)(periodBaseCount & 0xFF) }; 1288 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_TX, data, 3)); 1289 } 1290 1291 int16_t SX128x::setRx(uint16_t periodBaseCount, uint8_t periodBase) { 1292 uint8_t data[] = { periodBase, (uint8_t)((periodBaseCount >> 8) & 0xFF), (uint8_t)(periodBaseCount & 0xFF) }; 1293 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_RX, data, 3)); 1294 } 1295 1296 int16_t SX128x::setCad() { 1297 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_CAD, NULL, 0)); 1298 } 1299 1300 uint8_t SX128x::getPacketType() { 1301 uint8_t data = 0xFF; 1302 SPIreadCommand(RADIOLIB_SX128X_CMD_GET_PACKET_TYPE, &data, 1); 1303 return(data); 1304 } 1305 1306 int16_t SX128x::setRfFrequency(uint32_t frf) { 1307 uint8_t data[] = { (uint8_t)((frf >> 16) & 0xFF), (uint8_t)((frf >> 8) & 0xFF), (uint8_t)(frf & 0xFF) }; 1308 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_RF_FREQUENCY, data, 3)); 1309 } 1310 1311 int16_t SX128x::setTxParams(uint8_t power, uint8_t rampTime) { 1312 uint8_t data[] = { power, rampTime }; 1313 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_TX_PARAMS, data, 2)); 1314 } 1315 1316 int16_t SX128x::setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress) { 1317 uint8_t data[] = { txBaseAddress, rxBaseAddress }; 1318 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_BUFFER_BASE_ADDRESS, data, 2)); 1319 } 1320 1321 int16_t SX128x::setModulationParams(uint8_t modParam1, uint8_t modParam2, uint8_t modParam3) { 1322 uint8_t data[] = { modParam1, modParam2, modParam3 }; 1323 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_MODULATION_PARAMS, data, 3)); 1324 } 1325 1326 int16_t SX128x::setPacketParamsGFSK(uint8_t preambleLen, uint8_t syncWordLen, uint8_t syncWordMatch, uint8_t crcLen, uint8_t whitening, uint8_t payloadLen, uint8_t headerType) { 1327 uint8_t data[] = { preambleLen, syncWordLen, syncWordMatch, headerType, payloadLen, crcLen, whitening }; 1328 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_PACKET_PARAMS, data, 7)); 1329 } 1330 1331 int16_t SX128x::setPacketParamsBLE(uint8_t connState, uint8_t crcLen, uint8_t bleTestPayload, uint8_t whitening) { 1332 uint8_t data[] = { connState, crcLen, bleTestPayload, whitening, 0x00, 0x00, 0x00 }; 1333 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_PACKET_PARAMS, data, 7)); 1334 } 1335 1336 int16_t SX128x::setPacketParamsLoRa(uint8_t preambleLen, uint8_t headerType, uint8_t payloadLen, uint8_t crc, uint8_t invertIQ) { 1337 uint8_t data[] = { preambleLen, headerType, payloadLen, crc, invertIQ, 0x00, 0x00 }; 1338 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_PACKET_PARAMS, data, 7)); 1339 } 1340 1341 int16_t SX128x::setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask) { 1342 uint8_t data[] = { (uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)(irqMask & 0xFF), 1343 (uint8_t)((dio1Mask >> 8) & 0xFF), (uint8_t)(dio1Mask & 0xFF), 1344 (uint8_t)((dio2Mask >> 8) & 0xFF), (uint8_t)(dio2Mask & 0xFF), 1345 (uint8_t)((dio3Mask >> 8) & 0xFF), (uint8_t)(dio3Mask & 0xFF) }; 1346 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_DIO_IRQ_PARAMS, data, 8)); 1347 } 1348 1349 uint16_t SX128x::getIrqStatus() { 1350 uint8_t data[] = { 0x00, 0x00 }; 1351 SPIreadCommand(RADIOLIB_SX128X_CMD_GET_IRQ_STATUS, data, 2); 1352 return(((uint16_t)(data[0]) << 8) | data[1]); 1353 } 1354 1355 int16_t SX128x::clearIrqStatus(uint16_t clearIrqParams) { 1356 uint8_t data[] = { (uint8_t)((clearIrqParams >> 8) & 0xFF), (uint8_t)(clearIrqParams & 0xFF) }; 1357 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_CLEAR_IRQ_STATUS, data, 2)); 1358 } 1359 1360 int16_t SX128x::setRangingRole(uint8_t role) { 1361 uint8_t data[] = { role }; 1362 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_RANGING_ROLE, data, 1)); 1363 } 1364 1365 int16_t SX128x::setPacketType(uint8_t type) { 1366 uint8_t data[] = { type }; 1367 return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_PACKET_TYPE, data, 1)); 1368 } 1369 1370 int16_t SX128x::setHeaderType(uint8_t headerType, size_t len) { 1371 // check active modem 1372 uint8_t modem = getPacketType(); 1373 if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING))) { 1374 return(RADIOLIB_ERR_WRONG_MODEM); 1375 } 1376 1377 // update packet parameters 1378 _headerType = headerType; 1379 _payloadLen = len; 1380 return(setPacketParamsLoRa(_preambleLengthLoRa, _headerType, _payloadLen, _crcLoRa)); 1381 } 1382 1383 int16_t SX128x::config(uint8_t modem) { 1384 // reset buffer base address 1385 int16_t state = setBufferBaseAddress(); 1386 RADIOLIB_ASSERT(state); 1387 1388 // set modem 1389 uint8_t data[1]; 1390 data[0] = modem; 1391 state = SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_PACKET_TYPE, data, 1); 1392 RADIOLIB_ASSERT(state); 1393 1394 // set CAD parameters 1395 data[0] = RADIOLIB_SX128X_CAD_ON_8_SYMB; 1396 state = SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_CAD_PARAMS, data, 1); 1397 RADIOLIB_ASSERT(state); 1398 1399 // set regulator mode to DC-DC 1400 data[0] = RADIOLIB_SX128X_REGULATOR_DC_DC; 1401 state = SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_REGULATOR_MODE, data, 1); 1402 RADIOLIB_ASSERT(state); 1403 1404 return(RADIOLIB_ERR_NONE); 1405 } 1406 1407 int16_t SX128x::SPIwriteCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy) { 1408 return(SX128x::SPItransfer(cmd, cmdLen, true, data, NULL, numBytes, waitForBusy)); 1409 } 1410 1411 int16_t SX128x::SPIwriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy) { 1412 return(SX128x::SPItransfer(&cmd, 1, true, data, NULL, numBytes, waitForBusy)); 1413 } 1414 1415 int16_t SX128x::SPIreadCommand(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, uint8_t numBytes, bool waitForBusy) { 1416 return(SX128x::SPItransfer(cmd, cmdLen, false, NULL, data, numBytes, waitForBusy)); 1417 } 1418 1419 int16_t SX128x::SPIreadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes, bool waitForBusy) { 1420 return(SX128x::SPItransfer(&cmd, 1, false, NULL, data, numBytes, waitForBusy)); 1421 } 1422 1423 int16_t SX128x::SPItransfer(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, bool waitForBusy, uint32_t timeout) { 1424 #if defined(RADIOLIB_VERBOSE) 1425 uint8_t debugBuff[256]; 1426 #endif 1427 1428 // ensure BUSY is low (state machine ready) 1429 uint32_t start = _mod->millis(); 1430 while(_mod->digitalRead(_mod->getGpio())) { 1431 _mod->yield(); 1432 if(_mod->millis() - start >= timeout) { 1433 _mod->digitalWrite(_mod->getCs(), HIGH); 1434 return(RADIOLIB_ERR_SPI_CMD_TIMEOUT); 1435 } 1436 } 1437 1438 // pull NSS low 1439 _mod->digitalWrite(_mod->getCs(), LOW); 1440 1441 // start transfer 1442 _mod->SPIbeginTransaction(); 1443 1444 // send command byte(s) 1445 for(uint8_t n = 0; n < cmdLen; n++) { 1446 _mod->SPItransfer(cmd[n]); 1447 } 1448 1449 // variable to save error during SPI transfer 1450 uint8_t status = 0; 1451 1452 // send/receive all bytes 1453 if(write) { 1454 for(uint8_t n = 0; n < numBytes; n++) { 1455 // send byte 1456 uint8_t in = _mod->SPItransfer(dataOut[n]); 1457 #if defined(RADIOLIB_VERBOSE) 1458 debugBuff[n] = in; 1459 #endif 1460 1461 // check status 1462 if(((in & 0b00011100) == RADIOLIB_SX128X_STATUS_CMD_TIMEOUT) || 1463 ((in & 0b00011100) == RADIOLIB_SX128X_STATUS_CMD_ERROR) || 1464 ((in & 0b00011100) == RADIOLIB_SX128X_STATUS_CMD_FAILED)) { 1465 status = in & 0b00011100; 1466 break; 1467 } else if(in == 0x00 || in == 0xFF) { 1468 status = RADIOLIB_SX128X_STATUS_SPI_FAILED; 1469 break; 1470 } 1471 } 1472 1473 } else { 1474 // skip the first byte for read-type commands (status-only) 1475 uint8_t in = _mod->SPItransfer(RADIOLIB_SX128X_CMD_NOP); 1476 #if defined(RADIOLIB_VERBOSE) 1477 debugBuff[0] = in; 1478 #endif 1479 1480 // check status 1481 if(((in & 0b00011100) == RADIOLIB_SX128X_STATUS_CMD_TIMEOUT) || 1482 ((in & 0b00011100) == RADIOLIB_SX128X_STATUS_CMD_ERROR) || 1483 ((in & 0b00011100) == RADIOLIB_SX128X_STATUS_CMD_FAILED)) { 1484 status = in & 0b00011100; 1485 } else if(in == 0x00 || in == 0xFF) { 1486 status = RADIOLIB_SX128X_STATUS_SPI_FAILED; 1487 } else { 1488 for(uint8_t n = 0; n < numBytes; n++) { 1489 dataIn[n] = _mod->SPItransfer(RADIOLIB_SX128X_CMD_NOP); 1490 } 1491 } 1492 } 1493 1494 // stop transfer 1495 _mod->SPIendTransaction(); 1496 _mod->digitalWrite(_mod->getCs(), HIGH); 1497 1498 // wait for BUSY to go high and then low 1499 if(waitForBusy) { 1500 _mod->delayMicroseconds(1); 1501 start = _mod->millis(); 1502 while(_mod->digitalRead(_mod->getGpio())) { 1503 _mod->yield(); 1504 if(_mod->millis() - start >= timeout) { 1505 status = RADIOLIB_SX128X_STATUS_CMD_TIMEOUT; 1506 break; 1507 } 1508 } 1509 } 1510 1511 // print debug output 1512 #if defined(RADIOLIB_VERBOSE) 1513 // print command byte(s) 1514 RADIOLIB_VERBOSE_PRINT("CMD\t"); 1515 for(uint8_t n = 0; n < cmdLen; n++) { 1516 RADIOLIB_VERBOSE_PRINT(cmd[n], HEX); 1517 RADIOLIB_VERBOSE_PRINT('\t'); 1518 } 1519 RADIOLIB_VERBOSE_PRINTLN(); 1520 1521 // print data bytes 1522 RADIOLIB_VERBOSE_PRINT("DAT"); 1523 if(write) { 1524 RADIOLIB_VERBOSE_PRINT("W\t"); 1525 for(uint8_t n = 0; n < numBytes; n++) { 1526 RADIOLIB_VERBOSE_PRINT(dataOut[n], HEX); 1527 RADIOLIB_VERBOSE_PRINT('\t'); 1528 RADIOLIB_VERBOSE_PRINT(debugBuff[n], HEX); 1529 RADIOLIB_VERBOSE_PRINT('\t'); 1530 } 1531 RADIOLIB_VERBOSE_PRINTLN(); 1532 } else { 1533 RADIOLIB_VERBOSE_PRINT("R\t"); 1534 // skip the first byte for read-type commands (status-only) 1535 RADIOLIB_VERBOSE_PRINT(RADIOLIB_SX128X_CMD_NOP, HEX); 1536 RADIOLIB_VERBOSE_PRINT('\t'); 1537 RADIOLIB_VERBOSE_PRINT(debugBuff[0], HEX); 1538 RADIOLIB_VERBOSE_PRINT('\t') 1539 1540 for(uint8_t n = 0; n < numBytes; n++) { 1541 RADIOLIB_VERBOSE_PRINT(RADIOLIB_SX128X_CMD_NOP, HEX); 1542 RADIOLIB_VERBOSE_PRINT('\t'); 1543 RADIOLIB_VERBOSE_PRINT(dataIn[n], HEX); 1544 RADIOLIB_VERBOSE_PRINT('\t'); 1545 } 1546 RADIOLIB_VERBOSE_PRINTLN(); 1547 } 1548 RADIOLIB_VERBOSE_PRINTLN(); 1549 #else 1550 // some faster platforms require a short delay here 1551 // not sure why, but it seems that long enough SPI transaction 1552 // (e.g. setPacketParams for GFSK) will fail without it 1553 #if defined(RADIOLIB_SPI_SLOWDOWN) 1554 _mod->delay(1); 1555 #endif 1556 #endif 1557 1558 // parse status 1559 switch(status) { 1560 case RADIOLIB_SX128X_STATUS_CMD_TIMEOUT: 1561 return(RADIOLIB_ERR_SPI_CMD_TIMEOUT); 1562 case RADIOLIB_SX128X_STATUS_CMD_ERROR: 1563 return(RADIOLIB_ERR_SPI_CMD_INVALID); 1564 case RADIOLIB_SX128X_STATUS_CMD_FAILED: 1565 return(RADIOLIB_ERR_SPI_CMD_FAILED); 1566 case RADIOLIB_SX128X_STATUS_SPI_FAILED: 1567 return(RADIOLIB_ERR_CHIP_NOT_FOUND); 1568 default: 1569 return(RADIOLIB_ERR_NONE); 1570 } 1571 } 1572 1573 #endif