LCOV - code coverage report
Current view: top level - src/modules/SX127x - SX1278.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 63 389 16.2 %
Date: 2026-11-08 19:43:08 Functions: 13 28 46.4 %

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

Generated by: LCOV version 1.14