diff --git a/src/modules/SX1261.cpp b/src/modules/SX1261.cpp new file mode 100644 index 00000000..15d6e1fa --- /dev/null +++ b/src/modules/SX1261.cpp @@ -0,0 +1,40 @@ +#include "SX1261.h" + +// note that this is untested (lacking the hardware) and based purely on the datasheet. +int16_t SX1261::setOutputPower(int8_t power) { + // check allowed power range + if (!((power >= -17) && (power <= 14))) { + return(ERR_INVALID_OUTPUT_POWER); + } + + // get current OCP configuration + uint8_t ocp = 0; + int16_t state = readRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1); + if (state != ERR_NONE) { + return(state); + } + + // set PA config for optimal consumption as described in section 13-21 of the datasheet: + // the final column of Table 13-21 suggests that the value passed in SetTxParams is actually scaled depending on the parameters of setPaConfig. However, testing suggests this isn't the case. + if (power > 10) { + state = SX126x::setPaConfig(0x04, 0x00, SX126X_PA_CONFIG_HP_MAX/*0x07*/); + } + else { + state = SX126x::setPaConfig(0x01, 0x00, 0x05); + } + if (state != ERR_NONE) { + return(state); + } + // TODO investigate if better power efficiency can be achieved using undocumented even lower settings + + // set output power + // TODO power ramp time configuration + state = SX126x::setTxParams(power); + if (state != ERR_NONE) { + return state; + } + + + // restore OCP configuration + return(writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1)); +} diff --git a/src/modules/SX1261.h b/src/modules/SX1261.h index cb8a5758..b9c8c741 100644 --- a/src/modules/SX1261.h +++ b/src/modules/SX1261.h @@ -11,6 +11,19 @@ #define SX126X_PA_CONFIG_SX1262 0x00 // TODO: implement SX1261 class -using SX1261 = SX1262; +class SX1261 : public SX1262 { +public: + /*! + \brief Default constructor. + + \param mod Instance of Module that will be used to communicate with the radio. + */ + SX1261(Module* mod) + : SX1262(mod) { + } + + int16_t setOutputPower(int8_t power); +}; + #endif diff --git a/src/modules/SX1262.cpp b/src/modules/SX1262.cpp index 0bcce47d..d2482593 100644 --- a/src/modules/SX1262.cpp +++ b/src/modules/SX1262.cpp @@ -85,7 +85,7 @@ int16_t SX1262::setFrequency(float freq, bool calibrate) { int16_t SX1262::setOutputPower(int8_t power) { // check allowed power range - if(!((power >= -17) && (power <= 22))) { + if(!((power >= -9) && (power <= 22))) { return(ERR_INVALID_OUTPUT_POWER); } @@ -96,16 +96,31 @@ int16_t SX1262::setOutputPower(int8_t power) { return(state); } - // enable high power PA for output power higher than 14 dBm - if(power > 13) { - SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1262); + // set PA config for optimal consumption as described in section 13-21 of the datasheet: + // the final column of Table 13-21 suggests that the value passed in SetTxParams is actually scaled depending on the parameters of setPaConfig. However, testing suggests this isn't the case. + if (power >= 21) { + state = SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1262, SX126X_PA_CONFIG_HP_MAX/*0x07*/); + } else if (power >= 18) { + state = SX126x::setPaConfig(0x03, SX126X_PA_CONFIG_SX1262, 0x05); + } else if (power >= 15) { + state = SX126x::setPaConfig(0x02, SX126X_PA_CONFIG_SX1262, 0x03); } else { - SX126x::setPaConfig(0x04, SX126X_PA_CONFIG_SX1261); + state = SX126x::setPaConfig(0x02, SX126X_PA_CONFIG_SX1262, 0x02); } + if (state != ERR_NONE) { + return(state); + } + // TODO investigate if better power efficiency can be achieved using undocumented even lower settings + + // note that we set SX126X_PA_CONFIG_SX1262 for all power levels - setting SX126X_PA_CONFIG_SX1261 causes no output (on the nameless module I have). // set output power // TODO power ramp time configuration - SX126x::setTxParams(power); + state = SX126x::setTxParams(power); + if (state != ERR_NONE) { + return state; + } + // restore OCP configuration return(writeRegister(SX126X_REG_OCP_CONFIGURATION, &ocp, 1));