diff --git a/src/modules/SX126x/SX1262.cpp b/src/modules/SX126x/SX1262.cpp index c4e20eb2..85253ab8 100644 --- a/src/modules/SX126x/SX1262.cpp +++ b/src/modules/SX126x/SX1262.cpp @@ -1,4 +1,6 @@ #include "SX1262.h" +#include + #if !RADIOLIB_EXCLUDE_SX126X SX1262::SX1262(Module* mod) : SX126x(mod) { @@ -66,49 +68,16 @@ int16_t SX1262::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, bool narrowGrid, } int16_t SX1262::setFrequency(float freq) { - return(setFrequency(freq, true)); + return(setFrequency(freq, false)); } -int16_t SX1262::setFrequency(float freq, bool calibrate) { +int16_t SX1262::setFrequency(float freq, bool skipCalibration) { RADIOLIB_CHECK_RANGE(freq, 150.0, 960.0, RADIOLIB_ERR_INVALID_FREQUENCY); - // calibrate image rejection - if(calibrate) { - uint8_t data[2] = { 0, 0 }; - - // try to match the frequency ranges - int freqBand = (int)freq; - if((freqBand >= 902) && (freqBand <= 928)) { - data[0] = RADIOLIB_SX126X_CAL_IMG_902_MHZ_1; - data[1] = RADIOLIB_SX126X_CAL_IMG_902_MHZ_2; - } else if((freqBand >= 863) && (freqBand <= 870)) { - data[0] = RADIOLIB_SX126X_CAL_IMG_863_MHZ_1; - data[1] = RADIOLIB_SX126X_CAL_IMG_863_MHZ_2; - } else if((freqBand >= 779) && (freqBand <= 787)) { - data[0] = RADIOLIB_SX126X_CAL_IMG_779_MHZ_1; - data[1] = RADIOLIB_SX126X_CAL_IMG_779_MHZ_2; - } else if((freqBand >= 470) && (freqBand <= 510)) { - data[0] = RADIOLIB_SX126X_CAL_IMG_470_MHZ_1; - data[1] = RADIOLIB_SX126X_CAL_IMG_470_MHZ_2; - } else if((freqBand >= 430) && (freqBand <= 440)) { - data[0] = RADIOLIB_SX126X_CAL_IMG_430_MHZ_1; - data[1] = RADIOLIB_SX126X_CAL_IMG_430_MHZ_2; - } - - int16_t state; - if(data[0]) { - // matched with predefined ranges, do the calibration - state = SX126x::calibrateImage(data); - - } else { - // if nothing matched, try custom calibration - the may or may not work - RADIOLIB_DEBUG_BASIC_PRINTLN("Failed to match predefined frequency range, trying custom"); - state = SX126x::calibrateImageRejection(freq - 4.0f, freq + 4.0f); - - } - + // check if we need to recalibrate image + if(!skipCalibration && (fabsf(freq - this->freqMHz) >= RADIOLIB_SX126X_CAL_IMG_FREQ_TRIG_MHZ)) { + int16_t state = this->calibrateImage(freq); RADIOLIB_ASSERT(state); - } // set frequency diff --git a/src/modules/SX126x/SX1262.h b/src/modules/SX126x/SX1262.h index 0dc27444..a7e0b677 100644 --- a/src/modules/SX126x/SX1262.h +++ b/src/modules/SX126x/SX1262.h @@ -81,6 +81,8 @@ class SX1262: public SX126x { /*! \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_SX126X_CAL_IMG_FREQ_TRIG MHz. \param freq Carrier frequency to be set in MHz. \returns \ref status_codes */ @@ -88,11 +90,13 @@ class SX1262: public SX126x { /*! \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_SX126X_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. \returns \ref status_codes */ - int16_t setFrequency(float freq, bool calibrate); + int16_t setFrequency(float freq, bool skipCalibration); /*! \brief Sets output power. Allowed values are in range from -9 to 22 dBm. diff --git a/src/modules/SX126x/SX1268.cpp b/src/modules/SX126x/SX1268.cpp index a8095b5a..6ae42ea8 100644 --- a/src/modules/SX126x/SX1268.cpp +++ b/src/modules/SX126x/SX1268.cpp @@ -1,4 +1,6 @@ #include "SX1268.h" +#include + #if !RADIOLIB_EXCLUDE_SX126X SX1268::SX1268(Module* mod) : SX126x(mod) { @@ -66,44 +68,17 @@ int16_t SX1268::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, bool narrowGrid, } int16_t SX1268::setFrequency(float freq) { - return(setFrequency(freq, true)); + return(setFrequency(freq, false)); } /// \todo integers only (all modules - frequency, data rate, bandwidth etc.) -int16_t SX1268::setFrequency(float freq, bool calibrate) { +int16_t SX1268::setFrequency(float freq, bool skipCalibration) { RADIOLIB_CHECK_RANGE(freq, 410.0, 810.0, RADIOLIB_ERR_INVALID_FREQUENCY); - // calibrate image rejection - if(calibrate) { - uint8_t data[2] = { 0, 0 }; - - // try to match the frequency ranges - int freqBand = (int)freq; - if((freqBand >= 779) && (freqBand <= 787)) { - data[0] = RADIOLIB_SX126X_CAL_IMG_779_MHZ_1; - data[1] = RADIOLIB_SX126X_CAL_IMG_779_MHZ_2; - } else if((freqBand >= 470) && (freqBand <= 510)) { - data[0] = RADIOLIB_SX126X_CAL_IMG_470_MHZ_1; - data[1] = RADIOLIB_SX126X_CAL_IMG_470_MHZ_2; - } else if((freqBand >= 430) && (freqBand <= 440)) { - data[0] = RADIOLIB_SX126X_CAL_IMG_430_MHZ_1; - data[1] = RADIOLIB_SX126X_CAL_IMG_430_MHZ_2; - } - - int16_t state; - if(data[0]) { - // matched with predefined ranges, do the calibration - state = SX126x::calibrateImage(data); - - } else { - // if nothing matched, try custom calibration - the may or may not work - RADIOLIB_DEBUG_BASIC_PRINTLN("Failed to match predefined frequency range, trying custom"); - state = SX126x::calibrateImageRejection(freq - 4.0f, freq + 4.0f); - - } - + // check if we need to recalibrate image + if(!skipCalibration && (fabsf(freq - this->freqMHz) >= RADIOLIB_SX126X_CAL_IMG_FREQ_TRIG_MHZ)) { + int16_t state = this->calibrateImage(freq); RADIOLIB_ASSERT(state); - } // set frequency diff --git a/src/modules/SX126x/SX1268.h b/src/modules/SX126x/SX1268.h index 87cf9b5c..c34bec8d 100644 --- a/src/modules/SX126x/SX1268.h +++ b/src/modules/SX126x/SX1268.h @@ -80,6 +80,8 @@ class SX1268: public SX126x { /*! \brief Sets carrier frequency. Allowed values are in range from 410.0 to 810.0 MHz. + Will automatically perform image calibration if the frequency changes by + more than RADIOLIB_SX126X_CAL_IMG_FREQ_TRIG MHz. \param freq Carrier frequency to be set in MHz. \returns \ref status_codes */ @@ -87,11 +89,13 @@ class SX1268: public SX126x { /*! \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_SX126X_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. \returns \ref status_codes */ - int16_t setFrequency(float freq, bool calibrate); + int16_t setFrequency(float freq, bool skipCalibration); /*! \brief Sets output power. Allowed values are in range from -9 to 22 dBm. diff --git a/src/modules/SX126x/SX126x.cpp b/src/modules/SX126x/SX126x.cpp index 3e3e2e31..8f8878c2 100644 --- a/src/modules/SX126x/SX126x.cpp +++ b/src/modules/SX126x/SX126x.cpp @@ -1954,6 +1954,43 @@ int16_t SX126x::setRfFrequency(uint32_t frf) { return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_RF_FREQUENCY, data, 4)); } +int16_t SX126x::calibrateImage(float freq) { + uint8_t data[2] = { 0, 0 }; + + // try to match the frequency ranges + int freqBand = (int)freq; + if((freqBand >= 902) && (freqBand <= 928)) { + data[0] = RADIOLIB_SX126X_CAL_IMG_902_MHZ_1; + data[1] = RADIOLIB_SX126X_CAL_IMG_902_MHZ_2; + } else if((freqBand >= 863) && (freqBand <= 870)) { + data[0] = RADIOLIB_SX126X_CAL_IMG_863_MHZ_1; + data[1] = RADIOLIB_SX126X_CAL_IMG_863_MHZ_2; + } else if((freqBand >= 779) && (freqBand <= 787)) { + data[0] = RADIOLIB_SX126X_CAL_IMG_779_MHZ_1; + data[1] = RADIOLIB_SX126X_CAL_IMG_779_MHZ_2; + } else if((freqBand >= 470) && (freqBand <= 510)) { + data[0] = RADIOLIB_SX126X_CAL_IMG_470_MHZ_1; + data[1] = RADIOLIB_SX126X_CAL_IMG_470_MHZ_2; + } else if((freqBand >= 430) && (freqBand <= 440)) { + data[0] = RADIOLIB_SX126X_CAL_IMG_430_MHZ_1; + data[1] = RADIOLIB_SX126X_CAL_IMG_430_MHZ_2; + } + + int16_t state; + if(data[0]) { + // matched with predefined ranges, do the calibration + state = SX126x::calibrateImage(data); + + } else { + // if nothing matched, try custom calibration - the may or may not work + RADIOLIB_DEBUG_BASIC_PRINTLN("Failed to match predefined frequency range, trying custom"); + state = SX126x::calibrateImageRejection(freq - 4.0f, freq + 4.0f); + + } + + return(state); +} + int16_t SX126x::calibrateImageRejection(float freqMin, float freqMax) { // calculate the calibration coefficients and calibrate image uint8_t data[] = { (uint8_t)floor((freqMin - 1.0f) / 4.0f), (uint8_t)ceil((freqMax + 1.0f) / 4.0f) }; @@ -2103,8 +2140,9 @@ int16_t SX126x::clearDeviceErrors() { int16_t SX126x::setFrequencyRaw(float freq) { // calculate raw value - this->frf = (freq * (uint32_t(1) << RADIOLIB_SX126X_DIV_EXPONENT)) / RADIOLIB_SX126X_CRYSTAL_FREQ; - return(setRfFrequency(this->frf)); + this->freqMHz = freq; + uint32_t frf = (this->freqMHz * (uint32_t(1) << RADIOLIB_SX126X_DIV_EXPONENT)) / RADIOLIB_SX126X_CRYSTAL_FREQ; + return(setRfFrequency(frf)); } int16_t SX126x::fixSensitivity() { diff --git a/src/modules/SX126x/SX126x.h b/src/modules/SX126x/SX126x.h index e6444072..d1ca5451 100644 --- a/src/modules/SX126x/SX126x.h +++ b/src/modules/SX126x/SX126x.h @@ -201,6 +201,7 @@ #define RADIOLIB_SX126X_CAL_IMG_863_MHZ_2 0xDB #define RADIOLIB_SX126X_CAL_IMG_902_MHZ_1 0xE1 #define RADIOLIB_SX126X_CAL_IMG_902_MHZ_2 0xE9 +#define RADIOLIB_SX126X_CAL_IMG_FREQ_TRIG_MHZ (20.0) //RADIOLIB_SX126X_CMD_SET_PA_CONFIG #define RADIOLIB_SX126X_PA_CONFIG_HP_MAX 0x07 @@ -1195,6 +1196,15 @@ class SX126x: public PhysicalLayer { */ int16_t setPaConfig(uint8_t paDutyCycle, uint8_t deviceSel, uint8_t hpMax = RADIOLIB_SX126X_PA_CONFIG_HP_MAX, uint8_t paLut = RADIOLIB_SX126X_PA_CONFIG_PA_LUT); + /*! + \brief Perform image rejection calibration for the specified frequency. + Will try to use Semtech-defined presets first, and if none of them matches, + custom iamge calibration will be attempted using calibrateImageRejection. + \param freq Frequency to perform the calibration for. + \returns \ref status_codes + */ + int16_t calibrateImage(float freq); + /*! \brief Perform image rejection calibration for the specified frequency band. WARNING: Use at your own risk! Setting incorrect values may lead to decreased performance @@ -1246,6 +1256,7 @@ class SX126x: public PhysicalLayer { #endif const char* chipType = NULL; uint8_t bandwidth = 0; + float freqMHz = 0; // Allow subclasses to define different TX modes uint8_t txMode = Module::MODE_TX; @@ -1276,7 +1287,6 @@ class SX126x: public PhysicalLayer { uint32_t tcxoDelay = 0; uint8_t pwr = 0; - uint32_t frf = 0; size_t implicitLen = 0; uint8_t invertIQEnabled = RADIOLIB_SX126X_LORA_IQ_STANDARD; diff --git a/src/modules/SX126x/SX126x_LR_FHSS.cpp b/src/modules/SX126x/SX126x_LR_FHSS.cpp index f7cae378..b0e8a2b8 100644 --- a/src/modules/SX126x/SX126x_LR_FHSS.cpp +++ b/src/modules/SX126x/SX126x_LR_FHSS.cpp @@ -355,7 +355,8 @@ int16_t SX126x::setLRFHSSHop(uint8_t index) { uint32_t nb_channel_in_grid = this->lrFhssGridNonFcc ? 8 : 52; uint32_t grid_offset = (1 + (this->lrFhssNgrid % 2)) * (nb_channel_in_grid / 2); uint32_t grid_in_pll_steps = this->lrFhssGridNonFcc ? 4096 : 26624; - uint32_t freq_raw = this->frf - freq_table * grid_in_pll_steps - grid_offset * 512; + uint32_t frf = (this->freqMHz * (uint32_t(1) << RADIOLIB_SX126X_DIV_EXPONENT)) / RADIOLIB_SX126X_CRYSTAL_FREQ; + uint32_t freq_raw = frf - freq_table * grid_in_pll_steps - grid_offset * 512; if((this->lrFhssHopNum < this->lrFhssHdrCount)) { if((((this->lrFhssHdrCount - this->lrFhssHopNum) % 2) == 0)) {