LCOV - code coverage report
Current view: top level - src/modules/SX126x - SX126x_config.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 455 0.0 %
Date: 2025-11-15 20:31:27 Functions: 0 44 0.0 %

          Line data    Source code
       1             : #include "SX126x.h"
       2             : 
       3             : #include <math.h>
       4             : #include <string.h>
       5             : 
       6             : // this file contains all configuration methods
       7             : // of the SX126x, which let user control the
       8             : // modulation properties, packet configuration etc.
       9             : 
      10             : #if !RADIOLIB_EXCLUDE_SX126X
      11             : 
      12           0 : void SX126x::setDio1Action(void (*func)(void)) {
      13           0 :   this->mod->hal->attachInterrupt(this->mod->hal->pinToInterrupt(this->mod->getIrq()), func, this->mod->hal->GpioInterruptRising);
      14           0 : }
      15             : 
      16           0 : void SX126x::clearDio1Action() {
      17           0 :   this->mod->hal->detachInterrupt(this->mod->hal->pinToInterrupt(this->mod->getIrq()));
      18           0 : }
      19             : 
      20           0 : void SX126x::setPacketReceivedAction(void (*func)(void)) {
      21           0 :   this->setDio1Action(func);
      22           0 : }
      23             : 
      24           0 : void SX126x::clearPacketReceivedAction() {
      25           0 :   this->clearDio1Action();
      26           0 : }
      27             : 
      28           0 : void SX126x::setPacketSentAction(void (*func)(void)) {
      29           0 :   this->setDio1Action(func);
      30           0 : }
      31             : 
      32           0 : void SX126x::clearPacketSentAction() {
      33           0 :   this->clearDio1Action();
      34           0 : }
      35             : 
      36           0 : void SX126x::setChannelScanAction(void (*func)(void)) {
      37           0 :   this->setDio1Action(func);
      38           0 : }
      39             : 
      40           0 : void SX126x::clearChannelScanAction() {
      41           0 :   this->clearDio1Action();
      42           0 : }
      43             : 
      44           0 : int16_t SX126x::setBandwidth(float bw) {
      45             :   // check active modem
      46           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
      47           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
      48             :   }
      49             : 
      50             :   // ensure byte conversion doesn't overflow
      51           0 :   RADIOLIB_CHECK_RANGE(bw, 0.0f, 510.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
      52             : 
      53             :   // check allowed bandwidth values
      54           0 :   uint8_t bw_div2 = bw / 2 + 0.01f;
      55           0 :   switch (bw_div2)  {
      56           0 :     case 3: // 7.8:
      57           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_7_8;
      58           0 :       break;
      59           0 :     case 5: // 10.4:
      60           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_10_4;
      61           0 :       break;
      62           0 :     case 7: // 15.6:
      63           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_15_6;
      64           0 :       break;
      65           0 :     case 10: // 20.8:
      66           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_20_8;
      67           0 :       break;
      68           0 :     case 15: // 31.25:
      69           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_31_25;
      70           0 :       break;
      71           0 :     case 20: // 41.7:
      72           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_41_7;
      73           0 :       break;
      74           0 :     case 31: // 62.5:
      75           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_62_5;
      76           0 :       break;
      77           0 :     case 62: // 125.0:
      78           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_125_0;
      79           0 :       break;
      80           0 :     case 125: // 250.0
      81           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_250_0;
      82           0 :       break;
      83           0 :     case 250: // 500.0
      84           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_500_0;
      85           0 :       break;
      86           0 :     default:
      87           0 :       return(RADIOLIB_ERR_INVALID_BANDWIDTH);
      88             :   }
      89             : 
      90             :   // update modulation parameters
      91           0 :   this->bandwidthKhz = bw;
      92           0 :   return(setModulationParams(this->spreadingFactor, this->bandwidth, this->codingRate, this->ldrOptimize));
      93             : }
      94             : 
      95           0 : int16_t SX126x::setSpreadingFactor(uint8_t sf) {
      96             :   // check active modem
      97           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
      98           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
      99             :   }
     100             : 
     101           0 :   RADIOLIB_CHECK_RANGE(sf, 5, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
     102             : 
     103             :   // update modulation parameters
     104           0 :   this->spreadingFactor = sf;
     105           0 :   return(setModulationParams(this->spreadingFactor, this->bandwidth, this->codingRate, this->ldrOptimize));
     106             : }
     107             : 
     108           0 : int16_t SX126x::setCodingRate(uint8_t cr, bool longInterleave) {
     109             :   // check active modem
     110           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     111           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     112             :   }
     113             : 
     114           0 :   RADIOLIB_CHECK_RANGE(cr, 4, 8, RADIOLIB_ERR_INVALID_CODING_RATE);
     115             : 
     116           0 :   if(longInterleave) {
     117           0 :     switch(cr) {
     118           0 :       case 4:
     119           0 :         this->codingRate = 0;
     120           0 :         break;
     121           0 :       case 5:
     122             :       case 6:
     123           0 :         this->codingRate = cr;
     124           0 :         break;
     125           0 :       case 8: 
     126           0 :         this->codingRate = cr - 1;
     127           0 :         break;
     128           0 :       default:
     129           0 :         return(RADIOLIB_ERR_INVALID_CODING_RATE);
     130             :     }
     131             :   } else {
     132           0 :     this->codingRate = cr - 4;
     133             :   }
     134             : 
     135             :   // update modulation parameters
     136           0 :   return(setModulationParams(this->spreadingFactor, this->bandwidth, this->codingRate, this->ldrOptimize));
     137             : }
     138             : 
     139           0 : int16_t SX126x::setSyncWord(uint8_t syncWord, uint8_t controlBits) {
     140             :   // check active modem
     141           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     142           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     143             :   }
     144             : 
     145             :   // update register
     146           0 :   const uint8_t data[2] = {(uint8_t)((syncWord & 0xF0) | ((controlBits & 0xF0) >> 4)), (uint8_t)(((syncWord & 0x0F) << 4) | (controlBits & 0x0F))};
     147           0 :   return(writeRegister(RADIOLIB_SX126X_REG_LORA_SYNC_WORD_MSB, data, 2));
     148             : }
     149             : 
     150           0 : int16_t SX126x::setCurrentLimit(float currentLimit) {
     151             :   // check allowed range
     152           0 :   if(!((currentLimit >= 0) && (currentLimit <= 140))) {
     153           0 :     return(RADIOLIB_ERR_INVALID_CURRENT_LIMIT);
     154             :   }
     155             : 
     156             :   // calculate raw value
     157           0 :   uint8_t rawLimit = (uint8_t)(currentLimit / 2.5f);
     158             : 
     159             :   // update register
     160           0 :   return(writeRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &rawLimit, 1));
     161             : }
     162             : 
     163           0 : float SX126x::getCurrentLimit() {
     164             :   // get the raw value
     165           0 :   uint8_t ocp = 0;
     166           0 :   readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
     167             : 
     168             :   // return the actual value
     169           0 :   return((float)ocp * 2.5f);
     170             : }
     171             : 
     172           0 : int16_t SX126x::setPreambleLength(size_t preambleLength) {
     173           0 :   uint8_t modem = getPacketType();
     174           0 :   if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     175           0 :     this->preambleLengthLoRa = preambleLength;
     176           0 :     return(setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, this->implicitLen, this->headerType, this->invertIQEnabled));
     177           0 :   } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     178           0 :     this->preambleLengthFSK = preambleLength;
     179             :     // maximum preamble detector length is limited by sync word length
     180             :     // for details, see the note in SX1261 datasheet, Rev 2.1, section 6.2.2.1, page 45
     181           0 :     uint8_t maxDetLen = RADIOLIB_MIN(this->syncWordLength, this->preambleLengthFSK);
     182           0 :     this->preambleDetLength = maxDetLen >= 32 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_32 :
     183             :                               maxDetLen >= 24 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_24 :
     184             :                               maxDetLen >= 16 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_16 :
     185             :                               maxDetLen >   0 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_8 :
     186             :                               RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_OFF;
     187           0 :     return(setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType));
     188             :   }
     189             : 
     190           0 :   return(RADIOLIB_ERR_UNKNOWN);
     191             : }
     192             : 
     193           0 : int16_t SX126x::setFrequencyDeviation(float freqDev) {
     194             :   // check active modem
     195           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     196           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     197             :   }
     198             : 
     199             :   // set frequency deviation to lowest available setting (required for digimodes)
     200           0 :   float newFreqDev = freqDev;
     201           0 :   if(freqDev < 0.0f) {
     202           0 :     newFreqDev = 0.6f;
     203             :   }
     204             : 
     205           0 :   RADIOLIB_CHECK_RANGE(newFreqDev, 0.6f, 200.0f, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
     206             : 
     207             :   // calculate raw frequency deviation value
     208           0 :   uint32_t freqDevRaw = (uint32_t)(((newFreqDev * 1000.0f) * (float)((uint32_t)(1) << 25)) / (RADIOLIB_SX126X_CRYSTAL_FREQ * 1000000.0f));
     209             : 
     210             :   // check modulation parameters
     211           0 :   this->frequencyDev = freqDevRaw;
     212             : 
     213             :   // update modulation parameters
     214           0 :   return(setModulationParamsFSK(this->bitRate, this->pulseShape, this->rxBandwidth, this->frequencyDev));
     215             : }
     216             : 
     217           0 : int16_t SX126x::setBitRate(float br) {
     218             :   // check active modem
     219           0 :   uint8_t modem = getPacketType();
     220           0 :   if((modem != RADIOLIB_SX126X_PACKET_TYPE_GFSK) &&
     221           0 :      (modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) &&
     222             :      (modem != RADIOLIB_SX126X_PACKET_TYPE_BPSK)) {
     223           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     224             :   }
     225             : 
     226           0 :   if(modem == RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) {
     227             :     // at the moment only the very specific 488.28125 bps rate is supported
     228           0 :     RADIOLIB_CHECK_RANGE(br, 0.488f, 0.489f, RADIOLIB_ERR_INVALID_BIT_RATE);
     229           0 :   } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_BPSK) {
     230             :     // this should be just either 100 or 600 bps, not the range
     231             :     // but the BPSK support is so experimental it probably does not matter
     232           0 :     RADIOLIB_CHECK_RANGE(br, 0.1f, 0.6f, RADIOLIB_ERR_INVALID_BIT_RATE);
     233             :   }
     234             : 
     235             :   // calculate raw bit rate value
     236           0 :   uint32_t brRaw = (uint32_t)((RADIOLIB_SX126X_CRYSTAL_FREQ * 1000000.0f * 32.0f) / (br * 1000.0f));
     237             : 
     238             :   // check modulation parameters
     239           0 :   this->bitRate = brRaw;
     240             : 
     241             :   // update modulation parameters
     242           0 :   int16_t state = RADIOLIB_ERR_UNKNOWN;
     243           0 :   if(modem == RADIOLIB_SX126X_PACKET_TYPE_BPSK) {
     244           0 :     state = setModulationParamsBPSK(this->bitRate);
     245             :   } else {
     246           0 :     state = setModulationParamsFSK(this->bitRate, this->pulseShape, this->rxBandwidth, this->frequencyDev);
     247             :   }
     248           0 :   RADIOLIB_ASSERT(state);
     249             : 
     250             :   // apply workaround or reset it, as needed
     251           0 :   return(fixGFSK());
     252             : }
     253             : 
     254           0 : int16_t SX126x::setDataRate(DataRate_t dr, ModemType_t modem) {
     255             :   // get the current modem
     256             :   ModemType_t currentModem;
     257           0 :   int16_t state = this->getModem(&currentModem);
     258           0 :   RADIOLIB_ASSERT(state);
     259             : 
     260             :   // switch over if the requested modem is different
     261           0 :   if(modem != RADIOLIB_MODEM_NONE && modem != currentModem) {
     262           0 :     state = this->standby();
     263           0 :     RADIOLIB_ASSERT(state);
     264           0 :     state = this->setModem(modem);
     265           0 :     RADIOLIB_ASSERT(state);
     266             :   }
     267             :   
     268           0 :   if(modem == RADIOLIB_MODEM_NONE) {
     269           0 :     modem = currentModem;
     270             :   }
     271             : 
     272             :   // select interpretation based on modem
     273           0 :   if(modem == RADIOLIB_MODEM_FSK) {
     274             :     // set the bit rate
     275           0 :     state = this->setBitRate(dr.fsk.bitRate);
     276           0 :     RADIOLIB_ASSERT(state);
     277             : 
     278             :     // set the frequency deviation
     279           0 :     state = this->setFrequencyDeviation(dr.fsk.freqDev);
     280             : 
     281           0 :   } else if(modem == RADIOLIB_MODEM_LORA) {
     282             :     // set the spreading factor
     283           0 :     state = this->setSpreadingFactor(dr.lora.spreadingFactor);
     284           0 :     RADIOLIB_ASSERT(state);
     285             : 
     286             :     // set the bandwidth
     287           0 :     state = this->setBandwidth(dr.lora.bandwidth);
     288           0 :     RADIOLIB_ASSERT(state);
     289             : 
     290             :     // set the coding rate
     291           0 :     state = this->setCodingRate(dr.lora.codingRate);
     292             :   
     293           0 :   } else if(modem == RADIOLIB_MODEM_LRFHSS) {
     294             :     // set the basic config
     295           0 :     state = this->setLrFhssConfig(dr.lrFhss.bw, dr.lrFhss.cr);
     296           0 :     RADIOLIB_ASSERT(state);
     297             : 
     298             :     // set hopping grid
     299           0 :     this->lrFhssGridNonFcc = dr.lrFhss.narrowGrid ? RADIOLIB_SX126X_LR_FHSS_GRID_STEP_NON_FCC : RADIOLIB_SX126X_LR_FHSS_GRID_STEP_FCC;
     300             : 
     301             :   }
     302             : 
     303           0 :   return(state);
     304             : }
     305             : 
     306             : 
     307           0 : int16_t SX126x::checkDataRate(DataRate_t dr, ModemType_t modem) {
     308           0 :   int16_t state = RADIOLIB_ERR_UNKNOWN;
     309             : 
     310             :   // retrieve modem if not supplied
     311           0 :   if(modem == RADIOLIB_MODEM_NONE) {
     312           0 :     state = this->getModem(&modem);
     313           0 :     RADIOLIB_ASSERT(state);
     314             :   }
     315             : 
     316             :   // select interpretation based on modem
     317           0 :   if(modem == RADIOLIB_MODEM_FSK) {
     318           0 :     RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.6f, 300.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
     319           0 :     RADIOLIB_CHECK_RANGE(dr.fsk.freqDev, 0.6f, 200.0f, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
     320           0 :     return(RADIOLIB_ERR_NONE);
     321             : 
     322           0 :   } else if(modem == RADIOLIB_MODEM_LORA) {
     323           0 :     RADIOLIB_CHECK_RANGE(dr.lora.spreadingFactor, 5, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
     324           0 :     RADIOLIB_CHECK_RANGE(dr.lora.bandwidth, 0.0f, 510.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
     325           0 :     RADIOLIB_CHECK_RANGE(dr.lora.codingRate, 4, 8, RADIOLIB_ERR_INVALID_CODING_RATE);
     326           0 :     return(RADIOLIB_ERR_NONE);
     327             :   
     328             :   }
     329             : 
     330           0 :   return(state);
     331             : }
     332             : 
     333           0 : int16_t SX126x::setRxBandwidth(float rxBw) {
     334             :   // check active modem
     335           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     336           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     337             :   }
     338             : 
     339             :   // check modulation parameters
     340             :   /*if(2 * this->frequencyDev + this->bitRate > rxBw * 1000.0) {
     341             :     return(RADIOLIB_ERR_INVALID_MODULATION_PARAMETERS);
     342             :   }*/
     343           0 :   this->rxBandwidthKhz = rxBw;
     344             : 
     345             :   // check allowed receiver bandwidth values
     346           0 :   if(fabsf(rxBw - 4.8f) <= 0.001f) {
     347           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_4_8;
     348           0 :   } else if(fabsf(rxBw - 5.8f) <= 0.001f) {
     349           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_5_8;
     350           0 :   } else if(fabsf(rxBw - 7.3f) <= 0.001f) {
     351           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_7_3;
     352           0 :   } else if(fabsf(rxBw - 9.7f) <= 0.001f) {
     353           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_9_7;
     354           0 :   } else if(fabsf(rxBw - 11.7f) <= 0.001f) {
     355           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_11_7;
     356           0 :   } else if(fabsf(rxBw - 14.6f) <= 0.001f) {
     357           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_14_6;
     358           0 :   } else if(fabsf(rxBw - 19.5f) <= 0.001f) {
     359           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_19_5;
     360           0 :   } else if(fabsf(rxBw - 23.4f) <= 0.001f) {
     361           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_23_4;
     362           0 :   } else if(fabsf(rxBw - 29.3f) <= 0.001f) {
     363           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_29_3;
     364           0 :   } else if(fabsf(rxBw - 39.0f) <= 0.001f) {
     365           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_39_0;
     366           0 :   } else if(fabsf(rxBw - 46.9f) <= 0.001f) {
     367           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_46_9;
     368           0 :   } else if(fabsf(rxBw - 58.6f) <= 0.001f) {
     369           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_58_6;
     370           0 :   } else if(fabsf(rxBw - 78.2f) <= 0.001f) {
     371           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_78_2;
     372           0 :   } else if(fabsf(rxBw - 93.8f) <= 0.001f) {
     373           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_93_8;
     374           0 :   } else if(fabsf(rxBw - 117.3f) <= 0.001f) {
     375           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_117_3;
     376           0 :   } else if(fabsf(rxBw - 156.2f) <= 0.001f) {
     377           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_156_2;
     378           0 :   } else if(fabsf(rxBw - 187.2f) <= 0.001f) {
     379           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_187_2;
     380           0 :   } else if(fabsf(rxBw - 234.3f) <= 0.001f) {
     381           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_234_3;
     382           0 :   } else if(fabsf(rxBw - 312.0f) <= 0.001f) {
     383           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_312_0;
     384           0 :   } else if(fabsf(rxBw - 373.6f) <= 0.001f) {
     385           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_373_6;
     386           0 :   } else if(fabsf(rxBw - 467.0f) <= 0.001f) {
     387           0 :     this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_467_0;
     388             :   } else {
     389           0 :     return(RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
     390             :   }
     391             : 
     392             :   // update modulation parameters
     393           0 :   return(setModulationParamsFSK(this->bitRate, this->pulseShape, this->rxBandwidth, this->frequencyDev));
     394             : }
     395             : 
     396           0 : int16_t SX126x::setRxBoostedGainMode(bool rxbgm, bool persist) {
     397             :   // update RX gain setting register
     398           0 :   uint8_t rxGain = rxbgm ? RADIOLIB_SX126X_RX_GAIN_BOOSTED : RADIOLIB_SX126X_RX_GAIN_POWER_SAVING;
     399           0 :   int16_t state = writeRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1);
     400           0 :   RADIOLIB_ASSERT(state);
     401             : 
     402             :   // add Rx Gain register to retention memory if requested
     403           0 :   if(persist) {
     404             :     // values and registers below are specified in SX126x datasheet v2.1 section 9.6, just below table 9-3
     405           0 :     const uint8_t data[] = { 0x01, (uint8_t)((RADIOLIB_SX126X_REG_RX_GAIN >> 8) & 0xFF), (uint8_t)(RADIOLIB_SX126X_REG_RX_GAIN & 0xFF) };
     406           0 :     state = writeRegister(RADIOLIB_SX126X_REG_RX_GAIN_RETENTION_0, data, 3);
     407             :   }
     408             : 
     409           0 :   return(state);
     410             : }
     411             : 
     412           0 : int16_t SX126x::setDataShaping(uint8_t sh) {
     413             :   // check active modem
     414           0 :   uint8_t modem = getPacketType();
     415           0 :   if((modem != RADIOLIB_SX126X_PACKET_TYPE_GFSK) && (modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS)) {
     416           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     417             :   }
     418             : 
     419             :   // set data shaping
     420           0 :   switch(sh) {
     421           0 :     case RADIOLIB_SHAPING_NONE:
     422           0 :       this->pulseShape = RADIOLIB_SX126X_GFSK_FILTER_NONE;
     423           0 :       break;
     424           0 :     case RADIOLIB_SHAPING_0_3:
     425           0 :       this->pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_3;
     426           0 :       break;
     427           0 :     case RADIOLIB_SHAPING_0_5:
     428           0 :       this->pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_5;
     429           0 :       break;
     430           0 :     case RADIOLIB_SHAPING_0_7:
     431           0 :       this->pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_7;
     432           0 :       break;
     433           0 :     case RADIOLIB_SHAPING_1_0:
     434           0 :       this->pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_1;
     435           0 :       break;
     436           0 :     default:
     437           0 :       return(RADIOLIB_ERR_INVALID_DATA_SHAPING);
     438             :   }
     439             : 
     440             :   // update modulation parameters
     441           0 :   return(setModulationParamsFSK(this->bitRate, this->pulseShape, this->rxBandwidth, this->frequencyDev));
     442             : }
     443             : 
     444           0 : int16_t SX126x::setSyncWord(uint8_t* syncWord, size_t len) {
     445             :   // check active modem
     446           0 :   uint8_t modem = getPacketType();
     447           0 :   if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     448             :     // check sync word Length
     449           0 :     if(len > 8) {
     450           0 :       return(RADIOLIB_ERR_INVALID_SYNC_WORD);
     451             :     }
     452             : 
     453             :     // write sync word
     454           0 :     int16_t state = writeRegister(RADIOLIB_SX126X_REG_SYNC_WORD_0, syncWord, len);
     455           0 :     RADIOLIB_ASSERT(state);
     456             : 
     457             :     // update packet parameters
     458           0 :     this->syncWordLength = len * 8;
     459             :     
     460             :     // maximum preamble detector length is limited by sync word length
     461             :     // for details, see the note in SX1261 datasheet, Rev 2.1, section 6.2.2.1, page 45
     462           0 :     uint8_t maxDetLen = RADIOLIB_MIN(this->syncWordLength, this->preambleLengthFSK);
     463           0 :     this->preambleDetLength = maxDetLen >= 32 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_32 :
     464             :                               maxDetLen >= 24 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_24 :
     465             :                               maxDetLen >= 16 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_16 :
     466             :                               maxDetLen >   0 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_8 :
     467             :                               RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_OFF;
     468           0 :     state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType);
     469             : 
     470           0 :     return(state);
     471             :   
     472           0 :   } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     473             :     // with length set to 1 and LoRa modem active, assume it is the LoRa sync word
     474           0 :     if(len > 1) {
     475           0 :       return(RADIOLIB_ERR_INVALID_SYNC_WORD);
     476             :     }
     477           0 :     return(setSyncWord(syncWord[0]));
     478             : 
     479           0 :   } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) {
     480             :     // with length set to 4 and LR-FHSS modem active, assume it is the LR-FHSS sync word
     481           0 :     if(len != sizeof(uint32_t)) {
     482           0 :       return(RADIOLIB_ERR_INVALID_SYNC_WORD);
     483             :     }
     484           0 :     memcpy(this->lrFhssSyncWord, syncWord, sizeof(uint32_t));
     485             :   
     486             :   }
     487             : 
     488           0 :   return(RADIOLIB_ERR_WRONG_MODEM);
     489             : }
     490             : 
     491           0 : int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool inverted) {
     492             :   // check active modem
     493           0 :   uint8_t modem = getPacketType();
     494             : 
     495           0 :   if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     496             :     // update packet parameters
     497           0 :     switch(len) {
     498           0 :       case 0:
     499           0 :         this->crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_OFF;
     500           0 :         break;
     501           0 :       case 1:
     502           0 :         if(inverted) {
     503           0 :           this->crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_1_BYTE_INV;
     504             :         } else {
     505           0 :           this->crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_1_BYTE;
     506             :         }
     507           0 :         break;
     508           0 :       case 2:
     509           0 :         if(inverted) {
     510           0 :           this->crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_2_BYTE_INV;
     511             :         } else {
     512           0 :           this->crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_2_BYTE;
     513             :         }
     514           0 :         break;
     515           0 :       default:
     516           0 :         return(RADIOLIB_ERR_INVALID_CRC_CONFIGURATION);
     517             :     }
     518             : 
     519           0 :     int16_t state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType);
     520           0 :     RADIOLIB_ASSERT(state);
     521             : 
     522             :     // write initial CRC value
     523           0 :     uint8_t data[2] = {(uint8_t)((initial >> 8) & 0xFF), (uint8_t)(initial & 0xFF)};
     524           0 :     state = writeRegister(RADIOLIB_SX126X_REG_CRC_INITIAL_MSB, data, 2);
     525           0 :     RADIOLIB_ASSERT(state);
     526             : 
     527             :     // write CRC polynomial value
     528           0 :     data[0] = (uint8_t)((polynomial >> 8) & 0xFF);
     529           0 :     data[1] = (uint8_t)(polynomial & 0xFF);
     530           0 :     state = writeRegister(RADIOLIB_SX126X_REG_CRC_POLYNOMIAL_MSB, data, 2);
     531             : 
     532           0 :     return(state);
     533             : 
     534           0 :   } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     535             :     // LoRa CRC doesn't allow to set CRC polynomial, initial value, or inversion
     536             : 
     537             :     // update packet parameters
     538           0 :     if(len) {
     539           0 :       this->crcTypeLoRa = RADIOLIB_SX126X_LORA_CRC_ON;
     540             :     } else {
     541           0 :       this->crcTypeLoRa = RADIOLIB_SX126X_LORA_CRC_OFF;
     542             :     }
     543             : 
     544           0 :     return(setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, this->implicitLen, this->headerType, this->invertIQEnabled));
     545             :   }
     546             : 
     547           0 :   return(RADIOLIB_ERR_UNKNOWN);
     548             : }
     549             : 
     550           0 : int16_t SX126x::setWhitening(bool enabled, uint16_t initial) {
     551             :   // check active modem
     552           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     553           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     554             :   }
     555             : 
     556           0 :   int16_t state = RADIOLIB_ERR_NONE;
     557           0 :   if(!enabled) {
     558             :     // disable whitening
     559           0 :     this->whitening = RADIOLIB_SX126X_GFSK_WHITENING_OFF;
     560             : 
     561           0 :     state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType);
     562           0 :     RADIOLIB_ASSERT(state);
     563             : 
     564             :   } else {
     565             :     // enable whitening
     566           0 :     this->whitening = RADIOLIB_SX126X_GFSK_WHITENING_ON;
     567             : 
     568             :     // write initial whitening value
     569             :     // as per note on pg. 65 of datasheet v1.2: "The user should not change the value of the 7 MSB's of this register"
     570             :     uint8_t data[2];
     571             :     // first read the actual value and mask 7 MSB which we can not change
     572             :     // if different value is written in 7 MSB, the Rx won't even work (tested on HW)
     573           0 :     state = readRegister(RADIOLIB_SX126X_REG_WHITENING_INITIAL_MSB, data, 1);
     574           0 :     RADIOLIB_ASSERT(state);
     575             : 
     576           0 :     data[0] = (data[0] & 0xFE) | (uint8_t)((initial >> 8) & 0x01);
     577           0 :     data[1] = (uint8_t)(initial & 0xFF);
     578           0 :     state = writeRegister(RADIOLIB_SX126X_REG_WHITENING_INITIAL_MSB, data, 2);
     579           0 :     RADIOLIB_ASSERT(state);
     580             : 
     581           0 :     state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType);
     582           0 :     RADIOLIB_ASSERT(state);
     583             :   }
     584           0 :   return(state);
     585             : }
     586             : 
     587           0 : int16_t SX126x::fixedPacketLengthMode(uint8_t len) {
     588           0 :   return(setPacketMode(RADIOLIB_SX126X_GFSK_PACKET_FIXED, len));
     589             : }
     590             : 
     591           0 : int16_t SX126x::variablePacketLengthMode(uint8_t maxLen) {
     592           0 :   return(setPacketMode(RADIOLIB_SX126X_GFSK_PACKET_VARIABLE, maxLen));
     593             : }
     594           0 : int16_t SX126x::implicitHeader(size_t len) {
     595           0 :   return(setHeaderType(RADIOLIB_SX126X_LORA_HEADER_IMPLICIT, len));
     596             : }
     597             : 
     598           0 : int16_t SX126x::explicitHeader() {
     599           0 :   return(setHeaderType(RADIOLIB_SX126X_LORA_HEADER_EXPLICIT));
     600             : }
     601             : 
     602           0 : int16_t SX126x::setRegulatorLDO() {
     603           0 :   return(setRegulatorMode(RADIOLIB_SX126X_REGULATOR_LDO));
     604             : }
     605             : 
     606           0 : int16_t SX126x::setRegulatorDCDC() {
     607           0 :   return(setRegulatorMode(RADIOLIB_SX126X_REGULATOR_DC_DC));
     608             : }
     609             : 
     610           0 : int16_t SX126x::setEncoding(uint8_t encoding) {
     611           0 :   return(setWhitening(encoding));
     612             : }
     613             : 
     614           0 : void SX126x::setRfSwitchPins(uint32_t rxEn, uint32_t txEn) {
     615           0 :   this->mod->setRfSwitchPins(rxEn, txEn);
     616           0 : }
     617             : 
     618           0 : void SX126x::setRfSwitchTable(const uint32_t (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]) {
     619           0 :   this->mod->setRfSwitchTable(pins, table);
     620           0 : }
     621             : 
     622           0 : int16_t SX126x::forceLDRO(bool enable) {
     623             :   // check active modem
     624           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     625           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     626             :   }
     627             : 
     628             :   // update modulation parameters
     629           0 :   this->ldroAuto = false;
     630           0 :   this->ldrOptimize = (uint8_t)enable;
     631           0 :   return(setModulationParams(this->spreadingFactor, this->bandwidth, this->codingRate, this->ldrOptimize));
     632             : }
     633             : 
     634           0 : int16_t SX126x::autoLDRO() {
     635           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     636           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     637             :   }
     638             : 
     639           0 :   this->ldroAuto = true;
     640           0 :   return(RADIOLIB_ERR_NONE);
     641             : }
     642             : 
     643           0 : int16_t SX126x::invertIQ(bool enable) {
     644           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     645           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     646             :   }
     647             : 
     648           0 :   if(enable) {
     649           0 :     this->invertIQEnabled = RADIOLIB_SX126X_LORA_IQ_INVERTED;
     650             :   } else {
     651           0 :     this->invertIQEnabled = RADIOLIB_SX126X_LORA_IQ_STANDARD;
     652             :   }
     653             : 
     654           0 :   return(setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, this->implicitLen, this->headerType, this->invertIQEnabled));
     655             : }
     656             : 
     657           0 : int16_t SX126x::setTCXO(float voltage, uint32_t delay) {
     658             :   // check if TCXO is enabled at all
     659           0 :   if(this->XTAL) {
     660           0 :     return(RADIOLIB_ERR_INVALID_TCXO_VOLTAGE);
     661             :   }
     662             : 
     663             :   // set mode to standby
     664           0 :   standby();
     665             : 
     666             :   // check RADIOLIB_SX126X_XOSC_START_ERR flag and clear it
     667           0 :   if(getDeviceErrors() & RADIOLIB_SX126X_XOSC_START_ERR) {
     668           0 :     clearDeviceErrors();
     669             :   }
     670             : 
     671             :   // check 0 V disable
     672           0 :   if(fabsf(voltage - 0.0f) <= 0.001f) {
     673           0 :     return(reset(true));
     674             :   }
     675             : 
     676             :   // check alowed voltage values
     677             :   uint8_t data[4];
     678           0 :   if(fabsf(voltage - 1.6f) <= 0.001f) {
     679           0 :     data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_1_6;
     680           0 :   } else if(fabsf(voltage - 1.7f) <= 0.001f) {
     681           0 :     data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_1_7;
     682           0 :   } else if(fabsf(voltage - 1.8f) <= 0.001f) {
     683           0 :     data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_1_8;
     684           0 :   } else if(fabsf(voltage - 2.2f) <= 0.001f) {
     685           0 :     data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_2_2;
     686           0 :   } else if(fabsf(voltage - 2.4f) <= 0.001f) {
     687           0 :     data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_2_4;
     688           0 :   } else if(fabsf(voltage - 2.7f) <= 0.001f) {
     689           0 :     data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_2_7;
     690           0 :   } else if(fabsf(voltage - 3.0f) <= 0.001f) {
     691           0 :     data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_3_0;
     692           0 :   } else if(fabsf(voltage - 3.3f) <= 0.001f) {
     693           0 :     data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_3_3;
     694             :   } else {
     695           0 :     return(RADIOLIB_ERR_INVALID_TCXO_VOLTAGE);
     696             :   }
     697             : 
     698             :   // calculate delay
     699           0 :   uint32_t delayValue = (float)delay / 15.625f;
     700           0 :   data[1] = (uint8_t)((delayValue >> 16) & 0xFF);
     701           0 :   data[2] = (uint8_t)((delayValue >> 8) & 0xFF);
     702           0 :   data[3] = (uint8_t)(delayValue & 0xFF);
     703             : 
     704           0 :   this->tcxoDelay = delay;
     705             : 
     706             :   // enable TCXO control on DIO3
     707           0 :   return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_DIO3_AS_TCXO_CTRL, data, 4));
     708             : }
     709             : 
     710           0 : int16_t SX126x::setDio2AsRfSwitch(bool enable) {
     711           0 :   uint8_t data = enable ? RADIOLIB_SX126X_DIO2_AS_RF_SWITCH : RADIOLIB_SX126X_DIO2_AS_IRQ;
     712           0 :   return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL, &data, 1));
     713             : }
     714           0 : int16_t SX126x::setPaRampTime(uint8_t rampTime) {
     715           0 :   return(this->setTxParams(this->pwr, rampTime));
     716             : }
     717             : 
     718           0 : int16_t SX126x::setPacketMode(uint8_t mode, uint8_t len) {
     719             :   // check active modem
     720           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     721           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     722             :   }
     723             : 
     724             :   // set requested packet mode
     725           0 :   int16_t state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, mode, len);
     726           0 :   RADIOLIB_ASSERT(state);
     727             : 
     728             :   // update cached value
     729           0 :   this->packetType = mode;
     730           0 :   return(state);
     731             : }
     732             : 
     733           0 : int16_t SX126x::setHeaderType(uint8_t hdrType, size_t len) {
     734             :   // check active modem
     735           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     736           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     737             :   }
     738             : 
     739             :   // set requested packet mode
     740           0 :   int16_t state = setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, len, hdrType, this->invertIQEnabled);
     741           0 :   RADIOLIB_ASSERT(state);
     742             : 
     743             :   // update cached value
     744           0 :   this->headerType = hdrType;
     745           0 :   this->implicitLen = len;
     746             : 
     747           0 :   return(state);
     748             : }
     749             : 
     750           0 : int16_t SX126x::setFrequencyRaw(float freq) {
     751             :   // calculate raw value
     752           0 :   this->freqMHz = freq;
     753           0 :   uint32_t frf = (this->freqMHz * (uint32_t(1) << RADIOLIB_SX126X_DIV_EXPONENT)) / RADIOLIB_SX126X_CRYSTAL_FREQ;
     754           0 :   return(setRfFrequency(frf));
     755             : }
     756             : 
     757           0 : int16_t SX126x::config(uint8_t modem) {
     758             :   // reset buffer base address
     759           0 :   int16_t state = setBufferBaseAddress();
     760           0 :   RADIOLIB_ASSERT(state);
     761             : 
     762             :   // set modem
     763             :   uint8_t data[7];
     764           0 :   data[0] = modem;
     765           0 :   state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_PACKET_TYPE, data, 1);
     766           0 :   RADIOLIB_ASSERT(state);
     767             : 
     768             :   // set Rx/Tx fallback mode to STDBY_RC
     769           0 :   data[0] = this->standbyXOSC ? RADIOLIB_SX126X_RX_TX_FALLBACK_MODE_STDBY_XOSC : RADIOLIB_SX126X_RX_TX_FALLBACK_MODE_STDBY_RC;
     770           0 :   state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_RX_TX_FALLBACK_MODE, data, 1);
     771           0 :   RADIOLIB_ASSERT(state);
     772             : 
     773             :   // set some CAD parameters - will be overwritten when calling CAD anyway
     774           0 :   data[0] = RADIOLIB_SX126X_CAD_ON_8_SYMB;
     775           0 :   data[1] = this->spreadingFactor + 13;
     776           0 :   data[2] = RADIOLIB_SX126X_CAD_PARAM_DET_MIN;
     777           0 :   data[3] = RADIOLIB_SX126X_CAD_GOTO_STDBY;
     778           0 :   data[4] = 0x00;
     779           0 :   data[5] = 0x00;
     780           0 :   data[6] = 0x00;
     781           0 :   state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_CAD_PARAMS, data, 7);
     782           0 :   RADIOLIB_ASSERT(state);
     783             : 
     784             :   // clear IRQ
     785           0 :   state = clearIrqStatus();
     786           0 :   state |= setDioIrqParams(RADIOLIB_SX126X_IRQ_NONE, RADIOLIB_SX126X_IRQ_NONE);
     787           0 :   RADIOLIB_ASSERT(state);
     788             : 
     789             :   // calibrate all blocks
     790           0 :   data[0] = RADIOLIB_SX126X_CALIBRATE_ALL;
     791           0 :   state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_CALIBRATE, data, 1, true, false);
     792           0 :   RADIOLIB_ASSERT(state);
     793             : 
     794             :   // wait for calibration completion
     795           0 :   this->mod->hal->delay(5);
     796           0 :   while(this->mod->hal->digitalRead(this->mod->getGpio())) {
     797           0 :     this->mod->hal->yield();
     798             :   }
     799             : 
     800             :   // check calibration result
     801           0 :   state = this->mod->SPIcheckStream();
     802             : 
     803             :   // if something failed, show the device errors
     804             :   #if RADIOLIB_DEBUG_BASIC
     805             :   if(state != RADIOLIB_ERR_NONE) {
     806             :     // unless mode is forced to standby, device errors will be 0
     807             :     standby();
     808             :     uint16_t errors = getDeviceErrors();
     809             :     RADIOLIB_DEBUG_BASIC_PRINTLN("Calibration failed, device errors: 0x%X", errors);
     810             :   }
     811             :   #endif
     812             : 
     813           0 :   return(state);
     814             : }
     815             : 
     816             : #endif

Generated by: LCOV version 1.14