Эх сурвалжийг харах

Add LoRa FEM RX-path LNA control via CLI; restore enabled default

Ported from meshcore-dev/MeshCore#2140 (Quency-D <hj_zzns@163.com>).

The upstream v1.16.0 merge changed the Heltec FEM LNA to disabled by
default (upstream commit 696aae6e).  This patch restores the enabled
default for repeater via the new "radio.fem.rxgain" preference
(defaulted to 1), while also making the setting user-configurable
and persisted across reboots.
Valentin V. Bartenev 2 сар өмнө
parent
commit
1817248d97

+ 14 - 0
docs/cli_commands.md

@@ -263,6 +263,20 @@ This document provides an overview of CLI commands that can be sent to MeshCore
 
 ---
 
+#### View or change the LoRa FEM receive-path gain state on supported boards
+**Usage:**
+- `get radio.fem.rxgain`
+- `set radio.fem.rxgain <state>`
+
+**Parameters:**
+- `state`: `on`|`off`
+
+**Notes:**
+- This controls the external LoRa FEM receive-path LNA where the board supports it.
+- This is separate from `radio.rxgain`, which controls the radio chip receive gain mode.
+
+---
+
 ### System
 
 #### View or change this node's name

+ 2 - 0
examples/simple_repeater/MyMesh.cpp

@@ -1266,6 +1266,7 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
   _prefs.rx_boosted_gain = 1; // enabled by default;
 #endif
 #endif
+  _prefs.radio_fem_rxgain = 1;
 
   pending_discover_tag = 0;
   pending_discover_until = 0;
@@ -1360,6 +1361,7 @@ void MyMesh::begin(FILESYSTEM *fs, ArchiveStorage* archive) {
   radio_driver.setRxBoostedGainMode(_prefs.rx_boosted_gain);
   MESH_DEBUG_PRINTLN("RX Boosted Gain Mode: %s",
                      radio_driver.getRxBoostedGainMode() ? "Enabled" : "Disabled");
+  board.setLoRaFemLnaEnabled(_prefs.radio_fem_rxgain);
 
   updateAdvertTimer();
   updateFloodAdvertTimer();

+ 3 - 0
src/MeshCore.h

@@ -69,6 +69,9 @@ public:
   virtual uint8_t getStartupReason() const = 0;
   virtual bool getBootloaderVersion(char* version, size_t max_len) { return false; }
   virtual bool startOTAUpdate(const char* id, char reply[]) { return false; }   // not supported
+  virtual bool setLoRaFemLnaEnabled(bool enable) { return false; }
+  virtual bool canControlLoRaFemLna() const { return false; }
+  virtual bool isLoRaFemLnaEnabled() const { return false; }
 
   // Power management interface (boards with power management override these)
   virtual bool isExternalPowered() { return false; }

+ 36 - 2
src/helpers/CommonCLI.cpp

@@ -106,7 +106,10 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
     if (file.available() >= (int)sizeof(_prefs->flood_max_advert)) {
       file.read((uint8_t *)&_prefs->flood_max_advert, sizeof(_prefs->flood_max_advert));          // 296
     }
-    // next: 297
+    if (file.available() >= (int)sizeof(_prefs->radio_fem_rxgain)) {
+      file.read((uint8_t *)&_prefs->radio_fem_rxgain, sizeof(_prefs->radio_fem_rxgain));          // 297
+    }
+    // next: 298
 
     // sanitise bad pref values
     _prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f);
@@ -136,6 +139,8 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
 
     // sanitise settings
     _prefs->rx_boosted_gain = constrain(_prefs->rx_boosted_gain, 0, 1); // boolean
+    _prefs->radio_fem_rxgain = constrain(_prefs->radio_fem_rxgain, 0, 1); // boolean
+
     _prefs->fan_mode = constrain(_prefs->fan_mode, 0, 2);
     _prefs->fan_timeout_secs = constrain(_prefs->fan_timeout_secs, 0, 600);
 
@@ -204,7 +209,8 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
     file.write((uint8_t *)&_prefs->fan_timeout_secs, sizeof(_prefs->fan_timeout_secs));            // 293
     file.write((uint8_t *)&_prefs->flood_max_unscoped, sizeof(_prefs->flood_max_unscoped));        // 295
     file.write((uint8_t *)&_prefs->flood_max_advert, sizeof(_prefs->flood_max_advert));            // 296
-    // next: 297
+    file.write((uint8_t *)&_prefs->radio_fem_rxgain, sizeof(_prefs->radio_fem_rxgain));            // 297
+    // next: 298
 
     file.close();
   }
@@ -597,6 +603,28 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
     savePrefs();
     _callbacks->setRxBoostedGain(_prefs->rx_boosted_gain);
 #endif
+  } else if (memcmp(config, "radio.fem.rxgain ", 17) == 0) {
+    if (!_board->canControlLoRaFemLna()) {
+      strcpy(reply, "Error: unsupported");
+    } else if (memcmp(&config[17], "on", 2) == 0) {
+      if (_board->setLoRaFemLnaEnabled(true)) {
+        _prefs->radio_fem_rxgain = 1;
+        savePrefs();
+        strcpy(reply, "OK - LoRa FEM RX gain on");
+      } else {
+        strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
+      }
+    } else if (memcmp(&config[17], "off", 3) == 0) {
+      if (_board->setLoRaFemLnaEnabled(false)) {
+        _prefs->radio_fem_rxgain = 0;
+        savePrefs();
+        strcpy(reply, "OK - LoRa FEM RX gain off");
+      } else {
+        strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
+      }
+    } else {
+      strcpy(reply, "Error: state must be on or off");
+    }
   } else if (memcmp(config, "radio ", 6) == 0) {
     strcpy(tmp, &config[6]);
     const char *parts[4];
@@ -834,6 +862,12 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
   } else if (memcmp(config, "radio.rxgain", 12) == 0) {
     sprintf(reply, "> %s", _prefs->rx_boosted_gain ? "on" : "off");
 #endif
+  } else if (memcmp(config, "radio.fem.rxgain", 16) == 0) {
+    if (!_board->canControlLoRaFemLna()) {
+      strcpy(reply, "Error: unsupported");
+    } else {
+      sprintf(reply, "> %s", _board->isLoRaFemLnaEnabled() ? "on" : "off");
+    }
   } else if (memcmp(config, "radio", 5) == 0) {
     char freq[16], bw[16];
     strcpy(freq, StrHelper::ftoa(_prefs->freq));

+ 1 - 0
src/helpers/CommonCLI.h

@@ -62,6 +62,7 @@ struct NodePrefs { // persisted to file
   char owner_info[120];
   uint8_t reserved_290; // reserved to preserve on-disk prefs layout
   uint8_t rx_boosted_gain; // power settings
+  uint8_t radio_fem_rxgain; // LoRa FEM RX gain setting
   uint8_t path_hash_mode;   // which path mode to use when sending
   uint8_t loop_detect;
   uint8_t fan_mode;

+ 2 - 1
variants/heltec_t096/LoRaFEMControl.h

@@ -12,8 +12,9 @@ class LoRaFEMControl
     void setRxModeEnable(void);
     void setRxModeEnableWhenMCUSleep(void);
     void setLNAEnable(bool enabled);
-    bool isLnaCanControl(void) { return lna_can_control; }
+    bool isLnaCanControl(void) const { return lna_can_control; }
     void setLnaCanControl(bool can_control) { lna_can_control = can_control; }
+    bool isLNAEnabled(void) const { return lna_enabled; }
 
   private:
     bool lna_enabled = false;

+ 19 - 1
variants/heltec_t096/T096Board.cpp

@@ -123,4 +123,22 @@ void T096Board::powerOff() {
 
 const char* T096Board::getManufacturerName() const {
   return "Heltec T096";
-}
+}
+
+bool T096Board::setLoRaFemLnaEnabled(bool enable) {
+  if (!loRaFEMControl.isLnaCanControl()) {
+    return false;
+  }
+
+  loRaFEMControl.setLNAEnable(enable);
+  loRaFEMControl.setRxModeEnable();
+  return true;
+}
+
+bool T096Board::canControlLoRaFemLna() const {
+  return loRaFEMControl.isLnaCanControl();
+}
+
+bool T096Board::isLoRaFemLnaEnabled() const {
+  return loRaFEMControl.isLNAEnabled();
+}

+ 3 - 0
variants/heltec_t096/T096Board.h

@@ -25,4 +25,7 @@ public:
   uint16_t getBattMilliVolts() override;
   const char* getManufacturerName() const override ;
   void powerOff() override;
+  bool setLoRaFemLnaEnabled(bool enable) override;
+  bool canControlLoRaFemLna() const override;
+  bool isLoRaFemLnaEnabled() const override;
 };

+ 18 - 0
variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp

@@ -82,3 +82,21 @@ void HeltecTrackerV2Board::begin() {
   const char* HeltecTrackerV2Board::getManufacturerName() const {
     return "Heltec Tracker V2";
   }
+
+  bool HeltecTrackerV2Board::setLoRaFemLnaEnabled(bool enable) {
+    if (!loRaFEMControl.isLnaCanControl()) {
+      return false;
+    }
+
+    loRaFEMControl.setLNAEnable(enable);
+    loRaFEMControl.setRxModeEnable();
+    return true;
+  }
+
+  bool HeltecTrackerV2Board::canControlLoRaFemLna() const {
+    return loRaFEMControl.isLnaCanControl();
+  }
+
+  bool HeltecTrackerV2Board::isLoRaFemLnaEnabled() const {
+    return loRaFEMControl.isLNAEnabled();
+  }

+ 3 - 0
variants/heltec_tracker_v2/HeltecTrackerV2Board.h

@@ -21,5 +21,8 @@ public:
   void powerOff() override;
   uint16_t getBattMilliVolts() override;
   const char* getManufacturerName() const override ;
+  bool setLoRaFemLnaEnabled(bool enable) override;
+  bool canControlLoRaFemLna() const override;
+  bool isLoRaFemLnaEnabled() const override;
 
 };

+ 2 - 1
variants/heltec_tracker_v2/LoRaFEMControl.h

@@ -12,8 +12,9 @@ class LoRaFEMControl
     void setRxModeEnable(void);
     void setRxModeEnableWhenMCUSleep(void);
     void setLNAEnable(bool enabled);
-    bool isLnaCanControl(void) { return lna_can_control; }
+    bool isLnaCanControl(void) const { return lna_can_control; }
     void setLnaCanControl(bool can_control) { lna_can_control = can_control; }
+    bool isLNAEnabled(void) const { return lna_enabled; }
 
   private:
     bool lna_enabled = false;

+ 18 - 0
variants/heltec_v4/HeltecV4Board.cpp

@@ -83,3 +83,21 @@ void HeltecV4Board::begin() {
     return loRaFEMControl.getFEMType() == KCT8103L_PA ? "Heltec V4.3 OLED" : "Heltec V4 OLED";
 #endif
   }
+
+  bool HeltecV4Board::setLoRaFemLnaEnabled(bool enable) {
+    if (!loRaFEMControl.isLnaCanControl()) {
+      return false;
+    }
+
+    loRaFEMControl.setLNAEnable(enable);
+    loRaFEMControl.setRxModeEnable();
+    return true;
+  }
+
+  bool HeltecV4Board::canControlLoRaFemLna() const {
+    return loRaFEMControl.isLnaCanControl();
+  }
+
+  bool HeltecV4Board::isLoRaFemLnaEnabled() const {
+    return loRaFEMControl.isLNAEnabled();
+  }

+ 3 - 0
variants/heltec_v4/HeltecV4Board.h

@@ -25,6 +25,9 @@ public:
   void onAfterTransmit(void) override;
   void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1);
   void powerOff() override;
+  bool setLoRaFemLnaEnabled(bool enable) override;
+  bool canControlLoRaFemLna() const override;
+  bool isLoRaFemLnaEnabled() const override;
   uint16_t getBattMilliVolts() override;
   bool setAdcMultiplier(float multiplier) override {
     if (multiplier == 0.0f) {

+ 2 - 1
variants/heltec_v4/LoRaFEMControl.h

@@ -18,8 +18,9 @@ class LoRaFEMControl
     void setRxModeEnable(void);
     void setRxModeEnableWhenMCUSleep(void);
     void setLNAEnable(bool enabled);
-    bool isLnaCanControl(void) { return lna_can_control; }
+    bool isLnaCanControl(void) const { return lna_can_control; }
     void setLnaCanControl(bool can_control) { lna_can_control = can_control; }
+    bool isLNAEnabled(void) const { return lna_enabled; }
     LoRaFEMType getFEMType(void) const { return fem_type; }
   private:
     LoRaFEMType fem_type=OTHER_FEM_TYPES;