From 76ac7d3dad557b1094fe0b82046e90bc914f1376 Mon Sep 17 00:00:00 2001 From: jgromes Date: Sun, 16 Jul 2023 15:50:26 +0200 Subject: [PATCH] [STM32WL] Fixed output power for modules without LP (#798) --- .../STM32WLx_Channel_Activity_Detection.ino | 19 ++++++- ...x_Channel_Activity_Detection_Interrupt.ino | 19 ++++++- .../STM32WLx_Receive_Blocking.ino | 2 + .../STM32WLx_Receive_Interrupt.ino | 2 + .../STM32WLx_Transmit_Blocking.ino | 2 + .../STM32WLx_Transmit_Interrupt.ino | 2 + src/modules/SX126x/STM32WLx.cpp | 53 ++++++++++++++----- src/modules/SX126x/STM32WLx.h | 3 +- 8 files changed, 86 insertions(+), 16 deletions(-) diff --git a/examples/STM32WLx/STM32WLx_Channel_Activity_Detection/STM32WLx_Channel_Activity_Detection.ino b/examples/STM32WLx/STM32WLx_Channel_Activity_Detection/STM32WLx_Channel_Activity_Detection.ino index ef511dc8..da070782 100644 --- a/examples/STM32WLx/STM32WLx_Channel_Activity_Detection/STM32WLx_Channel_Activity_Detection.ino +++ b/examples/STM32WLx/STM32WLx_Channel_Activity_Detection/STM32WLx_Channel_Activity_Detection.ino @@ -19,11 +19,28 @@ // no need to configure pins, signals are routed to the radio internally STM32WLx radio = new STM32WLx_Module(); +// set RF switch configuration for Nucleo WL55JC1 +// NOTE: other boards may be different! +// Some boards may not have either LP or HP. +// For those, do not set the LP/HP entry in the table. +static const uint32_t rfswitch_pins[] = + {PC3, PC4, PC5}; +static const Module::RfSwitchMode_t rfswitch_table[] = { + {STM32WLx::MODE_IDLE, {LOW, LOW, LOW}}, + {STM32WLx::MODE_RX, {HIGH, HIGH, LOW}}, + {STM32WLx::MODE_TX_LP, {HIGH, HIGH, HIGH}}, + {STM32WLx::MODE_TX_HP, {HIGH, LOW, HIGH}}, + END_OF_MODE_TABLE, +}; void setup() { Serial.begin(9600); - // initialize STM32WLx with default settings + // set RF switch control configuration + // this has to be done prior to calling begin() + radio.setRfSwitchTable(rfswitch_pins, rfswitch_table); + + // initialize STM32WLx with default settings, except frequency Serial.print(F("[STM32WLx] Initializing ... ")); int state = radio.begin(868.0); if (state == RADIOLIB_ERR_NONE) { diff --git a/examples/STM32WLx/STM32WLx_Channel_Activity_Detection_Interrupt/STM32WLx_Channel_Activity_Detection_Interrupt.ino b/examples/STM32WLx/STM32WLx_Channel_Activity_Detection_Interrupt/STM32WLx_Channel_Activity_Detection_Interrupt.ino index 374a41f1..9c14329d 100644 --- a/examples/STM32WLx/STM32WLx_Channel_Activity_Detection_Interrupt/STM32WLx_Channel_Activity_Detection_Interrupt.ino +++ b/examples/STM32WLx/STM32WLx_Channel_Activity_Detection_Interrupt/STM32WLx_Channel_Activity_Detection_Interrupt.ino @@ -19,11 +19,28 @@ // no need to configure pins, signals are routed to the radio internally STM32WLx radio = new STM32WLx_Module(); +// set RF switch configuration for Nucleo WL55JC1 +// NOTE: other boards may be different! +// Some boards may not have either LP or HP. +// For those, do not set the LP/HP entry in the table. +static const uint32_t rfswitch_pins[] = + {PC3, PC4, PC5}; +static const Module::RfSwitchMode_t rfswitch_table[] = { + {STM32WLx::MODE_IDLE, {LOW, LOW, LOW}}, + {STM32WLx::MODE_RX, {HIGH, HIGH, LOW}}, + {STM32WLx::MODE_TX_LP, {HIGH, HIGH, HIGH}}, + {STM32WLx::MODE_TX_HP, {HIGH, LOW, HIGH}}, + END_OF_MODE_TABLE, +}; void setup() { Serial.begin(9600); - // initialize STM32WLx with default settings + // set RF switch control configuration + // this has to be done prior to calling begin() + radio.setRfSwitchTable(rfswitch_pins, rfswitch_table); + + // initialize STM32WLx with default settings, except frequency Serial.print(F("[STM32WLx] Initializing ... ")); int state = radio.begin(868.0); if (state == RADIOLIB_ERR_NONE) { diff --git a/examples/STM32WLx/STM32WLx_Receive_Blocking/STM32WLx_Receive_Blocking.ino b/examples/STM32WLx/STM32WLx_Receive_Blocking/STM32WLx_Receive_Blocking.ino index ae2cbdb1..e2e90d62 100644 --- a/examples/STM32WLx/STM32WLx_Receive_Blocking/STM32WLx_Receive_Blocking.ino +++ b/examples/STM32WLx/STM32WLx_Receive_Blocking/STM32WLx_Receive_Blocking.ino @@ -37,6 +37,8 @@ STM32WLx radio = new STM32WLx_Module(); // set RF switch configuration for Nucleo WL55JC1 // NOTE: other boards may be different! +// Some boards may not have either LP or HP. +// For those, do not set the LP/HP entry in the table. static const uint32_t rfswitch_pins[] = {PC3, PC4, PC5}; static const Module::RfSwitchMode_t rfswitch_table[] = { diff --git a/examples/STM32WLx/STM32WLx_Receive_Interrupt/STM32WLx_Receive_Interrupt.ino b/examples/STM32WLx/STM32WLx_Receive_Interrupt/STM32WLx_Receive_Interrupt.ino index d8b0af71..6d91cea4 100644 --- a/examples/STM32WLx/STM32WLx_Receive_Interrupt/STM32WLx_Receive_Interrupt.ino +++ b/examples/STM32WLx/STM32WLx_Receive_Interrupt/STM32WLx_Receive_Interrupt.ino @@ -31,6 +31,8 @@ STM32WLx radio = new STM32WLx_Module(); // set RF switch configuration for Nucleo WL55JC1 // NOTE: other boards may be different! +// Some boards may not have either LP or HP. +// For those, do not set the LP/HP entry in the table. static const uint32_t rfswitch_pins[] = {PC3, PC4, PC5}; static const Module::RfSwitchMode_t rfswitch_table[] = { diff --git a/examples/STM32WLx/STM32WLx_Transmit_Blocking/STM32WLx_Transmit_Blocking.ino b/examples/STM32WLx/STM32WLx_Transmit_Blocking/STM32WLx_Transmit_Blocking.ino index 3d2e3540..d35680a3 100644 --- a/examples/STM32WLx/STM32WLx_Transmit_Blocking/STM32WLx_Transmit_Blocking.ino +++ b/examples/STM32WLx/STM32WLx_Transmit_Blocking/STM32WLx_Transmit_Blocking.ino @@ -32,6 +32,8 @@ STM32WLx radio = new STM32WLx_Module(); // set RF switch configuration for Nucleo WL55JC1 // NOTE: other boards may be different! +// Some boards may not have either LP or HP. +// For those, do not set the LP/HP entry in the table. static const uint32_t rfswitch_pins[] = {PC3, PC4, PC5}; static const Module::RfSwitchMode_t rfswitch_table[] = { diff --git a/examples/STM32WLx/STM32WLx_Transmit_Interrupt/STM32WLx_Transmit_Interrupt.ino b/examples/STM32WLx/STM32WLx_Transmit_Interrupt/STM32WLx_Transmit_Interrupt.ino index 527c897c..60777c02 100644 --- a/examples/STM32WLx/STM32WLx_Transmit_Interrupt/STM32WLx_Transmit_Interrupt.ino +++ b/examples/STM32WLx/STM32WLx_Transmit_Interrupt/STM32WLx_Transmit_Interrupt.ino @@ -23,6 +23,8 @@ STM32WLx radio = new STM32WLx_Module(); // set RF switch configuration for Nucleo WL55JC1 // NOTE: other boards may be different! +// Some boards may not have either LP or HP. +// For those, do not set the LP/HP entry in the table. static const uint32_t rfswitch_pins[] = {PC3, PC4, PC5}; static const Module::RfSwitchMode_t rfswitch_table[] = { diff --git a/src/modules/SX126x/STM32WLx.cpp b/src/modules/SX126x/STM32WLx.cpp index dcc8c822..095e13ec 100644 --- a/src/modules/SX126x/STM32WLx.cpp +++ b/src/modules/SX126x/STM32WLx.cpp @@ -44,21 +44,48 @@ int16_t STM32WLx::setOutputPower(int8_t power) { int16_t state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1); RADIOLIB_ASSERT(state); - // Use HP only if available and needed for the requested power + // check the user did not request power output that is not possible bool hp_supported = this->mod->findRfSwitchMode(MODE_TX_HP); - bool use_hp = power > 14 && hp_supported; - - // set PA config. - if(use_hp) { - RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER); - state = SX126x::setPaConfig(0x04, 0x00, 0x07); // HP output up to 22dBm - this->txMode = MODE_TX_HP; - } else { - RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER); - state = SX126x::setPaConfig(0x04, 0x01, 0x00); // LP output up to 14dBm - this->txMode = MODE_TX_LP; + bool lp_supported = this->mod->findRfSwitchMode(MODE_TX_LP); + if((!lp_supported && (power < -9)) || (!hp_supported && (power > 14))) { + // LP not supported but requested power is below HP low bound or + // HP not supported but requested power is above LP high bound + return(RADIOLIB_ERR_INVALID_OUTPUT_POWER); + } + + // set PA config based on which PAs are supported + bool use_hp = false; + if(hp_supported && lp_supported) { + // both PAs supported, use HP when above 14 dBm + if(power > 14) { + RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER); + state = SX126x::setPaConfig(0x04, 0x00, 0x07); // HP output up to 22dBm + this->txMode = MODE_TX_HP; + use_hp = true; + } else { + RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER); + state = SX126x::setPaConfig(0x04, 0x01, 0x00); // LP output up to 14dBm + this->txMode = MODE_TX_LP; + } + + } else if(!hp_supported && lp_supported) { + // only LP supported + RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER); + state = SX126x::setPaConfig(0x04, 0x01, 0x00); + this->txMode = MODE_TX_LP; + + } else if(hp_supported && !lp_supported) { + // only HP supported + RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER); + state = SX126x::setPaConfig(0x04, 0x00, 0x07); + this->txMode = MODE_TX_HP; + use_hp = true; + + } else { + // neither PA is supported + return(RADIOLIB_ERR_INVALID_OUTPUT_POWER); + } - RADIOLIB_ASSERT(state); // Apply workaround for HP only state = SX126x::fixPaClamping(use_hp); diff --git a/src/modules/SX126x/STM32WLx.h b/src/modules/SX126x/STM32WLx.h index 42e073a4..aa964917 100644 --- a/src/modules/SX126x/STM32WLx.h +++ b/src/modules/SX126x/STM32WLx.h @@ -82,7 +82,8 @@ class STM32WLx : public SX1262 { LP is preferred and supports -17 to +14dBm. When a higher power is requested (or the LP amplifier is marked as unavailable using - setRfSwitchTable()), HP is used, which supports -9 to +22dBm. + setRfSwitchTable()), HP is used, which supports -9 to +22dBm. If the LP is marked as unavailable, + HP output will be used instead. \param power Output power to be set in dBm.