diff --git a/src/configuration.h b/src/configuration.h index 8ec3b2211d..1937b5dc3e 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -132,6 +132,10 @@ along with this program. If not, see . #endif // Default system gain to 0 if not defined +#ifndef NUM_PA_POINTS +#define NUM_PA_POINTS 1 +#endif + #ifndef TX_GAIN_LORA #define TX_GAIN_LORA 0 #endif diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 3c0da44944..fe047ec542 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -646,18 +646,24 @@ void RadioInterface::limitPower(int8_t loraMaxPower) power = maxPower; } -#ifndef NUM_PA_POINTS - if (TX_GAIN_LORA > 0 && !devicestate.owner.is_licensed) { - LOG_INFO("Requested Tx power: %d dBm; Device LoRa Tx gain: %d dB", power, TX_GAIN_LORA); - power -= TX_GAIN_LORA; - } +#ifdef ARCH_PORTDUINO + size_t num_pa_points = portduino_config.num_pa_points; + const uint16_t *tx_gain = portduino_config.tx_gain_lora; #else - if (!devicestate.owner.is_licensed) { + size_t num_pa_points = NUM_PA_POINTS; + const uint16_t tx_gain[NUM_PA_POINTS] = {TX_GAIN_LORA}; +#endif + + if (num_pa_points == 1) { + if (tx_gain[0] > 0 && !devicestate.owner.is_licensed) { + LOG_INFO("Requested Tx power: %d dBm; Device LoRa Tx gain: %d dB", power, tx_gain[0]); + power -= tx_gain[0]; + } + } else if (!devicestate.owner.is_licensed) { // we have an array of PA gain values. Find the highest power setting that works. - const uint16_t tx_gain[NUM_PA_POINTS] = {TX_GAIN_LORA}; - for (int radio_dbm = 0; radio_dbm < NUM_PA_POINTS; radio_dbm++) { + for (int radio_dbm = 0; radio_dbm < num_pa_points; radio_dbm++) { if (((radio_dbm + tx_gain[radio_dbm]) > power) || - ((radio_dbm == (NUM_PA_POINTS - 1)) && ((radio_dbm + tx_gain[radio_dbm]) <= power))) { + ((radio_dbm == (num_pa_points - 1)) && ((radio_dbm + tx_gain[radio_dbm]) <= power))) { // we've exceeded the power limit, or hit the max we can do LOG_INFO("Requested Tx power: %d dBm; Device LoRa Tx gain: %d dB", power, tx_gain[radio_dbm]); power -= tx_gain[radio_dbm]; @@ -665,7 +671,7 @@ void RadioInterface::limitPower(int8_t loraMaxPower) } } } -#endif + if (power > loraMaxPower) // Clamp power to maximum defined level power = loraMaxPower; diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 10b3a7fe47..825701a08d 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -544,6 +544,19 @@ bool loadConfig(const char *configPath) if (yamlConfig["Lora"]["RF95_MAX_POWER"]) portduino_config.rf95_max_power = yamlConfig["Lora"]["RF95_MAX_POWER"].as(20); + if (yamlConfig["Lora"]["TX_GAIN_LORA"]) { + YAML::Node tx_gain_node = yamlConfig["Lora"]["TX_GAIN_LORA"]; + if (tx_gain_node.IsSequence() && tx_gain_node.size() != 0) { + portduino_config.num_pa_points = min(tx_gain_node.size(), std::size(portduino_config.tx_gain_lora)); + for (int i = 0; i < portduino_config.num_pa_points; i++) { + portduino_config.tx_gain_lora[i] = tx_gain_node[i].as(); + } + } else { + portduino_config.num_pa_points = 1; + portduino_config.tx_gain_lora[0] = tx_gain_node.as(0); + } + } + if (portduino_config.lora_module != use_autoconf && portduino_config.lora_module != use_simradio && !portduino_config.force_simradio) { portduino_config.dio2_as_rf_switch = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as(false); diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 3fe017d5e1..ba7b3bb824 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -87,6 +87,8 @@ extern struct portduino_config_struct { int lora_usb_pid = 0x5512; int lora_usb_vid = 0x1A86; int spiSpeed = 2000000; + int num_pa_points = 1; // default to 1 point, with 0 gain + uint16_t tx_gain_lora[22] = {0}; pinMapping lora_cs_pin = {"Lora", "CS"}; pinMapping lora_irq_pin = {"Lora", "IRQ"}; pinMapping lora_busy_pin = {"Lora", "Busy"}; @@ -222,6 +224,17 @@ extern struct portduino_config_struct { out << YAML::Key << "LR1120_MAX_POWER" << YAML::Value << lr1120_max_power; if (rf95_max_power != 20) out << YAML::Key << "RF95_MAX_POWER" << YAML::Value << rf95_max_power; + + if (num_pa_points > 1) { + out << YAML::Key << "TX_GAIN_LORA" << YAML::Value << YAML::Flow << YAML::BeginSeq; + for (int i = 0; i < num_pa_points; i++) { + out << YAML::Value << tx_gain_lora[i]; + } + out << YAML::EndSeq; + } else if (tx_gain_lora[0] != 0) { + out << YAML::Key << "TX_GAIN_LORA" << YAML::Value << tx_gain_lora[0]; + } + out << YAML::Key << "DIO2_AS_RF_SWITCH" << YAML::Value << dio2_as_rf_switch; if (dio3_tcxo_voltage != 0) out << YAML::Key << "DIO3_TCXO_VOLTAGE" << YAML::Value << YAML::Precision(3) << (float)dio3_tcxo_voltage / 1000;