diff --git a/src/modules/LR11x0/LR1110.cpp b/src/modules/LR11x0/LR1110.cpp index 0950a3a3..26cbe2a7 100644 --- a/src/modules/LR11x0/LR1110.cpp +++ b/src/modules/LR11x0/LR1110.cpp @@ -1,4 +1,6 @@ #include "LR1110.h" +#include + #if !RADIOLIB_EXCLUDE_LR11X0 LR1110::LR1110(Module* mod) : LR11x0(mod) { @@ -45,20 +47,24 @@ int16_t LR1110::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, bool narrowGrid, } int16_t LR1110::setFrequency(float freq) { - return(this->setFrequency(freq, true)); + return(this->setFrequency(freq, false)); } -int16_t LR1110::setFrequency(float freq, bool calibrate, float band) { +int16_t LR1110::setFrequency(float freq, bool skipCalibration, float band) { RADIOLIB_CHECK_RANGE(freq, 150.0, 960.0, RADIOLIB_ERR_INVALID_FREQUENCY); - - // calibrate image rejection - if(calibrate) { - int16_t state = LR11x0::calibImage(freq - band, freq + band); + + // check if we need to recalibrate image + int16_t state; + if(!skipCalibration && (fabsf(freq - this->freqMHz) >= RADIOLIB_LR11X0_CAL_IMG_FREQ_TRIG_MHZ)) { + state = LR11x0::calibrateImageRejection(freq - band, freq + band); RADIOLIB_ASSERT(state); } // set frequency - return(LR11x0::setRfFrequency((uint32_t)(freq*1000000.0f))); + state = LR11x0::setRfFrequency((uint32_t)(freq*1000000.0f)); + RADIOLIB_ASSERT(state); + this->freqMHz = freq; + return(state); } int16_t LR1110::setOutputPower(int8_t power) { diff --git a/src/modules/LR11x0/LR1110.h b/src/modules/LR11x0/LR1110.h index bd7818f8..b2038859 100644 --- a/src/modules/LR11x0/LR1110.h +++ b/src/modules/LR11x0/LR1110.h @@ -71,7 +71,8 @@ class LR1110: public LR11x0 { /*! \brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz. - Will also perform calibrations. + Will automatically perform image calibration if the frequency changes by + more than RADIOLIB_LR11X0_CAL_IMG_FREQ_TRIG MHz. \param freq Carrier frequency to be set in MHz. \returns \ref status_codes */ @@ -79,14 +80,16 @@ class LR1110: public LR11x0 { /*! \brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz. + Will automatically perform image calibration if the frequency changes by + more than RADIOLIB_LR11X0_CAL_IMG_FREQ_TRIG MHz. \param freq Carrier frequency to be set in MHz. - \param calibrate Run image calibration. + \param skipCalibration Skip automated image calibration. \param band Half bandwidth for image calibration. For example, if carrier is 434 MHz and band is set to 4 MHz, then the image will be calibrate for band 430 - 438 MHz. Unused if calibrate is set to false, defaults to 4 MHz \returns \ref status_codes */ - int16_t setFrequency(float freq, bool calibrate, float band = 4); + int16_t setFrequency(float freq, bool skipCalibration, float band = 4); /*! \brief Sets output power. Allowed values are in range from -9 to 22 dBm (high-power PA) or -17 to 14 dBm (low-power PA). diff --git a/src/modules/LR11x0/LR1120.cpp b/src/modules/LR11x0/LR1120.cpp index ae4dc4a1..61294b7f 100644 --- a/src/modules/LR11x0/LR1120.cpp +++ b/src/modules/LR11x0/LR1120.cpp @@ -1,4 +1,6 @@ #include "LR1120.h" +#include + #if !RADIOLIB_EXCLUDE_LR11X0 LR1120::LR1120(Module* mod) : LR11x0(mod) { @@ -45,26 +47,27 @@ int16_t LR1120::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, bool narrowGrid, } int16_t LR1120::setFrequency(float freq) { - return(this->setFrequency(freq, true)); + return(this->setFrequency(freq, false)); } -int16_t LR1120::setFrequency(float freq, bool calibrate, float band) { +int16_t LR1120::setFrequency(float freq, bool skipCalibration, float band) { if(!(((freq >= 150.0) && (freq <= 960.0)) || ((freq >= 1900.0) && (freq <= 2200.0)) || ((freq >= 2400.0) && (freq <= 2500.0)))) { return(RADIOLIB_ERR_INVALID_FREQUENCY); } - // calibrate image rejection + // check if we need to recalibrate image int16_t state; - if(calibrate) { - state = LR11x0::calibImage(freq - band, freq + band); + if(!skipCalibration && (fabsf(freq - this->freqMHz) >= RADIOLIB_LR11X0_CAL_IMG_FREQ_TRIG_MHZ)) { + state = LR11x0::calibrateImageRejection(freq - band, freq + band); RADIOLIB_ASSERT(state); } // set frequency state = LR11x0::setRfFrequency((uint32_t)(freq*1000000.0f)); RADIOLIB_ASSERT(state); + this->freqMHz = freq; this->highFreq = (freq > 1000.0); return(RADIOLIB_ERR_NONE); } diff --git a/src/modules/LR11x0/LR1120.h b/src/modules/LR11x0/LR1120.h index dde24208..3c532ebd 100644 --- a/src/modules/LR11x0/LR1120.h +++ b/src/modules/LR11x0/LR1120.h @@ -71,7 +71,9 @@ class LR1120: public LR11x0 { /*! \brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz, - 1900 - 2200 MHz and 2400 - 2500 MHz. Will also perform calibrations. + 1900 - 2200 MHz and 2400 - 2500 MHz. + Will automatically perform image calibration if the frequency changes by + more than RADIOLIB_LR11X0_CAL_IMG_FREQ_TRIG MHz. NOTE: When switching between sub-GHz and high-frequency bands, after changing the frequency, setOutputPower() must be called in order to set the correct power amplifier! \param freq Carrier frequency to be set in MHz. @@ -81,17 +83,19 @@ class LR1120: public LR11x0 { /*! \brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz, - 1900 - 2200 MHz and 2400 - 2500 MHz. Will also perform calibrations. + 1900 - 2200 MHz and 2400 - 2500 MHz. + Will automatically perform image calibration if the frequency changes by + more than RADIOLIB_LR11X0_CAL_IMG_FREQ_TRIG MHz. NOTE: When switching between sub-GHz and high-frequency bands, after changing the frequency, setOutputPower() must be called in order to set the correct power amplifier! \param freq Carrier frequency to be set in MHz. - \param calibrate Run image calibration. + \param skipCalibration Skip automated image calibration. \param band Half bandwidth for image calibration. For example, if carrier is 434 MHz and band is set to 4 MHz, then the image will be calibrate for band 430 - 438 MHz. Unused if calibrate is set to false, defaults to 4 MHz \returns \ref status_codes */ - int16_t setFrequency(float freq, bool calibrate, float band = 4); + int16_t setFrequency(float freq, bool skipCalibration, float band = 4); /*! \brief Sets output power. Allowed values are in range from -9 to 22 dBm (high-power PA) or -17 to 14 dBm (low-power PA). diff --git a/src/modules/LR11x0/LR11x0.cpp b/src/modules/LR11x0/LR11x0.cpp index aaf00bfe..06686be2 100644 --- a/src/modules/LR11x0/LR11x0.cpp +++ b/src/modules/LR11x0/LR11x0.cpp @@ -2400,10 +2400,10 @@ int16_t LR11x0::setRegMode(uint8_t mode) { return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_REG_MODE, true, &mode, 1)); } -int16_t LR11x0::calibImage(float freq1, float freq2) { +int16_t LR11x0::calibrateImageRejection(float freqMin, float freqMax) { uint8_t buff[2] = { - (uint8_t)floor((freq1 - 1.0f) / 4.0f), - (uint8_t)ceil((freq2 + 1.0f) / 4.0f) + (uint8_t)floor((freqMin - 1.0f) / 4.0f), + (uint8_t)ceil((freqMax + 1.0f) / 4.0f) }; return(this->SPIcommand(RADIOLIB_LR11X0_CMD_CALIB_IMAGE, true, buff, sizeof(buff))); } diff --git a/src/modules/LR11x0/LR11x0.h b/src/modules/LR11x0/LR11x0.h index 490c1203..68a3f5de 100644 --- a/src/modules/LR11x0/LR11x0.h +++ b/src/modules/LR11x0/LR11x0.h @@ -233,6 +233,7 @@ #define RADIOLIB_LR11X0_CALIBRATE_HF_RC (0x01UL << 1) // 1 1 high frequency RC #define RADIOLIB_LR11X0_CALIBRATE_LF_RC (0x01UL << 0) // 0 0 low frequency RC #define RADIOLIB_LR11X0_CALIBRATE_ALL (0x3FUL << 0) // 5 0 everything +#define RADIOLIB_LR11X0_CAL_IMG_FREQ_TRIG_MHZ (20.0) // RADIOLIB_LR11X0_CMD_SET_REG_MODE #define RADIOLIB_LR11X0_REG_MODE_LDO (0x00UL << 0) // 0 0 regulator mode: LDO in all modes @@ -1609,6 +1610,15 @@ class LR11x0: public PhysicalLayer { \returns \ref status_codes */ int16_t getModem(ModemType_t* modem) override; + + /*! + \brief Perform image rejection calibration for the specified frequency band. + WARNING: Use at your own risk! Setting incorrect values may lead to decreased performance + \param freqMin Frequency band lower bound. + \param freqMax Frequency band upper bound. + \returns \ref status_codes + */ + int16_t calibrateImageRejection(float freqMin, float freqMax); #if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL protected: @@ -1629,7 +1639,6 @@ class LR11x0: public PhysicalLayer { int16_t clearErrors(void); int16_t calibrate(uint8_t params); int16_t setRegMode(uint8_t mode); - int16_t calibImage(float freq1, float freq2); int16_t setDioAsRfSwitch(uint8_t en, uint8_t stbyCfg, uint8_t rxCfg, uint8_t txCfg, uint8_t txHpCfg, uint8_t txHfCfg, uint8_t gnssCfg, uint8_t wifiCfg); int16_t setDioIrqParams(uint32_t irq1, uint32_t irq2); int16_t setDioIrqParams(uint32_t irq); @@ -1790,6 +1799,7 @@ class LR11x0: public PhysicalLayer { protected: #endif uint8_t chipType = 0; + float freqMHz = 0; #if !RADIOLIB_GODMODE private: