Apply saved TX power automatically across firmware roles
This commit is contained in:
1 parent
31e5d54074
commit
65928aae95
51 files changed
+3838
-2728
No files matched your search
@@ -1972,6 +1972,8 @@ void MyMesh::onRadioProfileCopyQueued(mesh::Packet* packet, const mesh::Packet*
|
||||
|
||||
void MyMesh::onSendComplete(mesh::Packet* packet) {
|
||||
mesh::Mesh::onSendComplete(packet);
|
||||
// Use the completed packet's idle gap before a busy queue starts another TX.
|
||||
servicePendingTxPower();
|
||||
_morse_reply.complete(packet);
|
||||
}
|
||||
|
||||
@@ -3534,8 +3536,7 @@ void MyMesh::finishRadioParamApply(float freq, float bw, uint8_t sf,
|
||||
return;
|
||||
}
|
||||
|
||||
// Preserve an outstanding power rollback; the full saved-radio recovery
|
||||
// checks both the tuple and TX power before clearing this latch.
|
||||
// Preserve any earlier saved-radio recovery while committing the tuple.
|
||||
saved_radio_apply_pending = previous_recovery_pending;
|
||||
radio_apply_retry_at = 0;
|
||||
radio_apply_failures = 0;
|
||||
@@ -3546,24 +3547,22 @@ void MyMesh::finishRadioParamApply(float freq, float bw, uint8_t sf,
|
||||
writeOKFrame(route);
|
||||
}
|
||||
|
||||
void MyMesh::deferRadioCommand(uint8_t kind) {
|
||||
void MyMesh::deferRadioCommand() {
|
||||
command_radio_reply_route = _serial->captureReplyRoute();
|
||||
if (command_radio_reply_route == NULL) {
|
||||
writeErrFrame(ERR_CODE_BAD_STATE);
|
||||
return;
|
||||
}
|
||||
command_radio_apply_pending = kind;
|
||||
command_radio_apply_pending = true;
|
||||
command_radio_apply_deadline = futureMillis(COMMAND_RADIO_APPLY_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
void MyMesh::cancelPendingRadioParamApply() {
|
||||
if (!command_radio_apply_pending) return;
|
||||
|
||||
const bool restore_tuple = command_radio_apply_pending == 1;
|
||||
command_radio_apply_pending = false;
|
||||
command_radio_apply_deadline = 0;
|
||||
command_radio_reply_route = NULL;
|
||||
if (!restore_tuple) return;
|
||||
// The requested tuple was not committed. Reassert the persisted tuple in
|
||||
// case a failed hardware apply only restored part of the old configuration.
|
||||
saved_radio_apply_pending = true;
|
||||
@@ -3583,20 +3582,6 @@ void MyMesh::servicePendingRadioParamApply() {
|
||||
|
||||
const bool expired = static_cast<int32_t>(static_cast<uint32_t>(
|
||||
_ms->getMillis() - command_radio_apply_deadline)) >= 0;
|
||||
if (command_radio_apply_pending == 2) {
|
||||
const auto result = expired ? RadioSettingResult::RadioBusy
|
||||
: applyAndSaveTxPower(static_cast<int8_t>(command_radio_repeat), true);
|
||||
if (result == RadioSettingResult::RadioBusy
|
||||
&& !expired) return;
|
||||
if (result == RadioSettingResult::Saved) writeOKFrame(command_radio_reply_route);
|
||||
else writeErrFrame(result == RadioSettingResult::SaveFailed
|
||||
? ERR_CODE_FILE_IO_ERROR : ERR_CODE_BAD_STATE, command_radio_reply_route);
|
||||
// The checked setter owns any failed-save rollback. Retire this command
|
||||
// without forcing a tuple restore or consuming a pending receive.
|
||||
cancelPendingRadioParamApply();
|
||||
return;
|
||||
}
|
||||
|
||||
mesh::RadioParamApplyResult result = tryApplyRadioParams(
|
||||
command_radio_freq, command_radio_bw, command_radio_sf, command_radio_cr);
|
||||
if (result == mesh::RadioParamApplyResult::APPLIED) {
|
||||
@@ -5687,9 +5672,10 @@ void MyMesh::execCommand(char* cmd, char* reply) {
|
||||
snprintf(reply, 160, "Error: TX -9..%d dBm", MAX_LORA_TX_POWER);
|
||||
} else {
|
||||
const auto result = applyAndSaveTxPower(static_cast<int8_t>(parsed));
|
||||
strcpy(reply, result == RadioSettingResult::Saved ? "OK"
|
||||
strcpy(reply, result == RadioSettingResult::Saved
|
||||
? (tx_power_apply_pending ? "OK - saved; pending" : "OK")
|
||||
: result != RadioSettingResult::SaveFailed
|
||||
? "Error: radio busy or TX power rejected"
|
||||
? "Error: TX power rejected"
|
||||
: "Error: TX not saved");
|
||||
}
|
||||
return;
|
||||
@@ -6808,7 +6794,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
command_radio_sf = sf;
|
||||
command_radio_cr = cr;
|
||||
command_radio_repeat = repeat;
|
||||
deferRadioCommand(1);
|
||||
deferRadioCommand();
|
||||
MESH_DEBUG_PRINTLN("Deferred CMD_SET_RADIO_PARAMS while radio is busy");
|
||||
return;
|
||||
}
|
||||
@@ -6836,15 +6822,8 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
int8_t power = (int8_t)cmd_frame[1];
|
||||
if (power < -9 || power > MAX_LORA_TX_POWER) {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
} else if (command_radio_apply_pending) {
|
||||
writeErrFrame(ERR_CODE_BAD_STATE);
|
||||
} else {
|
||||
const auto result = applyAndSaveTxPower(power);
|
||||
if (result == RadioSettingResult::RadioBusy) {
|
||||
command_radio_repeat = static_cast<uint8_t>(power);
|
||||
deferRadioCommand(2);
|
||||
return;
|
||||
}
|
||||
if (result == RadioSettingResult::Saved) writeOKFrame();
|
||||
else writeErrFrame(result == RadioSettingResult::RadioRejected
|
||||
? ERR_CODE_BAD_STATE : ERR_CODE_FILE_IO_ERROR);
|
||||
@@ -8488,32 +8467,47 @@ bool MyMesh::saveAdvertLocation(double latitude, double longitude) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MyMesh::RadioSettingResult MyMesh::applyAndSaveTxPower(int8_t power, bool from_pending) {
|
||||
if (command_radio_apply_pending && !from_pending) return RadioSettingResult::RadioBusy;
|
||||
MyMesh::RadioSettingResult MyMesh::applyAndSaveTxPower(int8_t power) {
|
||||
if (!radio_driver.isTxPowerValid(power)) return RadioSettingResult::RadioRejected;
|
||||
const int8_t previous = _prefs.tx_power_dbm;
|
||||
if (_radio_available) {
|
||||
const auto result = radio_driver.trySetTxPower(power);
|
||||
if (result != mesh::RadioParamApplyResult::APPLIED) {
|
||||
return result == mesh::RadioParamApplyResult::BUSY
|
||||
? RadioSettingResult::RadioBusy : RadioSettingResult::RadioRejected;
|
||||
}
|
||||
const auto result = _radio_available && !command_radio_apply_pending
|
||||
? radio_driver.trySetTxPower(power) : mesh::RadioParamApplyResult::BUSY;
|
||||
if (result == mesh::RadioParamApplyResult::FAILED) {
|
||||
// A rejected SPI transaction may have partly changed the hardware. Keep
|
||||
// the saved setting authoritative and restore it without retuning RX.
|
||||
tx_power_apply_pending = true;
|
||||
tx_power_apply_retry_at = 0;
|
||||
return RadioSettingResult::RadioRejected;
|
||||
}
|
||||
_prefs.tx_power_dbm = power;
|
||||
if (savePrefs()) return RadioSettingResult::Saved;
|
||||
if (savePrefs()) {
|
||||
tx_power_apply_pending = result != mesh::RadioParamApplyResult::APPLIED;
|
||||
tx_power_apply_retry_at = 0;
|
||||
return RadioSettingResult::Saved;
|
||||
}
|
||||
|
||||
_prefs.tx_power_dbm = previous;
|
||||
if (_radio_available && !radio_driver.setTxPower(previous)) {
|
||||
// An RX packet can arrive between the apply and its failed flash commit.
|
||||
// Keep retrying the durable power rather than leaving the rejected value
|
||||
// active until reboot. Recovery also restores the saved tuple, so an
|
||||
// active TempRadio lease deliberately delays it until the lease ends.
|
||||
saved_radio_apply_pending = true;
|
||||
radio_apply_retry_at = 0;
|
||||
radio_apply_failures = 0;
|
||||
// A busy attempt has not changed the earlier pending target or retry time.
|
||||
if (result == mesh::RadioParamApplyResult::APPLIED) {
|
||||
tx_power_apply_pending = !radio_driver.setTxPower(previous);
|
||||
tx_power_apply_retry_at = 0;
|
||||
}
|
||||
return RadioSettingResult::SaveFailed;
|
||||
}
|
||||
|
||||
void MyMesh::servicePendingTxPower() {
|
||||
if (!tx_power_apply_pending || !_radio_available || command_radio_apply_pending
|
||||
|| (_radio && _radio->isCarrierWaveActive())) return;
|
||||
const uint32_t now = _ms->getMillis();
|
||||
if (tx_power_apply_retry_at
|
||||
&& static_cast<int32_t>(now - tx_power_apply_retry_at) < 0) return;
|
||||
const auto result = radio_driver.trySetTxPower(_prefs.tx_power_dbm);
|
||||
if (result == mesh::RadioParamApplyResult::APPLIED) tx_power_apply_pending = false;
|
||||
// Busy admission does not touch RX. Back off actual hardware failures.
|
||||
tx_power_apply_retry_at = result == mesh::RadioParamApplyResult::FAILED
|
||||
? (now + 1000u ? now + 1000u : 1u) : 0;
|
||||
}
|
||||
|
||||
bool MyMesh::applyAndSaveFemRxGain(bool enabled) {
|
||||
// Binary Companion setters and WebConfig also enter through this helper.
|
||||
// Do not alter an external FEM while the Morse transmitter owns it.
|
||||
@@ -10957,6 +10951,17 @@ bool MyMesh::handleCommand(const char* command, uint32_t sender_timestamp,
|
||||
|
||||
if (handleLocalControlCommand(command, reply, reply_capacity)) return true;
|
||||
|
||||
#if defined(MESH_HIL_TX_FREQ_MHZ)
|
||||
// RF test builds verify active power before permitting any test TX.
|
||||
if (strcmp(command, "get tx.status") == 0) {
|
||||
snprintf(reply, reply_capacity, "> desired=%d,apply=%s", (int)_prefs.tx_power_dbm,
|
||||
!tx_power_apply_pending && _radio_available
|
||||
&& radio_driver.isTxPowerApplied(_prefs.tx_power_dbm)
|
||||
? "applied" : "pending");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strncmp(command, "set tx ", 7) == 0) {
|
||||
int32_t parsed = 0;
|
||||
if (!mesh::cli::parseIntegerStrict(command + 7, parsed)) {
|
||||
@@ -10967,12 +10972,13 @@ bool MyMesh::handleCommand(const char* command, uint32_t sender_timestamp,
|
||||
} else {
|
||||
const int8_t requested = static_cast<int8_t>(parsed);
|
||||
const auto result = applyAndSaveTxPower(requested);
|
||||
if (result == RadioSettingResult::RadioRejected || result == RadioSettingResult::RadioBusy) {
|
||||
mesh::cli::formatError(reply, reply_capacity, "radio busy or TX power rejected");
|
||||
if (result == RadioSettingResult::RadioRejected) {
|
||||
mesh::cli::formatError(reply, reply_capacity, "TX power rejected");
|
||||
} else if (result == RadioSettingResult::SaveFailed) {
|
||||
mesh::cli::formatError(reply, reply_capacity, "TX not saved");
|
||||
} else {
|
||||
strcpy(reply, "OK");
|
||||
snprintf(reply, reply_capacity, "%s",
|
||||
tx_power_apply_pending ? "OK - saved; pending" : "OK");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -11618,6 +11624,7 @@ void MyMesh::loop() {
|
||||
#endif
|
||||
}
|
||||
servicePendingRadioParamApply();
|
||||
servicePendingTxPower();
|
||||
#if MESH_ENABLE_ONE_KEY_DM
|
||||
if (held_dm_count != 0 || verified_pending_count != 0) releaseHeldOneKeyDMs();
|
||||
#endif
|
||||
@@ -11710,7 +11717,7 @@ bool MyMesh::canRecoverUsbLogging() const {
|
||||
&& !_store->hasPendingAdvertWrites()
|
||||
#endif
|
||||
&& !hasOutbound() && !isAnyTempRadioActive() && !hasPendingOtaApply()
|
||||
&& !command_radio_apply_pending && !saved_radio_apply_pending
|
||||
&& !command_radio_apply_pending && !saved_radio_apply_pending && !tx_power_apply_pending
|
||||
&& _scheduled_reboot_at == 0 && !hasPendingReqs()
|
||||
&& !_delayed_replies.hasBinaryTrace() && sign_data == NULL
|
||||
#if COMPANION_FEATURE_TEXT_TERMINAL
|
||||
@@ -11755,7 +11762,8 @@ mesh::powerdiag::Mask MyMesh::pendingWorkReason() const {
|
||||
if (_iter_started && _serial != NULL
|
||||
&& _serial->isReplyRouteAvailable(_iter_reply_route)) return mask(Reason::SerialIO);
|
||||
if (hasPendingOtaApply()) return mask(Reason::Ota);
|
||||
if (command_radio_apply_pending || _scheduled_reboot_at != 0) return mask(Reason::Scheduled);
|
||||
if (command_radio_apply_pending || (tx_power_apply_pending && _radio_available)
|
||||
|| _scheduled_reboot_at != 0) return mask(Reason::Scheduled);
|
||||
if (hasPendingReqs() || _delayed_replies.hasBinaryTrace()) return mask(Reason::Mesh);
|
||||
#if COMPANION_FEATURE_TEXT_TERMINAL
|
||||
if (_terminal_trace_pending) return mask(Reason::Mesh);
|
||||
|
||||
@@ -675,8 +675,9 @@ private:
|
||||
bool applyAndSaveFemRxGain(bool enabled);
|
||||
bool applyAndSaveFemTxGain(bool enabled);
|
||||
bool applyAndSaveRxBoostedGain(bool enabled);
|
||||
enum class RadioSettingResult { Saved, RadioRejected, SaveFailed, RadioBusy };
|
||||
RadioSettingResult applyAndSaveTxPower(int8_t power, bool from_pending = false);
|
||||
enum class RadioSettingResult { Saved, RadioRejected, SaveFailed };
|
||||
RadioSettingResult applyAndSaveTxPower(int8_t power);
|
||||
void servicePendingTxPower();
|
||||
bool handleCadCommand(const char* command, char* reply, size_t reply_size);
|
||||
bool saveBluetoothNameOverride(const char* name);
|
||||
bool applyAndSaveBluetoothName(const char* value, char* reply,
|
||||
@@ -749,7 +750,7 @@ private:
|
||||
void finishRadioParamApply(float freq, float bw, uint8_t sf, uint8_t cr,
|
||||
uint8_t repeat,
|
||||
BaseSerialInterface* route = nullptr);
|
||||
void deferRadioCommand(uint8_t kind);
|
||||
void deferRadioCommand();
|
||||
void cancelPendingRadioParamApply();
|
||||
void servicePendingRadioParamApply();
|
||||
void servicePendingSerialReply();
|
||||
@@ -911,10 +912,11 @@ private:
|
||||
#endif
|
||||
bool saved_radio_apply_pending;
|
||||
bool _radio_available;
|
||||
bool tx_power_apply_pending = false;
|
||||
uint32_t tx_power_apply_retry_at = 0;
|
||||
unsigned long radio_apply_retry_at;
|
||||
uint8_t radio_apply_failures;
|
||||
// 0: none, 1: modulation tuple, 2: TX power (stored in the repeat byte).
|
||||
uint8_t command_radio_apply_pending;
|
||||
bool command_radio_apply_pending;
|
||||
float command_radio_freq;
|
||||
float command_radio_bw;
|
||||
uint8_t command_radio_sf;
|
||||
|
||||
@@ -4376,6 +4376,7 @@ bool MyMesh::sendRepeatersFloodText(const char* text, const TransportKey* scope,
|
||||
|
||||
void MyMesh::onSendComplete(mesh::Packet* packet) {
|
||||
mesh::Mesh::onSendComplete(packet);
|
||||
_cli.servicePendingTxPower();
|
||||
_cli.morseReply().complete(packet);
|
||||
#if MESH_ENABLE_FLEET_CONTROL
|
||||
if (_cli.fleetChannel()) _cli.fleetChannel()->complete(packet, _cli.radioProfiles());
|
||||
@@ -5882,6 +5883,16 @@ bool MyMesh::setTxPower(int8_t power_dbm) {
|
||||
return radio_driver.setTxPower(power_dbm);
|
||||
}
|
||||
|
||||
mesh::RadioParamApplyResult MyMesh::trySetTxPower(int8_t power_dbm) {
|
||||
return radio_driver.trySetTxPower(power_dbm);
|
||||
}
|
||||
|
||||
#if defined(MESH_HIL_TX_FREQ_MHZ)
|
||||
bool MyMesh::isTxPowerApplied(int8_t power_dbm) const {
|
||||
return radio_driver.isTxPowerApplied(power_dbm);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool MyMesh::setRxPowerSaving(bool enable, uint32_t rx_us, uint32_t sleep_us) {
|
||||
bool ok = radio_driver.setRxPowerSaving(enable, rx_us, sleep_us);
|
||||
MESH_DEBUG_PRINTLN("RX Power Saving: %s (%lu/%lu us)%s",
|
||||
@@ -14791,7 +14802,8 @@ mesh::powerdiag::Mask MyMesh::pendingWorkReason() const {
|
||||
#if defined(WITH_WEBCONFIG) || defined(ETHERNET_ENABLED)
|
||||
if (_local_cli_output.busy()) return mask(Reason::SerialIO);
|
||||
#endif
|
||||
if (deferred_cli_command.pending || pending_self_advert || _cli.hasActiveUserGpioTimer()) return mask(Reason::Scheduled);
|
||||
if (deferred_cli_command.pending || pending_self_advert || _cli.hasActiveUserGpioTimer()
|
||||
|| _cli.hasPendingTxPower()) return mask(Reason::Scheduled);
|
||||
#if defined(WITH_BRIDGE)
|
||||
const AbstractBridge* active_bridge = activeBridge();
|
||||
if (active_bridge && active_bridge->isRunning()) {
|
||||
|
||||
@@ -1282,6 +1282,10 @@ public:
|
||||
void cancelPendingSerialOutput();
|
||||
#endif
|
||||
bool setTxPower(int8_t power_dbm) override;
|
||||
mesh::RadioParamApplyResult trySetTxPower(int8_t power_dbm) override;
|
||||
#if defined(MESH_HIL_TX_FREQ_MHZ)
|
||||
bool isTxPowerApplied(int8_t power_dbm) const override;
|
||||
#endif
|
||||
bool setRxPowerSaving(bool enable, uint32_t rx_us, uint32_t sleep_us) override;
|
||||
bool supportsRxPowerSavingRfRxDisable() const override;
|
||||
bool setRxPowerSavingRfRxDisabled(bool disabled) override;
|
||||
@@ -1356,7 +1360,7 @@ public:
|
||||
#endif
|
||||
bool canRecoverUsbLogging() const {
|
||||
return dirty_contacts_expiry == 0 && !hasOutbound() && !isAnyTempRadioActive()
|
||||
&& !hasPendingOtaApply() && !saved_radio_apply_pending
|
||||
&& !hasPendingOtaApply() && !saved_radio_apply_pending && !_cli.hasPendingTxPower()
|
||||
&& !temp_radio_handoff_pending && _ota_update_at == 0;
|
||||
}
|
||||
#if MESH_ENABLE_FLOOD_RULE_ENGINE
|
||||
|
||||
@@ -2424,6 +2424,7 @@ void MyMesh::onGroupPacketRecv(mesh::Packet* packet) {
|
||||
|
||||
void MyMesh::onSendComplete(mesh::Packet* packet) {
|
||||
mesh::Mesh::onSendComplete(packet);
|
||||
_cli.servicePendingTxPower();
|
||||
_cli.morseReply().complete(packet);
|
||||
#if MESH_ENABLE_FLEET_CONTROL
|
||||
if (_cli.fleetChannel()) _cli.fleetChannel()->complete(packet, _cli.radioProfiles());
|
||||
@@ -3190,6 +3191,16 @@ bool MyMesh::setTxPower(int8_t power_dbm) {
|
||||
return radio_driver.setTxPower(power_dbm);
|
||||
}
|
||||
|
||||
mesh::RadioParamApplyResult MyMesh::trySetTxPower(int8_t power_dbm) {
|
||||
return radio_driver.trySetTxPower(power_dbm);
|
||||
}
|
||||
|
||||
#if defined(MESH_HIL_TX_FREQ_MHZ)
|
||||
bool MyMesh::isTxPowerApplied(int8_t power_dbm) const {
|
||||
return radio_driver.isTxPowerApplied(power_dbm);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool MyMesh::setRxPowerSaving(bool enable, uint32_t rx_us, uint32_t sleep_us) {
|
||||
return radio_driver.setRxPowerSaving(enable, rx_us, sleep_us);
|
||||
}
|
||||
@@ -4489,6 +4500,7 @@ mesh::powerdiag::Mask MyMesh::pendingWorkReason() const {
|
||||
using mesh::powerdiag::Reason;
|
||||
if (!canIdleDualRadio()) return mask(Reason::DualRadio);
|
||||
if (hasPendingOtaApply()) return mask(Reason::Ota);
|
||||
if (_cli.hasPendingTxPower()) return mask(Reason::Scheduled);
|
||||
#if defined(ESP32_PLATFORM)
|
||||
if (mesh::wifi::networkPower().foregroundActive()) return mask(Reason::Network);
|
||||
#endif
|
||||
|
||||
@@ -620,6 +620,10 @@ public:
|
||||
void cancelPendingSerialOutput();
|
||||
#endif
|
||||
bool setTxPower(int8_t power_dbm) override;
|
||||
mesh::RadioParamApplyResult trySetTxPower(int8_t power_dbm) override;
|
||||
#if defined(MESH_HIL_TX_FREQ_MHZ)
|
||||
bool isTxPowerApplied(int8_t power_dbm) const override;
|
||||
#endif
|
||||
bool setRxPowerSaving(bool enable, uint32_t rx_us, uint32_t sleep_us) override;
|
||||
void recalibrateNoiseFloor() override { _radio->recalibrateNoiseFloor(); }
|
||||
void getRxPsWatchdogCounts(uint32_t* soft, uint32_t* hard) override;
|
||||
@@ -700,7 +704,7 @@ public:
|
||||
#endif
|
||||
bool canRecoverUsbLogging() const {
|
||||
return dirty_contacts_expiry == 0 && !hasOutbound() && !isAnyTempRadioActive()
|
||||
&& !hasPendingOtaApply() && !saved_radio_apply_pending
|
||||
&& !hasPendingOtaApply() && !saved_radio_apply_pending && !_cli.hasPendingTxPower()
|
||||
&& set_radio_at == 0 && _ota_update_at == 0;
|
||||
}
|
||||
#if MESH_ENABLE_ROOM_FLOOD_RULE_ENGINE
|
||||
|
||||
@@ -1110,6 +1110,7 @@ bool SensorMesh::handleIncomingMsg(ClientInfo& from, uint32_t timestamp, uint8_t
|
||||
#if !MESH_ENABLE_SENSOR_TRACKER
|
||||
void SensorMesh::onSendComplete(mesh::Packet* packet) {
|
||||
mesh::Mesh::onSendComplete(packet);
|
||||
_cli.servicePendingTxPower();
|
||||
_cli.morseReply().complete(packet);
|
||||
}
|
||||
|
||||
@@ -1460,6 +1461,16 @@ bool SensorMesh::setTxPower(int8_t power_dbm) {
|
||||
return radio_driver.setTxPower(power_dbm);
|
||||
}
|
||||
|
||||
mesh::RadioParamApplyResult SensorMesh::trySetTxPower(int8_t power_dbm) {
|
||||
return radio_driver.trySetTxPower(power_dbm);
|
||||
}
|
||||
|
||||
#if defined(MESH_HIL_TX_FREQ_MHZ)
|
||||
bool SensorMesh::isTxPowerApplied(int8_t power_dbm) const {
|
||||
return radio_driver.isTxPowerApplied(power_dbm);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool SensorMesh::setRxPowerSaving(bool enable, uint32_t rx_us, uint32_t sleep_us) {
|
||||
return radio_driver.setRxPowerSaving(enable, rx_us, sleep_us);
|
||||
}
|
||||
@@ -1730,7 +1741,7 @@ mesh::powerdiag::Mask SensorMesh::pendingWorkReason() const {
|
||||
#endif
|
||||
if (!canIdleDualRadio()) return mask(Reason::DualRadio);
|
||||
if (hasPendingOtaApply()) return mask(Reason::Ota);
|
||||
if (_cli.hasActiveUserGpioTimer()) return mask(Reason::Scheduled);
|
||||
if (_cli.hasActiveUserGpioTimer() || _cli.hasPendingTxPower()) return mask(Reason::Scheduled);
|
||||
if (radio_driver.isWatchdogObserving()) return mask(Reason::RadioWatchdog);
|
||||
uint32_t noise_floor_delay_ms;
|
||||
if (getNextNoiseFloorWakeDelay(noise_floor_delay_ms) && noise_floor_delay_ms == 0)
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
void loop();
|
||||
bool canRecoverUsbLogging() const {
|
||||
return dirty_contacts_expiry == 0 && !hasOutbound() && !isAnyTempRadioActive()
|
||||
&& !hasPendingOtaApply() && !saved_radio_apply_pending
|
||||
&& !hasPendingOtaApply() && !saved_radio_apply_pending && !_cli.hasPendingTxPower()
|
||||
&& set_radio_at == 0;
|
||||
}
|
||||
void handleCommand(uint32_t sender_timestamp, char* command, char* reply,
|
||||
@@ -115,6 +115,10 @@ public:
|
||||
void eraseLogFile() override { }
|
||||
void dumpLogFile() override { }
|
||||
bool setTxPower(int8_t power_dbm) override;
|
||||
mesh::RadioParamApplyResult trySetTxPower(int8_t power_dbm) override;
|
||||
#if defined(MESH_HIL_TX_FREQ_MHZ)
|
||||
bool isTxPowerApplied(int8_t power_dbm) const override;
|
||||
#endif
|
||||
bool setRxPowerSaving(bool enable, uint32_t rx_us, uint32_t sleep_us) override;
|
||||
void recalibrateNoiseFloor() override { _radio->recalibrateNoiseFloor(); }
|
||||
void getRxPsWatchdogCounts(uint32_t* soft, uint32_t* hard) override;
|
||||
|
||||
@@ -83,7 +83,8 @@ bool SensorMesh::trackerNeedsRadio() const {
|
||||
|| board.isRadioTestActive() || mesh::isUsbLoggingWatchdogArmed()
|
||||
|| isAnyTempRadioActive() || hasPendingOtaApply() || isDualRadioActive()
|
||||
|| set_radio_at || revert_radio_at || saved_radio_apply_pending
|
||||
|| _cli.hasActiveUserGpioTimer() || hasOutbound() || _mgr->getOutboundTotal() != 0)
|
||||
|| _cli.hasActiveUserGpioTimer() || _cli.hasPendingTxPower()
|
||||
|| hasOutbound() || _mgr->getOutboundTotal() != 0)
|
||||
return true;
|
||||
uint32_t delay;
|
||||
if (hasPendingRadioWork() || getNextRetryWakeDelay(delay)) return true;
|
||||
@@ -269,6 +270,7 @@ bool SensorMesh::handleTrackerPath(mesh::Packet* packet, uint8_t* path, uint8_t
|
||||
|
||||
void SensorMesh::onSendComplete(mesh::Packet* packet) {
|
||||
mesh::Mesh::onSendComplete(packet);
|
||||
_cli.servicePendingTxPower();
|
||||
_cli.morseReply().complete(packet);
|
||||
if (!tracker_pending || !packet || packet->getPayloadType() != PAYLOAD_TYPE_REQ) return;
|
||||
uint8_t hash[MAX_HASH_SIZE];
|
||||
|
||||
Reference in new issue
Block a user