LCOV - code coverage report
Current view: top level - src/modules/SX127x - SX1278.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 69 437 15.8 %
Date: 2026-02-22 10:42:45 Functions: 14 31 45.2 %

          Line data    Source code
       1             : #include "SX1278.h"
       2             : #include <math.h>
       3             : #if !RADIOLIB_EXCLUDE_SX127X
       4             : 
       5           3 : SX1278::SX1278(Module* mod) : SX127x(mod) {
       6             : 
       7           3 : }
       8             : 
       9           0 : int16_t SX1278::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, uint8_t gain) {
      10             :   // execute common part
      11           0 :   const uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
      12           0 :   int16_t state = SX127x::begin(versions, 3, syncWord, preambleLength);
      13           0 :   RADIOLIB_ASSERT(state);
      14             : 
      15             :   // configure publicly accessible settings
      16           0 :   state = setBandwidth(bw);
      17           0 :   RADIOLIB_ASSERT(state);
      18             : 
      19           0 :   state = setFrequency(freq);
      20           0 :   RADIOLIB_ASSERT(state);
      21             : 
      22           0 :   state = setSpreadingFactor(sf);
      23           0 :   RADIOLIB_ASSERT(state);
      24             : 
      25           0 :   state = setCodingRate(cr);
      26           0 :   RADIOLIB_ASSERT(state);
      27             : 
      28           0 :   state = setOutputPower(power);
      29           0 :   RADIOLIB_ASSERT(state);
      30             : 
      31           0 :   state = setGain(gain);
      32           0 :   RADIOLIB_ASSERT(state);
      33             : 
      34             :   // set publicly accessible settings that are not a part of begin method
      35           0 :   state = setCRC(true);
      36           0 :   RADIOLIB_ASSERT(state);
      37             : 
      38           0 :   return(state);
      39             : }
      40             : 
      41           0 : int16_t SX1278::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, bool enableOOK) {
      42             :   // execute common part
      43           0 :   const uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
      44           0 :   int16_t state = SX127x::beginFSK(versions, 3, freqDev, rxBw, preambleLength, enableOOK);
      45           0 :   RADIOLIB_ASSERT(state);
      46             : 
      47             :   // configure settings not accessible by API
      48           0 :   state = configFSK();
      49           0 :   RADIOLIB_ASSERT(state);
      50             : 
      51             :   // configure publicly accessible settings
      52           0 :   state = setFrequency(freq);
      53           0 :   RADIOLIB_ASSERT(state);
      54             : 
      55           0 :   state = setBitRate(br);
      56           0 :   RADIOLIB_ASSERT(state);
      57             : 
      58           0 :   state = setOutputPower(power);
      59           0 :   RADIOLIB_ASSERT(state);
      60             : 
      61           0 :   if(enableOOK) {
      62           0 :     state = setDataShapingOOK(RADIOLIB_SHAPING_NONE);
      63           0 :     RADIOLIB_ASSERT(state);
      64             :   } else {
      65           0 :     state = setDataShaping(RADIOLIB_SHAPING_NONE);
      66           0 :     RADIOLIB_ASSERT(state);
      67             :   }
      68             : 
      69             :   // set publicly accessible settings that are not a part of begin method
      70           0 :   state = setCRC(true);
      71           0 :   RADIOLIB_ASSERT(state);
      72             : 
      73           0 :   return(state);
      74             : }
      75             : 
      76           0 : void SX1278::reset() {
      77           0 :   Module* mod = this->getMod();
      78           0 :   mod->hal->pinMode(mod->getRst(), mod->hal->GpioModeOutput);
      79           0 :   mod->hal->digitalWrite(mod->getRst(), mod->hal->GpioLevelLow);
      80           0 :   mod->hal->delay(1);
      81           0 :   mod->hal->digitalWrite(mod->getRst(), mod->hal->GpioLevelHigh);
      82           0 :   mod->hal->delay(5);
      83           0 : }
      84             : 
      85           1 : int16_t SX1278::setFrequency(float freq) {
      86           1 :   RADIOLIB_CHECK_RANGE(freq, 137.0f, 525.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
      87             : 
      88             :   // set frequency and if successful, save the new setting
      89           0 :   int16_t state = SX127x::setFrequencyRaw(freq);
      90           0 :   if(state == RADIOLIB_ERR_NONE) {
      91           0 :     SX127x::frequency = freq;
      92             :   }
      93           0 :   return(state);
      94             : }
      95             : 
      96           0 : int16_t SX1278::setBandwidth(float bw) {
      97             :   // check active modem
      98           0 :   if(getActiveModem() != RADIOLIB_SX127X_LORA) {
      99           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     100             :   }
     101             : 
     102             :   uint8_t newBandwidth;
     103             : 
     104             :   // check allowed bandwidth values
     105           0 :   if(fabsf(bw - 7.8f) <= 0.001f) {
     106           0 :     newBandwidth = RADIOLIB_SX1278_BW_7_80_KHZ;
     107           0 :   } else if(fabsf(bw - 10.4f) <= 0.001f) {
     108           0 :     newBandwidth = RADIOLIB_SX1278_BW_10_40_KHZ;
     109           0 :   } else if(fabsf(bw - 15.6f) <= 0.001f) {
     110           0 :     newBandwidth = RADIOLIB_SX1278_BW_15_60_KHZ;
     111           0 :   } else if(fabsf(bw - 20.8f) <= 0.001f) {
     112           0 :     newBandwidth = RADIOLIB_SX1278_BW_20_80_KHZ;
     113           0 :   } else if(fabsf(bw - 31.25f) <= 0.001f) {
     114           0 :     newBandwidth = RADIOLIB_SX1278_BW_31_25_KHZ;
     115           0 :   } else if(fabsf(bw - 41.7f) <= 0.001f) {
     116           0 :     newBandwidth = RADIOLIB_SX1278_BW_41_70_KHZ;
     117           0 :   } else if(fabsf(bw - 62.5f) <= 0.001f) {
     118           0 :     newBandwidth = RADIOLIB_SX1278_BW_62_50_KHZ;
     119           0 :   } else if(fabsf(bw - 125.0f) <= 0.001f) {
     120           0 :     newBandwidth = RADIOLIB_SX1278_BW_125_00_KHZ;
     121           0 :   } else if(fabsf(bw - 250.0f) <= 0.001f) {
     122           0 :     newBandwidth = RADIOLIB_SX1278_BW_250_00_KHZ;
     123           0 :   } else if(fabsf(bw - 500.0f) <= 0.001f) {
     124           0 :     newBandwidth = RADIOLIB_SX1278_BW_500_00_KHZ;
     125             :   } else {
     126           0 :     return(RADIOLIB_ERR_INVALID_BANDWIDTH);
     127             :   }
     128             : 
     129             :   // set bandwidth and if successful, save the new setting
     130           0 :   int16_t state = SX1278::setBandwidthRaw(newBandwidth);
     131           0 :   if(state == RADIOLIB_ERR_NONE) {
     132           0 :     SX127x::bandwidth = bw;
     133             : 
     134             :     // calculate symbol length and set low data rate optimization, if auto-configuration is enabled
     135           0 :     if(this->ldroAuto) {
     136           0 :       float symbolLength = (float)(uint32_t(1) << SX127x::spreadingFactor) / (float)SX127x::bandwidth;
     137           0 :       Module* mod = this->getMod();
     138           0 :       if(symbolLength >= 16.0f) {
     139           0 :         this->ldroEnabled = true;
     140           0 :         state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_ON, 3, 3);
     141             :       } else {
     142           0 :         this->ldroEnabled = false;
     143           0 :         state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_OFF, 3, 3);
     144             :       }
     145             :     }
     146             :   }
     147           0 :   return(state);
     148             : }
     149             : 
     150           2 : int16_t SX1278::setSpreadingFactor(uint8_t sf) {
     151             :   // check active modem
     152           2 :   if(getActiveModem() != RADIOLIB_SX127X_LORA) {
     153           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     154             :   }
     155             : 
     156             :   uint8_t newSpreadingFactor;
     157             : 
     158             :   // check allowed spreading factor values
     159           2 :   switch(sf) {
     160           0 :     case 6:
     161           0 :       newSpreadingFactor = RADIOLIB_SX127X_SF_6;
     162           0 :       break;
     163           0 :     case 7:
     164           0 :       newSpreadingFactor = RADIOLIB_SX127X_SF_7;
     165           0 :       break;
     166           0 :     case 8:
     167           0 :       newSpreadingFactor = RADIOLIB_SX127X_SF_8;
     168           0 :       break;
     169           0 :     case 9:
     170           0 :       newSpreadingFactor = RADIOLIB_SX127X_SF_9;
     171           0 :       break;
     172           0 :     case 10:
     173           0 :       newSpreadingFactor = RADIOLIB_SX127X_SF_10;
     174           0 :       break;
     175           0 :     case 11:
     176           0 :       newSpreadingFactor = RADIOLIB_SX127X_SF_11;
     177           0 :       break;
     178           0 :     case 12:
     179           0 :       newSpreadingFactor = RADIOLIB_SX127X_SF_12;
     180           0 :       break;
     181           2 :     default:
     182           2 :       return(RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
     183             :   }
     184             : 
     185             :   // set spreading factor and if successful, save the new setting
     186           0 :   int16_t state = SX1278::setSpreadingFactorRaw(newSpreadingFactor);
     187           0 :   if(state == RADIOLIB_ERR_NONE) {
     188           0 :     SX127x::spreadingFactor = sf;
     189             : 
     190             :     // calculate symbol length and set low data rate optimization, if auto-configuration is enabled
     191           0 :     if(this->ldroAuto) {
     192           0 :       float symbolLength = (float)(uint32_t(1) << SX127x::spreadingFactor) / (float)SX127x::bandwidth;
     193           0 :       Module* mod = this->getMod();
     194           0 :       if(symbolLength >= 16.0f) {
     195           0 :         state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_ON, 3, 3);
     196             :       } else {
     197           0 :         state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_OFF, 3, 3);
     198             :       }
     199             :     }
     200             :   }
     201           0 :   return(state);
     202             : }
     203             : 
     204           0 : int16_t SX1278::setCodingRate(uint8_t cr) {
     205             :   // check active modem
     206           0 :   if(getActiveModem() != RADIOLIB_SX127X_LORA) {
     207           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     208             :   }
     209             : 
     210             :   uint8_t newCodingRate;
     211             : 
     212             :   // check allowed coding rate values
     213           0 :   switch(cr) {
     214           0 :     case 4:
     215           0 :       newCodingRate = RADIOLIB_SX1278_CR_4_4;
     216           0 :       break;
     217           0 :     case 5:
     218           0 :       newCodingRate = RADIOLIB_SX1278_CR_4_5;
     219           0 :       break;
     220           0 :     case 6:
     221           0 :       newCodingRate = RADIOLIB_SX1278_CR_4_6;
     222           0 :       break;
     223           0 :     case 7:
     224           0 :       newCodingRate = RADIOLIB_SX1278_CR_4_7;
     225           0 :       break;
     226           0 :     case 8:
     227           0 :       newCodingRate = RADIOLIB_SX1278_CR_4_8;
     228           0 :       break;
     229           0 :     default:
     230           0 :       return(RADIOLIB_ERR_INVALID_CODING_RATE);
     231             :   }
     232             : 
     233             :   // set coding rate and if successful, save the new setting
     234           0 :   int16_t state = SX1278::setCodingRateRaw(newCodingRate);
     235           0 :   if(state == RADIOLIB_ERR_NONE) {
     236           0 :     SX127x::codingRate = cr;
     237             :   }
     238           0 :   return(state);
     239             : }
     240             : 
     241           3 : int16_t SX1278::setBitRate(float br) {
     242           3 :   return(SX127x::setBitRateCommon(br, RADIOLIB_SX1278_REG_BIT_RATE_FRAC));
     243             : }
     244             : 
     245           2 : int16_t SX1278::setDataRate(DataRate_t dr, ModemType_t modem) {
     246             :   // get the current modem
     247             :   ModemType_t currentModem;
     248           2 :   int16_t state = this->getModem(&currentModem);
     249           2 :   RADIOLIB_ASSERT(state);
     250             : 
     251             :   // switch over if the requested modem is different
     252           2 :   if(modem != RADIOLIB_MODEM_NONE && modem != currentModem) {
     253           0 :     state = this->standby();
     254           0 :     RADIOLIB_ASSERT(state);
     255           0 :     state = this->setModem(modem);
     256           0 :     RADIOLIB_ASSERT(state);
     257             :   }
     258             :   
     259           2 :   if(modem == RADIOLIB_MODEM_NONE) {
     260           2 :     modem = currentModem;
     261             :   }
     262             : 
     263             :   // select interpretation based on modem
     264           2 :   if(modem == RADIOLIB_MODEM_FSK) {
     265             :     // set the bit rate
     266           0 :     state = this->setBitRate(dr.fsk.bitRate);
     267           0 :     RADIOLIB_ASSERT(state);
     268             : 
     269             :     // set the frequency deviation
     270           0 :     state = this->setFrequencyDeviation(dr.fsk.freqDev);
     271             : 
     272           2 :   } else if(modem == RADIOLIB_MODEM_LORA) {
     273             :     // set the spreading factor
     274           2 :     state = this->setSpreadingFactor(dr.lora.spreadingFactor);
     275           2 :     RADIOLIB_ASSERT(state);
     276             : 
     277             :     // set the bandwidth
     278           0 :     state = this->setBandwidth(dr.lora.bandwidth);
     279           0 :     RADIOLIB_ASSERT(state);
     280             : 
     281             :     // set the coding rate
     282           0 :     state = this->setCodingRate(dr.lora.codingRate);
     283             :   }
     284             : 
     285           0 :   return(state);
     286             : }
     287             : 
     288           2 : int16_t SX1278::checkDataRate(DataRate_t dr, ModemType_t modem) {
     289           2 :   int16_t state = RADIOLIB_ERR_UNKNOWN;
     290             : 
     291             :   // retrieve modem if not supplied
     292           2 :   if(modem == RADIOLIB_MODEM_NONE) {
     293           2 :     state = this->getModem(&modem);
     294           2 :     RADIOLIB_ASSERT(state);
     295             :   }
     296             : 
     297             :   // select interpretation based on modem
     298           2 :   if(modem == RADIOLIB_MODEM_FSK) {
     299           0 :     RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.5f, 300.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
     300           0 :     if(!((dr.fsk.freqDev + dr.fsk.bitRate/2.0f <= 250.0f) && (dr.fsk.freqDev <= 200.0f))) {
     301           0 :       return(RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
     302             :     }
     303           0 :     return(RADIOLIB_ERR_NONE);
     304             : 
     305           2 :   } else if(modem == RADIOLIB_MODEM_LORA) {
     306           2 :     RADIOLIB_CHECK_RANGE(dr.lora.spreadingFactor, 6, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
     307           0 :     RADIOLIB_CHECK_RANGE(dr.lora.bandwidth, 0.0f, 510.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
     308           0 :     RADIOLIB_CHECK_RANGE(dr.lora.codingRate, 4, 8, RADIOLIB_ERR_INVALID_CODING_RATE);
     309           0 :     return(RADIOLIB_ERR_NONE);
     310             :   
     311             :   }
     312             : 
     313           0 :   return(state);
     314             : }
     315             : 
     316           3 : int16_t SX1278::setOutputPower(int8_t power) {
     317           3 :   return(this->setOutputPower(power, false));
     318             : }
     319             : 
     320           3 : int16_t SX1278::setOutputPower(int8_t power, bool forceRfo) {
     321             :   // check if power value is configurable
     322           3 :   bool useRfo = (power < 2) || forceRfo;
     323           3 :   int16_t state = checkOutputPower(power, NULL, useRfo);
     324           3 :   RADIOLIB_ASSERT(state);
     325             : 
     326             :   // set mode to standby
     327           3 :   state = SX127x::standby();
     328           3 :   Module* mod = this->getMod();
     329             : 
     330           3 :   if(useRfo) {
     331           3 :     uint8_t paCfg = 0;
     332           3 :     if(power < 0) {
     333             :       // low power mode RFO output
     334           0 :       paCfg = RADIOLIB_SX1278_LOW_POWER | (power + 3);
     335             :     } else {
     336             :       // high power mode RFO output
     337           3 :       paCfg = RADIOLIB_SX1278_MAX_POWER | power;
     338             :     }
     339             : 
     340           3 :     state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX127X_PA_SELECT_RFO, 7, 7);
     341           3 :     state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, paCfg, 6, 0);
     342           3 :     state |= mod->SPIsetRegValue(RADIOLIB_SX1278_REG_PA_DAC, RADIOLIB_SX127X_PA_BOOST_OFF, 2, 0);
     343             : 
     344             :   } else {
     345           0 :     if(power != 20) {
     346             :       // power is 2 - 17 dBm, enable PA1 + PA2 on PA_BOOST
     347           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX127X_PA_SELECT_BOOST, 7, 7);
     348           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX1278_MAX_POWER | (power - 2), 6, 0);
     349           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX1278_REG_PA_DAC, RADIOLIB_SX127X_PA_BOOST_OFF, 2, 0);
     350             : 
     351             :     } else {
     352             :       // power is 20 dBm, enable PA1 + PA2 on PA_BOOST and enable high power control
     353           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX127X_PA_SELECT_BOOST, 7, 7);
     354           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_CONFIG, RADIOLIB_SX1278_MAX_POWER | 0x0F, 6, 0);
     355           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX1278_REG_PA_DAC, RADIOLIB_SX127X_PA_BOOST_ON, 2, 0);
     356             : 
     357             :     }
     358             :   }
     359             : 
     360           3 :   return(state);
     361             : }
     362             : 
     363           3 : int16_t SX1278::checkOutputPower(int8_t power, int8_t* clipped) {
     364           3 :   return(checkOutputPower(power, clipped, false));
     365             : }
     366             : 
     367           6 : int16_t SX1278::checkOutputPower(int8_t power, int8_t* clipped, bool useRfo) {
     368             :   // check allowed power range
     369           6 :   if(useRfo) {
     370             :     // RFO output
     371           3 :     if(clipped) {
     372           0 :       *clipped = RADIOLIB_MAX(-4, RADIOLIB_MIN(15, power));
     373             :     }
     374           3 :     RADIOLIB_CHECK_RANGE(power, -4, 15, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
     375             :   } else {
     376             :     // PA_BOOST output, check high-power operation
     377           3 :     if(clipped) {
     378           0 :       if(power != 20) {
     379           0 :         *clipped = RADIOLIB_MAX(2, RADIOLIB_MIN(17, power));
     380             :       } else {
     381           0 :         *clipped = 20;
     382             :       }
     383             :     }
     384           3 :     if(power != 20) {
     385           3 :       RADIOLIB_CHECK_RANGE(power, 2, 17, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
     386             :     }
     387             :   }
     388           3 :   return(RADIOLIB_ERR_NONE);
     389             : }
     390             : 
     391           0 : int16_t SX1278::setGain(uint8_t gain) {
     392             :   // check allowed range
     393           0 :   if(gain > 6) {
     394           0 :     return(RADIOLIB_ERR_INVALID_GAIN);
     395             :   }
     396             : 
     397             :   // set mode to standby
     398           0 :   int16_t state = SX127x::standby();
     399           0 :   Module* mod = this->getMod();
     400             : 
     401             :   // get modem
     402           0 :   int16_t modem = getActiveModem();
     403           0 :   if(modem == RADIOLIB_SX127X_LORA){
     404             :     // set gain
     405           0 :     if(gain == 0) {
     406             :       // gain set to 0, enable AGC loop
     407           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_AGC_AUTO_ON, 2, 2);
     408           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_LNA, RADIOLIB_SX127X_LNA_BOOST_ON, 1, 0);
     409             :     } else {
     410           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_AGC_AUTO_OFF, 2, 2);
     411           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_LNA, (gain << 5) | RADIOLIB_SX127X_LNA_BOOST_ON);
     412             :     }
     413             : 
     414           0 :   } else if(modem == RADIOLIB_SX127X_FSK_OOK) {
     415             :     // set gain
     416           0 :     if(gain == 0) {
     417             :       // gain set to 0, enable AGC loop
     418           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_RX_CONFIG, RADIOLIB_SX127X_AGC_AUTO_ON, 3, 3);
     419             :     } else {
     420           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_RX_CONFIG, RADIOLIB_SX1278_AGC_AUTO_OFF, 3, 3);
     421           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_LNA, (gain << 5) | RADIOLIB_SX127X_LNA_BOOST_ON);
     422             :     }
     423             : 
     424             :   }
     425             : 
     426           0 :   return(state);
     427             : }
     428             : 
     429           3 : int16_t SX1278::setDataShaping(uint8_t sh) {
     430             :   // check active modem
     431           3 :   if(getActiveModem() != RADIOLIB_SX127X_FSK_OOK) {
     432           3 :     return(RADIOLIB_ERR_WRONG_MODEM);
     433             :   }
     434             : 
     435             :   // check modulation
     436           0 :   if(SX127x::ookEnabled) {
     437             :     // we're in OOK mode, the only thing we can do is disable
     438           0 :     if(sh == RADIOLIB_SHAPING_NONE) {
     439           0 :       return(setDataShapingOOK(0));
     440             :     }
     441             : 
     442           0 :     return(RADIOLIB_ERR_INVALID_MODULATION);
     443             :   }
     444             : 
     445             :   // set mode to standby
     446           0 :   int16_t state = SX127x::standby();
     447           0 :   RADIOLIB_ASSERT(state);
     448             : 
     449             :   // set data shaping
     450           0 :   Module* mod = this->getMod();
     451           0 :   switch(sh) {
     452           0 :     case RADIOLIB_SHAPING_NONE:
     453           0 :       return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_NO_SHAPING, 6, 5));
     454           0 :     case RADIOLIB_SHAPING_0_3:
     455           0 :       return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_FSK_GAUSSIAN_0_3, 6, 5));
     456           0 :     case RADIOLIB_SHAPING_0_5:
     457           0 :       return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_FSK_GAUSSIAN_0_5, 6, 5));
     458           0 :     case RADIOLIB_SHAPING_1_0:
     459           0 :       return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_FSK_GAUSSIAN_1_0, 6, 5));
     460           0 :     default:
     461           0 :       return(RADIOLIB_ERR_INVALID_DATA_SHAPING);
     462             :   }
     463             : }
     464             : 
     465           0 : int16_t SX1278::setDataShapingOOK(uint8_t sh) {
     466             :   // check active modem
     467           0 :   if(getActiveModem() != RADIOLIB_SX127X_FSK_OOK) {
     468           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     469             :   }
     470             : 
     471             :   // check modulation
     472           0 :   if(!SX127x::ookEnabled) {
     473           0 :     return(RADIOLIB_ERR_INVALID_MODULATION);
     474             :   }
     475             : 
     476             :   // set mode to standby
     477           0 :   int16_t state = SX127x::standby();
     478             : 
     479             :   // set data shaping
     480           0 :   Module* mod = this->getMod();
     481           0 :   switch(sh) {
     482           0 :     case 0:
     483           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_NO_SHAPING, 6, 5);
     484           0 :       break;
     485           0 :     case 1:
     486           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_OOK_FILTER_BR, 6, 5);
     487           0 :       break;
     488           0 :     case 2:
     489           0 :       state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PA_RAMP, RADIOLIB_SX1278_OOK_FILTER_2BR, 6, 5);
     490           0 :       break;
     491           0 :     default:
     492           0 :       return(RADIOLIB_ERR_INVALID_DATA_SHAPING);
     493             :   }
     494             : 
     495           0 :   return(state);
     496             : }
     497             : 
     498           3 : float SX1278::getRSSI() {
     499           3 :   return(SX1278::getRSSI(true, false));
     500             : }
     501             : 
     502           3 : float SX1278::getRSSI(bool packet, bool skipReceive) {
     503           3 :   int16_t offset = -157;
     504           3 :   if(frequency < 868.0f) {
     505           3 :     offset = -164;
     506             :   }
     507           3 :   return(SX127x::getRSSI(packet, skipReceive, offset));
     508             : }
     509             : 
     510           0 : int16_t SX1278::setCRC(bool enable, bool mode) {
     511           0 :   Module* mod = this->getMod();
     512           0 :   if(getActiveModem() == RADIOLIB_SX127X_LORA) {
     513             :     // set LoRa CRC
     514           0 :     SX127x::crcEnabled = enable;
     515           0 :     if(enable) {
     516           0 :       return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX1278_RX_CRC_MODE_ON, 2, 2));
     517             :     } else {
     518           0 :       return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX1278_RX_CRC_MODE_OFF, 2, 2));
     519             :     }
     520             :   } else {
     521             :     // set FSK CRC
     522           0 :     int16_t state = RADIOLIB_ERR_NONE;
     523           0 :     if(enable) {
     524           0 :       state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_ON, 4, 4);
     525             :     } else {
     526           0 :       state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_OFF, 4, 4);
     527             :     }
     528           0 :     RADIOLIB_ASSERT(state);
     529             : 
     530             :     // set FSK CRC mode
     531           0 :     if(mode) {
     532           0 :       return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_WHITENING_TYPE_IBM, 0, 0));
     533             :     } else {
     534           0 :       return(mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, RADIOLIB_SX127X_CRC_WHITENING_TYPE_CCITT, 0, 0));
     535             :     }
     536             :   }
     537             : }
     538             : 
     539           0 : int16_t SX1278::forceLDRO(bool enable) {
     540           0 :   if(getActiveModem() != RADIOLIB_SX127X_LORA) {
     541           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     542             :   }
     543             : 
     544           0 :   Module* mod = this->getMod();
     545           0 :   this->ldroAuto = false;
     546           0 :   this->ldroEnabled = enable;
     547           0 :   if(enable) {
     548           0 :     return(mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_ON, 3, 3));
     549             :   } else {
     550           0 :     return(mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_OFF, 3, 3));
     551             :   }
     552             : }
     553             : 
     554           0 : int16_t SX1278::autoLDRO() {
     555           0 :   if(getActiveModem() != RADIOLIB_SX127X_LORA) {
     556           0 :     return(RADIOLIB_ERR_WRONG_MODEM);
     557             :   }
     558             : 
     559           0 :   this->ldroAuto = true;
     560           0 :   return(RADIOLIB_ERR_NONE);
     561             : }
     562             : 
     563           0 : int16_t SX1278::implicitHeader(size_t len) {
     564           0 :   this->implicitHdr = true;
     565           0 :   return(setHeaderType(RADIOLIB_SX1278_HEADER_IMPL_MODE, 0, len));
     566             : }
     567             : 
     568           0 : int16_t SX1278::explicitHeader() {
     569           0 :   this->implicitHdr = false;
     570           0 :   return(setHeaderType(RADIOLIB_SX1278_HEADER_EXPL_MODE, 0));
     571             : }
     572             : 
     573           0 : int16_t SX1278::setBandwidthRaw(uint8_t newBandwidth) {
     574             :   // set mode to standby
     575           0 :   int16_t state = SX127x::standby();
     576             : 
     577             :   // write register
     578           0 :   Module* mod = this->getMod();
     579           0 :   state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, newBandwidth, 7, 4);
     580           0 :   return(state);
     581             : }
     582             : 
     583           0 : int16_t SX1278::setSpreadingFactorRaw(uint8_t newSpreadingFactor) {
     584             :   // set mode to standby
     585           0 :   int16_t state = SX127x::standby();
     586             : 
     587             :   // write registers
     588           0 :   Module* mod = this->getMod();
     589           0 :   if(newSpreadingFactor == RADIOLIB_SX127X_SF_6) {
     590           0 :     this->implicitHdr = true;
     591           0 :     state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1278_HEADER_IMPL_MODE, 0, 0);
     592           0 :     state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX127X_SF_6 | RADIOLIB_SX127X_TX_MODE_SINGLE, 7, 3);
     593           0 :     state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECT_OPTIMIZE, RADIOLIB_SX127X_DETECT_OPTIMIZE_SF_6, 2, 0);
     594           0 :     state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECTION_THRESHOLD, RADIOLIB_SX127X_DETECTION_THRESHOLD_SF_6);
     595             :   } else {
     596           0 :     this->implicitHdr = false;
     597           0 :     state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1278_HEADER_EXPL_MODE, 0, 0);
     598           0 :     state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, newSpreadingFactor | RADIOLIB_SX127X_TX_MODE_SINGLE, 7, 3);
     599           0 :     state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECT_OPTIMIZE, RADIOLIB_SX127X_DETECT_OPTIMIZE_SF_7_12, 2, 0);
     600           0 :     state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECTION_THRESHOLD, RADIOLIB_SX127X_DETECTION_THRESHOLD_SF_7_12);
     601             :   }
     602           0 :   return(state);
     603             : }
     604             : 
     605           0 : int16_t SX1278::setCodingRateRaw(uint8_t newCodingRate) {
     606             :   // set mode to standby
     607           0 :   int16_t state = SX127x::standby();
     608             : 
     609             :   // write register
     610           0 :   Module* mod = this->getMod();
     611           0 :   state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, newCodingRate, 3, 1);
     612           0 :   return(state);
     613             : }
     614             : 
     615           0 : int16_t SX1278::configFSK() {
     616             :   // configure common registers
     617           0 :   int16_t state = SX127x::configFSK();
     618           0 :   RADIOLIB_ASSERT(state);
     619             : 
     620             :   // set fast PLL hop
     621           0 :   Module* mod = this->getMod();
     622           0 :   state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_PLL_HOP, RADIOLIB_SX127X_FAST_HOP_ON, 7, 7);
     623           0 :   return(state);
     624             : }
     625             : 
     626           0 : void SX1278::errataFix(bool rx) {
     627             :   // only apply in LoRa mode
     628           0 :   if(getActiveModem() != RADIOLIB_SX127X_LORA) {
     629           0 :     return;
     630             :   }
     631             : 
     632             :   // sensitivity optimization for 500kHz bandwidth
     633             :   // see SX1276/77/78 Errata, section 2.1 for details
     634           0 :   Module* mod = this->getMod();
     635           0 :   if(fabsf(SX127x::bandwidth - 500.0f) <= 0.001f) {
     636           0 :     if((frequency >= 862.0f) && (frequency <= 1020.0f)) {
     637           0 :       mod->SPIwriteRegister(0x36, 0x02);
     638           0 :       mod->SPIwriteRegister(0x3a, 0x64);
     639           0 :     } else if((frequency >= 410.0f) && (frequency <= 525.0f)) {
     640           0 :       mod->SPIwriteRegister(0x36, 0x02);
     641           0 :       mod->SPIwriteRegister(0x3a, 0x7F);
     642             :     }
     643             :   }
     644             : 
     645             :   // mitigation of receiver spurious response
     646             :   // see SX1276/77/78 Errata, section 2.3 for details
     647             : 
     648             :   // figure out what we need to set
     649           0 :   uint8_t fixedRegs[3] = { 0x00, 0x00, 0x00 };
     650           0 :   float rxFreq = frequency;
     651           0 :   if(fabsf(SX127x::bandwidth - 7.8f) <= 0.001f) {
     652           0 :     fixedRegs[0] = 0b00000000;
     653           0 :     fixedRegs[1] = 0x48;
     654           0 :     fixedRegs[2] = 0x00;
     655           0 :     rxFreq += 0.00781f;
     656           0 :   } else if(fabsf(SX127x::bandwidth - 10.4f) <= 0.001f) {
     657           0 :     fixedRegs[0] = 0b00000000;
     658           0 :     fixedRegs[1] = 0x44;
     659           0 :     fixedRegs[2] = 0x00;
     660           0 :     rxFreq += 0.01042f;
     661           0 :   } else if(fabsf(SX127x::bandwidth - 15.6f) <= 0.001f) {
     662           0 :     fixedRegs[0] = 0b00000000;
     663           0 :     fixedRegs[1] = 0x44;
     664           0 :     fixedRegs[2] = 0x00;
     665           0 :     rxFreq += 0.01562f;
     666           0 :   } else if(fabsf(SX127x::bandwidth - 20.8f) <= 0.001f) {
     667           0 :     fixedRegs[0] = 0b00000000;
     668           0 :     fixedRegs[1] = 0x44;
     669           0 :     fixedRegs[2] = 0x00;
     670           0 :     rxFreq += 0.02083f;
     671           0 :   } else if(fabsf(SX127x::bandwidth - 31.25f) <= 0.001f) {
     672           0 :     fixedRegs[0] = 0b00000000;
     673           0 :     fixedRegs[1] = 0x44;
     674           0 :     fixedRegs[2] = 0x00;
     675           0 :     rxFreq += 0.03125f;
     676           0 :   } else if(fabsf(SX127x::bandwidth - 41.7f) <= 0.001f) {
     677           0 :     fixedRegs[0] = 0b00000000;
     678           0 :     fixedRegs[1] = 0x44;
     679           0 :     fixedRegs[2] = 0x00;
     680           0 :     rxFreq += 0.04167f;
     681           0 :   } else if(fabsf(SX127x::bandwidth - 62.5f) <= 0.001f) {
     682           0 :     fixedRegs[0] = 0b00000000;
     683           0 :     fixedRegs[1] = 0x40;
     684           0 :     fixedRegs[2] = 0x00;
     685           0 :   } else if(fabsf(SX127x::bandwidth - 125.0f) <= 0.001f) {
     686           0 :     fixedRegs[0] = 0b00000000;
     687           0 :     fixedRegs[1] = 0x40;
     688           0 :     fixedRegs[2] = 0x00;
     689           0 :   } else if(fabsf(SX127x::bandwidth - 250.0f) <= 0.001f) {
     690           0 :     fixedRegs[0] = 0b00000000;
     691           0 :     fixedRegs[1] = 0x40;
     692           0 :     fixedRegs[2] = 0x00;
     693           0 :   } else if(fabsf(SX127x::bandwidth - 500.0f) <= 0.001f) {
     694           0 :     fixedRegs[0] = 0b10000000;
     695           0 :     fixedRegs[1] = mod->SPIreadRegister(0x2F);
     696           0 :     fixedRegs[2] = mod->SPIreadRegister(0x30);
     697             :   } else {
     698           0 :     return;
     699             :   }
     700             : 
     701             :   // first, go to standby
     702           0 :   standby();
     703             : 
     704             :   // shift the freqency up when receiving, or restore the original when transmitting
     705           0 :   if(rx) {
     706           0 :     SX127x::setFrequencyRaw(rxFreq);
     707             :   } else {
     708           0 :     SX127x::setFrequencyRaw(frequency);
     709             :   }
     710             : 
     711             :   // finally, apply errata fixes
     712           0 :   mod->SPIsetRegValue(0x31, fixedRegs[0], 7, 7);
     713           0 :   mod->SPIsetRegValue(0x2F, fixedRegs[1]);
     714           0 :   mod->SPIsetRegValue(0x30, fixedRegs[2]);
     715             : }
     716             : 
     717           1 : int16_t SX1278::setModem(ModemType_t modem) {
     718           1 :   switch(modem) {
     719           0 :     case(ModemType_t::RADIOLIB_MODEM_LORA): {
     720           0 :       return(this->begin());
     721             :     } break;
     722           0 :     case(ModemType_t::RADIOLIB_MODEM_FSK): {
     723           0 :       return(this->beginFSK());
     724             :     } break;
     725           1 :     default:
     726           1 :       return(RADIOLIB_ERR_WRONG_MODEM);
     727             :   }
     728             : }
     729             : 
     730             : #endif

Generated by: LCOV version 1.14