[SX126x] Calibrate image based on frequency change (#1292)
This commit is contained in:
parent
28360f9b0f
commit
b8b1afdae1
7 changed files with 79 additions and 78 deletions
|
@ -1,4 +1,6 @@
|
|||
#include "SX1262.h"
|
||||
#include <math.h>
|
||||
|
||||
#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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include "SX1268.h"
|
||||
#include <math.h>
|
||||
|
||||
#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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
Loading…
Add table
Reference in a new issue