v1.4.0: LVGL UI, async radio TX, live TCP management, input fixes

- Migrate all screens to LVGL v8.4 widget system
- Non-blocking radio TX (async endPacket via LoRaInterface)
- Live TCP server switching with transient node cleanup
- Fix UI freeze during radio transmit
- Trackball long-press delete, deferred click with debounce
- Pin microReticulum to 392363c, fix list_directory API
- Fix CI build: portable include path, remove hardcoded local path
This commit is contained in:
DeFiDude
2026-03-07 13:00:59 -07:00
parent 9b7980665c
commit 07025bfa23
51 changed files with 3895 additions and 309 deletions
+24 -6
View File
@@ -37,6 +37,13 @@ int Power::batteryPercent() const {
return (int)((v - 3.0f) / 1.2f * 100.0f);
}
uint8_t Power::percentToPWM(uint8_t pct) const {
if (pct == 0) return 0;
if (pct >= 100) return 255;
// Map 1-100 to ~6-255 (minimum visible PWM ~6)
return (uint8_t)(6 + (uint16_t)(pct - 1) * 249 / 99);
}
void Power::activity() {
_lastActivity = millis();
if (_state != ACTIVE) {
@@ -44,10 +51,18 @@ void Power::activity() {
}
}
void Power::setBrightness(uint8_t brightness) {
_fullBrightness = brightness;
void Power::weakActivity() {
_lastActivity = millis();
// Trackball wakes from DIM but not from SCREEN_OFF
if (_state == DIMMED) {
setState(ACTIVE);
}
}
void Power::setBrightness(uint8_t percent) {
_brightnessPct = constrain(percent, 1, 100);
if (_state == ACTIVE) {
display.setBrightness(_fullBrightness);
display.setBrightness(percentToPWM(_brightnessPct));
}
}
@@ -76,15 +91,18 @@ void Power::loop() {
void Power::setState(State newState) {
if (newState == _state) return;
State oldState = _state;
_state = newState;
switch (_state) {
case ACTIVE:
display.wakeup();
display.setBrightness(_fullBrightness);
if (oldState == SCREEN_OFF) {
display.wakeup();
}
display.setBrightness(percentToPWM(_brightnessPct));
break;
case DIMMED:
display.setBrightness(DIM_BRIGHTNESS);
display.setBrightness(DIM_PWM);
break;
case SCREEN_OFF:
display.setBrightness(0);