PowerSaving for companions
This commit is contained in:
1 parent
af23f95041
commit
b522479d11
6 files changed
+188
-4
No files matched your search
@@ -925,7 +925,14 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
|
||||
_prefs.tx_power_dbm = LORA_TX_POWER;
|
||||
_prefs.gps_enabled = 0; // GPS disabled by default
|
||||
_prefs.gps_interval = 0; // No automatic GPS updates by default
|
||||
_prefs.radio_fem_rxgain = 1;
|
||||
|
||||
// PowerSaving variant
|
||||
#ifdef RADIO_FEM_RXGAIN
|
||||
_prefs.radio_fem_rxgain = RADIO_FEM_RXGAIN;
|
||||
#else
|
||||
_prefs.radio_fem_rxgain = 0;
|
||||
#endif
|
||||
|
||||
#ifdef RADIO_FEM_TXGAIN
|
||||
_prefs.radio_fem_txgain = RADIO_FEM_TXGAIN; // board-specific default for PA
|
||||
#else
|
||||
@@ -940,6 +947,15 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
|
||||
_prefs.rx_boosted_gain = 1; // enabled by default
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// PowerSaving variant
|
||||
// PowerSaving defaults
|
||||
_prefs.powersaving_enabled = 1;
|
||||
|
||||
// RXPS defaults - Balanced profile
|
||||
_prefs.rxps.enabled = 1;
|
||||
_prefs.rxps.level = 6;
|
||||
_prefs.rxps.preamble = 16;
|
||||
}
|
||||
|
||||
void MyMesh::begin() {
|
||||
@@ -1003,6 +1019,10 @@ void MyMesh::begin() {
|
||||
_store->loadChannels(this);
|
||||
|
||||
radio_driver.setParams(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
|
||||
|
||||
// PowerSaving variant
|
||||
_prefs.getRadioPrefs()->applyRxPowerSaving(_prefs.sf, _prefs.bw);
|
||||
|
||||
radio_driver.setTxPower(_prefs.tx_power_dbm);
|
||||
radio_driver.setRxBoostedGainMode(_prefs.rx_boosted_gain);
|
||||
|
||||
@@ -1448,6 +1468,10 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
savePrefs();
|
||||
|
||||
radio_driver.setParams(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
|
||||
|
||||
// PowerSaving variant
|
||||
_prefs.getRadioPrefs()->applyRxPowerSaving(_prefs.sf, _prefs.bw);
|
||||
|
||||
MESH_DEBUG_PRINTLN("OK: CMD_SET_RADIO_PARAMS: f=%d, bw=%d, sf=%d, cr=%d", freq, bw, (uint32_t)sf,
|
||||
(uint32_t)cr);
|
||||
|
||||
@@ -1705,7 +1729,11 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, temperature); // Built-in MCU Temperature
|
||||
}
|
||||
|
||||
// PowerSaving variant
|
||||
// query other sensors -- target specific
|
||||
if (sensors.getLocationProvider() != NULL && sensors.getLocationProvider()->isPowerSavingEnabled()) {
|
||||
sensors.getLocationProvider()->syncTime(); // Request for GPS sync if GPS is in PowerSaving
|
||||
}
|
||||
sensors.querySensors(0xFF, telemetry);
|
||||
|
||||
int i = 0;
|
||||
@@ -2181,6 +2209,18 @@ bool MyMesh::handleCommand(const char* command, uint32_t sender_timestamp, char*
|
||||
}
|
||||
#endif
|
||||
|
||||
// PowerSaving variant
|
||||
if (strcmp(command, "powersaving on") == 0 || strcmp(command, "powersaving off") == 0) {
|
||||
_prefs.powersaving_enabled = strcmp(command, "powersaving on") == 0 ? 1 : 0;
|
||||
savePrefs();
|
||||
strcpy(reply, _prefs.powersaving_enabled ? "on" : "off");
|
||||
return true;
|
||||
}
|
||||
if (strcmp(command, "powersaving") == 0) {
|
||||
strcpy(reply, _prefs.powersaving_enabled ? "on" : "off");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strcmp(command, "board") == 0) {
|
||||
strcpy(reply, board.getManufacturerName());
|
||||
return true;
|
||||
@@ -2448,7 +2488,8 @@ bool MyMesh::advert() {
|
||||
}
|
||||
}
|
||||
|
||||
// PowerSaving variant
|
||||
// To check if there is pending work
|
||||
bool MyMesh::hasPendingWork() const {
|
||||
return _mgr->getOutboundTotal() > 0 || dirty_contacts_expiry != 0;
|
||||
return _mgr->getOutboundTotal() > 0 || dirty_contacts_expiry != 0 || isTransmitting() || _prefs.getRadioPrefs()->isRxPowerSavingCalibrationActive();
|
||||
}
|
||||
@@ -37,6 +37,10 @@ public:
|
||||
uint32_t gps_interval = 0; // GPS read interval in seconds
|
||||
uint8_t autoadd_config = 0; // bitmask for auto-add contacts config
|
||||
uint8_t rx_boosted_gain = 0; // SX126x RX boosted gain mode (0=power saving, 1=boosted)
|
||||
|
||||
// PowerSaving variant
|
||||
RxPowerSavingConfig rxps;
|
||||
|
||||
uint8_t radio_fem_rxgain = 0; // external LoRa FEM RX gain (LNA)
|
||||
uint8_t radio_fem_txgain = 0; // external LoRa FEM TX gain (low by default)
|
||||
uint8_t _client_repeat = 0; // DEPRECATED -> use repeat.disable_fwd
|
||||
@@ -48,6 +52,10 @@ public:
|
||||
char default_scope_name[31];
|
||||
uint8_t default_scope_key[16];
|
||||
int8_t tz_offset = 0;
|
||||
|
||||
// PowerSaving variant
|
||||
uint8_t powersaving_enabled = 0; // boolean
|
||||
|
||||
#ifdef ENABLE_WIFI_INTERFACE
|
||||
#ifndef WIFI_SSID
|
||||
#define WIFI_SSID ""
|
||||
@@ -81,10 +89,19 @@ private:
|
||||
def("agc_int", _parent->agc_reset_interval);
|
||||
def("hash_mode", _parent->path_hash_mode);
|
||||
def("multi_ack", _parent->multi_acks);
|
||||
// PowerSaving variant
|
||||
def("rxps_en", _parent->rxps.enabled);
|
||||
def("rxps_rx_us", _parent->rxps.rx_us);
|
||||
def("rxps_sleep_us", _parent->rxps.sleep_us);
|
||||
def("rxps_level", _parent->rxps.level);
|
||||
def("rxps_preamble", _parent->rxps.preamble);
|
||||
}
|
||||
public:
|
||||
RadioPrefs(NodePrefs* parent) : _parent(parent) { }
|
||||
|
||||
// PowerSaving variant
|
||||
RxPowerSavingConfig* getRxPowerSavingConfig() override { return &_parent->rxps; }
|
||||
|
||||
// CommonRadioPrefs interface
|
||||
float getFreq() const override { return _parent->freq; }
|
||||
void setFreq(float f) override { _parent->freq = f; markDirty(); }
|
||||
@@ -172,6 +189,18 @@ private:
|
||||
};
|
||||
CompanionPrefs companion;
|
||||
|
||||
// PowerSaving variant
|
||||
class PowerPrefs : public ConfigSerializer { // same keys as CommonCLI
|
||||
NodePrefs* _parent;
|
||||
protected:
|
||||
void structure() override {
|
||||
def("pwr_sav_en", _parent->powersaving_enabled);
|
||||
}
|
||||
public:
|
||||
PowerPrefs(NodePrefs* parent) : _parent(parent) { }
|
||||
};
|
||||
PowerPrefs power;
|
||||
|
||||
DynamicConfigSerializer custom;
|
||||
|
||||
#ifdef ENABLE_WIFI_INTERFACE
|
||||
@@ -200,13 +229,17 @@ protected:
|
||||
def("gps", gps);
|
||||
def("repeat", repeat);
|
||||
def("comp", companion);
|
||||
|
||||
// PowerSaving variant
|
||||
def("power", power);
|
||||
|
||||
def("custom", custom);
|
||||
#ifdef ENABLE_WIFI_INTERFACE
|
||||
def("wifi", wifi);
|
||||
#endif
|
||||
}
|
||||
public:
|
||||
NodePrefs() : radio(this), gps(this), companion(this), custom(&radio)
|
||||
NodePrefs() : radio(this), gps(this), companion(this), power(this), custom(&radio)
|
||||
#ifdef ENABLE_WIFI_INTERFACE
|
||||
, wifi(this)
|
||||
#endif
|
||||
@@ -220,6 +253,9 @@ public:
|
||||
void setRepeatEn(bool en) { repeat.disable_fwd = en ? 0 : 1; }
|
||||
|
||||
CommonRadioPrefs* getRadioPrefs() { return &radio; }
|
||||
// PowerSaving variant
|
||||
const CommonRadioPrefs* getRadioPrefs() const { return &radio; }
|
||||
|
||||
KeyValueStore* getCustom() { return &custom; }
|
||||
|
||||
bool isDirty() const override { return ConfigSerializer::isDirty() || radio.isDirty() || custom.isDirty(); }
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(ESP32_PLATFORM)
|
||||
// PowerSaving for companions
|
||||
static void enableCompanionPowerSaving() {
|
||||
#if defined(BLE_PIN_CODE) && !CONFIG_IDF_TARGET_ESP32C6
|
||||
// Enable BLE sleep
|
||||
esp_bt_sleep_enable();
|
||||
#endif
|
||||
|
||||
// Configure Power Management
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
esp_pm_config_esp32c3_t pm_config;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
esp_pm_config_esp32s3_t pm_config;
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
esp_pm_config_esp32_t pm_config;
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
esp_pm_config_t pm_config;
|
||||
#endif
|
||||
|
||||
#if (defined(ARDUINO_USB_CDC_ON_BOOT) && ARDUINO_USB_CDC_ON_BOOT) || defined(ENABLE_USB_INTERFACE)
|
||||
// Disable automatic light sleep for USB CDC Serial and USB Companion
|
||||
pm_config = { .max_freq_mhz = 80, .min_freq_mhz = 40, .light_sleep_enable = false };
|
||||
#else
|
||||
pm_config = { .max_freq_mhz = 80, .min_freq_mhz = 40, .light_sleep_enable = true };
|
||||
#endif
|
||||
|
||||
esp_err_t errPM = esp_pm_configure(&pm_config);
|
||||
if (errPM == ESP_OK) {
|
||||
Serial.println("Power Management configured successfully");
|
||||
} else {
|
||||
Serial.printf("Power Management failed to configure: %d\r\n", errPM);
|
||||
}
|
||||
}
|
||||
|
||||
static void disableCompanionPowerSaving() {
|
||||
// Disable BLE sleep
|
||||
esp_bt_sleep_disable();
|
||||
|
||||
// Configure Power Management
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
esp_pm_config_esp32c3_t pm_config;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
esp_pm_config_esp32s3_t pm_config;
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
esp_pm_config_esp32_t pm_config;
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
esp_pm_config_t pm_config;
|
||||
#endif
|
||||
|
||||
#if defined(ESP32_CPU_FREQ)
|
||||
pm_config = { .max_freq_mhz = ESP32_CPU_FREQ, .min_freq_mhz = ESP32_CPU_FREQ, .light_sleep_enable = false };
|
||||
#else
|
||||
pm_config = { .max_freq_mhz = 80, .min_freq_mhz = 80, .light_sleep_enable = false };
|
||||
#endif
|
||||
|
||||
esp_err_t errPM = esp_pm_configure(&pm_config);
|
||||
if (errPM == ESP_OK) {
|
||||
Serial.println("Power Management configured successfully");
|
||||
} else {
|
||||
Serial.printf("Power Management failed to configure: %d\r\n", errPM);
|
||||
}
|
||||
}
|
||||
|
||||
static void applyCompanionPowerSaving(bool powersaving_enabled) {
|
||||
if (the_mesh.getNodePrefs()->powersaving_enabled) {
|
||||
enableCompanionPowerSaving();
|
||||
} else {
|
||||
disableCompanionPowerSaving();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -2,6 +2,12 @@
|
||||
#include <Mesh.h>
|
||||
#include "MyMesh.h"
|
||||
|
||||
#ifdef ESP32_PLATFORM
|
||||
#include "esp_pm.h"
|
||||
#include "esp_bt.h"
|
||||
#include "PowerSaving.h"
|
||||
#endif
|
||||
|
||||
// Believe it or not, this std C function is busted on some platforms!
|
||||
static uint32_t _atoi(const char* sp) {
|
||||
uint32_t n = 0;
|
||||
@@ -287,6 +293,10 @@ void setup() {
|
||||
#endif
|
||||
|
||||
board.onBootComplete();
|
||||
|
||||
#if defined(ESP32_PLATFORM)
|
||||
applyCompanionPowerSaving(the_mesh.getNodePrefs()->powersaving_enabled);
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@@ -302,12 +312,28 @@ void loop() {
|
||||
external_watchdog.loop();
|
||||
#endif
|
||||
|
||||
if (!the_mesh.hasPendingWork()) {
|
||||
if (the_mesh.getNodePrefs()->powersaving_enabled && !the_mesh.hasPendingWork()) {
|
||||
#if defined(NRF52_PLATFORM)
|
||||
board.sleep(0); // nrf ignores seconds param, sleeps whenever possible
|
||||
#elif defined(ESP32_PLATFORM)
|
||||
#if defined(BLE_PIN_CODE)
|
||||
if (!bluetooth_interface.isReadBusy() && !bluetooth_interface.isWriteBusy()) { // BLE is not busy
|
||||
vTaskDelay(pdMS_TO_TICKS(10)); // attempt to sleep
|
||||
}
|
||||
#elif defined(ENABLE_USB_INTERFACE)
|
||||
vTaskDelay(pdMS_TO_TICKS(10)); // attempt to sleep
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(ESP32_PLATFORM)
|
||||
static uint8_t applied_powersaving = the_mesh.getNodePrefs()->powersaving_enabled;
|
||||
if (the_mesh.getNodePrefs()->powersaving_enabled != applied_powersaving) { // changed via CLI
|
||||
applied_powersaving = the_mesh.getNodePrefs()->powersaving_enabled;
|
||||
applyCompanionPowerSaving(applied_powersaving);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_WIFI_INTERFACE
|
||||
if (wifi_enabled) {
|
||||
// RP2040 has no WiFi event callbacks, so poll the link state instead
|
||||
|
||||
@@ -98,6 +98,9 @@ public:
|
||||
virtual Packet* removeOutboundByIdx(int i) = 0;
|
||||
virtual void queueInbound(Packet* packet, uint32_t scheduled_for) = 0;
|
||||
virtual Packet* getNextInbound(uint32_t now) = 0;
|
||||
|
||||
// PowerSaving variant
|
||||
virtual int getInboundTotal() const { return 0; } // delayed (rxdelay) packets not yet processed
|
||||
};
|
||||
|
||||
typedef uint32_t DispatcherAction;
|
||||
@@ -173,6 +176,8 @@ protected:
|
||||
virtual unsigned long getDutyCycleWindowMs() const { return 3600000; }
|
||||
|
||||
public:
|
||||
// PowerSaving variant
|
||||
bool isTransmitting() const { return outbound != nullptr; }
|
||||
void begin();
|
||||
void loop();
|
||||
|
||||
|
||||
@@ -38,4 +38,7 @@ public:
|
||||
mesh::Packet* removeOutboundByIdx(int i) override;
|
||||
void queueInbound(mesh::Packet* packet, uint32_t scheduled_for) override;
|
||||
mesh::Packet* getNextInbound(uint32_t now) override;
|
||||
|
||||
// PowerSaving variant
|
||||
int getInboundTotal() const override { return rx_queue.count(); }
|
||||
};
|
||||
Reference in new issue
Block a user