LCOV - code coverage report
Current view: top level - src/modules/SX126x - SX126x_config.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 47 382 12.3 %
Date: 2026-11-08 19:43:08 Functions: 13 40 32.5 %

          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           3 : int16_t SX126x::setBandwidth(uint32_t bw) {
      21           3 :   RADIOLIB_CHECK_RANGE(bw, 7800, RADIOLIB_UNIT_KILO(500), RADIOLIB_ERR_INVALID_BANDWIDTH);
      22             : 
      23             :   // check active modem
      24           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
      25           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
      26             :   }
      27             : 
      28           0 :   switch(bw)  {
      29           0 :     case(7800):
      30           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_7_8;
      31           0 :       break;
      32           0 :     case(10400):
      33           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_10_4;
      34           0 :       break;
      35           0 :     case(15600):
      36           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_15_6;
      37           0 :       break;
      38           0 :     case(20800):
      39           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_20_8;
      40           0 :       break;
      41           0 :     case(31250):
      42           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_31_25;
      43           0 :       break;
      44           0 :     case(41700):
      45           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_41_7;
      46           0 :       break;
      47           0 :     case(62500):
      48           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_62_5;
      49           0 :       break;
      50           0 :     case(RADIOLIB_UNIT_KILO(125)):
      51           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_125_0;
      52           0 :       break;
      53           0 :     case(RADIOLIB_UNIT_KILO(250)):
      54           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_250_0;
      55           0 :       break;
      56           0 :     case(RADIOLIB_UNIT_KILO(500)):
      57           0 :       this->bandwidth = RADIOLIB_SX126X_LORA_BW_500_0;
      58           0 :       break;
      59           0 :     default:
      60           0 :       return(RADIOLIB_ERR_INVALID_BANDWIDTH);
      61             :   }
      62             : 
      63             :   // update modulation parameters
      64           0 :   this->bandwidthHz = bw;
      65           0 :   return(setModulationParams(this->spreadingFactor, this->bandwidth, this->codingRate, this->ldrOptimize));
      66             : }
      67             : 
      68           3 : int16_t SX126x::setSpreadingFactor(uint8_t sf) {
      69           3 :   RADIOLIB_CHECK_RANGE(sf, 5, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
      70             : 
      71             :   // check active modem
      72           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
      73           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
      74             :   }
      75             : 
      76             :   // update modulation parameters
      77           0 :   this->spreadingFactor = sf;
      78           0 :   return(setModulationParams(this->spreadingFactor, this->bandwidth, this->codingRate, this->ldrOptimize));
      79             : }
      80             : 
      81           3 : int16_t SX126x::setCodingRate(uint8_t cr, bool longInterleave) {
      82           3 :   RADIOLIB_CHECK_RANGE(cr, 4, 8, RADIOLIB_ERR_INVALID_CODING_RATE);
      83             : 
      84             :   // check active modem
      85           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
      86           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
      87             :   }
      88             : 
      89           0 :   if(longInterleave) {
      90           0 :     switch(cr) {
      91           0 :       case 4:
      92           0 :         this->codingRate = 0;
      93           0 :         break;
      94           0 :       case 5:
      95             :       case 6:
      96           0 :         this->codingRate = cr;
      97           0 :         break;
      98           0 :       case 8: 
      99           0 :         this->codingRate = cr - 1;
     100           0 :         break;
     101           0 :       default:
     102           0 :         return(RADIOLIB_ERR_INVALID_CODING_RATE);
     103             :     }
     104             :   } else {
     105           0 :     this->codingRate = cr - 4;
     106             :   }
     107             : 
     108             :   // update modulation parameters
     109           0 :   return(setModulationParams(this->spreadingFactor, this->bandwidth, this->codingRate, this->ldrOptimize));
     110             : }
     111             : 
     112           0 : int16_t SX126x::setSyncWord(uint8_t syncWord, uint8_t controlBits) {
     113             :   // check active modem
     114           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     115           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     116             :   }
     117             : 
     118             :   // update register
     119           0 :   const uint8_t data[2] = {(uint8_t)((syncWord & 0xF0) | ((controlBits & 0xF0) >> 4)), (uint8_t)(((syncWord & 0x0F) << 4) | (controlBits & 0x0F))};
     120           0 :   return(writeRegister(RADIOLIB_SX126X_REG_LORA_SYNC_WORD_MSB, data, 2));
     121             : }
     122             : 
     123           0 : int16_t SX126x::setCurrentLimit(float currentLimit) {
     124             :   // check allowed range
     125           0 :   if(!((currentLimit >= 0) && (currentLimit <= 140))) {
     126           0 :     return(RADIOLIB_ERR_INVALID_CURRENT_LIMIT);
     127             :   }
     128             : 
     129             :   // calculate raw value
     130           0 :   uint8_t rawLimit = (uint8_t)(currentLimit / 2.5f);
     131             : 
     132             :   // update register
     133           0 :   return(writeRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &rawLimit, 1));
     134             : }
     135             : 
     136           0 : float SX126x::getCurrentLimit() {
     137             :   // get the raw value
     138           0 :   uint8_t ocp = 0;
     139           0 :   readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
     140             : 
     141             :   // return the actual value
     142           0 :   return((float)ocp * 2.5f);
     143             : }
     144             : 
     145           3 : int16_t SX126x::setPreambleLength(size_t preambleLength, size_t preambleDetLength) {
     146           3 :   uint8_t modem = getPacketType();
     147           3 :   if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     148           0 :     this->preambleLengthLoRa = preambleLength;
     149           0 :     return(setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, this->implicitLen, this->headerType, this->invertIQEnabled));
     150           3 :   } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     151           0 :     this->preambleLengthFSK = preambleLength;
     152             :     // maximum preamble detector length is limited by sync word length
     153             :     // for details, see the note in SX1261 datasheet, Rev 2.1, section 6.2.2.1, page 45
     154           0 :     uint8_t maxDetLen = RADIOLIB_MIN(this->syncWordLength, this->preambleLengthFSK);
     155           0 :     this->preambleDetLength = RADIOLIB_MIN(maxDetLen, preambleDetLength);
     156             : 
     157             :     // if no value is specified for preambleDetLength, use the value best corresponding to preambleLength
     158           0 :     if(preambleDetLength == 0xFFFFFFFF) {
     159           0 :       this->preambleDetLength = maxDetLen >= 32 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_32 :
     160             :                                 maxDetLen >= 24 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_24 :
     161             :                                 maxDetLen >= 16 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_16 :
     162             :                                 maxDetLen >   0 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_8 :
     163             :                                 RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_OFF;
     164             :     }
     165           0 :     return(setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening,
     166           0 :       this->packetType, (this->packetType == RADIOLIB_SX126X_GFSK_PACKET_FIXED) ? this->implicitLen : RADIOLIB_SX126X_MAX_PACKET_LENGTH));
     167             :   }
     168             : 
     169           3 :   return(RADIOLIB_ERR_UNKNOWN);
     170             : }
     171             : 
     172           3 : int16_t SX126x::setFrequencyDeviation(uint32_t freqDev) {
     173             :   // check active modem
     174           3 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     175           3 :     return(RADIOLIB_ERR_WRONG_MODEM);
     176             :   }
     177             : 
     178             :   // set frequency deviation to lowest available setting (required for digimodes)
     179           0 :   uint32_t newFreqDev = freqDev ? freqDev : 600;
     180           0 :   RADIOLIB_CHECK_RANGE(newFreqDev, 600, RADIOLIB_UNIT_KILO(500), RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
     181             : 
     182             :   // calculate raw frequency deviation value
     183           0 :   uint32_t freqDevRaw = (uint32_t)(((uint64_t)newFreqDev * (1UL << 25)) / (RADIOLIB_UNIT_MEGA(RADIOLIB_SX126X_CRYSTAL_FREQ)));
     184             : 
     185             :   // check modulation parameters
     186           0 :   this->frequencyDev = freqDevRaw;
     187             : 
     188             :   // update modulation parameters
     189           0 :   return(setModulationParamsFSK(this->bitRateRaw, this->pulseShape, this->rxBandwidth, this->frequencyDev));
     190             : }
     191             : 
     192           3 : int16_t SX126x::setBitRate(uint32_t br) {
     193             :   // check active modem and valid range
     194             :   uint32_t brRaw;
     195           3 :   uint8_t modem = getPacketType();
     196           3 :   if(modem == RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) {
     197             :     // at the moment only the very specific 488.28125 bps rate is supported
     198           0 :     if(br != 488) { return(RADIOLIB_ERR_INVALID_BIT_RATE); }
     199           0 :     brRaw = RADIOLIB_SX126X_LR_FHSS_BIT_RATE_RAW;
     200           3 :   } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_BPSK) {
     201             :     // this should be just either 100 or 600 bps, not the range
     202             :     // but the BPSK support is so experimental it probably does not matter
     203           0 :     RADIOLIB_CHECK_RANGE(br, 100, 600, RADIOLIB_ERR_INVALID_BIT_RATE);
     204           0 :     brRaw = RADIOLIB_SX126X_BIT_RATE_RAW(br);
     205           3 :   } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     206           0 :     RADIOLIB_CHECK_RANGE(br, 600, RADIOLIB_UNIT_KILO(300), RADIOLIB_ERR_INVALID_BIT_RATE);
     207           0 :     brRaw = RADIOLIB_SX126X_BIT_RATE_RAW(br);
     208             :   } else {
     209           3 :     return(RADIOLIB_ERR_WRONG_MODEM);
     210             :   }
     211             : 
     212             :   // check modulation parameters
     213           0 :   this->bitRateRaw = brRaw;
     214             : 
     215             :   // update modulation parameters
     216           0 :   int16_t state = RADIOLIB_ERR_UNKNOWN;
     217           0 :   if(modem == RADIOLIB_SX126X_PACKET_TYPE_BPSK) {
     218           0 :     state = setModulationParamsBPSK(this->bitRateRaw);
     219             :   } else {
     220           0 :     state = setModulationParamsFSK(this->bitRateRaw, this->pulseShape, this->rxBandwidth, this->frequencyDev);
     221             :   }
     222           0 :   RADIOLIB_ASSERT(state);
     223             : 
     224             :   // apply workaround or reset it, as needed
     225           0 :   return(fixGFSK());
     226             : }
     227             : 
     228           3 : int16_t SX126x::checkDataRate(DataRate_t dr, ModemType_t modem) {
     229           3 :   int16_t state = RADIOLIB_ERR_UNKNOWN;
     230             : 
     231             :   // retrieve modem if not supplied
     232           3 :   if(modem == RADIOLIB_MODEM_NONE) {
     233           3 :     state = this->getModem(&modem);
     234           3 :     RADIOLIB_ASSERT(state);
     235             :   }
     236             : 
     237             :   // select interpretation based on modem
     238           0 :   if(modem == RADIOLIB_MODEM_FSK) {
     239           0 :     RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 600, RADIOLIB_UNIT_KILO(300), RADIOLIB_ERR_INVALID_BIT_RATE);
     240           0 :     RADIOLIB_CHECK_RANGE(dr.fsk.freqDev, 600, RADIOLIB_UNIT_KILO(200), RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
     241           0 :     return(RADIOLIB_ERR_NONE);
     242             : 
     243           0 :   } else if(modem == RADIOLIB_MODEM_LORA) {
     244           0 :     RADIOLIB_CHECK_RANGE(dr.lora.spreadingFactor, 5, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
     245           0 :     RADIOLIB_CHECK_RANGE(dr.lora.bandwidth, 7800, RADIOLIB_UNIT_KILO(500), RADIOLIB_ERR_INVALID_BANDWIDTH);
     246           0 :     RADIOLIB_CHECK_RANGE(dr.lora.codingRate, 4, 8, RADIOLIB_ERR_INVALID_CODING_RATE);
     247           0 :     return(RADIOLIB_ERR_NONE);
     248             :   
     249             :   }
     250             : 
     251           0 :   return(state);
     252             : }
     253             : 
     254           0 : int16_t SX126x::setRxBandwidth(uint32_t rxBw) {
     255             :   // check active modem
     256           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     257           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     258             :   }
     259             : 
     260           0 :   const uint32_t rxBwAvg[] = {
     261             :     5300, 6600, 8500, 10700, 13200, 17100, 21500, 26400,
     262             :     34200, 43000, 52800, 68400, 86000, 105600, 136800,
     263             :     171700, 210800, 273200, 342800, 420300,
     264             :   };
     265             : 
     266           0 :   const uint8_t rxBwLut[] = {
     267             :     RADIOLIB_SX126X_GFSK_RX_BW_4_8,
     268             :     RADIOLIB_SX126X_GFSK_RX_BW_5_8,
     269             :     RADIOLIB_SX126X_GFSK_RX_BW_7_3,
     270             :     RADIOLIB_SX126X_GFSK_RX_BW_9_7,
     271             :     RADIOLIB_SX126X_GFSK_RX_BW_11_7,
     272             :     RADIOLIB_SX126X_GFSK_RX_BW_14_6,
     273             :     RADIOLIB_SX126X_GFSK_RX_BW_19_5,
     274             :     RADIOLIB_SX126X_GFSK_RX_BW_23_4,
     275             :     RADIOLIB_SX126X_GFSK_RX_BW_29_3,
     276             :     RADIOLIB_SX126X_GFSK_RX_BW_39_0,
     277             :     RADIOLIB_SX126X_GFSK_RX_BW_46_9,
     278             :     RADIOLIB_SX126X_GFSK_RX_BW_58_6,
     279             :     RADIOLIB_SX126X_GFSK_RX_BW_78_2,
     280             :     RADIOLIB_SX126X_GFSK_RX_BW_93_8,
     281             :     RADIOLIB_SX126X_GFSK_RX_BW_117_3,
     282             :     RADIOLIB_SX126X_GFSK_RX_BW_156_2,
     283             :     RADIOLIB_SX126X_GFSK_RX_BW_187_2,
     284             :     RADIOLIB_SX126X_GFSK_RX_BW_234_3,
     285             :     RADIOLIB_SX126X_GFSK_RX_BW_312_0,
     286             :     RADIOLIB_SX126X_GFSK_RX_BW_373_6,
     287             :     RADIOLIB_SX126X_GFSK_RX_BW_467_0,
     288             :   };
     289             : 
     290           0 :   int16_t state = findRxBw(rxBw, rxBwAvg, rxBwLut, sizeof(rxBwLut)/sizeof(rxBwLut[0]), RADIOLIB_UNIT_KILO(467), &this->rxBandwidth);
     291           0 :   RADIOLIB_ASSERT(state);
     292             : 
     293             :   // update modulation parameters
     294           0 :   return(setModulationParamsFSK(this->bitRateRaw, this->pulseShape, this->rxBandwidth, this->frequencyDev));
     295             : }
     296             : 
     297           0 : int16_t SX126x::setRxBoostedGainMode(bool rxbgm, bool persist) {
     298           0 :   this->rxBoostedGainMode = rxbgm;
     299             : 
     300             :   // update RX gain setting register
     301           0 :   uint8_t rxGain = rxbgm ? RADIOLIB_SX126X_RX_GAIN_BOOSTED : RADIOLIB_SX126X_RX_GAIN_POWER_SAVING;
     302           0 :   int16_t state = writeRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1);
     303           0 :   RADIOLIB_ASSERT(state);
     304             : 
     305             :   // add Rx Gain register to retention memory if requested
     306           0 :   if(persist) {
     307             :     // values and registers below are specified in SX126x datasheet v2.1 section 9.6, just below table 9-3
     308           0 :     const uint8_t data[] = { 0x01, (uint8_t)((RADIOLIB_SX126X_REG_RX_GAIN >> 8) & 0xFF), (uint8_t)(RADIOLIB_SX126X_REG_RX_GAIN & 0xFF) };
     309           0 :     state = writeRegister(RADIOLIB_SX126X_REG_RX_GAIN_RETENTION_0, data, 3);
     310             :   }
     311             : 
     312           0 :   return(state);
     313             : }
     314             : 
     315           3 : int16_t SX126x::setDataShaping(uint8_t sh) {
     316             :   // check active modem
     317           3 :   uint8_t modem = getPacketType();
     318           3 :   if((modem != RADIOLIB_SX126X_PACKET_TYPE_GFSK) && (modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS)) {
     319           3 :     return(RADIOLIB_ERR_WRONG_MODEM);
     320             :   }
     321             : 
     322             :   // set data shaping
     323           0 :   switch(sh) {
     324           0 :     case RADIOLIB_SHAPING_NONE:
     325           0 :       this->pulseShape = RADIOLIB_SX126X_GFSK_FILTER_NONE;
     326           0 :       break;
     327           0 :     case RADIOLIB_SHAPING_0_3:
     328           0 :       this->pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_3;
     329           0 :       break;
     330           0 :     case RADIOLIB_SHAPING_0_5:
     331           0 :       this->pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_5;
     332           0 :       break;
     333           0 :     case RADIOLIB_SHAPING_0_7:
     334           0 :       this->pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_7;
     335           0 :       break;
     336           0 :     case RADIOLIB_SHAPING_1_0:
     337           0 :       this->pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_1;
     338           0 :       break;
     339           0 :     default:
     340           0 :       return(RADIOLIB_ERR_INVALID_DATA_SHAPING);
     341             :   }
     342             : 
     343             :   // update modulation parameters
     344           0 :   return(setModulationParamsFSK(this->bitRateRaw, this->pulseShape, this->rxBandwidth, this->frequencyDev));
     345             : }
     346             : 
     347           3 : int16_t SX126x::setSyncWord(uint8_t* syncWord, size_t len) {
     348             :   // check active modem
     349           3 :   uint8_t modem = getPacketType();
     350           3 :   if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     351             :     // check sync word Length
     352           0 :     if(len > 8) {
     353           0 :       return(RADIOLIB_ERR_INVALID_SYNC_WORD);
     354             :     }
     355             : 
     356             :     // write sync word
     357           0 :     int16_t state = writeRegister(RADIOLIB_SX126X_REG_SYNC_WORD_0, syncWord, len);
     358           0 :     RADIOLIB_ASSERT(state);
     359             : 
     360             :     // update packet parameters
     361           0 :     this->syncWordLength = len * 8;
     362             :     
     363             :     // maximum preamble detector length is limited by sync word length
     364             :     // for details, see the note in SX1261 datasheet, Rev 2.1, section 6.2.2.1, page 45
     365           0 :     uint8_t maxDetLen = RADIOLIB_MIN(this->syncWordLength, this->preambleLengthFSK);
     366           0 :     this->preambleDetLength = maxDetLen >= 32 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_32 :
     367             :                               maxDetLen >= 24 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_24 :
     368             :                               maxDetLen >= 16 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_16 :
     369             :                               maxDetLen >   0 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_8 :
     370             :                               RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_OFF;
     371           0 :     state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening,
     372           0 :       this->packetType, (this->packetType == RADIOLIB_SX126X_GFSK_PACKET_FIXED) ? this->implicitLen : RADIOLIB_SX126X_MAX_PACKET_LENGTH);
     373           0 :     return(state);
     374             :   
     375           3 :   } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     376             :     // with length set to 1 and LoRa modem active, assume it is the LoRa sync word
     377           0 :     if(len > 1) {
     378           0 :       return(RADIOLIB_ERR_INVALID_SYNC_WORD);
     379             :     }
     380           0 :     return(setSyncWord(syncWord[0]));
     381             : 
     382           3 :   } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) {
     383             :     // with length set to 4 and LR-FHSS modem active, assume it is the LR-FHSS sync word
     384           0 :     if(len != sizeof(uint32_t)) {
     385           0 :       return(RADIOLIB_ERR_INVALID_SYNC_WORD);
     386             :     }
     387           0 :     memcpy(this->lrFhssSyncWord, syncWord, sizeof(uint32_t));
     388             :   
     389             :   }
     390             : 
     391           3 :   return(RADIOLIB_ERR_WRONG_MODEM);
     392             : }
     393             : 
     394           0 : int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool inverted) {
     395             :   // check active modem
     396           0 :   uint8_t modem = getPacketType();
     397             : 
     398           0 :   if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     399             :     // update packet parameters
     400           0 :     switch(len) {
     401           0 :       case 0:
     402           0 :         this->crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_OFF;
     403           0 :         break;
     404           0 :       case 1:
     405           0 :         if(inverted) {
     406           0 :           this->crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_1_BYTE_INV;
     407             :         } else {
     408           0 :           this->crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_1_BYTE;
     409             :         }
     410           0 :         break;
     411           0 :       case 2:
     412           0 :         if(inverted) {
     413           0 :           this->crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_2_BYTE_INV;
     414             :         } else {
     415           0 :           this->crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_2_BYTE;
     416             :         }
     417           0 :         break;
     418           0 :       default:
     419           0 :         return(RADIOLIB_ERR_INVALID_CRC_CONFIGURATION);
     420             :     }
     421             : 
     422           0 :     int16_t state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening,
     423           0 :       this->packetType, (this->packetType == RADIOLIB_SX126X_GFSK_PACKET_FIXED) ? this->implicitLen : RADIOLIB_SX126X_MAX_PACKET_LENGTH);
     424           0 :     RADIOLIB_ASSERT(state);
     425             : 
     426             :     // write initial CRC value
     427           0 :     uint8_t data[2] = {(uint8_t)((initial >> 8) & 0xFF), (uint8_t)(initial & 0xFF)};
     428           0 :     state = writeRegister(RADIOLIB_SX126X_REG_CRC_INITIAL_MSB, data, 2);
     429           0 :     RADIOLIB_ASSERT(state);
     430             : 
     431             :     // write CRC polynomial value
     432           0 :     data[0] = (uint8_t)((polynomial >> 8) & 0xFF);
     433           0 :     data[1] = (uint8_t)(polynomial & 0xFF);
     434           0 :     state = writeRegister(RADIOLIB_SX126X_REG_CRC_POLYNOMIAL_MSB, data, 2);
     435             : 
     436           0 :     return(state);
     437             : 
     438           0 :   } else if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     439             :     // LoRa CRC doesn't allow to set CRC polynomial, initial value, or inversion
     440             : 
     441             :     // update packet parameters
     442           0 :     if(len) {
     443           0 :       this->crcTypeLoRa = RADIOLIB_SX126X_LORA_CRC_ON;
     444             :     } else {
     445           0 :       this->crcTypeLoRa = RADIOLIB_SX126X_LORA_CRC_OFF;
     446             :     }
     447             : 
     448           0 :     return(setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, this->implicitLen, this->headerType, this->invertIQEnabled));
     449             :   }
     450             : 
     451           0 :   return(RADIOLIB_ERR_UNKNOWN);
     452             : }
     453             : 
     454           3 : int16_t SX126x::setWhitening(bool enabled, uint16_t initial) {
     455             :   // check active modem
     456           3 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     457           3 :     return(RADIOLIB_ERR_WRONG_MODEM);
     458             :   }
     459             : 
     460           0 :   int16_t state = RADIOLIB_ERR_NONE;
     461           0 :   if(!enabled) {
     462             :     // disable whitening
     463           0 :     this->whitening = RADIOLIB_SX126X_GFSK_WHITENING_OFF;
     464             : 
     465           0 :     state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening,
     466           0 :       this->packetType, (this->packetType == RADIOLIB_SX126X_GFSK_PACKET_FIXED) ? this->implicitLen : RADIOLIB_SX126X_MAX_PACKET_LENGTH);
     467           0 :     RADIOLIB_ASSERT(state);
     468             : 
     469             :   } else {
     470             :     // enable whitening
     471           0 :     this->whitening = RADIOLIB_SX126X_GFSK_WHITENING_ON;
     472             : 
     473             :     // write initial whitening value
     474             :     // 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"
     475             :     uint8_t data[2];
     476             :     // first read the actual value and mask 7 MSB which we can not change
     477             :     // if different value is written in 7 MSB, the Rx won't even work (tested on HW)
     478           0 :     state = readRegister(RADIOLIB_SX126X_REG_WHITENING_INITIAL_MSB, data, 1);
     479           0 :     RADIOLIB_ASSERT(state);
     480             : 
     481           0 :     data[0] = (data[0] & 0xFE) | (uint8_t)((initial >> 8) & 0x01);
     482           0 :     data[1] = (uint8_t)(initial & 0xFF);
     483           0 :     state = writeRegister(RADIOLIB_SX126X_REG_WHITENING_INITIAL_MSB, data, 2);
     484           0 :     RADIOLIB_ASSERT(state);
     485             : 
     486           0 :     state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening,
     487           0 :       this->packetType, (this->packetType == RADIOLIB_SX126X_GFSK_PACKET_FIXED) ? this->implicitLen : RADIOLIB_SX126X_MAX_PACKET_LENGTH);
     488           0 :     RADIOLIB_ASSERT(state);
     489             :   }
     490           0 :   return(state);
     491             : }
     492             : 
     493           0 : int16_t SX126x::fixedPacketLengthMode(uint8_t len) {
     494           0 :   return(setPacketMode(RADIOLIB_SX126X_GFSK_PACKET_FIXED, len));
     495             : }
     496             : 
     497           0 : int16_t SX126x::variablePacketLengthMode(uint8_t maxLen) {
     498           0 :   return(setPacketMode(RADIOLIB_SX126X_GFSK_PACKET_VARIABLE, maxLen));
     499             : }
     500           0 : int16_t SX126x::implicitHeader(size_t len) {
     501           0 :   return(setHeaderType(RADIOLIB_SX126X_LORA_HEADER_IMPLICIT, len));
     502             : }
     503             : 
     504           0 : int16_t SX126x::explicitHeader() {
     505           0 :   return(setHeaderType(RADIOLIB_SX126X_LORA_HEADER_EXPLICIT));
     506             : }
     507             : 
     508           0 : int16_t SX126x::setRegulatorLDO() {
     509           0 :   return(setRegulatorMode(RADIOLIB_SX126X_REGULATOR_LDO));
     510             : }
     511             : 
     512           0 : int16_t SX126x::setRegulatorDCDC() {
     513           0 :   return(setRegulatorMode(RADIOLIB_SX126X_REGULATOR_DC_DC));
     514             : }
     515             : 
     516           3 : int16_t SX126x::setEncoding(uint8_t encoding) {
     517           3 :   return(setWhitening(encoding));
     518             : }
     519             : 
     520           0 : void SX126x::setRfSwitchPins(uint32_t rxEn, uint32_t txEn) {
     521           0 :   this->mod->setRfSwitchPins(rxEn, txEn);
     522           0 : }
     523             : 
     524           0 : void SX126x::setRfSwitchTable(const uint32_t (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]) {
     525           0 :   this->mod->setRfSwitchTable(pins, table);
     526           0 : }
     527             : 
     528           0 : int16_t SX126x::forceLDRO(bool enable) {
     529             :   // check active modem
     530           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     531           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     532             :   }
     533             : 
     534             :   // update modulation parameters
     535           0 :   this->ldroAuto = false;
     536           0 :   this->ldrOptimize = (uint8_t)enable;
     537           0 :   return(setModulationParams(this->spreadingFactor, this->bandwidth, this->codingRate, this->ldrOptimize));
     538             : }
     539             : 
     540           0 : int16_t SX126x::autoLDRO() {
     541           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     542           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     543             :   }
     544             : 
     545           0 :   this->ldroAuto = true;
     546           0 :   return(RADIOLIB_ERR_NONE);
     547             : }
     548             : 
     549           3 : int16_t SX126x::invertIQ(bool enable) {
     550           3 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     551           3 :     return(RADIOLIB_ERR_WRONG_MODEM);
     552             :   }
     553             : 
     554           0 :   if(enable) {
     555           0 :     this->invertIQEnabled = RADIOLIB_SX126X_LORA_IQ_INVERTED;
     556             :   } else {
     557           0 :     this->invertIQEnabled = RADIOLIB_SX126X_LORA_IQ_STANDARD;
     558             :   }
     559             : 
     560           0 :   return(setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, this->implicitLen, this->headerType, this->invertIQEnabled));
     561             : }
     562             : 
     563           0 : int16_t SX126x::setTCXO(RadioLibTCXOVoltage_t voltage, uint32_t delay) {
     564             :   // set mode to standby
     565             :   // force RC oscillator - typically this is called on startup,
     566             :   // so we cannot rely on what the user may have provided
     567           0 :   (void)standby(RADIOLIB_SX126X_STANDBY_RC);
     568             : 
     569             :   // check RADIOLIB_SX126X_XOSC_START_ERR flag and clear it
     570           0 :   if(getDeviceErrors() & RADIOLIB_SX126X_XOSC_START_ERR) {
     571           0 :     clearDeviceErrors();
     572             :   }
     573             : 
     574             :   // check disable
     575           0 :   if(voltage == RadioLibTCXOVoltage_t::VoltageNone) {
     576           0 :     return(reset(true));
     577             :   }
     578             : 
     579             :   // check allowed voltage values
     580           0 :   if(voltage > RadioLibTCXOVoltage_t::Voltage3V3) {
     581           0 :     return(RADIOLIB_ERR_INVALID_TCXO_VOLTAGE);
     582             :   }
     583             : 
     584             :   // calculate delay
     585           0 :   this->tcxoDelay = delay;
     586           0 :   uint32_t delayValue = (this->tcxoDelay * 8) / 125; // divide by 15.625
     587             :   const uint8_t data[] = {
     588           0 :     (uint8_t)voltage, (uint8_t)((delayValue >> 16) & 0xFF),
     589           0 :     (uint8_t)((delayValue >> 8) & 0xFF), (uint8_t)(delayValue & 0xFF),
     590           0 :   };
     591             : 
     592             :   // enable TCXO control on DIO3
     593           0 :   return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_DIO3_AS_TCXO_CTRL, data, 4));
     594             : }
     595             : 
     596           0 : int16_t SX126x::setDio2AsRfSwitch(bool enable) {
     597           0 :   this->dio2RfSwitch = enable;
     598           0 :   uint8_t data = enable ? RADIOLIB_SX126X_DIO2_AS_RF_SWITCH : RADIOLIB_SX126X_DIO2_AS_IRQ;
     599           0 :   return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL, &data, 1));
     600             : }
     601             : 
     602           0 : int16_t SX126x::setPaRampTime(uint8_t rampTime) {
     603           0 :   return(this->setTxParams(this->pwr, rampTime));
     604             : }
     605             : 
     606           2 : int16_t SX126x::setOutputPower(int8_t power, uint8_t paDutyCycle, uint8_t hpMax, uint8_t deviceSel) {
     607             :   // get current OCP configuration
     608           2 :   uint8_t ocp = 0;
     609           2 :   int16_t state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
     610           2 :   RADIOLIB_ASSERT(state);
     611             : 
     612             :   // set PA config
     613           0 :   state = SX126x::setPaConfig(paDutyCycle, deviceSel, hpMax);
     614           0 :   RADIOLIB_ASSERT(state);
     615             : 
     616             :   // set output power with default 200us ramp
     617           0 :   state = SX126x::setTxParams(power, RADIOLIB_SX126X_PA_RAMP_200U);
     618           0 :   RADIOLIB_ASSERT(state);
     619             : 
     620             :   // restore OCP configuration
     621           0 :   return(writeRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
     622             : }
     623             : 
     624           0 : void SX126x::setPaTable(SX126x::paTableEntry_t* table) {
     625           0 :   this->paOptTable = table;
     626           0 : }
     627             : 
     628           0 : int16_t SX126x::setStandbyXOSC(bool enable) {
     629             :   // set the internal variable
     630           0 :   this->standbyXOSC = enable;
     631             : 
     632             :   // call standby to start the oscillator
     633           0 :   int16_t state = standby();
     634           0 :   RADIOLIB_ASSERT(state);
     635             : 
     636             :   // update Rx/Tx fallback mode
     637           0 :   uint8_t mode = this->standbyXOSC ? RADIOLIB_SX126X_RX_TX_FALLBACK_MODE_STDBY_XOSC : RADIOLIB_SX126X_RX_TX_FALLBACK_MODE_STDBY_RC;
     638           0 :   return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_RX_TX_FALLBACK_MODE, &mode, 1));
     639             : }
     640             : 
     641           0 : int16_t SX126x::setPacketMode(uint8_t mode, uint8_t len) {
     642             :   // check active modem
     643           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
     644           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     645             :   }
     646             : 
     647             :   // set requested packet mode
     648           0 :   int16_t state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, mode, len);
     649           0 :   RADIOLIB_ASSERT(state);
     650             : 
     651             :   // update cached value
     652           0 :   this->packetType = mode;
     653           0 :   this->implicitLen = len;
     654           0 :   return(state);
     655             : }
     656             : 
     657           0 : int16_t SX126x::setHeaderType(uint8_t hdrType, size_t len) {
     658             :   // check active modem
     659           0 :   if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
     660           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     661             :   }
     662             : 
     663             :   // set requested packet mode
     664           0 :   int16_t state = setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, len, hdrType, this->invertIQEnabled);
     665           0 :   RADIOLIB_ASSERT(state);
     666             : 
     667             :   // update cached value
     668           0 :   this->headerType = hdrType;
     669           0 :   this->implicitLen = len;
     670             : 
     671           0 :   return(state);
     672             : }
     673             : 
     674           0 : int16_t SX126x::setFrequencyRaw(uint32_t freq) {
     675             :   // calculate raw value
     676           0 :   this->freqHz = freq;
     677           0 :   uint32_t frf = ((uint64_t)this->freqHz * (uint64_t)((uint64_t)1 << RADIOLIB_SX126X_DIV_EXPONENT)) / RADIOLIB_UNIT_MEGA(RADIOLIB_SX126X_CRYSTAL_FREQ);
     678           0 :   return(setRfFrequency(frf));
     679             : }
     680             : 
     681           0 : int16_t SX126x::config(uint8_t modem) {
     682             :   // reset buffer base address
     683             :   int16_t state;
     684           0 :   if(this->resetOnStartup) {
     685           0 :     state = setBufferBaseAddress();
     686           0 :     RADIOLIB_ASSERT(state);
     687             :   }
     688             : 
     689             :   // set modem
     690             :   uint8_t data[7];
     691           0 :   data[0] = modem;
     692           0 :   state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_PACKET_TYPE, data, 1);
     693           0 :   RADIOLIB_ASSERT(state);
     694             : 
     695             :   // set Rx/Tx fallback mode to STDBY_RC
     696           0 :   data[0] = this->standbyXOSC ? RADIOLIB_SX126X_RX_TX_FALLBACK_MODE_STDBY_XOSC : RADIOLIB_SX126X_RX_TX_FALLBACK_MODE_STDBY_RC;
     697           0 :   state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_RX_TX_FALLBACK_MODE, data, 1);
     698           0 :   RADIOLIB_ASSERT(state);
     699             : 
     700             :   // set some CAD parameters - will be overwritten when calling CAD anyway
     701           0 :   data[0] = RADIOLIB_SX126X_CAD_ON_8_SYMB;
     702           0 :   data[1] = this->spreadingFactor + 13;
     703           0 :   data[2] = RADIOLIB_SX126X_CAD_PARAM_DET_MIN;
     704           0 :   data[3] = RADIOLIB_SX126X_CAD_GOTO_STDBY;
     705           0 :   data[4] = 0x00;
     706           0 :   data[5] = 0x00;
     707           0 :   data[6] = 0x00;
     708           0 :   state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_CAD_PARAMS, data, 7);
     709           0 :   RADIOLIB_ASSERT(state);
     710             : 
     711             :   // clear IRQ
     712           0 :   state = clearIrqStatus();
     713           0 :   state |= setDioIrqParams(RADIOLIB_SX126X_IRQ_NONE, RADIOLIB_SX126X_IRQ_NONE);
     714           0 :   RADIOLIB_ASSERT(state);
     715             : 
     716             :   // calibrate all blocks
     717           0 :   data[0] = RADIOLIB_SX126X_CALIBRATE_ALL;
     718           0 :   state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_CALIBRATE, data, 1, true, false);
     719           0 :   RADIOLIB_ASSERT(state);
     720             : 
     721             :   // wait for calibration completion
     722           0 :   this->mod->hal->delay(5);
     723           0 :   while(this->mod->hal->digitalRead(this->mod->getGpio())) {
     724           0 :     this->mod->hal->yield();
     725             :   }
     726             : 
     727             :   // check calibration result
     728           0 :   return(this->mod->SPIcheckStream());
     729             : }
     730             : 
     731             : #endif

Generated by: LCOV version 1.14