[LR11x0] Fix output power configuration at S-band (#1128)

This commit is contained in:
jgromes 2024-06-21 17:53:11 +02:00
parent 87fac1797e
commit e406c550b8
6 changed files with 354 additions and 121 deletions

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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;
};

View file

@ -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) {

View file

@ -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);