-
-
Notifications
You must be signed in to change notification settings - Fork 77
Feature additions #434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
KenVanHoeylandt
merged 23 commits into
ByteWelder:main
from
Shadowtrance:feature-additions
Jan 2, 2026
Merged
Feature additions #434
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
48c4f17
feature additions
Shadowtrance 55c431e
Systeminfo additions
Shadowtrance cea0b79
Espnow wifi coexist
Shadowtrance 2e7625d
Move systeminfo back
Shadowtrance cbf052c
Updates
Shadowtrance 6f6ae5d
Minor cleanup
Shadowtrance c805041
some fixes
Shadowtrance 6521292
More fixes...
Shadowtrance 47b2a4c
Update View.cpp
Shadowtrance 8221860
are we there yet...
Shadowtrance f47d4ac
are we thereeeeeee yet...
Shadowtrance dd52131
Update SystemInfo.cpp
Shadowtrance ef2d473
reduce trackball sensitivity
Shadowtrance c4c1123
maybe it builds now? hmm
Shadowtrance 7aab8e2
maybe now?
Shadowtrance 8b6cd10
Merge branch 'main' into feature-additions
Shadowtrance f717ee0
maybe now? yes? ok
Shadowtrance 1bae8ea
Simulator's stop being mad!
Shadowtrance a152fa3
Update SystemInfo.cpp
Shadowtrance 0bccf0c
Fix simulator build
Shadowtrance de137e5
minor cleanup
Shadowtrance b93e918
keyboardidle service
Shadowtrance 1c3b98e
Update TdeckKeyboard.cpp
Shadowtrance File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,5 @@ | ||
| language=en-US | ||
| timeFormat24h=true | ||
| timeFormat24h=true | ||
| dateFormat=MM/DD/YYYY | ||
| region=US | ||
| timezone=America/Los_Angeles |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
109 changes: 109 additions & 0 deletions
109
Devices/lilygo-tdeck/Source/KeyboardBacklight/KeyboardBacklight.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| #include "KeyboardBacklight.h" | ||
| #include <esp_log.h> | ||
| #include <cstring> | ||
|
|
||
| static const char* TAG = "KeyboardBacklight"; | ||
|
|
||
| namespace keyboardbacklight { | ||
|
|
||
| static const uint8_t CMD_BRIGHTNESS = 0x01; | ||
| static const uint8_t CMD_DEFAULT_BRIGHTNESS = 0x02; | ||
|
|
||
| static i2c_port_t g_i2cPort = I2C_NUM_MAX; | ||
| static uint8_t g_slaveAddress = 0x55; | ||
| static uint8_t g_currentBrightness = 127; | ||
|
|
||
| // TODO: Umm...something. Calls xxxBrightness, ignores return values. | ||
| bool init(i2c_port_t i2cPort, uint8_t slaveAddress) { | ||
| g_i2cPort = i2cPort; | ||
| g_slaveAddress = slaveAddress; | ||
|
|
||
| ESP_LOGI(TAG, "Keyboard backlight initialized on I2C port %d, address 0x%02X", g_i2cPort, g_slaveAddress); | ||
|
|
||
| // Set a reasonable default brightness | ||
| if (!setDefaultBrightness(127)) { | ||
| ESP_LOGE(TAG, "Failed to set default brightness"); | ||
| return false; | ||
| } | ||
|
|
||
| if (!setBrightness(127)) { | ||
| ESP_LOGE(TAG, "Failed to set brightness"); | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| bool setBrightness(uint8_t brightness) { | ||
| if (g_i2cPort >= I2C_NUM_MAX) { | ||
| ESP_LOGE(TAG, "Keyboard backlight not initialized"); | ||
| return false; | ||
| } | ||
|
|
||
| // Skip if brightness is already at target value (avoid I2C spam on every keypress) | ||
| if (brightness == g_currentBrightness) { | ||
| return true; | ||
| } | ||
|
|
||
| ESP_LOGI(TAG, "Setting brightness to %d on I2C port %d, address 0x%02X", brightness, g_i2cPort, g_slaveAddress); | ||
|
|
||
| i2c_cmd_handle_t cmd = i2c_cmd_link_create(); | ||
| i2c_master_start(cmd); | ||
| i2c_master_write_byte(cmd, (g_slaveAddress << 1) | I2C_MASTER_WRITE, true); | ||
| i2c_master_write_byte(cmd, CMD_BRIGHTNESS, true); | ||
| i2c_master_write_byte(cmd, brightness, true); | ||
| i2c_master_stop(cmd); | ||
|
|
||
| esp_err_t ret = i2c_master_cmd_begin(g_i2cPort, cmd, pdMS_TO_TICKS(100)); | ||
| i2c_cmd_link_delete(cmd); | ||
|
|
||
| if (ret == ESP_OK) { | ||
| g_currentBrightness = brightness; | ||
| ESP_LOGI(TAG, "Successfully set brightness to %d", brightness); | ||
| return true; | ||
| } else { | ||
| ESP_LOGE(TAG, "Failed to set brightness: %s (0x%x)", esp_err_to_name(ret), ret); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| bool setDefaultBrightness(uint8_t brightness) { | ||
| if (g_i2cPort >= I2C_NUM_MAX) { | ||
| ESP_LOGE(TAG, "Keyboard backlight not initialized"); | ||
| return false; | ||
| } | ||
|
|
||
| // Clamp to valid range for default brightness | ||
| if (brightness < 30) { | ||
| brightness = 30; | ||
| } | ||
|
|
||
| i2c_cmd_handle_t cmd = i2c_cmd_link_create(); | ||
| i2c_master_start(cmd); | ||
| i2c_master_write_byte(cmd, (g_slaveAddress << 1) | I2C_MASTER_WRITE, true); | ||
| i2c_master_write_byte(cmd, CMD_DEFAULT_BRIGHTNESS, true); | ||
| i2c_master_write_byte(cmd, brightness, true); | ||
| i2c_master_stop(cmd); | ||
|
|
||
| esp_err_t ret = i2c_master_cmd_begin(g_i2cPort, cmd, pdMS_TO_TICKS(100)); | ||
| i2c_cmd_link_delete(cmd); | ||
|
|
||
| if (ret == ESP_OK) { | ||
| ESP_LOGD(TAG, "Set default brightness to %d", brightness); | ||
| return true; | ||
| } else { | ||
| ESP_LOGE(TAG, "Failed to set default brightness: %s", esp_err_to_name(ret)); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| uint8_t getBrightness() { | ||
| if (g_i2cPort >= I2C_NUM_MAX) { | ||
| ESP_LOGE(TAG, "Keyboard backlight not initialized"); | ||
| return 0; | ||
| } | ||
|
|
||
| return g_currentBrightness; | ||
| } | ||
|
|
||
| } | ||
36 changes: 36 additions & 0 deletions
36
Devices/lilygo-tdeck/Source/KeyboardBacklight/KeyboardBacklight.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| #pragma once | ||
|
|
||
| #include <driver/i2c.h> | ||
| #include <cstdint> | ||
|
|
||
| namespace keyboardbacklight { | ||
|
|
||
| /** | ||
| * @brief Initialize keyboard backlight control | ||
| * @param i2cPort I2C port number (I2C_NUM_0 or I2C_NUM_1) | ||
| * @param slaveAddress I2C slave address (default 0x55 for T-Deck keyboard) | ||
| * @return true if initialization succeeded | ||
| */ | ||
| bool init(i2c_port_t i2cPort, uint8_t slaveAddress = 0x55); | ||
|
|
||
| /** | ||
| * @brief Set keyboard backlight brightness | ||
| * @param brightness Brightness level (0-255, 0=off, 255=max) | ||
| * @return true if command succeeded | ||
| */ | ||
| bool setBrightness(uint8_t brightness); | ||
|
|
||
| /** | ||
| * @brief Set default keyboard backlight brightness for ALT+B toggle | ||
| * @param brightness Default brightness level (30-255) | ||
| * @return true if command succeeded | ||
| */ | ||
| bool setDefaultBrightness(uint8_t brightness); | ||
|
|
||
| /** | ||
| * @brief Get current keyboard backlight brightness | ||
| * @return Current brightness level (0-255) | ||
| */ | ||
| uint8_t getBrightness(); | ||
|
|
||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| #include "Trackball.h" | ||
| #include <esp_log.h> | ||
|
|
||
| static const char* TAG = "Trackball"; | ||
|
|
||
| namespace trackball { | ||
|
|
||
| static TrackballConfig g_config; | ||
| static lv_indev_t* g_indev = nullptr; | ||
| static bool g_initialized = false; | ||
| static bool g_enabled = true; | ||
|
|
||
| // Track last GPIO states for edge detection | ||
| static bool g_lastState[5] = {false, false, false, false, false}; | ||
|
|
||
| static void read_cb(lv_indev_t* indev, lv_indev_data_t* data) { | ||
| if (!g_initialized || !g_enabled) { | ||
| data->state = LV_INDEV_STATE_RELEASED; | ||
| data->enc_diff = 0; | ||
| return; | ||
| } | ||
|
|
||
| const gpio_num_t pins[5] = { | ||
| g_config.pinRight, | ||
| g_config.pinUp, | ||
| g_config.pinLeft, | ||
| g_config.pinDown, | ||
| g_config.pinClick | ||
| }; | ||
|
|
||
| // Read GPIO states and detect changes (active low with pull-up) | ||
| bool currentStates[5]; | ||
| for (int i = 0; i < 5; i++) { | ||
| currentStates[i] = gpio_get_level(pins[i]) == 0; | ||
| } | ||
|
|
||
| // Process directional inputs as encoder steps | ||
| // Right/Down = positive diff (next item), Left/Up = negative diff (prev item) | ||
| int16_t diff = 0; | ||
|
|
||
| // Right pressed (rising edge) | ||
| if (currentStates[0] && !g_lastState[0]) { | ||
| diff += g_config.movementStep; | ||
| } | ||
| // Up pressed (rising edge) | ||
| if (currentStates[1] && !g_lastState[1]) { | ||
| diff -= g_config.movementStep; | ||
| } | ||
| // Left pressed (rising edge) | ||
| if (currentStates[2] && !g_lastState[2]) { | ||
| diff -= g_config.movementStep; | ||
| } | ||
| // Down pressed (rising edge) | ||
| if (currentStates[3] && !g_lastState[3]) { | ||
| diff += g_config.movementStep; | ||
| } | ||
|
|
||
| // Update last states | ||
| for (int i = 0; i < 5; i++) { | ||
| g_lastState[i] = currentStates[i]; | ||
| } | ||
|
|
||
| // Update encoder diff and button state | ||
| data->enc_diff = diff; | ||
| data->state = currentStates[4] ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; | ||
|
|
||
| // Trigger activity for wake-on-trackball | ||
| if (diff != 0 || currentStates[4]) { | ||
| lv_disp_trig_activity(nullptr); | ||
| } | ||
| } | ||
|
|
||
| lv_indev_t* init(const TrackballConfig& config) { | ||
| if (g_initialized) { | ||
| ESP_LOGW(TAG, "Trackball already initialized"); | ||
| return g_indev; | ||
| } | ||
|
|
||
| g_config = config; | ||
|
|
||
| // Set default movement step if not specified | ||
| if (g_config.movementStep == 0) { | ||
| g_config.movementStep = 10; | ||
| } | ||
|
|
||
| // Configure all GPIO pins as inputs with pull-ups (active low) | ||
| const gpio_num_t pins[5] = { | ||
| config.pinRight, | ||
| config.pinUp, | ||
| config.pinLeft, | ||
| config.pinDown, | ||
| config.pinClick | ||
| }; | ||
|
|
||
| gpio_config_t io_conf = {}; | ||
| io_conf.intr_type = GPIO_INTR_DISABLE; | ||
| io_conf.mode = GPIO_MODE_INPUT; | ||
| io_conf.pull_up_en = GPIO_PULLUP_ENABLE; | ||
| io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; | ||
|
|
||
| for (int i = 0; i < 5; i++) { | ||
| io_conf.pin_bit_mask = (1ULL << pins[i]); | ||
| gpio_config(&io_conf); | ||
| g_lastState[i] = gpio_get_level(pins[i]) == 0; | ||
| } | ||
|
|
||
| // Register as LVGL encoder input device for group navigation | ||
| g_indev = lv_indev_create(); | ||
| lv_indev_set_type(g_indev, LV_INDEV_TYPE_ENCODER); | ||
| lv_indev_set_read_cb(g_indev, read_cb); | ||
|
|
||
| if (g_indev) { | ||
| g_initialized = true; | ||
| ESP_LOGI(TAG, "Trackball initialized as encoder (R:%d U:%d L:%d D:%d Click:%d)", | ||
| config.pinRight, config.pinUp, config.pinLeft, config.pinDown, | ||
| config.pinClick); | ||
| return g_indev; | ||
| } else { | ||
| ESP_LOGE(TAG, "Failed to register LVGL input device"); | ||
| return nullptr; | ||
| } | ||
| } | ||
|
|
||
| void deinit() { | ||
| if (g_indev) { | ||
| lv_indev_delete(g_indev); | ||
| g_indev = nullptr; | ||
| } | ||
| g_initialized = false; | ||
| ESP_LOGI(TAG, "Trackball deinitialized"); | ||
| } | ||
|
|
||
| void setMovementStep(uint8_t step) { | ||
| if (step > 0) { | ||
| g_config.movementStep = step; | ||
| ESP_LOGD(TAG, "Movement step set to %d", step); | ||
| } | ||
| } | ||
|
|
||
| void setEnabled(bool enabled) { | ||
| g_enabled = enabled; | ||
| ESP_LOGI(TAG, "Trackball %s", enabled ? "enabled" : "disabled"); | ||
| } | ||
|
|
||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.