mirror of
https://github.com/ratspeak/ratdeck.git
synced 2026-05-16 04:15:10 +00:00
Add keyboard backlight config and control
- Add user config for brightness and auto-on/off control. - Auto-switch backlight on/off according to power state.
This commit is contained in:
@@ -52,6 +52,9 @@ bool UserConfig::parseJson(const String& json) {
|
||||
if (rawBri > 100) rawBri = rawBri * 100 / 255; // Migrate from PWM to percentage
|
||||
_settings.brightness = constrain(rawBri, 1, 100);
|
||||
_settings.denseFontMode = doc["dense_font"] | false;
|
||||
_settings.keyboardBrightness = doc["kb_brightness"] | 100;
|
||||
_settings.keyboardAutoOn = doc["kb_auto_on"] | false;
|
||||
_settings.keyboardAutoOff = doc["kb_auto_off"] | false;
|
||||
_settings.trackballSpeed = doc["trackball_speed"] | 3;
|
||||
_settings.touchSensitivity = doc["touch_sens"] | 3;
|
||||
_settings.bleEnabled = doc["ble_enabled"] | false;
|
||||
@@ -102,6 +105,9 @@ String UserConfig::serializeToJson() const {
|
||||
doc["screen_off"] = _settings.screenOffTimeout;
|
||||
doc["brightness"] = _settings.brightness;
|
||||
doc["dense_font"] = _settings.denseFontMode;
|
||||
doc["kb_brightness"] = _settings.keyboardBrightness;
|
||||
doc["kb_auto_on"] = _settings.keyboardAutoOn;
|
||||
doc["kb_auto_off"] = _settings.keyboardAutoOff;
|
||||
doc["trackball_speed"] = _settings.trackballSpeed;
|
||||
doc["touch_sens"] = _settings.touchSensitivity;
|
||||
doc["ble_enabled"] = _settings.bleEnabled;
|
||||
|
||||
@@ -42,6 +42,11 @@ struct UserSettings {
|
||||
uint8_t brightness = 100; // Percentage 1-100
|
||||
bool denseFontMode = false; // T-Deck Plus: adaptive font toggle
|
||||
|
||||
// Keyboard
|
||||
uint8_t keyboardBrightness = 100; // Percentage 1-100
|
||||
bool keyboardAutoOn = false; // Backlight ON when switching to ACTIVE power state
|
||||
bool keyboardAutoOff = false; // Backlight OFF when switching from ACTIVE power state
|
||||
|
||||
// Trackball
|
||||
uint8_t trackballSpeed = 3; // 1-5 sensitivity
|
||||
|
||||
|
||||
@@ -91,3 +91,33 @@ void Keyboard::update() {
|
||||
|
||||
_hasEvent = true;
|
||||
}
|
||||
|
||||
bool Keyboard::setBacklightBrightness(uint8_t percent) {
|
||||
percent = constrain(percent, 1, 100);
|
||||
// [1, 100] % -> [31, 255] PWM
|
||||
constexpr uint16_t SCALE = 255 - 31;
|
||||
constexpr uint16_t DIV = 100 - 1;
|
||||
uint16_t tmp = (uint16_t)(percent - 1) * SCALE;
|
||||
tmp = (tmp + DIV / 2) / DIV; // +DIV/2 for nearest‑integer rounding
|
||||
_backlightBrightness = (uint8_t)(31 + tmp);
|
||||
|
||||
Wire.beginTransmission(KB_I2C_ADDR);
|
||||
Wire.write(0x02); // LILYGO_KB_ALT_B_BRIGHTNESS_CMD
|
||||
Wire.write(_backlightBrightness);
|
||||
return Wire.endTransmission() == 0;
|
||||
}
|
||||
|
||||
bool Keyboard::backlightOn() {
|
||||
return setBrightness(_backlightBrightness);
|
||||
}
|
||||
|
||||
bool Keyboard::backlightOff() {
|
||||
return setBrightness(0);
|
||||
}
|
||||
|
||||
bool Keyboard::setBrightness(uint8_t pwm) {
|
||||
Wire.beginTransmission(KB_I2C_ADDR);
|
||||
Wire.write(0x01); // LILYGO_KB_BRIGHTNESS_CMD
|
||||
Wire.write(pwm);
|
||||
return Wire.endTransmission() == 0;
|
||||
}
|
||||
|
||||
@@ -42,8 +42,23 @@ public:
|
||||
bool hasEvent() const { return _hasEvent; }
|
||||
const KeyEvent& getEvent() const { return _event; }
|
||||
|
||||
// Backlight control
|
||||
// NOTES:
|
||||
// - Backlight control has been added to the ESP32-C3 F/W on 2024-12-25,
|
||||
// there's no way to detect if the installed F/W supports it
|
||||
// (no I2C reads except for key states, I2C writes are always ACK'ed).
|
||||
// - Backlight toggle via <Alt>+<B> is implemented in the ESP32-C3 F/W,
|
||||
// we can't track the actual backlight ON/OFF state.
|
||||
// - The ESP32-C3 F/W uses 2 brightness settings, one for <Alt>+<B> (which doesn't
|
||||
// change the current brightness), the other one for the current brightness.
|
||||
// The range for the 1st one is limited to [31, 255], we use it for the 2nd one, too.
|
||||
bool setBacklightBrightness(uint8_t percent); // doesn't change the current brightness
|
||||
bool backlightOn();
|
||||
bool backlightOff();
|
||||
|
||||
private:
|
||||
uint8_t readKey(uint8_t* modOut);
|
||||
static bool setBrightness(uint8_t pwm);
|
||||
|
||||
InputMode _mode = InputMode::Navigation;
|
||||
KeyEvent _event = {};
|
||||
@@ -51,6 +66,7 @@ private:
|
||||
uint8_t _lastKey = 0;
|
||||
bool _altHeld = false; // Software Alt tracking
|
||||
unsigned long _altPressTime = 0; // When Alt was detected
|
||||
uint8_t _backlightBrightness = 255; // [31, 255]
|
||||
|
||||
static Keyboard* _instance;
|
||||
static int _debugCount; // Log first N keypresses
|
||||
|
||||
+19
-1
@@ -1,8 +1,10 @@
|
||||
#include "Power.h"
|
||||
#include "hal/Display.h"
|
||||
#include "hal/Keyboard.h"
|
||||
|
||||
// Forward declaration — display instance provided externally
|
||||
// Forward declarations — display & keyboard instances provided externally
|
||||
extern Display display;
|
||||
extern Keyboard keyboard;
|
||||
|
||||
void Power::enablePeripherals() {
|
||||
// CRITICAL: GPIO 10 must be HIGH to enable all T-Deck Plus peripherals
|
||||
@@ -66,6 +68,13 @@ void Power::setBrightness(uint8_t percent) {
|
||||
}
|
||||
}
|
||||
|
||||
void Power::setKbBrightness(uint8_t percent, bool apply) {
|
||||
keyboard.setBacklightBrightness(constrain(percent, 1, 100));
|
||||
if (apply) { // Show the new brightness
|
||||
keyboard.backlightOn();
|
||||
}
|
||||
}
|
||||
|
||||
void Power::loop() {
|
||||
unsigned long elapsed = millis() - _lastActivity;
|
||||
|
||||
@@ -102,13 +111,22 @@ void Power::setState(State newState) {
|
||||
display.wakeup();
|
||||
}
|
||||
display.setBrightness(percentToPWM(_brightnessPct));
|
||||
if (_kbAutoOn) {
|
||||
keyboard.backlightOn();
|
||||
}
|
||||
break;
|
||||
case DIMMED:
|
||||
display.setBrightness(DIM_PWM);
|
||||
if (_kbAutoOff) {
|
||||
keyboard.backlightOff();
|
||||
}
|
||||
break;
|
||||
case SCREEN_OFF:
|
||||
display.setBrightness(0);
|
||||
display.sleep();
|
||||
if (_kbAutoOff) {
|
||||
keyboard.backlightOff();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -20,11 +20,16 @@ public:
|
||||
float batteryVoltage() const;
|
||||
int batteryPercent() const;
|
||||
|
||||
// Backlight — accepts percentage 1-100
|
||||
// Display backlight — accepts percentage 1-100
|
||||
void setBrightness(uint8_t percent);
|
||||
void setDimTimeout(uint16_t seconds) { _dimTimeout = seconds * 1000UL; }
|
||||
void setOffTimeout(uint16_t seconds) { _offTimeout = seconds * 1000UL; }
|
||||
|
||||
// Keyboard backlight — accepts percentage 1-100
|
||||
void setKbBrightness(uint8_t percent, bool apply=false);
|
||||
void setKbAutoOn(bool enable) { _kbAutoOn = enable; }
|
||||
void setKbAutoOff(bool enable) { _kbAutoOff = enable; }
|
||||
|
||||
enum State { ACTIVE, DIMMED, SCREEN_OFF };
|
||||
State state() const { return _state; }
|
||||
bool isScreenOn() const { return _state != SCREEN_OFF; }
|
||||
@@ -40,4 +45,6 @@ private:
|
||||
unsigned long _offTimeout = 60000;
|
||||
uint8_t _brightnessPct = 100; // User brightness as 1-100%
|
||||
static constexpr uint8_t DIM_PWM = 40; // ~15% PWM when dimmed
|
||||
bool _kbAutoOn = false;
|
||||
bool _kbAutoOff = false;
|
||||
};
|
||||
|
||||
@@ -654,6 +654,9 @@ void setup() {
|
||||
powerMgr.setDimTimeout(userConfig.settings().screenDimTimeout);
|
||||
powerMgr.setOffTimeout(userConfig.settings().screenOffTimeout);
|
||||
powerMgr.setBrightness(userConfig.settings().brightness);
|
||||
powerMgr.setKbBrightness(userConfig.settings().keyboardBrightness);
|
||||
powerMgr.setKbAutoOn(userConfig.settings().keyboardAutoOn);
|
||||
powerMgr.setKbAutoOff(userConfig.settings().keyboardAutoOff);
|
||||
|
||||
// Step 24.5: GPS init
|
||||
#if HAS_GPS
|
||||
@@ -903,6 +906,11 @@ void setup() {
|
||||
}
|
||||
}
|
||||
|
||||
if (userConfig.settings().keyboardAutoOn) {
|
||||
// We are in ACTIVE power state here, switch keyboard backlight ON
|
||||
keyboard.backlightOn();
|
||||
}
|
||||
|
||||
Serial.println("[BOOT] RatDeck ready");
|
||||
Serial.printf("[BOOT] Summary: radio=%s flash=%s sd=%s\n",
|
||||
radioOnline ? "ONLINE" : "OFFLINE",
|
||||
|
||||
@@ -218,18 +218,32 @@ void LvSettingsScreen::buildItems() {
|
||||
|
||||
// Display & Input
|
||||
int dispStart = idx;
|
||||
_items.push_back({"Brightness", SettingType::INTEGER,
|
||||
_items.push_back({"Display Brightness", SettingType::INTEGER,
|
||||
[&s]() { return s.brightness; }, [&s](int v) { s.brightness = v; },
|
||||
[](int v) { return String(v) + "%"; }, 5, 100, 5});
|
||||
idx++;
|
||||
_items.push_back({"Dim Timeout", SettingType::INTEGER,
|
||||
_items.push_back({"Display Dim Timeout", SettingType::INTEGER,
|
||||
[&s]() { return s.screenDimTimeout; }, [&s](int v) { s.screenDimTimeout = v; },
|
||||
[](int v) { return String(v) + "s"; }, 5, 300, 5});
|
||||
idx++;
|
||||
_items.push_back({"Off Timeout", SettingType::INTEGER,
|
||||
_items.push_back({"Display Off Timeout", SettingType::INTEGER,
|
||||
[&s]() { return s.screenOffTimeout; }, [&s](int v) { s.screenOffTimeout = v; },
|
||||
[](int v) { return String(v) + "s"; }, 10, 600, 10});
|
||||
idx++;
|
||||
_items.push_back({"Keyboard Backlight Brightness", SettingType::INTEGER,
|
||||
[&s]() { return s.keyboardBrightness; }, [&s](int v) { s.keyboardBrightness = v; },
|
||||
[](int v) { return String(v) + "%"; }, 5, 100, 5});
|
||||
idx++;
|
||||
_items.push_back({"Keyboard Backlight Auto-ON", SettingType::TOGGLE,
|
||||
[&s]() { return s.keyboardAutoOn ? 1 : 0; },
|
||||
[&s](int v) { s.keyboardAutoOn = (v != 0); },
|
||||
[](int v) { return v ? String("ON") : String("OFF"); }});
|
||||
idx++;
|
||||
_items.push_back({"Keyboard Backlight Auto-OFF", SettingType::TOGGLE,
|
||||
[&s]() { return s.keyboardAutoOff ? 1 : 0; },
|
||||
[&s](int v) { s.keyboardAutoOff = (v != 0); },
|
||||
[](int v) { return v ? String("ON") : String("OFF"); }});
|
||||
idx++;
|
||||
_items.push_back({"Trackball Speed", SettingType::INTEGER,
|
||||
[&s]() { return s.trackballSpeed; }, [&s](int v) { s.trackballSpeed = v; },
|
||||
[](int v) { return String(v); }, 1, 5, 1});
|
||||
@@ -702,6 +716,7 @@ void LvSettingsScreen::onEnter() {
|
||||
_textEditing = false;
|
||||
_confirmingReset = false;
|
||||
_confirmingDevMode = false;
|
||||
_kbBrightness = _cfg ? _cfg->settings().keyboardBrightness : 0;
|
||||
rebuildCategoryList();
|
||||
}
|
||||
|
||||
@@ -1334,6 +1349,12 @@ void LvSettingsScreen::applyAndSave() {
|
||||
_power->setBrightness(s.brightness);
|
||||
_power->setDimTimeout(s.screenDimTimeout);
|
||||
_power->setOffTimeout(s.screenOffTimeout);
|
||||
if (_kbBrightness != s.keyboardBrightness) {
|
||||
_power->setKbBrightness(s.keyboardBrightness, true);
|
||||
_kbBrightness = s.keyboardBrightness;
|
||||
}
|
||||
_power->setKbAutoOn(s.keyboardAutoOn);
|
||||
_power->setKbAutoOff(s.keyboardAutoOff);
|
||||
}
|
||||
if (_radio && _radio->isRadioOnline()) {
|
||||
_radio->setFrequency(s.loraFrequency);
|
||||
|
||||
@@ -166,6 +166,9 @@ private:
|
||||
void snapshotTCPSettings();
|
||||
bool tcpSettingsChanged() const;
|
||||
|
||||
// Keyboard backlight change detection
|
||||
uint8_t _kbBrightness = 0;
|
||||
|
||||
// LVGL widgets
|
||||
lv_obj_t* _scrollContainer = nullptr;
|
||||
std::vector<lv_obj_t*> _rowObjs;
|
||||
|
||||
Reference in New Issue
Block a user