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;