From 9980c56d8132999dddf752b0e447e6aea9a0aeee Mon Sep 17 00:00:00 2001 From: Jason P Date: Thu, 25 Sep 2025 17:48:34 -0500 Subject: [PATCH 01/11] Correct Inverted Mute Icon on Clock Display (#8111) --- src/graphics/SharedUIDisplay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphics/SharedUIDisplay.cpp b/src/graphics/SharedUIDisplay.cpp index 3937bcf50..dcaa5d69b 100644 --- a/src/graphics/SharedUIDisplay.cpp +++ b/src/graphics/SharedUIDisplay.cpp @@ -284,7 +284,7 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti int iconX = iconRightEdge - mute_symbol_big_width; int iconY = textY + (FONT_HEIGHT_SMALL - mute_symbol_big_height) / 2; - if (isInverted) { + if (isInverted && !force_no_invert) { display->setColor(WHITE); display->fillRect(iconX - 1, iconY - 1, mute_symbol_big_width + 2, mute_symbol_big_height + 2); display->setColor(BLACK); From 06240596833a31b08b9e95530027b3708a7d635f Mon Sep 17 00:00:00 2001 From: Jason P Date: Fri, 26 Sep 2025 11:17:15 -0500 Subject: [PATCH 02/11] Saving changes are required (#8122) --- src/graphics/draw/MenuHandler.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index 7c4f4e05f..43b3fb8ab 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -852,24 +852,31 @@ void menuHandler::GPSFormatMenu() bannerOptions.bannerCallback = [](int selected) -> void { if (selected == 1) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_DEC; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else if (selected == 2) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_DMS; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else if (selected == 3) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_UTM; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else if (selected == 4) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_MGRS; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else if (selected == 5) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_OLC; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else if (selected == 6) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_OSGR; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else if (selected == 7) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else { menuQueue = position_base_menu; From 2f1198ddf3a5558f31ccde577edf763a8e80f8f1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 11:17:38 -0500 Subject: [PATCH 03/11] Upgrade trunk (#8118) Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com> --- .trunk/trunk.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index e9bbba9ff..4e9de6a02 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -9,7 +9,7 @@ plugins: lint: enabled: - checkov@3.2.471 - - renovate@41.127.2 + - renovate@41.130.1 - prettier@3.6.2 - trufflehog@3.90.8 - yamllint@1.37.1 From bc3db1b5c137db93088476467219fc1ab36e4932 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Fri, 26 Sep 2025 18:23:09 -0500 Subject: [PATCH 04/11] Properly output the TCXO Voltage in yaml (#8128) --- src/platform/portduino/PortduinoGlue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 106900c48..ec6209487 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -224,7 +224,7 @@ extern struct portduino_config_struct { out << YAML::Key << "RF95_MAX_POWER" << YAML::Value << rf95_max_power; 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 << dio3_tcxo_voltage; + out << YAML::Key << "DIO3_TCXO_VOLTAGE" << YAML::Value << YAML::Precision(3) << (float)dio3_tcxo_voltage / 1000; if (lora_usb_pid != 0x5512) out << YAML::Key << "USB_PID" << YAML::Value << YAML::Hex << lora_usb_pid; if (lora_usb_vid != 0x1A86) From ab00e991f6bd616f572f25686acb830c63749b76 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sat, 27 Sep 2025 07:09:24 -0500 Subject: [PATCH 05/11] Revert cross-preset default-key bridging with UDP and disable UDP by default (#8130) * Revert cross-preset UDP bridging * Don't enable UDP by default --- src/mesh/NodeDB.cpp | 2 +- src/mesh/Router.cpp | 29 ----------------------------- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 97dfb3e52..a7172f4d1 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -701,7 +701,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) #ifdef USERPREFS_NETWORK_ENABLED_PROTOCOLS config.network.enabled_protocols = USERPREFS_NETWORK_ENABLED_PROTOCOLS; #else - config.network.enabled_protocols = 1; + config.network.enabled_protocols = 0; #endif #endif diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 171c383ba..145b4dde8 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -483,35 +483,6 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p) } } -#if HAS_UDP_MULTICAST - // Fallback: for UDP multicast, try default preset names with default PSK if normal channel match failed - if (!decrypted && p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP) { - if (channels.setDefaultPresetCryptoForHash(p->channel)) { - memcpy(bytes, p->encrypted.bytes, rawSize); - crypto->decrypt(p->from, p->id, rawSize, bytes); - - meshtastic_Data decodedtmp; - memset(&decodedtmp, 0, sizeof(decodedtmp)); - if (pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &decodedtmp) && - decodedtmp.portnum != meshtastic_PortNum_UNKNOWN_APP) { - p->decoded = decodedtmp; - p->which_payload_variant = meshtastic_MeshPacket_decoded_tag; - // Map to our local default channel index (name+PSK default), not necessarily primary - ChannelIndex defaultIndex = channels.getPrimaryIndex(); - for (ChannelIndex i = 0; i < channels.getNumChannels(); ++i) { - if (channels.isDefaultChannel(i)) { - defaultIndex = i; - break; - } - } - chIndex = defaultIndex; - decrypted = true; - } else { - LOG_WARN("UDP fallback decode attempted but failed for hash 0x%x", p->channel); - } - } - } -#endif if (decrypted) { // parsing was successful p->channel = chIndex; // change to store the index instead of the hash From 045176789e2c4fe50ce4b8ce8a44b4bbfc710cdc Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sat, 27 Sep 2025 08:32:43 -0500 Subject: [PATCH 06/11] Fix int comparison and client_base base should really not be on this list --- src/mesh/Router.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 145b4dde8..7f17737e5 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -90,7 +90,7 @@ bool Router::shouldDecrementHopLimit(const meshtastic_MeshPacket *p) // For subsequent hops, check if previous relay is a favorite router // Optimized search for favorite routers with matching last byte // Check ordering optimized for IoT devices (cheapest checks first) - for (int i = 0; i < nodeDB->getNumMeshNodes(); i++) { + for (size_t i = 0; i < nodeDB->getNumMeshNodes(); i++) { meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(i); if (!node) continue; @@ -105,7 +105,7 @@ bool Router::shouldDecrementHopLimit(const meshtastic_MeshPacket *p) // Check 3: role check (moderate cost - multiple comparisons) if (!IS_ONE_OF(node->user.role, meshtastic_Config_DeviceConfig_Role_ROUTER, - meshtastic_Config_DeviceConfig_Role_ROUTER_LATE, meshtastic_Config_DeviceConfig_Role_CLIENT_BASE)) { + meshtastic_Config_DeviceConfig_Role_ROUTER_LATE)) { continue; } From bc516ebbacf9cb1cf112c55386771863ef2121a5 Mon Sep 17 00:00:00 2001 From: dfsx1 <60702962+dfsx1@users.noreply.github.com> Date: Sat, 27 Sep 2025 13:33:07 +0000 Subject: [PATCH 07/11] Remove memcpy (#8079) Obsolete since #7652 returns false for mismatching keys Co-authored-by: dfsx1 Co-authored-by: Ben Meadors --- src/mesh/NodeDB.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index a7172f4d1..b512ae675 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -1667,9 +1667,6 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde return false; } LOG_INFO("Public Key set for node, not updating!"); - // we copy the key into the incoming packet, to prevent overwrite - p.public_key.size = 32; - memcpy(p.public_key.bytes, info->user.public_key.bytes, 32); } else if (p.public_key.size == 32) { LOG_INFO("Update Node Pubkey!"); } From 067939ca24ee3f40f8be9e8fa5bfc215a1a17272 Mon Sep 17 00:00:00 2001 From: Jason P Date: Sun, 28 Sep 2025 06:11:01 -0500 Subject: [PATCH 08/11] Correct altitudeLine getting clobbered in the great merge (#8138) * Correct altitudeLine getting clobbered in the great merge * Fix variable usage in altitude calculation --- src/graphics/draw/UIRenderer.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/graphics/draw/UIRenderer.cpp b/src/graphics/draw/UIRenderer.cpp index 2ccc0f861..ff8cd20c5 100644 --- a/src/graphics/draw/UIRenderer.cpp +++ b/src/graphics/draw/UIRenderer.cpp @@ -1105,6 +1105,18 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU // === Fourth Row: Line 2 GPS Info === UIRenderer::drawGpsCoordinates(display, x, getTextPositions(display)[line++], gpsStatus, "line2"); } + + // === Final Row: Altitude === + char altitudeLine[32] = {0}; + int32_t alt = (strcmp(displayLine, "Phone GPS") == 0 && ourNode && nodeDB->hasValidPosition(ourNode)) + ? ourNode->position.altitude + : geoCoord.getAltitude(); + if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) { + snprintf(altitudeLine, sizeof(altitudeLine), "Alt: %.0fft", alt * METERS_TO_FEET); + } else { + snprintf(altitudeLine, sizeof(altitudeLine), "Alt: %.0im", alt); + } + display->drawString(x, getTextPositions(display)[line++], altitudeLine); } #if !defined(M5STACK_UNITC6L) // === Draw Compass if heading is valid === From 8717c60f13e640d4b9367cd0ddc02765e6d457ca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 28 Sep 2025 07:35:56 -0500 Subject: [PATCH 09/11] Update protobufs (#8142) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/apponly.pb.h | 2 +- src/mesh/generated/meshtastic/channel.pb.h | 14 +++++++++----- src/mesh/generated/meshtastic/config.pb.h | 3 ++- src/mesh/generated/meshtastic/deviceonly.pb.h | 4 ++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/protobufs b/protobufs index 46b81e822..082bb7cfe 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 46b81e822af1b8e408f437092337f129dee693e6 +Subproject commit 082bb7cfeb2cba9d41be139cd324c4b43a14b3f9 diff --git a/src/mesh/generated/meshtastic/apponly.pb.h b/src/mesh/generated/meshtastic/apponly.pb.h index f4c33bd79..db9dedaaf 100644 --- a/src/mesh/generated/meshtastic/apponly.pb.h +++ b/src/mesh/generated/meshtastic/apponly.pb.h @@ -55,7 +55,7 @@ extern const pb_msgdesc_t meshtastic_ChannelSet_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_APPONLY_PB_H_MAX_SIZE meshtastic_ChannelSet_size -#define meshtastic_ChannelSet_size 679 +#define meshtastic_ChannelSet_size 695 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/channel.pb.h b/src/mesh/generated/meshtastic/channel.pb.h index ca4310bf1..d5573a1e2 100644 --- a/src/mesh/generated/meshtastic/channel.pb.h +++ b/src/mesh/generated/meshtastic/channel.pb.h @@ -97,6 +97,8 @@ typedef struct _meshtastic_ChannelSettings { /* Per-channel module settings. */ bool has_module_settings; meshtastic_ModuleSettings module_settings; + /* Whether or not we should receive notifactions / alerts through this channel */ + bool mute; } meshtastic_ChannelSettings; /* A pair of a channel number, mode and the (sharable) settings for that channel */ @@ -128,10 +130,10 @@ extern "C" { /* Initializer values for message structs */ -#define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_default} +#define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_default, 0} #define meshtastic_ModuleSettings_init_default {0, 0} #define meshtastic_Channel_init_default {0, false, meshtastic_ChannelSettings_init_default, _meshtastic_Channel_Role_MIN} -#define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_zero} +#define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_zero, 0} #define meshtastic_ModuleSettings_init_zero {0, 0} #define meshtastic_Channel_init_zero {0, false, meshtastic_ChannelSettings_init_zero, _meshtastic_Channel_Role_MIN} @@ -145,6 +147,7 @@ extern "C" { #define meshtastic_ChannelSettings_uplink_enabled_tag 5 #define meshtastic_ChannelSettings_downlink_enabled_tag 6 #define meshtastic_ChannelSettings_module_settings_tag 7 +#define meshtastic_ChannelSettings_mute_tag 8 #define meshtastic_Channel_index_tag 1 #define meshtastic_Channel_settings_tag 2 #define meshtastic_Channel_role_tag 3 @@ -157,7 +160,8 @@ X(a, STATIC, SINGULAR, STRING, name, 3) \ X(a, STATIC, SINGULAR, FIXED32, id, 4) \ X(a, STATIC, SINGULAR, BOOL, uplink_enabled, 5) \ X(a, STATIC, SINGULAR, BOOL, downlink_enabled, 6) \ -X(a, STATIC, OPTIONAL, MESSAGE, module_settings, 7) +X(a, STATIC, OPTIONAL, MESSAGE, module_settings, 7) \ +X(a, STATIC, SINGULAR, BOOL, mute, 8) #define meshtastic_ChannelSettings_CALLBACK NULL #define meshtastic_ChannelSettings_DEFAULT NULL #define meshtastic_ChannelSettings_module_settings_MSGTYPE meshtastic_ModuleSettings @@ -187,8 +191,8 @@ extern const pb_msgdesc_t meshtastic_Channel_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_CHANNEL_PB_H_MAX_SIZE meshtastic_Channel_size -#define meshtastic_ChannelSettings_size 72 -#define meshtastic_Channel_size 87 +#define meshtastic_ChannelSettings_size 74 +#define meshtastic_Channel_size 89 #define meshtastic_ModuleSettings_size 8 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 0453ecad2..327568316 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -26,7 +26,8 @@ typedef enum _meshtastic_Config_DeviceConfig_Role { meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT = 3, /* Description: Infrastructure node for extending network coverage by relaying messages with minimal overhead. Not visible in Nodes list. Technical Details: Mesh packets will simply be rebroadcasted over this node. Nodes configured with this role will not originate NodeInfo, Position, Telemetry - or any other packet type. They will simply rebroadcast any mesh packets on the same frequency, channel num, spread factor, and coding rate. */ + or any other packet type. They will simply rebroadcast any mesh packets on the same frequency, channel num, spread factor, and coding rate. + Deprecated in v2.7.11 because it creates "holes" in the mesh rebroadcast chain. */ meshtastic_Config_DeviceConfig_Role_REPEATER = 4, /* Description: Broadcasts GPS position packets as priority. Technical Details: Position Mesh packets will be prioritized higher and sent more frequently by default. diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 7fab82ff7..b5b116137 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -360,8 +360,8 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_NodeDatabase_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size -#define meshtastic_BackupPreferences_size 2277 -#define meshtastic_ChannelFile_size 718 +#define meshtastic_BackupPreferences_size 2293 +#define meshtastic_ChannelFile_size 734 #define meshtastic_DeviceState_size 1737 #define meshtastic_NodeInfoLite_size 196 #define meshtastic_PositionLite_size 28 From 777e11bad97777d6351c04cf0e09c4983b0faff0 Mon Sep 17 00:00:00 2001 From: Clive Blackledge Date: Sun, 28 Sep 2025 14:42:51 -0700 Subject: [PATCH 10/11] Bug / Send upgraded (duplicate) packets to phone if the queue removal failed. (#8148) * Add seenRecently = true if wasUpgraded is true but unable to remove from queue (i.e. already sent/processed). * Consistent comment between FloodingRouter and HopRouter --- src/mesh/FloodingRouter.cpp | 4 ++++ src/mesh/NextHopRouter.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index 3caee78f8..7ce106317 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -54,6 +54,10 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) // We already enqueued the improved copy, so make sure the incoming packet stops here. return true; } + + // No queue entry was replaced by this upgraded copy, so treat it as a duplicate to avoid + // delivering the same packet to applications/phone twice with different hop limits. + seenRecently = true; } if (seenRecently) { diff --git a/src/mesh/NextHopRouter.cpp b/src/mesh/NextHopRouter.cpp index 4ae0a818e..dce436471 100644 --- a/src/mesh/NextHopRouter.cpp +++ b/src/mesh/NextHopRouter.cpp @@ -64,6 +64,10 @@ bool NextHopRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) // We already enqueued the improved copy, so make sure the incoming packet stops here. return true; } + + // No queue entry was replaced by this upgraded copy, so treat it as a duplicate to avoid + // delivering the same packet to applications/phone twice with different hop limits. + seenRecently = true; } if (seenRecently) { From a3e6f16378bfd89bcae91191dfd734278dd9cc6b Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Tue, 30 Sep 2025 08:20:39 +1000 Subject: [PATCH 11/11] Introduce non-linear TX_GAIN_LORA (#8107) * Introduce non-linear TX_GAIN_LORA Previously, our TX_GAIN_LORA setting was a single number, intended to represent the signal gain going through a power amp (plus or minus antenna, attenuator, and other parts of the RF chain). It turns out the relationship between the input power (i.e. from an SX1262) and total output power is often non-linear. While we fudged a 1dBm difference here and there with existing chips, the Heltec v4 has a 5dBm difference in gain depending on which end of the input power (and frequency) you are at. To allow people to run their Heltec v4 at max power when legal, and future proof our code, this patch introduced an optional array-based TX_GAIN_LORA. Define NUM_PA_POINTS and set TX_GAIN_LORA to gain values for a given input power in 1dBm increments, and all will work. For linear systems, just continue to define TX_GAIN_LORA as a number. Fixes https://github.com/meshtastic/firmware/issues/8070 * Remove temporary power limit on heltec v4 * Add function RadioLibInterface::checkOutputPower * Ensure SX126x reaches minimum supported power. * Keep it simple, instead. --- src/configuration.h | 6 ++++++ src/mesh/RadioInterface.cpp | 14 ++++++++++++++ src/mesh/SX126xInterface.cpp | 7 +++++-- variants/esp32s3/heltec_v4/platformio.ini | 1 - 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/configuration.h b/src/configuration.h index 1b386ec17..91181890b 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -117,6 +117,12 @@ along with this program. If not, see . #define SX126X_MAX_POWER 22 #endif +#ifdef HELTEC_V4 +// Power Amps are often non-linear, so we can use an array of values for the power curve +#define NUM_PA_POINTS 22 +#define TX_GAIN_LORA 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 9, 8, 7 +#endif + // Default system gain to 0 if not defined #ifndef TX_GAIN_LORA #define TX_GAIN_LORA 0 diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 31c68c302..b891ec89c 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -674,11 +674,25 @@ void RadioInterface::limitPower(int8_t loraMaxPower) power = maxPower; } +#ifndef NUM_PA_POINTS if (TX_GAIN_LORA > 0) { LOG_INFO("Requested Tx power: %d dBm; Device LoRa Tx gain: %d dB", power, TX_GAIN_LORA); power -= TX_GAIN_LORA; } +#else + // 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++) { + if (((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]; + break; + } + } +#endif if (power > loraMaxPower) // Clamp power to maximum defined level power = loraMaxPower; diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index 3fc2562b3..785338483 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -80,6 +80,9 @@ template bool SX126xInterface::init() RadioLibInterface::init(); limitPower(SX126X_MAX_POWER); + // Make sure we reach the minimum power supported to turn the chip on (-9dBm) + if (power < -9) + power = -9; int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage, useRegulatorLDO); // \todo Display actual typename of the adapter, not just `SX126x` @@ -118,8 +121,8 @@ template bool SX126xInterface::init() LOG_DEBUG("Set DIO2 as %sRF switch, result: %d", dio2AsRfSwitch ? "" : "not ", res); } - // If a pin isn't defined, we set it to RADIOLIB_NC, it is safe to always do external RF switching with RADIOLIB_NC as it has - // no effect +// If a pin isn't defined, we set it to RADIOLIB_NC, it is safe to always do external RF switching with RADIOLIB_NC as it has +// no effect #if ARCH_PORTDUINO if (res == RADIOLIB_ERR_NONE) { LOG_DEBUG("Use MCU pin %i as RXEN and pin %i as TXEN to control RF switching", portduino_config.lora_rxen_pin.pin, diff --git a/variants/esp32s3/heltec_v4/platformio.ini b/variants/esp32s3/heltec_v4/platformio.ini index 1a448bc99..d0a250ad3 100644 --- a/variants/esp32s3/heltec_v4/platformio.ini +++ b/variants/esp32s3/heltec_v4/platformio.ini @@ -8,4 +8,3 @@ build_flags = -D HELTEC_V4 -I variants/esp32s3/heltec_v4 -D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. - -D SX126X_MAX_POWER=11