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