mirror of
https://github.com/agessaman/MeshCore.git
synced 2026-10-22 17:31:28 +00:00
kiss_modem: reach FEM gain through the board's radio.fem CLI commands
Boards own their FEM control through handleCommand() ("get/set
radio.fem.rxgain|txgain"). Use that instead of a parallel set of FEM
virtuals on MainBoard, so any board that implements the commands works
in KISS with no extra code.
- Remove the six FEM virtuals from MainBoard and the board overrides.
- KissModem talks to the board in one adapter. A gain counts as
controllable only if "get" replies exactly "> on" or "> off". "set"
is checked by reading the state back, never by its reply wording.
- SetFemState always replies with the read-back state once the
requested bits pass the capability check.
- Guard the boards' prefs writes against a NULL store. KISS attaches
no prefs, so "set radio.fem.*" would dereference NULL.
- Wio Tracker L1 1W TX gain is exposed again, matching its CLI.
This commit is contained in:
1 parent
c387fc22c3
commit
720f0f1528
18 files changed
+161
-100
No files matched your search
@@ -283,7 +283,7 @@ FemState response data:
|
||||
|
||||
Example: enable RX gain without changing TX gain: apply `0x01`, value `0x01`.
|
||||
|
||||
If any bit in the apply mask is not in the board's capability mask (including reserved bits), the modem replies `Unsupported` and changes nothing. On success, SetFemState replies with the FemState response carrying the new state. A SetFemState received while a packet is on air (before its TxDone is queued) is held and applied after TxDone, so its FemState response follows TxDone. While a SetFemState is held or its response is still waiting for output space, GetFemState responses are queued behind it in order, and a further SetFemState returns `TxBusy`. Capabilities come from the board, so a board with a fixed, board-managed FEM (for example RAK3401) reports none.
|
||||
If any bit in the apply mask is not in the board's capability mask (including reserved bits), the modem replies `Unsupported` and changes nothing. Otherwise SetFemState replies with the FemState response carrying the state read back from the board; if a bit differs from the request, that change did not take effect. A SetFemState received while a packet is on air (before its TxDone is queued) is held and applied after TxDone, so its FemState response follows TxDone. While a SetFemState is held or its response is still waiting for output space, GetFemState responses are queued behind it in order, and a further SetFemState returns `TxBusy`. Capabilities come from the board's own `get/set radio.fem.rxgain` and `radio.fem.txgain` CLI commands (see [cli_commands.md](./cli_commands.md)): a gain is controllable when the board answers `get` with `> on` or `> off`. Any board that implements those commands is supported without KISS changes, and a board with a fixed, board-managed FEM (for example RAK3401) reports none. Changes made over KISS are not saved to the board's preferences.
|
||||
|
||||
The setting is not persisted; the board's power-on default applies after reboot.
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "KissModem.h"
|
||||
#include <CayenneLPP.h>
|
||||
#include <stdio.h>
|
||||
|
||||
KissModem::KissModem(Stream& serial, mesh::LocalIdentity& identity, mesh::RNG& rng,
|
||||
mesh::Radio& radio, mesh::MainBoard& board, SensorManager& sensors)
|
||||
@@ -31,7 +32,6 @@ KissModem::KissModem(Stream& serial, mesh::LocalIdentity& identity, mesh::RNG& r
|
||||
_fem_deferred_apply = 0;
|
||||
_fem_deferred_value = 0;
|
||||
_fem_reply_pending = false;
|
||||
_fem_reply_ok = false;
|
||||
_fem_deferred_gets = 0;
|
||||
resetOutputQueue();
|
||||
}
|
||||
@@ -785,8 +785,10 @@ void KissModem::handleGetSignalReport() {
|
||||
|
||||
void KissModem::handleGetCapabilities() {
|
||||
uint32_t caps = HW_CAP_AGC_RESET;
|
||||
if (_board.canControlLoRaFemLna()) caps |= HW_CAP_FEM_RX_GAIN;
|
||||
if (_board.canControlLoRaFemPaGain()) caps |= HW_CAP_FEM_TX_GAIN;
|
||||
uint8_t fem_caps, fem_values;
|
||||
readFemState(&fem_caps, &fem_values);
|
||||
if (fem_caps & HW_FEM_RX_GAIN) caps |= HW_CAP_FEM_RX_GAIN;
|
||||
if (fem_caps & HW_FEM_TX_GAIN) caps |= HW_CAP_FEM_TX_GAIN;
|
||||
if (_setRxBoostedGainCallback && _getRxBoostedGainCallback) caps |= HW_CAP_RX_BOOSTED_GAIN;
|
||||
uint8_t buf[4] = { (uint8_t)caps, (uint8_t)(caps >> 8), (uint8_t)(caps >> 16), (uint8_t)(caps >> 24) };
|
||||
writeHardwareFrame(HW_RESP(HW_CMD_GET_CAPABILITIES), buf, 4);
|
||||
@@ -812,55 +814,81 @@ void KissModem::handleGetAgcResetInterval() {
|
||||
writeHardwareFrame(HW_RESP(HW_CMD_GET_AGC_RESET_INTERVAL), buf, 2);
|
||||
}
|
||||
|
||||
uint8_t KissModem::femCapabilityMask() const {
|
||||
uint8_t mask = 0;
|
||||
if (_board.canControlLoRaFemLna()) mask |= HW_FEM_RX_GAIN;
|
||||
if (_board.canControlLoRaFemPaGain()) mask |= HW_FEM_TX_GAIN;
|
||||
return mask;
|
||||
// FEM gain is reached through the board's own "radio.fem.*" CLI commands, the same ones users run.
|
||||
static const char* femGainName(uint8_t bit) {
|
||||
return bit == HW_FEM_RX_GAIN ? "rxgain" : "txgain";
|
||||
}
|
||||
|
||||
uint8_t KissModem::femValueMask() const {
|
||||
uint8_t mask = 0;
|
||||
if (_board.canControlLoRaFemLna() && _board.isLoRaFemLnaEnabled()) mask |= HW_FEM_RX_GAIN;
|
||||
if (_board.canControlLoRaFemPaGain() && _board.isLoRaFemPaGainEnabled()) mask |= HW_FEM_TX_GAIN;
|
||||
return mask;
|
||||
}
|
||||
|
||||
bool KissModem::queueFemReply(bool ok, bool mark_busy_error) {
|
||||
if (!ok) {
|
||||
const uint8_t err = HW_ERR_UNSUPPORTED;
|
||||
return queueHardwareFrame(HW_RESP_ERROR, &err, 1, mark_busy_error);
|
||||
// Anything but an exact "> on" / "> off" (not handled, "Error: ...", unexpected text) means unsupported.
|
||||
bool KissModem::queryFemGain(uint8_t bit, bool* enabled) {
|
||||
char cmd[32];
|
||||
char reply[KISS_BOARD_REPLY_SIZE] = { 0 };
|
||||
snprintf(cmd, sizeof(cmd), "get radio.fem.%s", femGainName(bit));
|
||||
if (!_board.handleCommand(cmd, 0, reply)) return false;
|
||||
if (strcmp(reply, "> on") == 0) {
|
||||
*enabled = true;
|
||||
} else if (strcmp(reply, "> off") == 0) {
|
||||
*enabled = false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
uint8_t buf[2] = { femCapabilityMask(), femValueMask() };
|
||||
return true;
|
||||
}
|
||||
|
||||
// Success is judged by reading the state back, not by the wording of the set reply.
|
||||
bool KissModem::setFemGain(uint8_t bit, bool enable) {
|
||||
char cmd[32];
|
||||
char reply[KISS_BOARD_REPLY_SIZE] = { 0 };
|
||||
snprintf(cmd, sizeof(cmd), "set radio.fem.%s %s", femGainName(bit), enable ? "on" : "off");
|
||||
_board.handleCommand(cmd, 0, reply);
|
||||
bool now;
|
||||
return queryFemGain(bit, &now) && now == enable;
|
||||
}
|
||||
|
||||
void KissModem::readFemState(uint8_t* caps, uint8_t* values) {
|
||||
*caps = 0;
|
||||
*values = 0;
|
||||
const uint8_t bits[] = { HW_FEM_RX_GAIN, HW_FEM_TX_GAIN };
|
||||
for (uint8_t bit : bits) {
|
||||
bool enabled;
|
||||
if (queryFemGain(bit, &enabled)) {
|
||||
*caps |= bit;
|
||||
if (enabled) *values |= bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool KissModem::queueFemReply(bool mark_busy_error) {
|
||||
uint8_t buf[2];
|
||||
readFemState(&buf[0], &buf[1]);
|
||||
return queueHardwareFrame(HW_RESP(HW_CMD_GET_FEM_STATE), buf, 2, mark_busy_error);
|
||||
}
|
||||
|
||||
bool KissModem::applyFemState(uint8_t apply_mask, uint8_t value_mask) {
|
||||
bool ok = true;
|
||||
// The reply always carries the read-back state, so a bit that failed to apply shows its real value.
|
||||
void KissModem::applyFemState(uint8_t apply_mask, uint8_t value_mask) {
|
||||
if (apply_mask & HW_FEM_RX_GAIN) {
|
||||
ok &= _board.setLoRaFemLnaEnabled((value_mask & HW_FEM_RX_GAIN) != 0);
|
||||
setFemGain(HW_FEM_RX_GAIN, (value_mask & HW_FEM_RX_GAIN) != 0);
|
||||
}
|
||||
if (apply_mask & HW_FEM_TX_GAIN) {
|
||||
ok &= _board.setLoRaFemPaGainEnabled((value_mask & HW_FEM_TX_GAIN) != 0);
|
||||
setFemGain(HW_FEM_TX_GAIN, (value_mask & HW_FEM_TX_GAIN) != 0);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
void KissModem::processDeferredFem() {
|
||||
// wait for TxDone to be queued so the host sees the TX result before the FEM change
|
||||
if (_fem_deferred && _tx_state != TX_SENDING && _tx_state != TX_DONE_PENDING) {
|
||||
_fem_reply_ok = applyFemState(_fem_deferred_apply, _fem_deferred_value);
|
||||
applyFemState(_fem_deferred_apply, _fem_deferred_value);
|
||||
_fem_deferred = false;
|
||||
_fem_reply_pending = true;
|
||||
}
|
||||
if (_fem_deferred) return;
|
||||
// replies are retained until queued, and GetFemState replies stay behind the Set reply
|
||||
if (_fem_reply_pending) {
|
||||
if (!queueFemReply(_fem_reply_ok, false)) return;
|
||||
if (!queueFemReply(false)) return;
|
||||
_fem_reply_pending = false;
|
||||
}
|
||||
while (_fem_deferred_gets > 0) {
|
||||
if (!queueFemReply(true, false)) return;
|
||||
if (!queueFemReply(false)) return;
|
||||
_fem_deferred_gets--;
|
||||
}
|
||||
}
|
||||
@@ -873,7 +901,9 @@ void KissModem::handleSetFemState(const uint8_t* data, uint16_t len) {
|
||||
uint8_t apply_mask = data[0];
|
||||
uint8_t value_mask = data[1];
|
||||
// validate every requested bit before touching hardware so a request is all-or-nothing
|
||||
if (apply_mask & ~femCapabilityMask()) {
|
||||
uint8_t fem_caps, fem_values;
|
||||
readFemState(&fem_caps, &fem_values);
|
||||
if (apply_mask & ~fem_caps) {
|
||||
writeHardwareError(HW_ERR_UNSUPPORTED);
|
||||
return;
|
||||
}
|
||||
@@ -888,7 +918,7 @@ void KissModem::handleSetFemState(const uint8_t* data, uint16_t len) {
|
||||
_fem_deferred_value = value_mask;
|
||||
return;
|
||||
}
|
||||
_fem_reply_ok = applyFemState(apply_mask, value_mask);
|
||||
applyFemState(apply_mask, value_mask);
|
||||
_fem_reply_pending = true;
|
||||
processDeferredFem();
|
||||
}
|
||||
@@ -902,7 +932,7 @@ void KissModem::handleGetFemState() {
|
||||
_fem_deferred_gets++;
|
||||
return;
|
||||
}
|
||||
queueFemReply(true, true);
|
||||
queueFemReply(true);
|
||||
}
|
||||
|
||||
void KissModem::handleSetRxBoostedGain(const uint8_t* data, uint16_t len) {
|
||||
|
||||
@@ -100,6 +100,9 @@
|
||||
#define HW_FEM_RX_GAIN (1 << 0)
|
||||
#define HW_FEM_TX_GAIN (1 << 1)
|
||||
|
||||
/* Matches the CLI reply buffer boards write into from handleCommand() */
|
||||
#define KISS_BOARD_REPLY_SIZE 160
|
||||
|
||||
#define KISS_AGC_RESET_DEFAULT_SEC 30
|
||||
#define KISS_AGC_RESET_MAX_SEC 1020
|
||||
#define KISS_AGC_RESET_STEP_SEC 4
|
||||
@@ -173,7 +176,6 @@ class KissModem {
|
||||
uint8_t _fem_deferred_apply;
|
||||
uint8_t _fem_deferred_value;
|
||||
bool _fem_reply_pending;
|
||||
bool _fem_reply_ok;
|
||||
uint8_t _fem_deferred_gets;
|
||||
uint8_t _tx_frame_buf[KISS_TX_FRAME_QUEUE_DEPTH][KISS_MAX_ENCODED_FRAME_SIZE];
|
||||
uint16_t _tx_frame_len[KISS_TX_FRAME_QUEUE_DEPTH];
|
||||
@@ -202,10 +204,11 @@ class KissModem {
|
||||
void handleHardwareCommand(uint8_t sub_cmd, const uint8_t* data, uint16_t len);
|
||||
void processTx();
|
||||
void maybeResetAgc();
|
||||
uint8_t femCapabilityMask() const;
|
||||
uint8_t femValueMask() const;
|
||||
bool queueFemReply(bool ok, bool mark_busy_error);
|
||||
bool applyFemState(uint8_t apply_mask, uint8_t value_mask);
|
||||
bool queryFemGain(uint8_t bit, bool* enabled);
|
||||
bool setFemGain(uint8_t bit, bool enable);
|
||||
void readFemState(uint8_t* caps, uint8_t* values);
|
||||
bool queueFemReply(bool mark_busy_error);
|
||||
void applyFemState(uint8_t apply_mask, uint8_t value_mask);
|
||||
bool isFemReplyQueued() const { return _fem_deferred || _fem_reply_pending || _fem_deferred_gets > 0; }
|
||||
void processDeferredFem();
|
||||
|
||||
|
||||
@@ -77,14 +77,6 @@ public:
|
||||
|
||||
virtual bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) { return false; }
|
||||
|
||||
// External LoRa front-end (FEM) gain control. Boards without a controllable FEM keep these defaults.
|
||||
virtual bool canControlLoRaFemLna() const { return false; }
|
||||
virtual bool setLoRaFemLnaEnabled(bool enable) { return false; }
|
||||
virtual bool isLoRaFemLnaEnabled() const { return false; }
|
||||
virtual bool canControlLoRaFemPaGain() const { return false; }
|
||||
virtual bool setLoRaFemPaGainEnabled(bool enable) { return false; }
|
||||
virtual bool isLoRaFemPaGainEnabled() const { return false; }
|
||||
|
||||
// Called from the example main loops. Lets a board feed its watchdog and
|
||||
// run periodic housekeeping. Default no-op.
|
||||
virtual void loop() { /* no op */ }
|
||||
|
||||
+1
-6
@@ -23,12 +23,7 @@ public:
|
||||
virtual float getMCUTemperature() { return 25.0f; }
|
||||
virtual const char* getManufacturerName() { return "mock-board"; }
|
||||
virtual void reboot() {}
|
||||
virtual bool canControlLoRaFemLna() const { return false; }
|
||||
virtual bool setLoRaFemLnaEnabled(bool) { return false; }
|
||||
virtual bool isLoRaFemLnaEnabled() const { return false; }
|
||||
virtual bool canControlLoRaFemPaGain() const { return false; }
|
||||
virtual bool setLoRaFemPaGainEnabled(bool) { return false; }
|
||||
virtual bool isLoRaFemPaGainEnabled() const { return false; }
|
||||
virtual bool handleCommand(const char*, uint32_t, char*) { return false; }
|
||||
};
|
||||
|
||||
}
|
||||
@@ -72,31 +72,50 @@ public:
|
||||
int agc_resets = 0;
|
||||
};
|
||||
|
||||
// Implements FEM through the "radio.fem.*" CLI text, worded like the Heltec / Station G3 boards.
|
||||
class FemBoard : public mesh::MainBoard {
|
||||
public:
|
||||
const char* getManufacturerName() override { return "fem-board"; }
|
||||
|
||||
bool canControlLoRaFemLna() const override { return has_lna; }
|
||||
bool setLoRaFemLnaEnabled(bool enable) override {
|
||||
if (!has_lna) return false;
|
||||
lna = enable;
|
||||
lna_sets++;
|
||||
return true;
|
||||
bool handleCommand(const char* command, uint32_t, char* reply) override {
|
||||
commands++;
|
||||
if (handleGain(command, reply, "rxgain", has_lna, lna, lna_sets, lna_sticks)) return true;
|
||||
if (handleGain(command, reply, "txgain", has_pa, pa, pa_sets, pa_sticks)) return true;
|
||||
return false;
|
||||
}
|
||||
bool isLoRaFemLnaEnabled() const override { return lna; }
|
||||
|
||||
bool canControlLoRaFemPaGain() const override { return has_pa; }
|
||||
bool setLoRaFemPaGainEnabled(bool enable) override {
|
||||
if (!has_pa) return false;
|
||||
pa = enable;
|
||||
pa_sets++;
|
||||
return true;
|
||||
}
|
||||
bool isLoRaFemPaGainEnabled() const override { return pa; }
|
||||
|
||||
bool has_lna = false, has_pa = false;
|
||||
bool lna = false, pa = false;
|
||||
int lna_sets = 0, pa_sets = 0;
|
||||
bool lna_sticks = false, pa_sticks = false; // set reports OK but the state does not change
|
||||
bool unhandled = false; // board does not implement radio.fem.* at all
|
||||
const char* odd_get_reply = nullptr; // unexpected get wording
|
||||
int commands = 0;
|
||||
|
||||
private:
|
||||
bool handleGain(const char* command, char* reply, const char* name, bool has, bool& state, int& sets, bool sticks) {
|
||||
if (unhandled) return false;
|
||||
char get_cmd[32], set_cmd[32];
|
||||
snprintf(get_cmd, sizeof(get_cmd), "get radio.fem.%s", name);
|
||||
snprintf(set_cmd, sizeof(set_cmd), "set radio.fem.%s ", name);
|
||||
if (strcmp(command, get_cmd) == 0) {
|
||||
if (!has) strcpy(reply, "Error: unsupported");
|
||||
else if (odd_get_reply) strcpy(reply, odd_get_reply);
|
||||
else sprintf(reply, "> %s", state ? "on" : "off");
|
||||
return true;
|
||||
}
|
||||
if (strncmp(command, set_cmd, strlen(set_cmd)) == 0) {
|
||||
if (!has) {
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else {
|
||||
sets++;
|
||||
if (!sticks) state = strcmp(command + strlen(set_cmd), "on") == 0;
|
||||
strcpy(reply, "OK - LoRa FEM gain changed");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class NoSensors : public SensorManager {
|
||||
@@ -276,6 +295,31 @@ TEST_F(KissHwControlTest, FemUnknownBitsAreUnsupported) {
|
||||
EXPECT_EQ(hw1({HW_CMD_SET_FEM_STATE, 0x04, 0x04}), ERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
TEST_F(KissHwControlTest, FemUnhandledCommandsMeanUnsupported) {
|
||||
board.has_lna = board.has_pa = true;
|
||||
board.unhandled = true;
|
||||
EXPECT_EQ(hw1({HW_CMD_GET_FEM_STATE}), (std::vector<uint8_t>{0x9F, 0x00, 0x00}));
|
||||
EXPECT_EQ(hw1({HW_CMD_GET_CAPABILITIES}), (std::vector<uint8_t>{0x9B, 0x01, 0x00, 0x00, 0x00}));
|
||||
EXPECT_EQ(hw1({HW_CMD_SET_FEM_STATE, HW_FEM_RX_GAIN, HW_FEM_RX_GAIN}), ERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
TEST_F(KissHwControlTest, FemUnexpectedGetWordingMeansUnsupported) {
|
||||
board.has_lna = true;
|
||||
board.odd_get_reply = "> enabled";
|
||||
EXPECT_EQ(hw1({HW_CMD_GET_FEM_STATE}), (std::vector<uint8_t>{0x9F, 0x00, 0x00}));
|
||||
EXPECT_EQ(hw1({HW_CMD_SET_FEM_STATE, HW_FEM_RX_GAIN, HW_FEM_RX_GAIN}), ERR_UNSUPPORTED);
|
||||
EXPECT_EQ(board.lna_sets, 0);
|
||||
}
|
||||
|
||||
TEST_F(KissHwControlTest, FemSetThatDoesNotTakeRepliesWithReadBackState) {
|
||||
board.has_lna = board.has_pa = true;
|
||||
board.lna_sticks = true; // board says OK but LNA stays off
|
||||
EXPECT_EQ(hw1({HW_CMD_SET_FEM_STATE, HW_FEM_RX_GAIN | HW_FEM_TX_GAIN, HW_FEM_RX_GAIN | HW_FEM_TX_GAIN}),
|
||||
(std::vector<uint8_t>{0x9F, 0x03, 0x02}));
|
||||
EXPECT_FALSE(board.lna);
|
||||
EXPECT_TRUE(board.pa);
|
||||
}
|
||||
|
||||
TEST_F(KissHwControlTest, FemShortPayloadIsInvalidLength) {
|
||||
EXPECT_EQ(hw1({HW_CMD_SET_FEM_STATE, HW_FEM_RX_GAIN}), (std::vector<uint8_t>{HW_RESP_ERROR, HW_ERR_INVALID_LENGTH}));
|
||||
}
|
||||
|
||||
@@ -158,14 +158,14 @@ bool T096Board::handleCommand(const char* command, uint32_t sender_timestamp, ch
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemLnaEnabled(true)) {
|
||||
_prefs->setByKey("fem_rxgain", "1");
|
||||
if (_prefs) _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");
|
||||
if (_prefs) _prefs->setByKey("fem_rxgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
|
||||
@@ -16,6 +16,9 @@ protected:
|
||||
#endif
|
||||
void variant_shutdown();
|
||||
|
||||
bool setLoRaFemLnaEnabled(bool enable);
|
||||
bool isLoRaFemLnaEnabled() const;
|
||||
|
||||
public:
|
||||
RefCountedDigitalPin periph_power;
|
||||
LoRaFEMControl loRaFEMControl;
|
||||
@@ -24,9 +27,6 @@ public:
|
||||
void begin();
|
||||
void attachDynamicPrefs(KeyValueStore* prefs);
|
||||
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
|
||||
bool canControlLoRaFemLna() const override { return loRaFEMControl.isLnaCanControl(); }
|
||||
bool setLoRaFemLnaEnabled(bool enable) override;
|
||||
bool isLoRaFemLnaEnabled() const override;
|
||||
|
||||
void onBeforeTransmit(void) override;
|
||||
void onAfterTransmit(void) override;
|
||||
|
||||
@@ -99,14 +99,14 @@ bool HeltecTrackerV2Board::handleCommand(const char* command, uint32_t sender_ti
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemLnaEnabled(true)) {
|
||||
_prefs->setByKey("fem_rxgain", "1");
|
||||
if (_prefs) _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");
|
||||
if (_prefs) _prefs->setByKey("fem_rxgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
class HeltecTrackerV2Board : public ESP32Board {
|
||||
KeyValueStore* _prefs = NULL;
|
||||
|
||||
bool setLoRaFemLnaEnabled(bool enable);
|
||||
bool isLoRaFemLnaEnabled() const;
|
||||
|
||||
public:
|
||||
RefCountedDigitalPin periph_power;
|
||||
LoRaFEMControl loRaFEMControl;
|
||||
@@ -17,9 +20,6 @@ public:
|
||||
void begin();
|
||||
void attachDynamicPrefs(KeyValueStore* prefs);
|
||||
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
|
||||
bool canControlLoRaFemLna() const override { return loRaFEMControl.isLnaCanControl(); }
|
||||
bool setLoRaFemLnaEnabled(bool enable) override;
|
||||
bool isLoRaFemLnaEnabled() const override;
|
||||
|
||||
void onBeforeTransmit(void) override;
|
||||
void onAfterTransmit(void) override;
|
||||
|
||||
@@ -100,14 +100,14 @@ bool HeltecV4Board::handleCommand(const char* command, uint32_t sender_timestamp
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemLnaEnabled(true)) {
|
||||
_prefs->setByKey("fem_rxgain", "1");
|
||||
if (_prefs) _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");
|
||||
if (_prefs) _prefs->setByKey("fem_rxgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
class HeltecV4Board : public ESP32Board {
|
||||
KeyValueStore* _prefs = NULL;
|
||||
|
||||
bool setLoRaFemLnaEnabled(bool enable);
|
||||
bool isLoRaFemLnaEnabled() const;
|
||||
|
||||
protected:
|
||||
float adc_mult = ADC_MULTIPLIER;
|
||||
|
||||
@@ -23,9 +26,6 @@ public:
|
||||
void begin();
|
||||
void attachDynamicPrefs(KeyValueStore* prefs);
|
||||
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
|
||||
bool canControlLoRaFemLna() const override { return loRaFEMControl.isLnaCanControl(); }
|
||||
bool setLoRaFemLnaEnabled(bool enable) override;
|
||||
bool isLoRaFemLnaEnabled() const override;
|
||||
|
||||
void onBeforeTransmit(void) override;
|
||||
void onAfterTransmit(void) override;
|
||||
|
||||
@@ -122,14 +122,14 @@ bool HeltecV4R8Board::handleCommand(const char* command, uint32_t sender_timesta
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemLnaEnabled(true)) {
|
||||
_prefs->setByKey("fem_rxgain", "1");
|
||||
if (_prefs) _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");
|
||||
if (_prefs) _prefs->setByKey("fem_rxgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
class HeltecV4R8Board : public ESP32Board {
|
||||
KeyValueStore* _prefs = NULL;
|
||||
|
||||
bool setLoRaFemLnaEnabled(bool enable);
|
||||
bool isLoRaFemLnaEnabled() const;
|
||||
protected:
|
||||
float adc_mult = ADC_MULTIPLIER;
|
||||
|
||||
@@ -25,9 +27,6 @@ public:
|
||||
void begin();
|
||||
void attachDynamicPrefs(KeyValueStore* prefs);
|
||||
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
|
||||
bool canControlLoRaFemLna() const override { return loRaFEMControl.isLnaCanControl(); }
|
||||
bool setLoRaFemLnaEnabled(bool enable) override;
|
||||
bool isLoRaFemLnaEnabled() const override;
|
||||
|
||||
void onBeforeTransmit(void) override;
|
||||
void onAfterTransmit(void) override;
|
||||
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
void setRxModeEnable(void);
|
||||
void setRxModeEnableWhenMCUSleep(void);
|
||||
void setLNAEnable(bool enabled);
|
||||
bool isLnaCanControl(void) const { return true; }
|
||||
bool isLnaCanControl(void) { return true; }
|
||||
void setLnaCanControl(bool can_control) { }
|
||||
bool isLNAEnabled(void) const { return lna_enabled; }
|
||||
LoRaFEMType getFEMType(void) const { return KCT8103L_PA; }
|
||||
|
||||
@@ -65,14 +65,14 @@ bool StationG3Board::handleCommand(const char* command, uint32_t sender_timestam
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemLnaEnabled(true)) {
|
||||
_prefs->setByKey("fem_rxgain", "1");
|
||||
if (_prefs) _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");
|
||||
if (_prefs) _prefs->setByKey("fem_rxgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM RX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM RX gain");
|
||||
@@ -96,14 +96,14 @@ bool StationG3Board::handleCommand(const char* command, uint32_t sender_timestam
|
||||
strcpy(reply, "Error: unsupported");
|
||||
} else if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemPaGainEnabled(true)) {
|
||||
_prefs->setByKey("fem_txgain", "1");
|
||||
if (_prefs) _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");
|
||||
if (_prefs) _prefs->setByKey("fem_txgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM TX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM TX gain");
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
class StationG3Board : public ESP32Board {
|
||||
KeyValueStore* _prefs = NULL;
|
||||
|
||||
bool setLoRaFemLnaEnabled(bool enable);
|
||||
bool isLoRaFemLnaEnabled() const;
|
||||
bool setLoRaFemPaGainEnabled(bool enable);
|
||||
bool isLoRaFemPaGainEnabled() const;
|
||||
public:
|
||||
LoRaFEMControl loRaFEMControl;
|
||||
|
||||
@@ -30,12 +34,6 @@ public:
|
||||
void attachDynamicPrefs(KeyValueStore* prefs);
|
||||
|
||||
bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override;
|
||||
bool canControlLoRaFemLna() const override { return loRaFEMControl.canControlLNA(); }
|
||||
bool setLoRaFemLnaEnabled(bool enable) override;
|
||||
bool isLoRaFemLnaEnabled() const override;
|
||||
bool canControlLoRaFemPaGain() const override { return loRaFEMControl.canControlPAGain(); }
|
||||
bool setLoRaFemPaGainEnabled(bool enable) override;
|
||||
bool isLoRaFemPaGainEnabled() const override;
|
||||
|
||||
void setPrimaryLNAEnable(bool enabled) {
|
||||
loRaFEMControl.setLNAEnable(enabled);
|
||||
|
||||
@@ -65,14 +65,14 @@ bool WioTrackerL1Board::handleCommand(const char* command, uint32_t sender_times
|
||||
if (memcmp(command, "set radio.fem.txgain ", 21) == 0) {
|
||||
if (memcmp(&command[21], "on", 2) == 0) {
|
||||
if (setLoRaFemPaGainEnabled(true)) {
|
||||
_prefs->setByKey("fem_txgain", "1");
|
||||
if (_prefs) _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");
|
||||
if (_prefs) _prefs->setByKey("fem_txgain", "0");
|
||||
strcpy(reply, "OK - LoRa FEM TX gain off");
|
||||
} else {
|
||||
strcpy(reply, "Error: failed to apply LoRa FEM TX gain");
|
||||
|
||||
Reference in new issue
Block a user