LCOV - code coverage report
Current view: top level - src/modules/LR2021 - LR2021.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 144 567 25.4 %
Date: 2026-04-20 19:58:46 Functions: 32 45 71.1 %

          Line data    Source code
       1             : #include "LR2021.h"
       2             : 
       3             : #include <string.h>
       4             : #include <math.h>
       5             : 
       6             : #if !RADIOLIB_EXCLUDE_LR2021
       7             : 
       8           1 : LR2021::LR2021(Module* mod) : LRxxxx(mod) {
       9           1 :   this->freqStep = RADIOLIB_LR2021_FREQUENCY_STEP_SIZE;
      10           1 :   this->maxPacketLength = RADIOLIB_LR2021_MAX_PACKET_LENGTH;
      11           1 :   this->implicitLen = RADIOLIB_LR2021_MAX_PACKET_LENGTH;
      12           1 :   this->irqMap[RADIOLIB_IRQ_TX_DONE] = RADIOLIB_LR2021_IRQ_TX_DONE;
      13           1 :   this->irqMap[RADIOLIB_IRQ_RX_DONE] = RADIOLIB_LR2021_IRQ_RX_DONE;
      14           1 :   this->irqMap[RADIOLIB_IRQ_PREAMBLE_DETECTED] = RADIOLIB_LR2021_IRQ_PREAMBLE_DETECTED;
      15           1 :   this->irqMap[RADIOLIB_IRQ_SYNC_WORD_VALID] = RADIOLIB_LR2021_IRQ_LORA_HEADER_VALID;
      16           1 :   this->irqMap[RADIOLIB_IRQ_HEADER_VALID] = RADIOLIB_LR2021_IRQ_LORA_HEADER_VALID;
      17           1 :   this->irqMap[RADIOLIB_IRQ_HEADER_ERR] = RADIOLIB_LR2021_IRQ_LORA_HDR_CRC_ERROR;
      18           1 :   this->irqMap[RADIOLIB_IRQ_CRC_ERR] = RADIOLIB_LR2021_IRQ_CRC_ERROR;
      19           1 :   this->irqMap[RADIOLIB_IRQ_CAD_DONE] = RADIOLIB_LR2021_IRQ_CAD_DONE;
      20           1 :   this->irqMap[RADIOLIB_IRQ_CAD_DETECTED] = RADIOLIB_LR2021_IRQ_CAD_DETECTED;
      21           1 :   this->irqMap[RADIOLIB_IRQ_TIMEOUT] = RADIOLIB_LR2021_IRQ_TIMEOUT;
      22           1 : }
      23             : 
      24           0 : int16_t LR2021::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
      25             :   // set module properties and perform initial setup
      26           0 :   int16_t state = this->modSetup(freq, tcxoVoltage, RADIOLIB_LR2021_PACKET_TYPE_LORA);
      27           0 :   RADIOLIB_ASSERT(state);
      28             : 
      29             :   // configure publicly accessible settings
      30           0 :   state = setBandwidth(bw);
      31           0 :   RADIOLIB_ASSERT(state);
      32             : 
      33           0 :   state = setSpreadingFactor(sf);
      34           0 :   RADIOLIB_ASSERT(state);
      35             : 
      36           0 :   state = setCodingRate(cr);
      37           0 :   RADIOLIB_ASSERT(state);
      38             : 
      39           0 :   state = setSyncWord(syncWord);
      40           0 :   RADIOLIB_ASSERT(state);
      41             : 
      42           0 :   state = setOutputPower(power);
      43           0 :   RADIOLIB_ASSERT(state);
      44             : 
      45           0 :   state = setPreambleLength(preambleLength);
      46           0 :   RADIOLIB_ASSERT(state);
      47             : 
      48             :   // set publicly accessible settings that are not a part of begin method
      49           0 :   state = setCRC(2);
      50           0 :   RADIOLIB_ASSERT(state);
      51             : 
      52           0 :   state = invertIQ(false);
      53           0 :   return(state);
      54             : }
      55             : 
      56           0 : int16_t LR2021::beginGFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
      57           0 :   this->rxBandwidth = RADIOLIB_LR2021_GFSK_OOK_RX_BW_153_8;
      58           0 :   this->frequencyDev = freqDev * 1000.0f;
      59             : 
      60             :   // set module properties and perform initial setup
      61           0 :   int16_t state = this->modSetup(freq, tcxoVoltage, RADIOLIB_LR2021_PACKET_TYPE_GFSK);
      62           0 :   RADIOLIB_ASSERT(state);
      63             : 
      64             :   // configure publicly accessible settings
      65           0 :   state = setBitRate(br);
      66           0 :   RADIOLIB_ASSERT(state);
      67             : 
      68           0 :   state = setFrequencyDeviation(freqDev);
      69           0 :   RADIOLIB_ASSERT(state);
      70             : 
      71           0 :   state = setRxBandwidth(rxBw);
      72           0 :   RADIOLIB_ASSERT(state);
      73             : 
      74           0 :   state = setOutputPower(power);
      75           0 :   RADIOLIB_ASSERT(state);
      76             : 
      77           0 :   state = setPreambleLength(preambleLength);
      78           0 :   RADIOLIB_ASSERT(state);
      79             : 
      80             :   // set publicly accessible settings that are not a part of begin method
      81           0 :   uint8_t sync[] = { 0x12, 0xAD };
      82           0 :   state = setSyncWord(sync, 2);
      83           0 :   RADIOLIB_ASSERT(state);
      84             : 
      85           0 :   state = setDataShaping(RADIOLIB_SHAPING_NONE);
      86           0 :   RADIOLIB_ASSERT(state);
      87             : 
      88           0 :   state = setEncoding(RADIOLIB_ENCODING_NRZ);
      89           0 :   RADIOLIB_ASSERT(state);
      90             : 
      91           0 :   state = variablePacketLengthMode(RADIOLIB_LR2021_MAX_PACKET_LENGTH);
      92           0 :   RADIOLIB_ASSERT(state);
      93             : 
      94           0 :   state = setCRC(2);
      95           0 :   return(state);
      96             : }
      97             : 
      98           0 : int16_t LR2021::beginOOK(float freq, float br, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
      99           0 :   this->rxBandwidth = RADIOLIB_LR2021_GFSK_OOK_RX_BW_153_8;
     100             : 
     101             :   // set module properties and perform initial setup
     102           0 :   int16_t state = this->modSetup(freq, tcxoVoltage, RADIOLIB_LR2021_PACKET_TYPE_OOK);
     103           0 :   RADIOLIB_ASSERT(state);
     104             : 
     105             :   // configure publicly accessible settings
     106           0 :   state = setBitRate(br);
     107           0 :   RADIOLIB_ASSERT(state);
     108             : 
     109           0 :   state = setRxBandwidth(rxBw);
     110           0 :   RADIOLIB_ASSERT(state);
     111             : 
     112           0 :   state = setOutputPower(power);
     113           0 :   RADIOLIB_ASSERT(state);
     114             : 
     115           0 :   state = setPreambleLength(preambleLength);
     116           0 :   RADIOLIB_ASSERT(state);
     117             : 
     118             :   // set publicly accessible settings that are not a part of begin method
     119           0 :   uint8_t sync[] = { 0x12, 0xAD };
     120           0 :   state = setSyncWord(sync, 2);
     121           0 :   RADIOLIB_ASSERT(state);
     122             : 
     123           0 :   state = setDataShaping(RADIOLIB_SHAPING_NONE);
     124           0 :   RADIOLIB_ASSERT(state);
     125             : 
     126           0 :   state = setEncoding(RADIOLIB_ENCODING_NRZ);
     127           0 :   RADIOLIB_ASSERT(state);
     128             : 
     129           0 :   state = variablePacketLengthMode(RADIOLIB_LR2021_MAX_PACKET_LENGTH);
     130           0 :   RADIOLIB_ASSERT(state);
     131             : 
     132           0 :   state = setCRC(2);
     133           0 :   return(state);
     134             : }
     135             :     
     136           0 : int16_t LR2021::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, bool narrowGrid, int8_t power, float tcxoVoltage) {
     137             : // set module properties and perform initial setup
     138           0 :   int16_t state = this->modSetup(freq, tcxoVoltage, RADIOLIB_LR2021_PACKET_TYPE_LR_FHSS);
     139           0 :   RADIOLIB_ASSERT(state);
     140             : 
     141             :   // set grid spacing
     142           0 :   this->lrFhssGrid = narrowGrid ? RADIOLIB_LRXXXX_LR_FHSS_GRID_STEP_NON_FCC : RADIOLIB_LRXXXX_LR_FHSS_GRID_STEP_FCC;
     143             : 
     144             :   // configure publicly accessible settings
     145           0 :   state = setLrFhssConfig(bw, cr);
     146           0 :   RADIOLIB_ASSERT(state);
     147             : 
     148           0 :   state = setOutputPower(power);
     149           0 :   RADIOLIB_ASSERT(state);
     150             : 
     151           0 :   uint8_t syncWord[] = { 0x12, 0xAD, 0x10, 0x1B };
     152           0 :   state = setSyncWord(syncWord, 4);
     153           0 :   return(state);
     154             : }
     155             : 
     156           0 : int16_t LR2021::beginFLRC(float freq, uint16_t br, uint8_t cr, int8_t pwr, uint16_t preambleLength, uint8_t dataShaping, float tcxoVoltage) {
     157             :   // initialize FLRC modulation variables
     158           0 :   this->bitRateFlrc = br;
     159           0 :   this->codingRateFlrc = RADIOLIB_LR2021_FLRC_CR_3_4;
     160           0 :   this->pulseShape = RADIOLIB_LR2021_GFSK_BPSK_FLRC_OOK_SHAPING_GAUSS_BT_0_5;
     161             : 
     162             :   // initialize FLRC packet variables
     163           0 :   this->preambleLengthGFSK = preambleLength;
     164           0 :   this->crcLenGFSK = 1;
     165             : 
     166             :   // set module properties and perform initial setup
     167           0 :   int16_t state = this->modSetup(freq, tcxoVoltage, RADIOLIB_LR2021_PACKET_TYPE_FLRC);
     168           0 :   RADIOLIB_ASSERT(state);
     169             : 
     170             :   // configure publicly accessible settings
     171           0 :   state = setFrequency(freq);
     172           0 :   RADIOLIB_ASSERT(state);
     173             : 
     174           0 :   state = setBitRate(br);
     175           0 :   RADIOLIB_ASSERT(state);
     176             : 
     177           0 :   state = setCodingRate(cr);
     178           0 :   RADIOLIB_ASSERT(state);
     179             : 
     180           0 :   state = setOutputPower(pwr);
     181           0 :   RADIOLIB_ASSERT(state);
     182             : 
     183           0 :   state = setPreambleLength(preambleLength);
     184           0 :   RADIOLIB_ASSERT(state);
     185             : 
     186           0 :   state = setDataShaping(dataShaping);
     187           0 :   RADIOLIB_ASSERT(state);
     188             : 
     189             :   // set publicly accessible settings that are not a part of begin method
     190           0 :   uint8_t sync[] = { 0x2D, 0x01, 0x4B, 0x1D};
     191           0 :   state = setSyncWord(sync, 4);
     192           0 :   RADIOLIB_ASSERT(state);
     193             : 
     194           0 :   state = variablePacketLengthMode(RADIOLIB_LR2021_MAX_PACKET_LENGTH);
     195           0 :   RADIOLIB_ASSERT(state);
     196             : 
     197           0 :   state = setCRC(2);
     198           0 :   return(state);
     199             : }
     200             : 
     201           1 : int16_t LR2021::transmit(const uint8_t* data, size_t len, uint8_t addr) {
     202             :    // set mode to standby
     203           1 :   int16_t state = standby();
     204           1 :   RADIOLIB_ASSERT(state);
     205             : 
     206             :   // check packet length
     207           0 :   if (this->codingRate > RADIOLIB_LR2021_LORA_CR_4_8) {
     208             :     // Long Interleaver needs at least 8 bytes
     209           0 :     if(len < 8) {
     210           0 :       return(RADIOLIB_ERR_PACKET_TOO_SHORT);
     211             :     }
     212             : 
     213             :     // Long Interleaver supports up to 253 bytes if CRC is enabled
     214           0 :     if (this->crcTypeLoRa == RADIOLIB_LR2021_LORA_CRC_ENABLED && (len > RADIOLIB_LR2021_MAX_PACKET_LENGTH - 2)) {
     215           0 :       return(RADIOLIB_ERR_PACKET_TOO_LONG);
     216             :     }  
     217             :   } 
     218           0 :   if(len > RADIOLIB_LR2021_MAX_PACKET_LENGTH) {
     219           0 :     return(RADIOLIB_ERR_PACKET_TOO_LONG);
     220             :   }
     221             : 
     222             :   // get currently active modem
     223           0 :   uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
     224           0 :   state = getPacketType(&modem);
     225           0 :   RADIOLIB_ASSERT(state);
     226           0 :   RadioLibTime_t timeout = getTimeOnAir(len);
     227           0 :   if(modem == RADIOLIB_LR2021_PACKET_TYPE_LORA) {
     228             :     // calculate timeout (150% of expected time-on-air)
     229           0 :     timeout = (timeout * 3) / 2;
     230             : 
     231           0 :   } else if((modem == RADIOLIB_LR2021_PACKET_TYPE_GFSK) || 
     232           0 :             (modem == RADIOLIB_LR2021_PACKET_TYPE_LR_FHSS) ||
     233           0 :             (modem == RADIOLIB_LR2021_PACKET_TYPE_FLRC) ||
     234           0 :             (modem == RADIOLIB_LR2021_PACKET_TYPE_OOK)) {
     235             :     // calculate timeout (500% of expected time-on-air)
     236           0 :     timeout = timeout * 5;
     237             : 
     238             :   } else {
     239           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     240             :   }
     241             : 
     242             :   RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu us", timeout);
     243             : 
     244             :   // start transmission
     245           0 :   state = startTransmit(data, len, addr);
     246           0 :   RADIOLIB_ASSERT(state);
     247             : 
     248             :   // wait for packet transmission or timeout
     249           0 :   RadioLibTime_t start = this->mod->hal->micros();
     250           0 :   while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
     251           0 :     this->mod->hal->yield();
     252           0 :     if(this->mod->hal->micros() - start > timeout) {
     253           0 :       finishTransmit();
     254           0 :       return(RADIOLIB_ERR_TX_TIMEOUT);
     255             :     }
     256             :   }
     257             : 
     258           0 :   return(finishTransmit());
     259             : }
     260             : 
     261           1 : int16_t LR2021::receive(uint8_t* data, size_t len, RadioLibTime_t timeout) {
     262             :   // set mode to standby
     263           1 :   int16_t state = standby();
     264           1 :   RADIOLIB_ASSERT(state);
     265             : 
     266             :   // calculate timeout based on the configured modem
     267           0 :   RadioLibTime_t timeoutInternal = timeout;
     268           0 :   if(!timeoutInternal) {
     269             :     // get currently active modem
     270           0 :     uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
     271           0 :     state = getPacketType(&modem);
     272           0 :     RADIOLIB_ASSERT(state);
     273           0 :     if((modem == RADIOLIB_LR2021_PACKET_TYPE_LORA) ||
     274           0 :        (modem == RADIOLIB_LR2021_PACKET_TYPE_GFSK) ||
     275           0 :        (modem == RADIOLIB_LR2021_PACKET_TYPE_FLRC) ||
     276           0 :        (modem == RADIOLIB_LR2021_PACKET_TYPE_OOK)) {
     277             :       // calculate timeout (500 % of expected time-one-air)
     278           0 :       size_t maxLen = len;
     279           0 :       if(len == 0) { maxLen = RADIOLIB_LR2021_MAX_PACKET_LENGTH; }
     280           0 :       timeoutInternal = (getTimeOnAir(maxLen) * 5) / 1000;
     281             :     
     282           0 :     } else if(modem == RADIOLIB_LR2021_PACKET_TYPE_LR_FHSS) {
     283             :       // this modem cannot receive
     284           0 :       return(RADIOLIB_ERR_WRONG_MODEM);
     285             : 
     286             :     } else {
     287           0 :       return(RADIOLIB_ERR_UNKNOWN);
     288             :     
     289             :     }
     290             :   }
     291             : 
     292             :   RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeoutInternal);
     293             : 
     294             :   // start reception
     295           0 :   uint32_t timeoutValue = (uint32_t)(((float)timeoutInternal * 1000.0f) / 30.52f);
     296           0 :   state = startReceive(timeoutValue);
     297           0 :   RADIOLIB_ASSERT(state);
     298             : 
     299             :   // wait for packet reception or timeout
     300           0 :   bool softTimeout = false;
     301           0 :   RadioLibTime_t start = this->mod->hal->millis();
     302           0 :   while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
     303           0 :     this->mod->hal->yield();
     304             :     // safety check, the timeout should be done by the radio
     305           0 :     if(this->mod->hal->millis() - start > timeoutInternal) {
     306           0 :       softTimeout = true;
     307           0 :       break;
     308             :     }
     309             :   }
     310             : 
     311             :   // if it was a timeout, this will return an error code
     312             :   //! \TODO: [LR2021] taken from SX126x, does this really work?
     313           0 :   state = standby();
     314           0 :   if((state != RADIOLIB_ERR_NONE) && (state != RADIOLIB_ERR_SPI_CMD_TIMEOUT)) {
     315           0 :     return(state);
     316             :   }
     317             : 
     318             :   // check whether this was a timeout or not
     319           0 :   if(softTimeout || (getIrqFlags() & this->irqMap[RADIOLIB_IRQ_TIMEOUT])) {
     320           0 :     (void)finishReceive();
     321           0 :     return(RADIOLIB_ERR_RX_TIMEOUT);
     322             :   }
     323             : 
     324             :   // read the received data
     325           0 :   return(readData(data, len));
     326             : }
     327             : 
     328           1 : int16_t LR2021::transmitDirect(uint32_t frf) {
     329             :   // set RF switch (if present)
     330           1 :   this->mod->setRfSwitchState(Module::MODE_TX);
     331             : 
     332             :   // user requested to start transmitting immediately (required for RTTY)
     333           1 :   int16_t state = RADIOLIB_ERR_NONE;
     334           1 :   if(frf != 0) {
     335           0 :     state = setRfFrequency(frf);
     336             :   }
     337           1 :   RADIOLIB_ASSERT(state);
     338             : 
     339             :   // start transmitting
     340           1 :   return(setTxTestMode(RADIOLIB_LR2021_TX_TEST_MODE_CW));
     341             : }
     342             : 
     343           1 : int16_t LR2021::receiveDirect() {
     344             :   // set RF switch (if present)
     345           1 :   this->mod->setRfSwitchState(Module::MODE_RX);
     346             : 
     347             :   // LR2021 is unable to output received data directly
     348           1 :   return(RADIOLIB_ERR_UNKNOWN);
     349             : }
     350             : 
     351           1 : int16_t LR2021::scanChannel() {
     352           1 :   ChannelScanConfig_t cfg = {
     353             :     .cad = {
     354             :       .symNum = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
     355             :       .detPeak = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
     356             :       .detMin = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
     357             :       .exitMode = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
     358             :       .timeout = 0,
     359             :       .irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
     360             :       .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK,
     361             :     },
     362             :   };
     363           2 :   return(this->scanChannel(cfg));
     364             : }
     365             : 
     366           2 : int16_t LR2021::scanChannel(const ChannelScanConfig_t &config) {
     367             :   // set mode to CAD
     368           2 :   int state = startChannelScan(config);
     369           2 :   RADIOLIB_ASSERT(state);
     370             : 
     371             :   // wait for channel activity detected or timeout
     372           0 :   while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
     373           0 :     this->mod->hal->yield();
     374             :   }
     375             : 
     376             :   // check CAD result
     377           0 :   return(getChannelScanResult());
     378             : }
     379             : 
     380           5 : int16_t LR2021::standby() {
     381           5 :   return(this->standby(RADIOLIB_LR2021_STANDBY_RC));
     382             : }
     383             : 
     384           6 : int16_t LR2021::standby(uint8_t mode) {
     385           6 :   return(this->standby(mode, true));
     386             : }
     387             : 
     388           6 : int16_t LR2021::standby(uint8_t mode, bool wakeup) {
     389             :   // set RF switch (if present)
     390           6 :   this->mod->setRfSwitchState(Module::MODE_IDLE);
     391             : 
     392           6 :   if(wakeup) {
     393             :     // send a NOP command - this pulls the NSS low to exit the sleep mode,
     394             :     // while preventing interference with possible other SPI transactions
     395           6 :     (void)this->mod->SPIwriteStream((uint16_t)RADIOLIB_LR2021_CMD_NOP, NULL, 0, false, false);
     396             :   }
     397             :   
     398           6 :   uint8_t buff[] = { mode };
     399          12 :   return(this->SPIcommand(RADIOLIB_LR2021_CMD_SET_STANDBY, true, buff, sizeof(buff)));
     400             : }
     401             : 
     402           1 : int16_t LR2021::sleep() {
     403           1 :   return(this->sleep(true, 0));
     404             : }
     405             : 
     406           1 : int16_t LR2021::sleep(bool retainConfig, uint32_t sleepTime) {
     407             :   // set RF switch (if present)
     408           1 :   this->mod->setRfSwitchState(Module::MODE_IDLE);
     409             : 
     410             :   uint8_t buff[] = { (uint8_t)(retainConfig ? RADIOLIB_LR2021_SLEEP_RETENTION_ENABLED : RADIOLIB_LR2021_SLEEP_RETENTION_DISABLED),
     411           1 :     (uint8_t)((sleepTime >> 24) & 0xFF), (uint8_t)((sleepTime >> 16) & 0xFF),
     412           1 :     (uint8_t)((sleepTime >> 8) & 0xFF), (uint8_t)(sleepTime & 0xFF),
     413           1 :   };
     414             : 
     415             :   // in sleep, the busy line will remain high, so we have to use this method to disable waiting for it to go low
     416           1 :   int16_t state = this->mod->SPIwriteStream(RADIOLIB_LR2021_CMD_SET_SLEEP, buff, sizeof(buff), false, false);
     417             : 
     418             :   // wait for the module to safely enter sleep mode
     419           1 :   this->mod->hal->delay(1);
     420             : 
     421           1 :   return(state);
     422             : }
     423             : 
     424           1 : size_t LR2021::getPacketLength(bool update) {
     425             :   (void)update;
     426             : 
     427             :   // in implicit mode, return the cached value
     428           1 :   uint8_t type = RADIOLIB_LR2021_PACKET_TYPE_NONE;
     429           1 :   (void)getPacketType(&type);
     430           1 :   if((type == RADIOLIB_LR2021_PACKET_TYPE_LORA) && (this->headerType == RADIOLIB_LR2021_LORA_HEADER_IMPLICIT)) {
     431           0 :     return(this->implicitLen);
     432             :   }
     433             : 
     434           1 :   uint16_t len = 0;
     435           1 :   (void)getRxPktLength(&len);
     436           1 :   return((size_t)len);
     437             : }
     438             : 
     439           1 : int16_t LR2021::finishTransmit() {
     440             :   // clear interrupt flags
     441           1 :   clearIrqState(RADIOLIB_LR2021_IRQ_ALL);
     442             : 
     443             :   // set mode to standby to disable transmitter/RF switch
     444           1 :   return(standby());
     445             : }
     446             : 
     447           1 : int16_t LR2021::startReceive() {
     448           1 :   return(this->startReceive(RADIOLIB_LR2021_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0));
     449             : }
     450             : 
     451           1 : int16_t LR2021::readData(uint8_t* data, size_t len) {
     452             :   // check active modem
     453           1 :   int16_t state = RADIOLIB_ERR_NONE;
     454           1 :   uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
     455           1 :   state = getPacketType(&modem);
     456           1 :   RADIOLIB_ASSERT(state);
     457           0 :   if((modem != RADIOLIB_LR2021_PACKET_TYPE_LORA) && 
     458           0 :      (modem != RADIOLIB_LR2021_PACKET_TYPE_GFSK) && 
     459           0 :      (modem != RADIOLIB_LR2021_PACKET_TYPE_FLRC) && 
     460           0 :      (modem != RADIOLIB_LR2021_PACKET_TYPE_OOK)) {
     461           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     462             :   }
     463             : 
     464             :   // check integrity CRC
     465           0 :   uint32_t irq = getIrqStatus();
     466           0 :   int16_t crcState = RADIOLIB_ERR_NONE;
     467             :   // report CRC mismatch when there's a payload CRC error
     468           0 :   if(irq & RADIOLIB_LR2021_IRQ_CRC_ERROR) {
     469           0 :     crcState = RADIOLIB_ERR_CRC_MISMATCH;
     470             :   }
     471             : 
     472             :   // for LoRa modem and explicit header mode, check also also header valid flag
     473           0 :   if((modem == RADIOLIB_LR2021_PACKET_TYPE_LORA) &&
     474           0 :      (this->headerType == RADIOLIB_LR2021_LORA_HEADER_EXPLICIT) && 
     475           0 :      (!(irq & RADIOLIB_LR2021_IRQ_LORA_HEADER_VALID))) {
     476           0 :     crcState = RADIOLIB_ERR_LORA_HEADER_DAMAGED;
     477             :   }
     478             : 
     479             :   // get packet length
     480           0 :   size_t length = getPacketLength();
     481           0 :   if((len != 0) && (len < length)) {
     482             :     // user requested less data than we got, only return what was requested
     483           0 :     length = len;
     484             :   }
     485             : 
     486             :   // read packet data
     487           0 :   state = readRadioRxFifo(data, length);
     488           0 :   RADIOLIB_ASSERT(state);
     489             : 
     490             :   // clear the Rx buffer
     491           0 :   state = clearRxFifo();
     492           0 :   RADIOLIB_ASSERT(state);
     493             : 
     494             :   // clear interrupt flags
     495           0 :   state = clearIrqState(RADIOLIB_LR2021_IRQ_ALL);
     496             : 
     497             :   // check if CRC failed - this is done after reading data to give user the option to keep them
     498           0 :   RADIOLIB_ASSERT(crcState);
     499             : 
     500           0 :   return(state);
     501             : }
     502             : 
     503           1 : int16_t LR2021::finishReceive() {
     504             :   // set mode to standby to disable RF switch
     505           1 :   int16_t state = standby();
     506           1 :   RADIOLIB_ASSERT(state);
     507             : 
     508             :   // clear interrupt flags
     509           0 :   return(clearIrqState(RADIOLIB_LR2021_IRQ_ALL));
     510             : }
     511             : 
     512           1 : int16_t LR2021::startChannelScan() {
     513           1 :   ChannelScanConfig_t cfg = {
     514             :     .cad = {
     515             :       .symNum = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
     516             :       .detPeak = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
     517             :       .detMin = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
     518             :       .exitMode = RADIOLIB_LR2021_CAD_PARAM_DEFAULT,
     519             :       .timeout = 0,
     520             :       .irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS,
     521             :       .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK,
     522             :     },
     523             :   };
     524           2 :   return(this->startChannelScan(cfg));
     525             : }
     526             : 
     527           4 : int16_t LR2021::startChannelScan(const ChannelScanConfig_t &config) {
     528             :   // check active modem
     529           4 :   int16_t state = RADIOLIB_ERR_NONE;
     530           4 :   uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
     531           4 :   state = getPacketType(&modem);
     532           4 :   RADIOLIB_ASSERT(state);
     533           0 :   if(modem != RADIOLIB_LR2021_PACKET_TYPE_LORA) {
     534           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     535             :   }
     536             : 
     537             :   // set mode to standby
     538           0 :   state = standby();
     539           0 :   RADIOLIB_ASSERT(state);
     540             : 
     541             :   // set RF switch (if present)
     542           0 :   this->mod->setRfSwitchState(Module::MODE_RX);
     543             : 
     544             :   // set DIO pin mapping
     545           0 :   uint32_t irqFlags = (config.cad.irqFlags == RADIOLIB_IRQ_NOT_SUPPORTED) ? RADIOLIB_LR2021_IRQ_CAD_DETECTED | RADIOLIB_LR2021_IRQ_CAD_DONE : config.cad.irqFlags;
     546           0 :   state = setDioIrqConfig(this->irqDioNum, getIrqMapped(irqFlags));
     547           0 :   RADIOLIB_ASSERT(state);
     548             : 
     549             :   // clear interrupt flags
     550           0 :   state = clearIrqState(RADIOLIB_LR2021_IRQ_ALL);
     551           0 :   RADIOLIB_ASSERT(state);
     552             : 
     553             :   // set mode to CAD
     554           0 :   return(startCad(config.cad.symNum, config.cad.detPeak, this->fastCad, config.cad.exitMode, config.cad.timeout));
     555             : }
     556             : 
     557           1 : int16_t LR2021::getChannelScanResult() {
     558             :   // check active modem
     559           1 :   int16_t state = RADIOLIB_ERR_NONE;
     560           1 :   uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
     561           1 :   state = getPacketType(&modem);
     562           1 :   RADIOLIB_ASSERT(state);
     563           0 :   if(modem != RADIOLIB_LR2021_PACKET_TYPE_LORA) {
     564           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     565             :   }
     566             : 
     567             :   // check CAD result
     568           0 :   uint32_t cadResult = getIrqStatus();
     569           0 :   if(cadResult & RADIOLIB_LR2021_IRQ_CAD_DETECTED) {
     570             :     // detected some LoRa activity
     571           0 :     return(RADIOLIB_LORA_DETECTED);
     572           0 :   } else if(cadResult & RADIOLIB_LR2021_IRQ_CAD_DONE) {
     573             :     // channel is free
     574           0 :     return(RADIOLIB_CHANNEL_FREE);
     575             :   }
     576             : 
     577           0 :   return(RADIOLIB_ERR_UNKNOWN);
     578             : }
     579             : 
     580           1 : uint32_t LR2021::getIrqFlags() {
     581           1 :   return(getIrqStatus());
     582             : }
     583             : 
     584           1 : int16_t LR2021::setIrqFlags(uint32_t irq) {
     585           1 :   return(this->setDioIrqConfig(this->irqDioNum, irq));
     586             : }
     587             : 
     588           1 : int16_t LR2021::clearIrqFlags(uint32_t irq) {
     589           1 :   return(this->clearIrqState(irq));
     590             : }
     591             : 
     592           1 : int16_t LR2021::setModem(ModemType_t modem) {
     593           1 :   switch(modem) {
     594           0 :     case(ModemType_t::RADIOLIB_MODEM_LORA): {
     595           0 :       return(this->begin());
     596             :     } break;
     597           0 :     case(ModemType_t::RADIOLIB_MODEM_FSK): {
     598           0 :       return(this->beginGFSK());
     599             :     } break;
     600           0 :     case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
     601           0 :       return(this->beginLRFHSS());
     602             :     } break;
     603           1 :     default:
     604           1 :       return(RADIOLIB_ERR_WRONG_MODEM);
     605             :   }
     606             : }
     607             : 
     608           0 : Module* LR2021::getMod() {
     609           0 :   return(this->mod);
     610             : }
     611             : 
     612           0 : int16_t LR2021::modSetup(float freq, float tcxoVoltage, uint8_t modem) {
     613           0 :   this->mod->init();
     614           0 :   this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
     615           0 :   this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
     616           0 :   this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_LR2021_CMD_READ_REG_MEM_32;
     617           0 :   this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_LR2021_CMD_WRITE_REG_MEM_32;
     618           0 :   this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_LR2021_CMD_NOP;
     619           0 :   this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_LR2021_CMD_GET_STATUS;
     620           0 :   this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_24;
     621           0 :   this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = Module::BITS_16;
     622             : 
     623             :   // try to find the chip - this will also reset the module at least once
     624           0 :   if(!this->findChip()) {
     625             :     RADIOLIB_DEBUG_BASIC_PRINTLN("No LR2021 found!");
     626           0 :     this->mod->term();
     627           0 :     return(RADIOLIB_ERR_CHIP_NOT_FOUND);
     628             :   }
     629             :   RADIOLIB_DEBUG_BASIC_PRINTLN("M\tLR2021");
     630             : 
     631             :   // set mode to standby
     632           0 :   int16_t state = standby();
     633           0 :   RADIOLIB_ASSERT(state);
     634             : 
     635             :   // set TCXO control, if requested
     636           0 :   if(!this->XTAL && tcxoVoltage > 0.0f) {
     637           0 :     state = setTCXO(tcxoVoltage);
     638           0 :     RADIOLIB_ASSERT(state);
     639             :   }
     640             : 
     641             :   // configure settings not accessible by API
     642           0 :   state = config(modem);
     643           0 :   RADIOLIB_ASSERT(state);
     644             : 
     645           0 :   state = setFrequency(freq);
     646           0 :   return(state);
     647             : }
     648             : 
     649           0 : bool LR2021::findChip(void) {
     650             :   // this is the only version mentioned in datasheet
     651           0 :   const uint8_t expMajor = 0x01;
     652           0 :   const uint8_t expMinor = 0x18;
     653             : 
     654           0 :   uint8_t i = 0;
     655           0 :   bool flagFound = false;
     656           0 :   uint8_t fwMajor = 0, fwMinor = 0;
     657           0 :   while((i < 10) && !flagFound) {
     658             :     // reset the module
     659           0 :     reset();
     660             : 
     661             :     // read the version
     662           0 :     int16_t state = getVersion(&fwMajor, &fwMinor);
     663           0 :     RADIOLIB_ASSERT(state);
     664             : 
     665           0 :     if((fwMajor == expMajor) && (fwMinor == expMinor)) {
     666             :       RADIOLIB_DEBUG_BASIC_PRINTLN("Found LR2021");
     667             :       RADIOLIB_DEBUG_BASIC_PRINTLN("Base FW version: %d.%d", (int)fwMajor, (int)fwMinor);
     668           0 :       flagFound = true;
     669             :     } else {
     670             :       RADIOLIB_DEBUG_BASIC_PRINTLN("LR2021 not found! (%d of 10 tries) FW version: = %d.%d", (int)fwMajor, (int)fwMinor);
     671             :       RADIOLIB_DEBUG_BASIC_PRINTLN("Expected: %d.%d", (int)expMajor, (int)expMinor);
     672           0 :       this->mod->hal->delay(10);
     673           0 :       i++;
     674             :     }
     675             :   }
     676             : 
     677           0 :   return(flagFound);
     678             : }
     679             : 
     680           0 : int16_t LR2021::config(uint8_t modem) {
     681             :   // set Rx/Tx fallback mode to STDBY_RC
     682           0 :   int16_t state = this->setRxTxFallbackMode(RADIOLIB_LR2021_FALLBACK_MODE_STBY_RC);
     683           0 :   RADIOLIB_ASSERT(state);
     684             : 
     685             :   // clear IRQ
     686           0 :   state = this->clearIrqState(RADIOLIB_LR2021_IRQ_ALL);
     687           0 :   RADIOLIB_ASSERT(state);
     688             : 
     689             :   // validate DIO pin number
     690           0 :   if((this->irqDioNum < 5) || (this->irqDioNum > 11)) {
     691           0 :     return(RADIOLIB_ERR_INVALID_DIO_PIN);
     692             :   }
     693             : 
     694             :   // set the DIO to IRQ
     695             :   // DIO5 can only be pull up
     696           0 :   uint8_t pull = this->irqDioNum == 5 ? RADIOLIB_LR2021_DIO_SLEEP_PULL_UP : RADIOLIB_LR2021_DIO_SLEEP_PULL_NONE;
     697           0 :   state = this->setDioFunction(this->irqDioNum, RADIOLIB_LR2021_DIO_FUNCTION_IRQ, pull);
     698           0 :   RADIOLIB_ASSERT(state);
     699             : 
     700             :   // calibrate all blocks
     701           0 :   state = this->calibrate(RADIOLIB_LR2021_CALIBRATE_ALL);
     702             : 
     703             :   // wait for calibration completion
     704           0 :   this->mod->hal->delay(5);
     705           0 :   while(this->mod->hal->digitalRead(this->mod->getGpio())) {
     706           0 :     this->mod->hal->yield();
     707             :   }
     708             :   
     709             :   // if something failed, show the device errors
     710             :   #if RADIOLIB_DEBUG_BASIC
     711             :   if(state != RADIOLIB_ERR_NONE) {
     712             :     uint16_t errors = 0;
     713             :     getErrors(&errors);
     714             :     RADIOLIB_DEBUG_BASIC_PRINTLN("Calibration failed, device errors: 0x%X", errors);
     715             :   }
     716             :   #else
     717           0 :   RADIOLIB_ASSERT(state);
     718             :   #endif
     719             : 
     720             :   // set modem
     721           0 :   state = this->setPacketType(modem);
     722           0 :   return(state);
     723             : }
     724             : 
     725           0 : int16_t LR2021::startCad(uint8_t symbolNum, uint8_t detPeak, bool fast, uint8_t exitMode, RadioLibTime_t timeout) {
     726             :   // check active modem
     727           0 :   uint8_t type = RADIOLIB_LR2021_PACKET_TYPE_NONE;
     728           0 :   int16_t state = getPacketType(&type);
     729           0 :   RADIOLIB_ASSERT(state);
     730           0 :   if(type != RADIOLIB_LR2021_PACKET_TYPE_LORA) {
     731           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     732             :   }
     733             : 
     734             :   // select CAD parameters
     735           0 :   uint8_t num = symbolNum;
     736           0 :   if(num == RADIOLIB_LR2021_CAD_PARAM_DEFAULT) {
     737           0 :     num = 2;
     738             :   }
     739             :   
     740             :   // reference values ​​from the datasheet for 2 symbols
     741             :   //! \TODO: [LR2021] allow CAD peak detection autoconfiguration
     742           0 :   const uint8_t detPeakValues[8] = { 56, 56, 56, 58, 58, 60, 64, 68 };
     743           0 :   uint8_t peak = detPeak;
     744           0 :   if(peak == RADIOLIB_LR2021_CAD_PARAM_DEFAULT) {
     745           0 :     peak = detPeakValues[this->spreadingFactor - 5];
     746             :   }
     747             : 
     748             :   // in Fast CAD mode enable acceleration
     749           0 :   uint8_t pnrDelta = fast ? RADIOLIB_LR2021_LORA_CAD_PNR_DELTA_FAST : RADIOLIB_LR2021_LORA_CAD_PNR_DELTA_STANDARD;
     750             : 
     751           0 :   uint8_t mode = exitMode; 
     752           0 :   if(mode == RADIOLIB_LR2021_CAD_PARAM_DEFAULT) {
     753           0 :     mode = RADIOLIB_LR2021_CAD_EXIT_MODE_FALLBACK;
     754             :   }
     755             : 
     756           0 :   uint32_t timeout_raw = (float)timeout / 30.52f;
     757             : 
     758             :   // set LoRa CAD parameters
     759             :   // preamble only mode is intentionally disabled, as it is unreliable according to the datasheet
     760           0 :   state = setLoRaCadParams(num, false, pnrDelta, mode, timeout_raw, peak);
     761           0 :   RADIOLIB_ASSERT(state);
     762             : 
     763             :   // start LoraCAD
     764           0 :   return(setLoRaCad());
     765             : }
     766             : 
     767           1 : RadioLibTime_t LR2021::getTimeOnAir(size_t len) {
     768           1 :   uint8_t type = RADIOLIB_LR2021_PACKET_TYPE_NONE;
     769           1 :   int16_t state = getPacketType(&type);
     770           1 :   RADIOLIB_ASSERT(state);
     771             : 
     772           0 :   switch(type) {
     773             :     // basic modems are supported by the LRxxxx base class
     774           0 :     case(RADIOLIB_LR2021_PACKET_TYPE_LORA):
     775           0 :       return(LRxxxx::getTimeOnAir(len, ModemType_t::RADIOLIB_MODEM_LORA));
     776           0 :     case(RADIOLIB_LR2021_PACKET_TYPE_GFSK):
     777           0 :       return(LRxxxx::getTimeOnAir(len, ModemType_t::RADIOLIB_MODEM_FSK));
     778           0 :     case(RADIOLIB_LR2021_PACKET_TYPE_LR_FHSS):
     779           0 :       return(LRxxxx::getTimeOnAir(len, ModemType_t::RADIOLIB_MODEM_LRFHSS));
     780           0 :     case(RADIOLIB_LR2021_PACKET_TYPE_FLRC): {
     781             :       //! \todo [LR2021] Add FLRC to the modems supported in ModemType_t
     782             : 
     783             :       // calculate the bits of the uncoded part of the packet
     784           0 :       size_t n_uncoded_bits = (this->preambleLengthGFSK + 1)*4 + 21 + this->syncWordLength*8;
     785           0 :       if(this->packetType != RADIOLIB_LR2021_GFSK_OOK_PACKET_FORMAT_FIXED) { n_uncoded_bits+= 16; }
     786             : 
     787             :       // calculate bits in the coded part
     788           0 :       size_t n_coded_bits = len*8;
     789           0 :       if(this->crcLenGFSK != 0) { n_coded_bits += (this->crcLenGFSK + 1)*8; }
     790           0 :       if(this->codingRateFlrc <= RADIOLIB_LR2021_FLRC_CR_3_4) { n_coded_bits += 6; }
     791           0 :       float n_coded_bits_flt = n_coded_bits;
     792           0 :       switch(this->codingRateFlrc) {
     793           0 :         case(RADIOLIB_LR2021_FLRC_CR_1_2):
     794           0 :           n_coded_bits += 6;
     795           0 :           n_coded_bits_flt = (float)n_coded_bits*2.0f;
     796           0 :           break;
     797           0 :         case(RADIOLIB_LR2021_FLRC_CR_3_4):
     798           0 :           n_coded_bits += 6;
     799           0 :           n_coded_bits_flt = ((float)n_coded_bits*4.0f)/3.0f;
     800           0 :           break;
     801           0 :         case(RADIOLIB_LR2021_FLRC_CR_2_3):
     802           0 :           n_coded_bits_flt = ((float)n_coded_bits*3.0f)/2.0f;
     803           0 :           break;
     804             :       }
     805           0 :       n_coded_bits = n_coded_bits_flt + 0.5f;
     806             : 
     807             :       // now calculate the real time on air
     808           0 :       return((float)(n_uncoded_bits + n_coded_bits) / (float)(this->bitRate / 1000.0f));
     809             :     } 
     810             :   }
     811             : 
     812             :   RADIOLIB_DEBUG_BASIC_PRINTLN("Called getTimeOnAir() for invalid modem (%02x)!", type);
     813           0 :   return(0);
     814             : }
     815             : 
     816           3 : int16_t LR2021::getModem(ModemType_t* modem) {
     817           3 :   RADIOLIB_ASSERT_PTR(modem);
     818             : 
     819           3 :   uint8_t type = RADIOLIB_LR2021_PACKET_TYPE_NONE;
     820           3 :   int16_t state = getPacketType(&type);
     821           3 :   RADIOLIB_ASSERT(state);
     822             : 
     823           0 :   switch(type) {
     824           0 :     case(RADIOLIB_LR2021_PACKET_TYPE_LORA):
     825           0 :       *modem = ModemType_t::RADIOLIB_MODEM_LORA;
     826           0 :       return(RADIOLIB_ERR_NONE);
     827           0 :     case(RADIOLIB_LR2021_PACKET_TYPE_GFSK):
     828           0 :       *modem = ModemType_t::RADIOLIB_MODEM_FSK;
     829           0 :       return(RADIOLIB_ERR_NONE);
     830           0 :     case(RADIOLIB_LR2021_PACKET_TYPE_LR_FHSS):
     831           0 :       *modem = ModemType_t::RADIOLIB_MODEM_LRFHSS;
     832           0 :       return(RADIOLIB_ERR_NONE);
     833             :   }
     834             :   
     835           0 :   return(RADIOLIB_ERR_WRONG_MODEM);
     836             : }
     837             : 
     838           4 : int16_t LR2021::stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) {
     839             :   int16_t state;
     840             : 
     841           4 :   switch(mode) {
     842           3 :     case(RADIOLIB_RADIO_MODE_RX): {
     843             :       // check active modem
     844           3 :       uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
     845           3 :       state = getPacketType(&modem);
     846           3 :       RADIOLIB_ASSERT(state);
     847           0 :       if((modem != RADIOLIB_LR2021_PACKET_TYPE_LORA) && 
     848           0 :         (modem != RADIOLIB_LR2021_PACKET_TYPE_GFSK) && 
     849           0 :         (modem != RADIOLIB_LR2021_PACKET_TYPE_FLRC) && 
     850           0 :         (modem != RADIOLIB_LR2021_PACKET_TYPE_OOK)) {
     851           0 :         return(RADIOLIB_ERR_WRONG_MODEM);
     852             :       }
     853             :       
     854             :       // set the correct Rx path
     855           0 :       state = setRxPath(this->highFreq ? RADIOLIB_LR2021_RX_PATH_HF : RADIOLIB_LR2021_RX_PATH_LF, this->highFreq ? this->gainModeHf : this->gainModeLf);
     856           0 :       RADIOLIB_ASSERT(state);
     857             : 
     858             :       // set DIO mapping
     859           0 :       if(cfg->receive.timeout != RADIOLIB_LR2021_RX_TIMEOUT_INF) {
     860           0 :         cfg->receive.irqMask |= (1UL << RADIOLIB_IRQ_TIMEOUT);
     861             :       }
     862           0 :       state = setDioIrqConfig(this->irqDioNum, getIrqMapped(cfg->receive.irqFlags & cfg->receive.irqMask));
     863           0 :       RADIOLIB_ASSERT(state);
     864             : 
     865             :       // clear interrupt flags
     866           0 :       state = clearIrqState(RADIOLIB_LR2021_IRQ_ALL);
     867           0 :       RADIOLIB_ASSERT(state);
     868             : 
     869             :       // set implicit mode and expected len if applicable
     870           0 :       if((this->headerType == RADIOLIB_LR2021_LORA_HEADER_IMPLICIT) && (modem == RADIOLIB_LR2021_PACKET_TYPE_LORA)) {
     871           0 :         state = setLoRaPacketParams(this->preambleLengthLoRa, this->headerType, 
     872           0 :           (this->packetType == RADIOLIB_LR2021_LORA_HEADER_IMPLICIT) ? this->implicitLen : RADIOLIB_LR2021_MAX_PACKET_LENGTH, this->crcTypeLoRa, this->invertIQEnabled);
     873           0 :         RADIOLIB_ASSERT(state);
     874             :       }
     875             : 
     876             :       // if max(uint32_t) is used, revert to RxContinuous
     877           0 :       if(cfg->receive.timeout == 0xFFFFFFFF) {
     878           0 :         cfg->receive.timeout = 0xFFFFFF;
     879             :       }
     880           0 :       this->rxTimeout = cfg->receive.timeout;
     881           0 :     } break;
     882             :   
     883           1 :     case(RADIOLIB_RADIO_MODE_TX): {
     884             :       // check packet length
     885           1 :       if(cfg->transmit.len > RADIOLIB_LR2021_MAX_PACKET_LENGTH) {
     886           1 :         return(RADIOLIB_ERR_PACKET_TOO_LONG);
     887             :       }
     888             : 
     889             :       // maximum packet length is decreased by 1 when address filtering is active
     890             :       //! \todo [LR2021] implement GFSK address filtering
     891             : 
     892             :       // set packet Length
     893           1 :       uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
     894           1 :       state = getPacketType(&modem);
     895           1 :       RADIOLIB_ASSERT(state);
     896           0 :       if(modem == RADIOLIB_LR2021_PACKET_TYPE_LORA) {
     897           0 :         state = setLoRaPacketParams(this->preambleLengthLoRa, this->headerType, cfg->transmit.len, this->crcTypeLoRa, this->invertIQEnabled);
     898             :       
     899           0 :       } else if(modem == RADIOLIB_LR2021_PACKET_TYPE_GFSK) {
     900           0 :         state = setGfskPacketParams(this->preambleLengthGFSK, this->preambleDetLength, false, false, this->addrComp, this->packetType, cfg->transmit.len, this->crcTypeGFSK, this->whitening);
     901             : 
     902           0 :       } else if(modem == RADIOLIB_LR2021_PACKET_TYPE_OOK) {
     903           0 :         state = setOokPacketParams(this->preambleLengthGFSK, this->addrComp, this->packetType, cfg->transmit.len, this->crcTypeGFSK, this->whitening);
     904             : 
     905           0 :       } else if(modem == RADIOLIB_LR2021_PACKET_TYPE_FLRC) {
     906           0 :         state = setFlrcPacketParams(this->preambleLengthGFSK, this->syncWordLength, 1, 0x01, this->packetType == RADIOLIB_LR2021_GFSK_OOK_PACKET_FORMAT_FIXED, this->crcLenGFSK, cfg->transmit.len);
     907             :       
     908             :       } else {
     909           0 :         return(RADIOLIB_ERR_WRONG_MODEM);
     910             :       }
     911             : 
     912           0 :       RADIOLIB_ASSERT(state);
     913             : 
     914             :       // set DIO mapping
     915           0 :       state = setDioIrqConfig(this->irqDioNum, RADIOLIB_LR2021_IRQ_TX_DONE | RADIOLIB_LR2021_IRQ_TIMEOUT);
     916           0 :       RADIOLIB_ASSERT(state);
     917             : 
     918           0 :       if(modem == RADIOLIB_LR2021_PACKET_TYPE_LR_FHSS) {
     919             :         // in LR-FHSS mode, the packet is built by the device
     920             :         //! \todo [LR2021] add configurable LR-FHSS device offset
     921           0 :         state = LRxxxx::lrFhssBuildFrame(RADIOLIB_LR2021_CMD_LR_FHSS_BUILD_FRAME, this->lrFhssHdrCount, this->lrFhssCr, this->lrFhssGrid, true, this->lrFhssBw, this->lrFhssHopSeq, 0, cfg->transmit.data, cfg->transmit.len);
     922           0 :         RADIOLIB_ASSERT(state);
     923             : 
     924             :       } else {
     925             :         // write packet to buffer
     926           0 :         state = writeRadioTxFifo(cfg->transmit.data, cfg->transmit.len);
     927           0 :         RADIOLIB_ASSERT(state);
     928             : 
     929             :       }
     930             : 
     931             :       // clear interrupt flags
     932           0 :       state = clearIrqState(RADIOLIB_LR2021_IRQ_ALL);
     933           0 :       RADIOLIB_ASSERT(state);
     934           0 :     } break;
     935             :     
     936           0 :     default:
     937           0 :       return(RADIOLIB_ERR_UNSUPPORTED);
     938             :   }
     939             : 
     940           0 :   this->stagedMode = mode;
     941           0 :   return(state);
     942             : }
     943             : 
     944           1 : int16_t LR2021::launchMode() {
     945             :   int16_t state;
     946           1 :   switch(this->stagedMode) {
     947           1 :     case(RADIOLIB_RADIO_MODE_RX): {
     948           1 :       this->mod->setRfSwitchState(Module::MODE_RX);
     949           1 :       state = setRx(this->rxTimeout);
     950           1 :     } break;
     951             :   
     952           0 :     case(RADIOLIB_RADIO_MODE_TX): {
     953           0 :       this->mod->setRfSwitchState(Module::MODE_TX);
     954           0 :       state = setTx(RADIOLIB_LR2021_TX_TIMEOUT_NONE);
     955           0 :       RADIOLIB_ASSERT(state);
     956             : 
     957             :       // wait for BUSY to go low (= PA ramp up done)
     958           0 :       while(this->mod->hal->digitalRead(this->mod->getGpio())) {
     959           0 :         this->mod->hal->yield();
     960             :       }
     961           0 :     } break;
     962             :     
     963           0 :     default:
     964           0 :       return(RADIOLIB_ERR_UNSUPPORTED);
     965             :   }
     966             : 
     967           1 :   this->stagedMode = RADIOLIB_RADIO_MODE_NONE;
     968           1 :   return(state);
     969             : }
     970             : 
     971           0 : float LR2021::getVoltage(uint8_t bits) {
     972           0 :   if((bits < 8) || (bits > 13)) {
     973           0 :     return(0);
     974             :   }
     975             : 
     976             :   uint16_t val;
     977           0 :   if(getVbat(bits, &val) != RADIOLIB_ERR_NONE) {
     978           0 :     return(0);
     979             :   }
     980             :   
     981           0 :   return((float)val / 1000.0f);
     982             : }
     983             : 
     984           0 : float LR2021::getTemperature(uint8_t source, uint8_t bits) {
     985           0 :   if((bits < 8) || (bits > 13)) {
     986           0 :     return(0);
     987             :   }
     988             : 
     989             :   float val;
     990           0 :   if(getTemp(source, bits, &val) != RADIOLIB_ERR_NONE) {
     991           0 :     return(0);
     992             :   }
     993             : 
     994           0 :   return(val);
     995             : }
     996             : 
     997           1 : float LR2021::getRSSI() {
     998           1 :   return(this->getRSSI(true));
     999             : }
    1000             : 
    1001           1 : float LR2021::getRSSI(bool packet, bool skipReceive) {
    1002           1 :   float rssi = 0;
    1003             :   int16_t state;
    1004           1 :   if(!packet) { 
    1005             :     // get instantaneous RSSI value
    1006           0 :     if(!skipReceive) { (void)startReceive(); }
    1007           0 :     state = this->getRssiInst(&rssi);
    1008           0 :     if(!skipReceive) { (void)standby(); }
    1009           0 :     if(state != RADIOLIB_ERR_NONE) { return(0); }
    1010           0 :     return(rssi);
    1011             :   }
    1012             : 
    1013             :   // check modem type
    1014           1 :   uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
    1015           1 :   state = this->getPacketType(&modem);
    1016           1 :   if(state != RADIOLIB_ERR_NONE) { return(0); }
    1017           0 :   if(modem == RADIOLIB_LR2021_PACKET_TYPE_LORA) {
    1018           0 :     state = this->getLoRaPacketStatus(NULL, NULL, NULL, NULL, &rssi, NULL);
    1019           0 :   } else if(modem == RADIOLIB_LR2021_PACKET_TYPE_GFSK) {
    1020           0 :     state = this->getGfskPacketStatus(NULL, &rssi, NULL, NULL, NULL, NULL);
    1021           0 :   } else if(modem == RADIOLIB_LR2021_PACKET_TYPE_OOK) {
    1022           0 :     state = this->getOokPacketStatus(NULL, NULL, &rssi, NULL, NULL, NULL);
    1023             :   } else {
    1024           0 :     return(0);
    1025             :   }
    1026             : 
    1027           0 :   if(state != RADIOLIB_ERR_NONE) { return(0); }
    1028           0 :   return(rssi);
    1029             : }
    1030             : 
    1031           1 : float LR2021::getSNR() {
    1032             :   float snr;
    1033           1 :   uint8_t modem = RADIOLIB_LR2021_PACKET_TYPE_NONE;
    1034           1 :   int16_t state = this->getPacketType(&modem);
    1035           1 :   if(state != RADIOLIB_ERR_NONE) { return(0); }
    1036           0 :   if(modem != RADIOLIB_LR2021_PACKET_TYPE_LORA) { return(0); }
    1037           0 :   state = this->getLoRaPacketStatus(NULL, NULL, NULL, &snr, NULL, NULL);
    1038           0 :   if(state != RADIOLIB_ERR_NONE) { return(0); }
    1039           0 :   return(snr);  
    1040             : }
    1041             : 
    1042           1 : uint8_t LR2021::randomByte() {
    1043           1 :   uint32_t num = 0;
    1044           1 :   (void)getRandomNumber(&num);
    1045           1 :   return((uint8_t)num);
    1046             : }
    1047             : 
    1048           0 : int16_t LR2021::getLoRaRxHeaderInfo(uint8_t* cr, bool* hasCRC){
    1049           0 :   return(this->getLoRaPacketStatus(cr, hasCRC, NULL, NULL, NULL, NULL));
    1050             : }
    1051             : 
    1052             : #endif

Generated by: LCOV version 1.14