LCOV - code coverage report
Current view: top level - src/modules/LR2021 - LR2021.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 143 563 25.4 %
Date: 2026-02-22 10:42:45 Functions: 32 44 72.7 %

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

Generated by: LCOV version 1.14