LCOV - code coverage report
Current view: top level - src/modules/SX126x - SX1268.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 25 121 20.7 %
Date: 2026-06-03 18:53:41 Functions: 7 15 46.7 %

          Line data    Source code
       1             : #include "SX1268.h"
       2             : #include <math.h>
       3             : 
       4             : #if !RADIOLIB_EXCLUDE_SX126X
       5             : 
       6             : // this is a lookup table for optimized PA configuration
       7             : // it was determined by testing in https://github.com/jgromes/RadioLib/issues/1628
       8             : // see also https://github.com/radiolib-org/power-tests
       9             : static const SX126x::paTableEntry_t paOptimizedTable[RADIOLIB_SX126X_PA_TABLE_LEN] = {
      10             :   { .paDutyCycle = 2, .hpMax = 1, .paVal = -3 },
      11             :   { .paDutyCycle = 2, .hpMax = 1, .paVal = -2 },
      12             :   { .paDutyCycle = 1, .hpMax = 1, .paVal = 0 },
      13             :   { .paDutyCycle = 4, .hpMax = 1, .paVal = -1 },
      14             :   { .paDutyCycle = 2, .hpMax = 1, .paVal = 2 },
      15             :   { .paDutyCycle = 2, .hpMax = 2, .paVal = 0 },
      16             :   { .paDutyCycle = 2, .hpMax = 2, .paVal = 1 },
      17             :   { .paDutyCycle = 1, .hpMax = 2, .paVal = 3 },
      18             :   { .paDutyCycle = 1, .hpMax = 3, .paVal = 3 },
      19             :   { .paDutyCycle = 1, .hpMax = 2, .paVal = 5 },
      20             :   { .paDutyCycle = 1, .hpMax = 1, .paVal = 9 },
      21             :   { .paDutyCycle = 4, .hpMax = 1, .paVal = 8 },
      22             :   { .paDutyCycle = 2, .hpMax = 2, .paVal = 7 },
      23             :   { .paDutyCycle = 1, .hpMax = 1, .paVal = 13 },
      24             :   { .paDutyCycle = 4, .hpMax = 1, .paVal = 11 },
      25             :   { .paDutyCycle = 1, .hpMax = 1, .paVal = 19 },
      26             :   { .paDutyCycle = 2, .hpMax = 1, .paVal = 19 },
      27             :   { .paDutyCycle = 4, .hpMax = 1, .paVal = 17 },
      28             :   { .paDutyCycle = 1, .hpMax = 6, .paVal = 12 },
      29             :   { .paDutyCycle = 1, .hpMax = 2, .paVal = 16 },
      30             :   { .paDutyCycle = 4, .hpMax = 1, .paVal = 22 },
      31             :   { .paDutyCycle = 2, .hpMax = 2, .paVal = 18 },
      32             :   { .paDutyCycle = 1, .hpMax = 2, .paVal = 21 },
      33             :   { .paDutyCycle = 2, .hpMax = 2, .paVal = 21 },
      34             :   { .paDutyCycle = 3, .hpMax = 2, .paVal = 21 },
      35             :   { .paDutyCycle = 2, .hpMax = 3, .paVal = 20 },
      36             :   { .paDutyCycle = 1, .hpMax = 6, .paVal = 20 },
      37             :   { .paDutyCycle = 1, .hpMax = 5, .paVal = 22 },
      38             :   { .paDutyCycle = 2, .hpMax = 5, .paVal = 22 },
      39             :   { .paDutyCycle = 3, .hpMax = 5, .paVal = 22 },
      40             :   { .paDutyCycle = 3, .hpMax = 7, .paVal = 22 },
      41             :   { .paDutyCycle = 4, .hpMax = 7, .paVal = 22 },
      42             : };
      43             : 
      44           1 : SX1268::SX1268(Module* mod) : SX126x(mod) {
      45           1 :   chipType = RADIOLIB_SX1268_CHIP_TYPE;
      46           1 : }
      47             : 
      48           0 : int16_t SX1268::begin(const ConfigLoRa_t& cfg) {
      49           0 :   int16_t state = SX126x::begin(cfg.codingRate, cfg.syncWord, cfg.preambleLength);
      50           0 :   RADIOLIB_ASSERT(state);
      51             : 
      52             :   // configure publicly accessible settings
      53           0 :   state = setSpreadingFactor(cfg.spreadingFactor);
      54           0 :   RADIOLIB_ASSERT(state);
      55             : 
      56           0 :   state = setBandwidth(cfg.bandwidth);
      57           0 :   RADIOLIB_ASSERT(state);
      58             : 
      59           0 :   state = setFrequency(cfg.frequency);
      60           0 :   RADIOLIB_ASSERT(state);
      61             : 
      62           0 :   state = SX126x::fixPaClamping();
      63           0 :   RADIOLIB_ASSERT(state);
      64             : 
      65           0 :   state = setOutputPower(cfg.power);
      66           0 :   RADIOLIB_ASSERT(state);
      67             : 
      68           0 :   return(state);
      69             : }
      70             : 
      71           0 : int16_t SX1268::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
      72           0 :   ConfigLoRa_t cfg;
      73           0 :   cfg.frequency = freq;
      74           0 :   cfg.bandwidth = bw;
      75           0 :   cfg.spreadingFactor = sf;
      76           0 :   cfg.codingRate = cr;
      77           0 :   cfg.syncWord = syncWord;
      78           0 :   cfg.power = power;
      79           0 :   cfg.preambleLength = preambleLength;
      80           0 :   this->tcxoVoltage = tcxoVoltage;
      81           0 :   this->useRegulatorLDO = useRegulatorLDO;
      82           0 :   return(begin(cfg));
      83             : }
      84             : 
      85           0 : int16_t SX1268::beginFSK(const ConfigFSK_t& cfg) {
      86             :   // execute common part
      87           0 :   int16_t state = SX126x::beginFSK(cfg.bitRate, cfg.frequencyDeviation, cfg.receiverBandwidth, cfg.preambleLength);
      88           0 :   RADIOLIB_ASSERT(state);
      89             : 
      90             :   // configure publicly accessible settings
      91           0 :   state = setFrequency(cfg.frequency);
      92           0 :   RADIOLIB_ASSERT(state);
      93             : 
      94           0 :   state = SX126x::fixPaClamping();
      95           0 :   RADIOLIB_ASSERT(state);
      96             : 
      97           0 :   state = setOutputPower(cfg.power);
      98           0 :   RADIOLIB_ASSERT(state);
      99             : 
     100           0 :   return(state);
     101             : }
     102             : 
     103           0 : int16_t SX1268::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
     104           0 :   ConfigFSK_t cfg;
     105           0 :   cfg.frequency = freq;
     106           0 :   cfg.bitRate = br;
     107           0 :   cfg.frequencyDeviation = freqDev;
     108           0 :   cfg.receiverBandwidth = rxBw;
     109           0 :   cfg.power = power;
     110           0 :   cfg.preambleLength = preambleLength;
     111           0 :   this->tcxoVoltage = tcxoVoltage;
     112           0 :   this->useRegulatorLDO = useRegulatorLDO;
     113           0 :   return(beginFSK(cfg));
     114             : }
     115             : 
     116           0 : int16_t SX1268::beginBPSK(const ConfigBPSK_t& cfg) {
     117             :   // execute common part
     118           0 :   int16_t state = SX126x::beginBPSK(cfg.bitRate);
     119           0 :   RADIOLIB_ASSERT(state);
     120             : 
     121             :   // configure publicly accessible settings
     122           0 :   state = setFrequency(cfg.frequency);
     123           0 :   RADIOLIB_ASSERT(state);
     124             : 
     125           0 :   state = SX126x::fixPaClamping();
     126           0 :   RADIOLIB_ASSERT(state);
     127             : 
     128           0 :   state = setOutputPower(cfg.power);
     129           0 :   RADIOLIB_ASSERT(state);
     130             : 
     131           0 :   return(state);
     132             : }
     133             : 
     134           0 : int16_t SX1268::beginBPSK(float freq, float br, int8_t power, float tcxoVoltage, bool useRegulatorLDO) {
     135           0 :   ConfigBPSK_t cfg;
     136           0 :   cfg.frequency = freq;
     137           0 :   cfg.bitRate = br;
     138           0 :   cfg.power = power;
     139           0 :   this->tcxoVoltage = tcxoVoltage;
     140           0 :   this->useRegulatorLDO = useRegulatorLDO;
     141           0 :   return(beginBPSK(cfg));
     142             : }
     143             : 
     144           0 : int16_t SX1268::beginLRFHSS(const ConfigLRFHSS_t& cfg) {
     145             :   // execute common part
     146           0 :   int16_t state = SX126x::beginLRFHSS(cfg.bandwidth, cfg.codingRate, cfg.narrowGrid);
     147           0 :   RADIOLIB_ASSERT(state);
     148             : 
     149             :   // configure publicly accessible settings
     150           0 :   state = setFrequency(cfg.frequency);
     151           0 :   RADIOLIB_ASSERT(state);
     152             : 
     153           0 :   state = SX126x::fixPaClamping();
     154           0 :   RADIOLIB_ASSERT(state);
     155             : 
     156           0 :   state = setOutputPower(cfg.power);
     157           0 :   RADIOLIB_ASSERT(state);
     158             : 
     159           0 :   return(state);
     160             : }
     161             : 
     162           0 : int16_t SX1268::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, bool narrowGrid, int8_t power, float tcxoVoltage, bool useRegulatorLDO) {
     163           0 :   ConfigLRFHSS_t cfg;
     164           0 :   cfg.frequency = freq;
     165           0 :   cfg.bandwidth = bw;
     166           0 :   cfg.codingRate = cr;
     167           0 :   cfg.narrowGrid = narrowGrid;
     168           0 :   cfg.power = power;
     169           0 :   this->tcxoVoltage = tcxoVoltage;
     170           0 :   this->useRegulatorLDO = useRegulatorLDO;
     171           0 :   return(beginLRFHSS(cfg));
     172             : }
     173             : 
     174           1 : int16_t SX1268::setFrequency(float freq) {
     175           1 :   return(setFrequency(freq, false));
     176             : }
     177             : 
     178             : /// \todo integers only (all modules - frequency, data rate, bandwidth etc.)
     179           1 : int16_t SX1268::setFrequency(float freq, bool skipCalibration) {
     180           1 :   RADIOLIB_CHECK_RANGE(freq, 410.0f, 810.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
     181             : 
     182             :   // check if we need to recalibrate image
     183           0 :   if(!skipCalibration && (fabsf(freq - this->freqMHz) >= RADIOLIB_SX126X_CAL_IMG_FREQ_TRIG_MHZ)) {
     184           0 :     int16_t state = this->calibrateImage(freq);
     185           0 :     RADIOLIB_ASSERT(state);
     186             :   }
     187             : 
     188             :   // set frequency
     189           0 :   return(SX126x::setFrequencyRaw(freq));
     190             : }
     191             : 
     192           1 : int16_t SX1268::setOutputPower(int8_t power) {
     193           1 :   return(setOutputPower(power, true));
     194             : }
     195             : 
     196           1 : int16_t SX1268::setOutputPower(int8_t power, bool optimize) {
     197             :   // check if power value is configurable
     198           1 :   int16_t state = checkOutputPower(power, NULL);
     199           1 :   RADIOLIB_ASSERT(state);
     200             : 
     201             :   // set PA config
     202           1 :   SX126x::paTableEntry_t* paTable = this->paOptTable ? this->paOptTable : const_cast<SX126x::paTableEntry_t*>(paOptimizedTable);
     203           1 :   int8_t paVal = optimize ? paTable[power + 9].paVal : power;
     204           1 :   uint8_t paDutyCycle = optimize ? paTable[power + 9].paDutyCycle : 0x04;
     205           1 :   uint8_t hpMax = optimize ? paTable[power + 9].hpMax : 0x07;
     206           1 :   return(SX126x::setOutputPower(paVal, paDutyCycle, hpMax, RADIOLIB_SX126X_PA_CONFIG_SX1268));
     207             : }
     208             : 
     209           2 : int16_t SX1268::checkOutputPower(int8_t power, int8_t* clipped) {
     210           2 :   if(clipped) {
     211           0 :     *clipped = RADIOLIB_MAX(-9, RADIOLIB_MIN(22, power));
     212             :   }
     213           2 :   RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
     214           2 :   return(RADIOLIB_ERR_NONE);
     215             : }
     216             : 
     217           1 : int16_t SX1268::setModem(ModemType_t modem) {
     218           1 :   switch(modem) {
     219           0 :     case(ModemType_t::RADIOLIB_MODEM_LORA): {
     220           0 :       return(this->begin());
     221             :     } break;
     222           0 :     case(ModemType_t::RADIOLIB_MODEM_FSK): {
     223           0 :       return(this->beginFSK());
     224             :     } break;
     225           0 :     case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
     226           0 :       return(this->beginLRFHSS());
     227             :     } break;
     228           1 :     default:
     229           1 :       return(RADIOLIB_ERR_WRONG_MODEM);
     230             :   }
     231             : }
     232             : 
     233             : #endif

Generated by: LCOV version 1.14