[LR11x0] Fix output power configuration at S-band (#1128)
This commit is contained in:
parent
87fac1797e
commit
e406c550b8
6 changed files with 354 additions and 121 deletions
|
@ -7,31 +7,40 @@ LR1110::LR1110(Module* mod) : LR11x0(mod) {
|
|||
|
||||
int16_t LR1110::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::begin(bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage);
|
||||
int16_t state = LR11x0::begin(bw, sf, cr, syncWord, preambleLength, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1110::beginGFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::beginGFSK(br, freqDev, rxBw, power, preambleLength, tcxoVoltage);
|
||||
int16_t state = LR11x0::beginGFSK(br, freqDev, rxBw, preambleLength, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1110::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, int8_t power, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::beginLRFHSS(bw, cr, power, tcxoVoltage);
|
||||
int16_t state = LR11x0::beginLRFHSS(bw, cr, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -52,4 +61,48 @@ int16_t LR1110::setFrequency(float freq, bool calibrate, float band) {
|
|||
return(LR11x0::setRfFrequency((uint32_t)(freq*1000000.0f)));
|
||||
}
|
||||
|
||||
int16_t LR1110::setOutputPower(int8_t power) {
|
||||
return(this->setOutputPower(power, false));
|
||||
}
|
||||
|
||||
int16_t LR1110::setOutputPower(int8_t power, bool forceHighPower) {
|
||||
// check if power value is configurable
|
||||
int16_t state = this->checkOutputPower(power, NULL, forceHighPower);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// determine whether to use HP or LP PA and check range accordingly
|
||||
bool useHp = forceHighPower || (power > 14);
|
||||
|
||||
// TODO how and when to configure OCP?
|
||||
|
||||
// update PA config - always use VBAT for high-power PA
|
||||
state = setPaConfig((uint8_t)useHp, (uint8_t)useHp, 0x04, 0x07);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set output power
|
||||
state = setTxParams(power, RADIOLIB_LR11X0_PA_RAMP_48U);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1110::checkOutputPower(int8_t power, int8_t* clipped) {
|
||||
return(checkOutputPower(power, clipped, false));
|
||||
}
|
||||
|
||||
int16_t LR1110::checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPower) {
|
||||
if(forceHighPower || (power > 14)) {
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(-9, RADIOLIB_MIN(22, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
|
||||
} else {
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(-17, RADIOLIB_MIN(14, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
|
||||
}
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -86,6 +86,41 @@ class LR1110: public LR11x0 {
|
|||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq, bool calibrate, 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).
|
||||
\param power Output power to be set in dBm, output PA is determined automatically preferring the low-power PA.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t power) override;
|
||||
|
||||
/*!
|
||||
\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).
|
||||
\param power Output power to be set in dBm.
|
||||
\param forceHighPower Force using the high-power PA. If set to false, PA will be determined automatically
|
||||
based on configured output power, preferring the low-power PA. If set to true, only high-power PA will be used.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t power, bool forceHighPower);
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
This method is needed for compatibility with PhysicalLayer::checkOutputPower.
|
||||
\param power Output power in dBm, PA will be determined automatically.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped) override;
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
\param power Output power in dBm.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\param forceHighPower Force using the high-power PA. If set to false, PA will be determined automatically
|
||||
based on configured output power, preferring the low-power PA. If set to true, only high-power PA will be used.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPower);
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
|
|
|
@ -7,31 +7,40 @@ LR1120::LR1120(Module* mod) : LR11x0(mod) {
|
|||
|
||||
int16_t LR1120::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::begin(bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage);
|
||||
int16_t state = LR11x0::begin(bw, sf, cr, syncWord, preambleLength, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1120::beginGFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::beginGFSK(br, freqDev, rxBw, power, preambleLength, tcxoVoltage);
|
||||
int16_t state = LR11x0::beginGFSK(br, freqDev, rxBw, preambleLength, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1120::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, int8_t power, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::beginLRFHSS(bw, cr, power, tcxoVoltage);
|
||||
int16_t state = LR11x0::beginLRFHSS(bw, cr, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
return(state);
|
||||
}
|
||||
|
||||
|
@ -47,13 +56,76 @@ int16_t LR1120::setFrequency(float freq, bool calibrate, float band) {
|
|||
}
|
||||
|
||||
// calibrate image rejection
|
||||
int16_t state;
|
||||
if(calibrate) {
|
||||
int16_t state = LR11x0::calibImage(freq - band, freq + band);
|
||||
state = LR11x0::calibImage(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->highFreq = (freq > 1000.0);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t LR1120::setOutputPower(int8_t power) {
|
||||
return(this->setOutputPower(power, false));
|
||||
}
|
||||
|
||||
int16_t LR1120::setOutputPower(int8_t power, bool forceHighPower) {
|
||||
// check if power value is configurable
|
||||
int16_t state = this->checkOutputPower(power, NULL, forceHighPower);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// determine whether to use HP or LP PA and check range accordingly
|
||||
uint8_t paSel = 0;
|
||||
uint8_t paSupply = 0;
|
||||
if(this->highFreq) {
|
||||
paSel = 2;
|
||||
} else if(forceHighPower || (power > 14)) {
|
||||
paSel = 1;
|
||||
paSupply = 1;
|
||||
}
|
||||
|
||||
// TODO how and when to configure OCP?
|
||||
|
||||
// update PA config - always use VBAT for high-power PA
|
||||
state = setPaConfig(paSel, paSupply, 0x04, 0x07);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set output power
|
||||
state = setTxParams(power, RADIOLIB_LR11X0_PA_RAMP_48U);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1120::checkOutputPower(int8_t power, int8_t* clipped) {
|
||||
return(checkOutputPower(power, clipped, false));
|
||||
}
|
||||
|
||||
int16_t LR1120::checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPower) {
|
||||
if(this->highFreq) {
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(-18, RADIOLIB_MIN(13, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, -18, 13, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
if(forceHighPower || (power > 14)) {
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(-9, RADIOLIB_MIN(22, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
|
||||
} else {
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(-17, RADIOLIB_MIN(14, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
|
||||
}
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -71,6 +71,8 @@ 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.
|
||||
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.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
|
@ -79,6 +81,8 @@ 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.
|
||||
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 band Half bandwidth for image calibration. For example,
|
||||
|
@ -88,9 +92,51 @@ class LR1120: public LR11x0 {
|
|||
*/
|
||||
int16_t setFrequency(float freq, bool calibrate, 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).
|
||||
\param power Output power to be set in dBm, output PA is determined automatically preferring the low-power PA.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t power) override;
|
||||
|
||||
/*!
|
||||
\brief Sets output power. Allowed values are in range from -9 to 22 dBm (high-power PA), -17 to 14 dBm (low-power PA)
|
||||
or -18 to 13 dBm (high-frequency PA).
|
||||
\param power Output power to be set in dBm.
|
||||
\param forceHighPower Force using the high-power PA in sub-GHz bands, or high-frequency PA in 2.4 GHz band.
|
||||
If set to false, PA will be determined automatically based on configured output power and frequency,
|
||||
preferring the low-power PA but always using high-frequency PA in 2.4 GHz band.
|
||||
Ignored when operating in 2.4 GHz band.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t power, bool forceHighPower);
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
This method is needed for compatibility with PhysicalLayer::checkOutputPower.
|
||||
\param power Output power in dBm, PA will be determined automatically.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped) override;
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
\param power Output power in dBm.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\param forceHighPower Force using the high-power PA. If set to false, PA will be determined automatically
|
||||
based on configured output power, preferring the low-power PA. If set to true, only high-power PA will be used.
|
||||
Ignored when operating in 2.4 GHz band.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPower);
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
// flag to determine whether we are in the sub-GHz or 2.4 GHz range
|
||||
// this is needed to automatically detect which PA to use
|
||||
bool highFreq = false;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ LR11x0::LR11x0(Module* mod) : PhysicalLayer(RADIOLIB_LR11X0_FREQUENCY_STEP_SIZE,
|
|||
this->XTAL = false;
|
||||
}
|
||||
|
||||
int16_t LR11x0::begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
|
||||
int16_t LR11x0::begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, uint16_t preambleLength, float tcxoVoltage) {
|
||||
// set module properties and perform initial setup
|
||||
int16_t state = this->modSetup(tcxoVoltage, RADIOLIB_LR11X0_PACKET_TYPE_LORA);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
@ -30,9 +30,6 @@ int16_t LR11x0::begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t
|
|||
|
||||
state = setSyncWord(syncWord);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setPreambleLength(preambleLength);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
@ -50,7 +47,7 @@ int16_t LR11x0::begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t
|
|||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t LR11x0::beginGFSK(float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
|
||||
int16_t LR11x0::beginGFSK(float br, float freqDev, float rxBw, uint16_t preambleLength, float tcxoVoltage) {
|
||||
// set module properties and perform initial setup
|
||||
int16_t state = this->modSetup(tcxoVoltage, RADIOLIB_LR11X0_PACKET_TYPE_GFSK);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
@ -64,9 +61,6 @@ int16_t LR11x0::beginGFSK(float br, float freqDev, float rxBw, int8_t power, uin
|
|||
|
||||
state = setRxBandwidth(rxBw);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setPreambleLength(preambleLength);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
@ -94,7 +88,7 @@ int16_t LR11x0::beginGFSK(float br, float freqDev, float rxBw, int8_t power, uin
|
|||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t LR11x0::beginLRFHSS(uint8_t bw, uint8_t cr, int8_t power, float tcxoVoltage) {
|
||||
int16_t LR11x0::beginLRFHSS(uint8_t bw, uint8_t cr, float tcxoVoltage) {
|
||||
// set module properties and perform initial setup
|
||||
int16_t state = this->modSetup(tcxoVoltage, RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
@ -103,9 +97,6 @@ int16_t LR11x0::beginLRFHSS(uint8_t bw, uint8_t cr, int8_t power, float tcxoVolt
|
|||
state = setLrFhssConfig(bw, cr);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setOutputPower(power);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = setSyncWord(0x12AD101B);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
|
@ -605,50 +596,6 @@ int16_t LR11x0::getChannelScanResult() {
|
|||
return(RADIOLIB_ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
int16_t LR11x0::setOutputPower(int8_t power) {
|
||||
return(this->setOutputPower(power, false));
|
||||
}
|
||||
|
||||
int16_t LR11x0::setOutputPower(int8_t power, bool forceHighPower) {
|
||||
// check if power value is configurable
|
||||
int16_t state = checkOutputPower(power, NULL, forceHighPower);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// determine whether to use HP or LP PA and check range accordingly
|
||||
bool useHp = forceHighPower || (power > 14);
|
||||
|
||||
// TODO how and when to configure OCP?
|
||||
|
||||
// update PA config - always use VBAT for high-power PA
|
||||
state = setPaConfig((uint8_t)useHp, (uint8_t)useHp, 0x04, 0x07);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set output power
|
||||
state = setTxParams(power, RADIOLIB_LR11X0_PA_RAMP_48U);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR11x0::checkOutputPower(int8_t power, int8_t* clipped) {
|
||||
return(checkOutputPower(power, clipped, false));
|
||||
}
|
||||
|
||||
int16_t LR11x0::checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPower) {
|
||||
if(forceHighPower || (power > 14)) {
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(-9, RADIOLIB_MIN(22, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
|
||||
} else {
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(-17, RADIOLIB_MIN(14, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
|
||||
}
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t LR11x0::setBandwidth(float bw) {
|
||||
// check active modem
|
||||
uint8_t type = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
|
||||
|
@ -1057,6 +1004,10 @@ int16_t LR11x0::setDataRate(DataRate_t dr) {
|
|||
|
||||
// set the coding rate
|
||||
state = this->setCodingRate(dr.lora.codingRate);
|
||||
|
||||
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
return(state);
|
||||
|
@ -1701,6 +1652,112 @@ int16_t LR11x0::updateFirmware(const uint32_t* image, size_t size, bool nonvolat
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR11x0::isGnssScanCapable() {
|
||||
// get the version
|
||||
LR11x0VersionInfo_t version;
|
||||
int16_t state = this->getVersionInfo(&version);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// check the device firmware version is sufficient
|
||||
uint16_t versionFull = ((uint16_t)version.fwMajor << 8) | (uint16_t)version.fwMinor;
|
||||
if((version.device == RADIOLIB_LR11X0_DEVICE_LR1110) && (versionFull >= 0x0401)) {
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
} else if((version.device == RADIOLIB_LR11X0_DEVICE_LR1120) && (versionFull >= 0x0201)) {
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
return(RADIOLIB_ERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
int16_t LR11x0::gnssScan(uint16_t* resSize) {
|
||||
// go to standby
|
||||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set DIO mapping
|
||||
state = setDioIrqParams(RADIOLIB_LR11X0_IRQ_GNSS_DONE, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
state = this->gnssSetConstellationToUse(0x03);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set scan mode
|
||||
state = this->gnssSetMode(0x03);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// start scan with high effort
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("GNSS scan start");
|
||||
state = this->gnssPerformScan(0x01, 0x3C, 8);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for scan finished or timeout
|
||||
RadioLibTime_t softTimeout = 300UL * 1000UL;
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
if(this->mod->hal->millis() - start > softTimeout) {
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout waiting for IRQ");
|
||||
this->standby();
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("GNSS scan done in %lu ms", (long unsigned int)(this->mod->hal->millis() - start));
|
||||
|
||||
state = this->clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
int8_t status = 0;
|
||||
uint8_t info = 0;
|
||||
state = this->gnssReadDemodStatus(&status, &info);
|
||||
RADIOLIB_ASSERT(state);
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Demod status %d, info %02x", (int)status, (unsigned int)info);
|
||||
|
||||
uint8_t fwVersion = 0;
|
||||
uint32_t almanacCrc = 0;
|
||||
uint8_t errCode = 0;
|
||||
uint8_t almUpdMask = 0;
|
||||
uint8_t freqSpace = 0;
|
||||
state = this->gnssGetContextStatus(&fwVersion, &almanacCrc, &errCode, &almUpdMask, &freqSpace);
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Context status fwVersion %d, almanacCrc %lx, errCode %d, almUpdMask %d, freqSpace %d",
|
||||
(int)fwVersion, (unsigned long)almanacCrc, (int)errCode, (int)almUpdMask, (int)freqSpace);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
uint8_t stat[53] = { 0 };
|
||||
state = this->gnssReadAlmanacStatus(stat);
|
||||
RADIOLIB_ASSERT(state);
|
||||
//Module::hexdump(NULL, stat, 53);
|
||||
|
||||
return(this->gnssGetResultSize(resSize));
|
||||
}
|
||||
|
||||
int16_t LR11x0::getGnssScanResult(uint16_t size) {
|
||||
// read the result
|
||||
uint8_t res[256] = { 0 };
|
||||
int16_t state = this->gnssReadResults(res, size);
|
||||
RADIOLIB_ASSERT(state);
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Result type: %02x", (int)res[0]);
|
||||
//Module::hexdump(NULL, res, size);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR11x0::getGnssPosition(float* lat, float* lon, bool filtered) {
|
||||
uint8_t error = 0;
|
||||
uint8_t nbSvUsed = 0;
|
||||
uint16_t accuracy = 0;
|
||||
int16_t state;
|
||||
if(filtered) {
|
||||
state = this->gnssReadDopplerSolverRes(&error, &nbSvUsed, NULL, NULL, NULL, NULL, lat, lon, &accuracy, NULL);
|
||||
} else {
|
||||
state = this->gnssReadDopplerSolverRes(&error, &nbSvUsed, lat, lon, &accuracy, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Solver error %d, nbSvUsed %d, accuracy = %u", (int)error, (int)nbSvUsed, (unsigned int)accuracy);
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR11x0::modSetup(float tcxoVoltage, uint8_t modem) {
|
||||
this->mod->init();
|
||||
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
|
||||
|
@ -2885,21 +2942,17 @@ int16_t LR11x0::gnssPushDmMsg(uint8_t* payload, size_t len) {
|
|||
}
|
||||
|
||||
int16_t LR11x0::gnssGetContextStatus(uint8_t* fwVersion, uint32_t* almanacCrc, uint8_t* errCode, uint8_t* almUpdMask, uint8_t* freqSpace) {
|
||||
// send the command
|
||||
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_CONTEXT_STATUS, true, NULL, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// read the result - this requires some magic bytes first, that's why LR11x0::SPIcommand cannot be used
|
||||
uint8_t cmd_buff[3] = { 0x00, 0x02, 0x18 };
|
||||
// send the command - datasheet here shows extra bytes being sent in the request
|
||||
// but doing that fails so treat it like any other read command
|
||||
uint8_t buff[9] = { 0 };
|
||||
state = this->mod->SPItransferStream(cmd_buff, sizeof(cmd_buff), false, NULL, buff, sizeof(buff), true);
|
||||
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_CONTEXT_STATUS, false, buff, sizeof(buff));
|
||||
|
||||
// pass the replies
|
||||
if(fwVersion) { *fwVersion = buff[0]; }
|
||||
if(almanacCrc) { *almanacCrc = ((uint32_t)(buff[1]) << 24) | ((uint32_t)(buff[2]) << 16) | ((uint32_t)(buff[3]) << 8) | (uint32_t)buff[4]; }
|
||||
if(errCode) { *errCode = (buff[5] & 0xF0) >> 4; }
|
||||
if(almUpdMask) { *almUpdMask = (buff[5] & 0x0E) >> 1; }
|
||||
if(freqSpace) { *freqSpace = ((buff[5] & 0x01) << 1) | ((buff[6] & 0x80) >> 7); }
|
||||
if(fwVersion) { *fwVersion = buff[2]; }
|
||||
if(almanacCrc) { *almanacCrc = ((uint32_t)(buff[3]) << 24) | ((uint32_t)(buff[4]) << 16) | ((uint32_t)(buff[5]) << 8) | (uint32_t)buff[6]; }
|
||||
if(errCode) { *errCode = (buff[7] & 0xF0) >> 4; }
|
||||
if(almUpdMask) { *almUpdMask = (buff[7] & 0x0E) >> 1; }
|
||||
if(freqSpace) { *freqSpace = ((buff[7] & 0x01) << 1) | ((buff[8] & 0x80) >> 7); }
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
@ -3000,10 +3053,10 @@ int16_t LR11x0::gnssGetSvVisible(uint32_t time, float lat, float lon, uint8_t co
|
|||
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_SV_VISIBLE, false, nbSv, 1, reqBuff, sizeof(reqBuff)));
|
||||
}
|
||||
|
||||
// TODO check version > 02.01
|
||||
int16_t LR11x0::gnssScan(uint8_t effort, uint8_t resMask, uint8_t nbSvMax) {
|
||||
int16_t LR11x0::gnssPerformScan(uint8_t effort, uint8_t resMask, uint8_t nbSvMax) {
|
||||
uint8_t buff[3] = { effort, resMask, nbSvMax };
|
||||
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_SCAN, true, buff, sizeof(buff)));
|
||||
// call the SPI write stream directly to skip waiting for BUSY - it will be set to high once the scan starts
|
||||
return(this->mod->SPIwriteStream(RADIOLIB_LR11X0_CMD_GNSS_SCAN, buff, sizeof(buff), false, false));
|
||||
}
|
||||
|
||||
int16_t LR11x0::gnssReadLastScanModeLaunched(uint8_t* lastScanMode) {
|
||||
|
|
|
@ -700,6 +700,10 @@ struct LR11x0VersionInfo_t {
|
|||
uint8_t almanacGNSS;
|
||||
};
|
||||
|
||||
struct LR11x0GnssResult_t {
|
||||
|
||||
};
|
||||
|
||||
/*!
|
||||
\class LR11x0
|
||||
\brief Base class for %LR11x0 series. All derived classes for %LR11x0 (e.g. LR1110 or LR1120) inherit from this base class.
|
||||
|
@ -753,34 +757,31 @@ class LR11x0: public PhysicalLayer {
|
|||
\param sf LoRa spreading factor.
|
||||
\param cr LoRa coding rate denominator.
|
||||
\param syncWord 1-byte LoRa sync word.
|
||||
\param power Output power in dBm.
|
||||
\param preambleLength LoRa preamble length in symbols
|
||||
\param tcxoVoltage TCXO reference voltage to be set.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage);
|
||||
int16_t begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, uint16_t preambleLength, float tcxoVoltage);
|
||||
|
||||
/*!
|
||||
\brief Initialization method for FSK modem.
|
||||
\param br FSK bit rate in kbps.
|
||||
\param freqDev Frequency deviation from carrier frequency in kHz.
|
||||
\param rxBw Receiver bandwidth in kHz.
|
||||
\param power Output power in dBm.
|
||||
\param preambleLength FSK preamble length in bits.
|
||||
\param tcxoVoltage TCXO reference voltage to be set.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginGFSK(float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage);
|
||||
int16_t beginGFSK(float br, float freqDev, float rxBw, uint16_t preambleLength, float tcxoVoltage);
|
||||
|
||||
/*!
|
||||
\brief Initialization method for LR-FHSS modem.
|
||||
\param bw LR-FHSS bandwidth, one of RADIOLIB_LR11X0_LR_FHSS_BW_* values.
|
||||
\param cr LR-FHSS coding rate, one of RADIOLIB_LR11X0_LR_FHSS_CR_* values.
|
||||
\param power Output power in dBm.
|
||||
\param tcxoVoltage TCXO reference voltage to be set.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginLRFHSS(uint8_t bw, uint8_t cr, int8_t power, float tcxoVoltage);
|
||||
int16_t beginLRFHSS(uint8_t bw, uint8_t cr, float tcxoVoltage);
|
||||
|
||||
/*!
|
||||
\brief Reset method. Will reset the chip to the default state using RST pin.
|
||||
|
@ -980,41 +981,6 @@ class LR11x0: public PhysicalLayer {
|
|||
int16_t getChannelScanResult() override;
|
||||
|
||||
// configuration methods
|
||||
|
||||
/*!
|
||||
\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).
|
||||
\param power Output power to be set in dBm, output PA is determined automatically preferring the low-power PA.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t power) override;
|
||||
|
||||
/*!
|
||||
\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).
|
||||
\param power Output power to be set in dBm.
|
||||
\param forceHighPower Force using the high-power PA. If set to false, PA will be determined automatically
|
||||
based on configured output power, preferring the low-power PA. If set to true, only high-power PA will be used.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t power, bool forceHighPower);
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
This method is needed for compatibility with PhysicalLayer::checkOutputPower.
|
||||
\param power Output power in dBm, PA will be determined automatically.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped) override;
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
\param power Output power in dBm.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\param forceHighPower Force using the high-power PA. If set to false, PA will be determined automatically
|
||||
based on configured output power, preferring the low-power PA. If set to true, only high-power PA will be used.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPower);
|
||||
|
||||
/*!
|
||||
\brief Sets LoRa bandwidth. Allowed values are 62.5, 125.0, 250.0 and 500.0 kHz.
|
||||
|
@ -1392,6 +1358,14 @@ class LR11x0: public PhysicalLayer {
|
|||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t updateFirmware(const uint32_t* image, size_t size, bool nonvolatile = true);
|
||||
|
||||
int16_t isGnssScanCapable();
|
||||
|
||||
int16_t gnssScan(uint16_t* resSize);
|
||||
|
||||
int16_t getGnssScanResult(uint16_t size);
|
||||
|
||||
int16_t getGnssPosition(float* lat, float* lon, bool filtered);
|
||||
|
||||
#if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
|
||||
protected:
|
||||
|
@ -1514,7 +1488,7 @@ class LR11x0: public PhysicalLayer {
|
|||
int16_t gnssAlmanacFullUpdateHeader(uint16_t date, uint32_t globalCrc);
|
||||
int16_t gnssAlmanacFullUpdateSV(uint8_t svn, uint8_t* svnAlmanac);
|
||||
int16_t gnssGetSvVisible(uint32_t time, float lat, float lon, uint8_t constellation, uint8_t* nbSv);
|
||||
int16_t gnssScan(uint8_t effort, uint8_t resMask, uint8_t nbSvMax);
|
||||
int16_t gnssPerformScan(uint8_t effort, uint8_t resMask, uint8_t nbSvMax);
|
||||
int16_t gnssReadLastScanModeLaunched(uint8_t* lastScanMode);
|
||||
int16_t gnssFetchTime(uint8_t effort, uint8_t opt);
|
||||
int16_t gnssReadTime(uint8_t* err, uint32_t* time, uint32_t* nbUs, uint32_t* timeAccuracy);
|
||||
|
|
Loading…
Add table
Reference in a new issue