mirror of
https://github.com/pelgraine/Meck.git
synced 2026-06-11 16:54:45 +02:00
353048aab3
GPS — fixed (the "off" toggle and boot path now actually cut the XL9555 rail). Kept in main.cpp + UITask.cpp. BLE controller — the ~13 mA between the BLE build (BLE off) and standalone is the controller staying initialised; the boot-gate in SerialBLEInterface.cpp/.h defers BLEDevice::init() until first enable, reclaiming it. That's the meaningful idle win. CPU, gyro rail, ES8311, frontlight — all measured and ruled out. The residual ~12 mA Max-vs-Pro is distributed always-on hardware with no software switch — hardware overhead, not a bug. Defer ESP32 BLE controller bring-up to first user enable MyMesh::startInterface() called serial.enable() unconditionally at boot. On the ESP32 BLE build this ran the deferred-init SerialBLEInterface's _realBegin()/BLEDevice::init() and powered the BT controller before main.cpp's boot-time disable(), which only stops advertising and cannot power the controller back down -- so the controller stayed up while "off", drawing ~13 mA at idle. Guard the enable() so ESP32 BLE builds skip it at boot; the controller now comes up lazily on the first enable() when the user turns Bluetooth on from the Bluetooth page. WiFi builds are unaffected and still enable at boot.
113 lines
3.1 KiB
C++
113 lines
3.1 KiB
C++
#pragma once
|
|
|
|
#include <Arduino.h>
|
|
|
|
// CPU Frequency Scaling for ESP32-S3
|
|
//
|
|
// Typical current draw (CPU only, rough):
|
|
// 240 MHz ~70-80 mA
|
|
// 160 MHz ~50-60 mA
|
|
// 80 MHz ~30-40 mA
|
|
// 40 MHz ~15-20 mA (low-power / lock screen mode)
|
|
//
|
|
// SPI peripherals and UART use their own clock dividers from the APB clock,
|
|
// so LoRa, e-ink, and GPS serial all work fine at 80MHz and 40MHz.
|
|
|
|
#ifdef ESP32
|
|
|
|
#ifndef CPU_FREQ_IDLE
|
|
#define CPU_FREQ_IDLE 80 // MHz — normal mesh listening
|
|
#endif
|
|
|
|
#ifndef CPU_FREQ_BOOST
|
|
#define CPU_FREQ_BOOST 240 // MHz — heavy processing
|
|
#endif
|
|
|
|
#ifndef CPU_FREQ_LOW_POWER
|
|
#define CPU_FREQ_LOW_POWER 80 // MHz — lock screen / idle standby (40 MHz breaks I2C)
|
|
#endif
|
|
|
|
#ifndef CPU_BOOST_TIMEOUT_MS
|
|
#define CPU_BOOST_TIMEOUT_MS 10000 // 10 seconds
|
|
#endif
|
|
|
|
class CPUPowerManager {
|
|
public:
|
|
CPUPowerManager() : _boosted(false), _lowPower(false), _boost_started(0) {}
|
|
|
|
void begin() {
|
|
setCpuFrequencyMhz(CPU_FREQ_IDLE);
|
|
_boosted = false;
|
|
_lowPower = false;
|
|
MESH_DEBUG_PRINTLN("CPU power: idle at %d MHz", CPU_FREQ_IDLE);
|
|
}
|
|
|
|
void loop() {
|
|
if (_boosted && (millis() - _boost_started >= CPU_BOOST_TIMEOUT_MS)) {
|
|
// Return to low-power if locked, otherwise normal idle
|
|
if (_lowPower) {
|
|
setCpuFrequencyMhz(CPU_FREQ_LOW_POWER);
|
|
MESH_DEBUG_PRINTLN("CPU power: boost expired, returning to low-power %d MHz", CPU_FREQ_LOW_POWER);
|
|
} else {
|
|
setCpuFrequencyMhz(CPU_FREQ_IDLE);
|
|
MESH_DEBUG_PRINTLN("CPU power: idle at %d MHz", CPU_FREQ_IDLE);
|
|
}
|
|
_boosted = false;
|
|
}
|
|
}
|
|
|
|
void setBoost() {
|
|
if (!_boosted) {
|
|
setCpuFrequencyMhz(CPU_FREQ_BOOST);
|
|
_boosted = true;
|
|
MESH_DEBUG_PRINTLN("CPU power: boosted to %d MHz", CPU_FREQ_BOOST);
|
|
}
|
|
_boost_started = millis();
|
|
}
|
|
|
|
void setIdle() {
|
|
if (_boosted) {
|
|
setCpuFrequencyMhz(CPU_FREQ_IDLE);
|
|
_boosted = false;
|
|
MESH_DEBUG_PRINTLN("CPU power: idle at %d MHz", CPU_FREQ_IDLE);
|
|
}
|
|
if (_lowPower) {
|
|
_lowPower = false;
|
|
}
|
|
}
|
|
|
|
// Low-power mode — drops CPU to 40 MHz for lock screen standby.
|
|
// If currently boosted, the boost timeout will return to 40 MHz
|
|
// instead of 80 MHz.
|
|
void setLowPower() {
|
|
_lowPower = true;
|
|
if (!_boosted) {
|
|
setCpuFrequencyMhz(CPU_FREQ_LOW_POWER);
|
|
MESH_DEBUG_PRINTLN("CPU power: low-power at %d MHz", CPU_FREQ_LOW_POWER);
|
|
}
|
|
// If boosted, the loop() timeout will drop to low-power instead of idle
|
|
}
|
|
|
|
// Exit low-power mode — returns to normal idle (80 MHz).
|
|
// If currently boosted, the boost timeout will return to idle
|
|
// instead of low-power.
|
|
void clearLowPower() {
|
|
_lowPower = false;
|
|
if (!_boosted) {
|
|
setCpuFrequencyMhz(CPU_FREQ_IDLE);
|
|
MESH_DEBUG_PRINTLN("CPU power: idle at %d MHz (low-power cleared)", CPU_FREQ_IDLE);
|
|
}
|
|
// If boosted, the loop() timeout will drop to idle as normal
|
|
}
|
|
|
|
bool isBoosted() const { return _boosted; }
|
|
bool isLowPower() const { return _lowPower; }
|
|
uint32_t getFrequencyMHz() const { return getCpuFrequencyMhz(); }
|
|
|
|
private:
|
|
bool _boosted;
|
|
bool _lowPower;
|
|
unsigned long _boost_started;
|
|
};
|
|
|
|
#endif // ESP32
|