* T096, and Station G3: refactoring the 'FEM' prefs to variant-specific code

* CommonCLI: 'FEM' commands removed
* introduced static no-op attachDynamicPrefs() for all boards
This commit is contained in:
Scott Powell
2026-08-24 01:50:22 +10:00
parent e485d01dcb
commit 47b0b7b3b8
21 changed files with 243 additions and 101 deletions
+9 -2
View File
@@ -989,8 +989,9 @@ void MyMesh::begin(bool has_display) {
radio_driver.setParams(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
radio_driver.setTxPower(_prefs.tx_power_dbm);
radio_driver.setRxBoostedGainMode(_prefs.rx_boosted_gain);
board.setLoRaFemLnaEnabled(_prefs.radio_fem_rxgain);
board.setLoRaFemPaGainEnabled(_prefs.radio_fem_txgain);
board.attachDynamicPrefs(_prefs.getRadioPrefs());
MESH_DEBUG_PRINTLN("RX Boosted Gain Mode: %s",
radio_driver.getRxBoostedGainMode() ? "Enabled" : "Disabled");
}
@@ -2073,6 +2074,12 @@ bool MyMesh::handleCommand(const char* command, uint32_t sender_timestamp, char*
return true;
}
// hook for variant-specific CLI processing
if (board.handleCommand(command, sender_timestamp, reply)) {
if (_prefs.isDirty()) { savePrefs(); }
return true;
}
if (memcmp(command, "set name ", 9) == 0) {
if (AdvertDataParser::isValidName(&command[9])) {
StrHelper::strncpy(_prefs.node_name, &command[9], sizeof(_prefs.node_name));
+7 -6
View File
@@ -54,12 +54,8 @@ private:
//def("cad", _parent->cad_enabled);
//def("int_thr", _parent->interference_threshold);
def("rxgain", _parent->rx_boosted_gain);
#if 0
// NOTE: these cannot be set (yet) so don't load/save until we can.
// also, fem_rxgain WAS mapped to wrong JSON property previously
def("fem_rxgain", _parent->radio_fem_rxgain);
def("fem_rxgain", _parent->radio_fem_rxgain); // fem_rxgain WAS mapped to wrong JSON property previously
def("fem_txgain", _parent->radio_fem_txgain);
#endif
def("tx", _parent->tx_power_dbm);
def("af", _parent->airtime_factor);
def("rxdelay", _parent->rx_delay_base);
@@ -103,6 +99,10 @@ private:
void setFloodTxDelay(float d) override { /* no-op */ }
float getDirectTxDelay() const override { return 0.2f; } // currently hard-coded
void setDirectTxDelay(float d) override { /* no-op */ }
uint8_t getFEMRxGain() const override { return _parent->radio_fem_rxgain; }
void setFEMRxGain(uint8_t g) override { _parent->radio_fem_rxgain = g; markDirty(); }
uint8_t getFEMTxGain() const override { return _parent->radio_fem_txgain; }
void setFEMTxGain(uint8_t g) override { _parent->radio_fem_txgain = g; markDirty(); }
};
RadioPrefs radio;
@@ -177,5 +177,6 @@ public:
void setRepeatEn(bool en) { repeat.disable_fwd = en ? 0 : 1; }
CommonRadioPrefs* getRadioPrefs() { return &radio; }
void clearDirty() { radio.clearDirty(); }
bool isDirty() const override { return ConfigSerializer::isDirty() || radio.isDirty(); }
void clearDirty() override { ConfigSerializer::clearDirty(); radio.clearDirty(); }
};
+2 -2
View File
@@ -982,8 +982,8 @@ void MyMesh::begin(FILESYSTEM *fs) {
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);
board.setLoRaFemPaGainEnabled(_prefs.radio_fem_txgain);
board.attachDynamicPrefs(_prefs.getRadioPrefs());
updateAdvertTimer();
updateFloodAdvertTimer();
+2 -2
View File
@@ -725,8 +725,8 @@ void MyMesh::begin(FILESYSTEM *fs) {
radio_driver.setParams(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
radio_driver.setTxPower(_prefs.tx_power_dbm);
radio_driver.setRxBoostedGainMode(_prefs.rx_boosted_gain);
board.setLoRaFemLnaEnabled(_prefs.radio_fem_rxgain);
board.setLoRaFemPaGainEnabled(_prefs.radio_fem_txgain);
board.attachDynamicPrefs(_prefs.getRadioPrefs());
updateAdvertTimer();
updateFloodAdvertTimer();
+2 -2
View File
@@ -771,8 +771,8 @@ void SensorMesh::begin(FILESYSTEM* fs) {
radio_driver.setParams(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
radio_driver.setTxPower(_prefs.tx_power_dbm);
board.setLoRaFemLnaEnabled(_prefs.radio_fem_rxgain);
board.setLoRaFemPaGainEnabled(_prefs.radio_fem_txgain);
board.attachDynamicPrefs(_prefs.getRadioPrefs());
updateAdvertTimer();
updateFloodAdvertTimer();
+2 -7
View File
@@ -64,13 +64,6 @@ 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; }
// Software-selectable external FEM transmit gain. This is not a PA power switch.
virtual bool setLoRaFemPaGainEnabled(bool enable) { return false; }
virtual bool canControlLoRaFemPaGain() const { return false; }
virtual bool isLoRaFemPaGainEnabled() const { return false; }
// Power management interface (boards with power management override these)
virtual bool isExternalPowered() { return false; }
@@ -79,6 +72,8 @@ public:
virtual const char* getResetReasonString(uint32_t reason) { return "Not available"; }
virtual uint8_t getShutdownReason() const { return 0; }
virtual const char* getShutdownReasonString(uint8_t reason) { return "Not available"; }
virtual bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) { return false; }
};
/**
+5 -56
View File
@@ -185,6 +185,11 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
if (_prefs->getRadioPrefs()->isDirty()) { savePrefs(); }
return;
}
// hook for variant-specific CLI processing
if (_board->handleCommand(command, sender_timestamp, reply)) {
if (_prefs->isDirty()) { savePrefs(); }
return;
}
if (memcmp(command, "poweroff", 8) == 0 || memcmp(command, "shutdown", 8) == 0) {
_board->powerOff(); // doesn't return
@@ -507,50 +512,6 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
_prefs->disable_fwd = memcmp(&config[7], "off", 3) == 0;
savePrefs();
strcpy(reply, _prefs->disable_fwd ? "OK - repeat is now OFF" : "OK - repeat is now ON");
} 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.fem.txgain ", 17) == 0) {
if (!_board->canControlLoRaFemPaGain()) {
strcpy(reply, "Error: unsupported");
} else if (memcmp(&config[17], "on", 2) == 0) {
if (_board->setLoRaFemPaGainEnabled(true)) {
_prefs->radio_fem_txgain = 1;
savePrefs();
strcpy(reply, "OK - LoRa FEM TX gain on");
} else {
strcpy(reply, "Error: failed to apply LoRa FEM TX gain");
}
} else if (memcmp(&config[17], "off", 3) == 0) {
if (_board->setLoRaFemPaGainEnabled(false)) {
_prefs->radio_fem_txgain = 0;
savePrefs();
strcpy(reply, "OK - LoRa FEM TX gain off");
} else {
strcpy(reply, "Error: failed to apply LoRa FEM TX gain");
}
} else {
strcpy(reply, "Error: state must be on or off");
}
} else if (memcmp(config, "lat ", 4) == 0) {
_prefs->node_lat = atof(&config[4]);
savePrefs();
@@ -733,18 +694,6 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->node_lat));
} else if (memcmp(config, "lon", 3) == 0) {
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->node_lon));
} 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.fem.txgain", 16) == 0) {
if (!_board->canControlLoRaFemPaGain()) {
strcpy(reply, "Error: unsupported");
} else {
sprintf(reply, "> %s", _board->isLoRaFemPaGainEnabled() ? "on" : "off");
}
} else if (memcmp(config, "flood.max.advert", 16) == 0) {
sprintf(reply, "> %d", (uint32_t)_prefs->flood_max_advert);
} else if (memcmp(config, "flood.max.unscoped", 18) == 0) {
+6 -1
View File
@@ -128,6 +128,10 @@ private:
void setFloodTxDelay(float d) override { _parent->tx_delay_factor = d; markDirty(); }
float getDirectTxDelay() const override { return _parent->direct_tx_delay_factor; }
void setDirectTxDelay(float d) override { _parent->direct_tx_delay_factor = d; markDirty(); }
uint8_t getFEMRxGain() const override { return _parent->radio_fem_rxgain; }
void setFEMRxGain(uint8_t g) override { _parent->radio_fem_rxgain = g; markDirty(); }
uint8_t getFEMTxGain() const override { return _parent->radio_fem_txgain; }
void setFEMTxGain(uint8_t g) override { _parent->radio_fem_txgain = g; markDirty(); }
};
RadioPrefs radio;
@@ -226,7 +230,8 @@ public:
}
CommonRadioPrefs* getRadioPrefs() { return &radio; }
void clearDirty() { radio.clearDirty(); }
bool isDirty() const override { return ConfigSerializer::isDirty() || radio.isDirty(); }
void clearDirty() override { ConfigSerializer::clearDirty(); radio.clearDirty(); }
};
class CommonCLICallbacks {
+21
View File
@@ -3,6 +3,27 @@
#include "Utils.h"
#include "target.h"
void CommonRadioPrefs::getByKey(const char* key, char* value, size_t max_len) {
if (strcmp(key, "fem_rxgain") == 0) {
snprintf(value, max_len, "%d", (uint32_t)getFEMRxGain());
} else if (strcmp(key, "fem_txgain") == 0) {
snprintf(value, max_len, "%d", (uint32_t)getFEMTxGain());
} else {
MESH_DEBUG_PRINTLN("Error: getBykey() unknown key: %s", key);
}
}
void CommonRadioPrefs::setByKey(const char* key, const char* value) {
if (strcmp(key, "fem_rxgain") == 0) {
setFEMRxGain(atoi(value));
markDirty();
} else if (strcmp(key, "fem_txgain") == 0) {
setFEMTxGain(atoi(value));
markDirty();
} else {
MESH_DEBUG_PRINTLN("Error: setBykey() unknown key: %s", key);
}
}
bool CommonRadioPrefs::handleCommand(const char* command, uint32_t sender_timestamp, char* reply) {
if (strcmp(command, "get radio") == 0) {
char freq[16], bw[16];
+12 -1
View File
@@ -1,6 +1,8 @@
#pragma once
#include "ConfigSerializer.h"
#include "KeyValueStore.h"
class CommonRadioPrefs : public ConfigSerializer {
class CommonRadioPrefs : public ConfigSerializer, public KeyValueStore{
bool _is_dirty = false;
protected:
CommonRadioPrefs() { }
@@ -54,5 +56,14 @@ public:
virtual float getDirectTxDelay() const = 0;
virtual void setDirectTxDelay(float d) = 0;
virtual uint8_t getFEMRxGain() const = 0;
virtual void setFEMRxGain(uint8_t g) = 0;
virtual uint8_t getFEMTxGain() const = 0;
virtual void setFEMTxGain(uint8_t g) = 0;
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply);
void setByKey(const char* key, const char* value) override; // for dynamic key/value access
void getByKey(const char* key, char* value, size_t max_len) override;
};
+6
View File
@@ -17,6 +17,7 @@
class ConfigSerializer {
bool _first;
int8_t _depth;
bool _dirty = false;
enum OP { READ, WRITE };
@@ -62,7 +63,12 @@ protected:
virtual void structure() = 0;
void markDirty() { _dirty = true; }
public:
bool loadSerial(Stream& s);
bool saveSerial(Stream& s);
virtual bool isDirty() const { return _dirty; }
virtual void clearDirty() { _dirty = false; }
};
+3
View File
@@ -15,6 +15,7 @@
#include "soc/rtc.h"
#include "esp_system.h"
#include <driver/rtc_io.h>
#include <helpers/KeyValueStore.h>
class ESP32Board : public mesh::MainBoard {
protected:
@@ -51,6 +52,8 @@ public:
#endif
}
void attachDynamicPrefs(KeyValueStore* prefs) { } // no-op
// Temperature from ESP32 MCU
float getMCUTemperature() override {
uint32_t raw = 0;
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include <stdint.h>
#include <string.h>
class KeyValueStore {
protected:
KeyValueStore() { }
public:
virtual void setByKey(const char* key, const char* value) { }
virtual void getByKey(const char* key, char* value, size_t max_len) { }
};
+3
View File
@@ -2,6 +2,7 @@
#include <Arduino.h>
#include <MeshCore.h>
#include <helpers/KeyValueStore.h>
#if defined(NRF52_PLATFORM)
@@ -57,6 +58,8 @@ public:
virtual void sleep(uint32_t secs) override;
bool isExternalPowered() override;
void attachDynamicPrefs(KeyValueStore* prefs) { } // no-op
#ifdef NRF52_POWER_MANAGEMENT
uint16_t getBootVoltage() override { return boot_voltage_mv; }
virtual uint32_t getResetReason() const override { return reset_reason; }
+3
View File
@@ -2,6 +2,7 @@
#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/KeyValueStore.h>
class STM32Board : public mesh::MainBoard {
protected:
@@ -12,6 +13,8 @@ public:
startup_reason = BD_STARTUP_NORMAL;
}
void attachDynamicPrefs(KeyValueStore* prefs) { } // no-op
uint8_t getStartupReason() const override { return startup_reason; }
uint16_t getBattMilliVolts() override {
+44 -4
View File
@@ -131,10 +131,50 @@ bool T096Board::setLoRaFemLnaEnabled(bool enable) {
return true;
}
bool T096Board::canControlLoRaFemLna() const {
return loRaFEMControl.isLnaCanControl();
}
bool T096Board::isLoRaFemLnaEnabled() const {
return loRaFEMControl.isLNAEnabled();
}
void T096Board::attachDynamicPrefs(KeyValueStore* prefs) {
_prefs = prefs;
char radio_fem_rxgain[8] = { 0 };
_prefs->getByKey("radio.fem_rxgain", radio_fem_rxgain, 7); // get initial values
setLoRaFemLnaEnabled(strcmp(radio_fem_rxgain, "1") == 0);
}
bool T096Board::handleCommand(const char* command, uint32_t sender_timestamp, char* reply) {
if (strcmp(command, "get radio.fem.rxgain") == 0) {
if (!loRaFEMControl.isLnaCanControl()) {
strcpy(reply, "Error: unsupported");
} else {
sprintf(reply, "> %s", isLoRaFemLnaEnabled() ? "on" : "off");
}
return true;
}
if (memcmp(command, "set radio.fem.rxgain ", 21) == 0) {
if (!loRaFEMControl.isLnaCanControl()) {
strcpy(reply, "Error: unsupported");
} else if (memcmp(&command[21], "on", 2) == 0) {
if (setLoRaFemLnaEnabled(true)) {
_prefs->setByKey("radio.fem_rxgain", "1");
strcpy(reply, "OK - LoRa FEM RX gain on");
} else {
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
}
} else if (memcmp(&command[21], "off", 3) == 0) {
if (setLoRaFemLnaEnabled(false)) {
_prefs->setByKey("radio.fem_rxgain", "0");
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");
}
return true;
}
return false; // not handled
}
+9 -3
View File
@@ -4,28 +4,34 @@
#include <Arduino.h>
#include <helpers/NRF52Board.h>
#include <helpers/RefCountedDigitalPin.h>
#include <helpers/KeyValueStore.h>
#include "LoRaFEMControl.h"
class T096Board : public NRF52BoardDCDC {
KeyValueStore* _prefs = NULL;
protected:
#ifdef NRF52_POWER_MANAGEMENT
void initiateShutdown(uint8_t reason) override;
#endif
void variant_shutdown();
bool setLoRaFemLnaEnabled(bool enable);
bool isLoRaFemLnaEnabled() const;
public:
RefCountedDigitalPin periph_power;
LoRaFEMControl loRaFEMControl;
T096Board() :periph_power(PIN_VEXT_EN,PIN_VEXT_EN_ACTIVE), NRF52Board("T096_OTA") {}
void begin();
void attachDynamicPrefs(KeyValueStore* prefs);
void onBeforeTransmit(void) override;
void onAfterTransmit(void) override;
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;
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
};
+80 -8
View File
@@ -21,10 +21,6 @@ bool StationG3Board::setLoRaFemLnaEnabled(bool enable) {
return true;
}
bool StationG3Board::canControlLoRaFemLna() const {
return loRaFEMControl.canControlLNA();
}
bool StationG3Board::isLoRaFemLnaEnabled() const {
return loRaFEMControl.isLNAEnabled();
}
@@ -37,10 +33,86 @@ bool StationG3Board::setLoRaFemPaGainEnabled(bool enable) {
return true;
}
bool StationG3Board::canControlLoRaFemPaGain() const {
return loRaFEMControl.canControlPAGain();
}
bool StationG3Board::isLoRaFemPaGainEnabled() const {
return loRaFEMControl.isPAGainEnabled();
}
void StationG3Board::attachDynamicPrefs(KeyValueStore* prefs) {
_prefs = prefs;
char gain[8];
gain[0] = 0;
_prefs->getByKey("fem_rxgain", gain, 7); // get initial values
setLoRaFemLnaEnabled(strcmp(gain, "1") == 0);
gain[0] = 0;
_prefs->getByKey("fem_txgain", gain, 7); // get initial values
setLoRaFemPaGainEnabled(strcmp(gain, "1") == 0);
}
bool StationG3Board::handleCommand(const char* command, uint32_t sender_timestamp, char* reply) {
if (strcmp(command, "get radio.fem.rxgain") == 0) {
if (!loRaFEMControl.canControlLNA()) {
strcpy(reply, "Error: unsupported");
} else {
sprintf(reply, "> %s", isLoRaFemLnaEnabled() ? "on" : "off");
}
return true;
}
if (memcmp(command, "set radio.fem.rxgain ", 21) == 0) {
if (!loRaFEMControl.canControlLNA()) {
strcpy(reply, "Error: unsupported");
} else if (memcmp(&command[21], "on", 2) == 0) {
if (setLoRaFemLnaEnabled(true)) {
_prefs->setByKey("fem_rxgain", "1");
strcpy(reply, "OK - LoRa FEM RX gain on");
} else {
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
}
} else if (memcmp(&command[21], "off", 3) == 0) {
if (setLoRaFemLnaEnabled(false)) {
_prefs->setByKey("fem_rxgain", "0");
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");
}
return true;
}
if (strcmp(command, "get radio.fem.txgain") == 0) {
if (!loRaFEMControl.canControlPAGain()) {
strcpy(reply, "Error: unsupported");
} else {
sprintf(reply, "> %s", isLoRaFemPaGainEnabled() ? "on" : "off");
}
return true;
}
if (memcmp(command, "set radio.fem.txgain ", 21) == 0) {
if (!loRaFEMControl.canControlPAGain()) {
strcpy(reply, "Error: unsupported");
} else if (memcmp(&command[21], "on", 2) == 0) {
if (setLoRaFemPaGainEnabled(true)) {
_prefs->setByKey("fem_txgain", "1");
strcpy(reply, "OK - LoRa FEM TX gain on");
} else {
strcpy(reply, "Error: failed to apply LoRa FEM TX gain");
}
} else if (memcmp(&command[21], "off", 3) == 0) {
if (setLoRaFemPaGainEnabled(false)) {
_prefs->setByKey("fem_txgain", "0");
strcpy(reply, "OK - LoRa FEM TX gain off");
} else {
strcpy(reply, "Error: failed to apply LoRa FEM TX gain");
}
} else {
strcpy(reply, "Error: state must be on or off");
}
return true;
}
return false; // not handled
}
+10 -7
View File
@@ -6,6 +6,12 @@
#include "LoRaFEMControl.h"
class StationG3Board : public ESP32Board {
KeyValueStore* _prefs = NULL;
bool setLoRaFemLnaEnabled(bool enable);
bool isLoRaFemLnaEnabled() const;
bool setLoRaFemPaGainEnabled(bool enable);
bool isLoRaFemPaGainEnabled() const;
public:
LoRaFEMControl loRaFEMControl;
@@ -25,6 +31,10 @@ public:
}
}
void attachDynamicPrefs(KeyValueStore* prefs);
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
void setPrimaryLNAEnable(bool enabled) {
loRaFEMControl.setLNAEnable(enabled);
}
@@ -43,13 +53,6 @@ public:
loRaFEMControl.setRxModeEnable();
}
bool setLoRaFemLnaEnabled(bool enable) override;
bool canControlLoRaFemLna() const override;
bool isLoRaFemLnaEnabled() const override;
bool setLoRaFemPaGainEnabled(bool enable) override;
bool canControlLoRaFemPaGain() const override;
bool isLoRaFemPaGainEnabled() const override;
void powerOff() override;
uint16_t getBattMilliVolts() override {
@@ -2,6 +2,7 @@
#include <Arduino.h>
#include <MeshCore.h>
#include <helpers/KeyValueStore.h>
// LoRa radio module pins for Waveshare RP2040-LoRa-HF/LF
// https://files.waveshare.com/wiki/RP2040-LoRa/Rp2040-lora-sch.pdf
@@ -32,6 +33,8 @@ public:
void begin();
uint8_t getStartupReason() const override { return startup_reason; }
void attachDynamicPrefs(KeyValueStore* prefs) { } // no-op
#ifdef P_LORA_TX_LED
void onBeforeTransmit() override { digitalWrite(P_LORA_TX_LED, HIGH); }
void onAfterTransmit() override { digitalWrite(P_LORA_TX_LED, LOW); }
+3
View File
@@ -2,6 +2,7 @@
#include <Arduino.h>
#include <MeshCore.h>
#include <helpers/KeyValueStore.h>
/*
* This board has no built-in way to read battery voltage.
@@ -30,6 +31,8 @@ public:
void begin();
uint8_t getStartupReason() const override { return startup_reason; }
void attachDynamicPrefs(KeyValueStore* prefs) { } // no-op
#ifdef P_LORA_TX_LED
void onBeforeTransmit() override { digitalWrite(P_LORA_TX_LED, HIGH); }
void onAfterTransmit() override { digitalWrite(P_LORA_TX_LED, LOW); }