From 6b34d72fba10fc73320e9d4aac477135af6d744d Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Tue, 24 Feb 2026 16:45:06 -0600 Subject: [PATCH] Add GPIO_DETECT_PA portduino config, and support 13302 detection with it. --- bin/config.d/lora-hat-rak-6421-pi-hat.yaml | 2 ++ bin/config.d/lora-usb-umesh-1262-30dbm.yaml | 3 +-- bin/config.d/lora-usb-umesh-1268-30dbm.yaml | 3 +-- src/platform/portduino/PortduinoGlue.cpp | 26 +++++++++++++++++++++ src/platform/portduino/PortduinoGlue.h | 9 ++++++- 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/bin/config.d/lora-hat-rak-6421-pi-hat.yaml b/bin/config.d/lora-hat-rak-6421-pi-hat.yaml index 066e36a10..80df34ca7 100644 --- a/bin/config.d/lora-hat-rak-6421-pi-hat.yaml +++ b/bin/config.d/lora-hat-rak-6421-pi-hat.yaml @@ -9,3 +9,5 @@ Lora: DIO3_TCXO_VOLTAGE: true DIO2_AS_RF_SWITCH: true spidev: spidev0.0 + GPIO_DETECT_PA: 13 + TX_GAIN_LORA: [8, 8, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 8, 8, 7] \ No newline at end of file diff --git a/bin/config.d/lora-usb-umesh-1262-30dbm.yaml b/bin/config.d/lora-usb-umesh-1262-30dbm.yaml index 7726eccd1..8b32c5af2 100644 --- a/bin/config.d/lora-usb-umesh-1262-30dbm.yaml +++ b/bin/config.d/lora-usb-umesh-1262-30dbm.yaml @@ -13,8 +13,7 @@ Lora: # USB_Serialnum: 12345678 SX126X_MAX_POWER: 22 # Reduce output power to improve EMI - NUM_PA_POINTS: 22 - TX_GAIN_LORA: 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 8, 8, 7 + TX_GAIN_LORA: [12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 8, 8, 7] # Note: This module integrates an additional PA to achieve higher output power. # The 'power' parameter here does not represent the actual RF output. # TX_GAIN_LORA defines the gain offset applied at each SX1262 input power step (1–22 dBm). diff --git a/bin/config.d/lora-usb-umesh-1268-30dbm.yaml b/bin/config.d/lora-usb-umesh-1268-30dbm.yaml index c054a92f9..df772184c 100644 --- a/bin/config.d/lora-usb-umesh-1268-30dbm.yaml +++ b/bin/config.d/lora-usb-umesh-1268-30dbm.yaml @@ -13,8 +13,7 @@ Lora: # USB_Serialnum: 12345678 SX126X_MAX_POWER: 22 # Reduce output power to improve EMI - NUM_PA_POINTS: 22 - TX_GAIN_LORA: 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 8, 8, 7 + TX_GAIN_LORA: [12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 8, 8, 7] # Note: This module integrates an additional PA to achieve higher output power. # The 'power' parameter here does not represent the actual RF output. # TX_GAIN_LORA defines the gain offset applied at each SX1262 input power step (1–22 dBm). diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 3f0b2147c..92d10f0d2 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -537,6 +537,27 @@ void portduinoSetup() } } + // In one test, this dance seemed necessary to trigger the pin to detect properly. + if (portduino_config.has_gpio_detect_pa) { + pinMode(portduino_config.lora_pa_detect_pin.pin, INPUT_PULLDOWN); + sleep(1); + if (digitalRead(portduino_config.lora_pa_detect_pin.pin) == LOW) { + std::cout << "Pin " << portduino_config.lora_pa_detect_pin.pin << " PULLDOWN is LOW" << std::endl; + } + pinMode(portduino_config.lora_pa_detect_pin.pin, INPUT_PULLUP); + sleep(1); + if (digitalRead(portduino_config.lora_pa_detect_pin.pin) == HIGH) { + std::cout << "Pin " << portduino_config.lora_pa_detect_pin.pin << " PULLUP is HIGH, dropping PA curve" << std::endl; + portduino_config.num_pa_points = 1; + portduino_config.tx_gain_lora[0] = 0; + } else { + std::cout << "Pin " << portduino_config.lora_pa_detect_pin.pin << " PULLUP is LOW, using PA curve" << std::endl; + } + + // disable bias once finished + pinMode(portduino_config.lora_pa_detect_pin.pin, INPUT); + } + // Only initialize the radio pins when dealing with real, kernel controlled SPI hardware if (portduino_config.lora_spi_dev != "" && portduino_config.lora_spi_dev != "ch341") { SPI.begin(portduino_config.lora_spi_dev.c_str()); @@ -660,6 +681,11 @@ bool loadConfig(const char *configPath) portduino_config.lr1120_max_power = yamlConfig["Lora"]["LR1120_MAX_POWER"].as(13); if (yamlConfig["Lora"]["RF95_MAX_POWER"]) portduino_config.rf95_max_power = yamlConfig["Lora"]["RF95_MAX_POWER"].as(20); + if (yamlConfig["Lora"]["GPIO_DETECT_PA"]) { + portduino_config.has_gpio_detect_pa = true; + portduino_config.gpio_detect_pa = yamlConfig["Lora"]["GPIO_DETECT_PA"].as(0); + portduino_config.lora_pa_detect_pin.pin = portduino_config.gpio_detect_pa; + } if (yamlConfig["Lora"]["TX_GAIN_LORA"]) { YAML::Node tx_gain_node = yamlConfig["Lora"]["TX_GAIN_LORA"]; diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index aa8847fd7..8e826f9b3 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -98,6 +98,8 @@ extern struct portduino_config_struct { int lora_usb_pid = 0x5512; int lora_usb_vid = 0x1A86; int spiSpeed = 2000000; + bool has_gpio_detect_pa = false; + int gpio_detect_pa = 0; 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"}; @@ -107,6 +109,7 @@ extern struct portduino_config_struct { pinMapping lora_txen_pin = {"Lora", "TXen"}; pinMapping lora_rxen_pin = {"Lora", "RXen"}; pinMapping lora_sx126x_ant_sw_pin = {"Lora", "SX126X_ANT_SW"}; + pinMapping lora_pa_detect_pin = {"Lora", "GPIO_DETECT_PA"}; std::vector extra_pins = {}; // GPS @@ -194,13 +197,14 @@ extern struct portduino_config_struct { int maxtophone = 100; int MaxNodes = 200; - pinMapping *all_pins[20] = {&lora_cs_pin, + pinMapping *all_pins[21] = {&lora_cs_pin, &lora_irq_pin, &lora_busy_pin, &lora_reset_pin, &lora_txen_pin, &lora_rxen_pin, &lora_sx126x_ant_sw_pin, + &lora_pa_detect_pin, &displayDC, &displayCS, &displayBacklight, @@ -245,6 +249,9 @@ extern struct portduino_config_struct { if (rf95_max_power != 20) out << YAML::Key << "RF95_MAX_POWER" << YAML::Value << rf95_max_power; + if (has_gpio_detect_pa) + out << YAML::Key << "GPIO_DETECT_PA" << YAML::Value << gpio_detect_pa; + 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++) {