Enhance T-Deck support with CI build, flasher, and keyboard features#302
Closed
3rdIteration wants to merge 21 commits into
Closed
Enhance T-Deck support with CI build, flasher, and keyboard features#3023rdIteration wants to merge 21 commits into
3rdIteration wants to merge 21 commits into
Conversation
…loop) Passing explicit flashMode/flashFreq/flashSize makes esptool-js patch the bootloader image header in flash without recomputing the appended SHA-256 digest. The ESP32-S3 ROM verifies that digest when loading the second-stage bootloader, rejects the image (ets_loader.c 78) and the device bootloops. Use 'keep' so the image is written byte-identical to the build output. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
power_backlight_on() scaled brightness as a 0-255 value, but Jade passes levels BACKLIGHT_MIN..BACKLIGHT_MAX (1..5), so the result was always 0 and the backlight switched off as soon as the stored brightness was applied after boot. Clamp and map levels 1..5 linearly onto dimmer steps 1..16. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop the pulse-train step dimmer; drive the backlight GPIO high for any requested brightness level and low for off. Level-based dimming can be reinstated once the display path is proven out. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Restore the pulse-step dimmer, mapping Jade brightness levels BACKLIGHT_MIN..BACKLIGHT_MAX (1..5) linearly onto dimmer steps 1..16 (the earlier code scaled as if brightness were 0-255, always yielding 0). Add short delays around the step pulses to respect dimmer timing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The trackball direction lines toggle level once per step of ball travel; driving them through iot_button meant that whenever a line came to rest low the driver saw a held button and fired LONG_PRESS_HOLD forever, causing runaway scrolling until the ball was nudged. Handle all four direction lines with ANYEDGE GPIO interrupts feeding a queue/watcher task (same pattern as the Jade v1 wheel), with a 2ms debounce. Also wire up the previously unused up/down lines: up scrolls prev, down scrolls next, matching forward/back in vertical UI contexts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…vity Mnemonic word entry only understood the on-screen keyboard: - letters: the screen posts uppercase A-Z, but the T-Deck keyboard sends lowercase ascii, so typed letters were ignored; accept either case - enter: the on-screen enter button is inactive during mnemonic entry, but a physical keyboard can post BTN_KEYBOARD_ENTER at any time, which set done_entering_words early and tripped the words_entered==nwords assert (mnemonic.c:865); only honour enter when the on-screen button would be active - letter validity: the on-screen keyboard disables letters that match no word, a physical keyboard cannot - reject letters yielding a stem with no matching words (previously would trip the possible_words>0 assert) Also halve trackball sensitivity: require 2 edges per scroll step, with the accumulator reset on direction change or a 300ms pause. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add HAS_KEYBOARD config (selected by the T-Deck board) and lay out the on-screen keyboards qwerty to match the physical keys: the mnemonic word-entry keyboard and the upper/lower-case passphrase keyboards. The passphrase space key moves to the end of the middle row as qwerty needs all ten bottom-row columns for zxcvbnm plus the control keys. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Passphrase: replace the show-and-confirm (Yes/No) screen with a second, deliberately blank, keyboard entry titled Confirm Passphrase; the two entries are compared and a mismatch restarts entry from scratch. The old display-confirm activity is removed, and both entry buffers are registered with the sensitive-data stack. PIN/number entry: accept physical keyboard input alongside the wheel. Adds gui_activity_wait_event_of_either_base() so the digit-entry loop can wait on gui navigation and keyboard button events simultaneously. Digits accepted as ascii 0-9 plus the letter keys with digits printed on them on the T-Deck (w,e,r,s,d,f,z,x,c = 1-9); backspace steps back (abandoning entry on the first digit), enter completes index entry. Also log raw keyboard bytes at DEBUG level to identify unmapped keys (eg. the mic key, which carries the printed 0). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The CI shallow/tagless checkout (plus the git dubious-ownership error inside the IDF container) made git describe fail, so JADE_VERSION in get_version_info was "1". Companion apps parse this as semver against a minimum firmware version and refuse to proceed (endless get_version_info retries / "please reconnect your hardware wallet"). Fetch full history and tags, mark the workspace safe for git in the container, and log the version at build time. Also report BOARD_TYPE "TDECK" instead of "UNKNOWN", and simplify PIN entry keys to actual ascii digits only - the T-Deck keyboard sends these with the SYM modifier held, so the letter-alias mapping is unnecessary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Send the keyboard controller brightness command (0x01 <level>) so the keyboard backlight turns on/off and dims with the screen (levels 1-5 map to 51-255). The request is latched and applied by the keyboard task, which owns the i2c device, retrying until the write succeeds. The Alt+B manual toggle in the keyboard firmware still works. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Average 8 adc samples and use a 2.11 divider multiplier (2.0 nominal plus ~10% load correction, matching other t-deck firmwares) instead of a single noisy sample scaled by 2. - usb/charging detection used tud_mounted(), which is always false on the debug (usb-serial-jtag) build where TinyUSB is never initialised; infer usb connection from usb_serial_jtag_is_connected() there. - Report charging as usb present while below 4300mV - with no charger status line, a higher reading means the charger is holding up the sense node with the battery full. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
handle_display_battery_volts() only formats a reading for a hardcoded set of boards and falls back to "NO BAT" otherwise; add the tdeck (power_get_vbat() already returns divider-corrected millivolts). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds LilyGO T-Deck (ESP32-S3) as a first-class board target, extending the firmware configuration, input/power drivers, UI keyboard behavior, and introducing a CI-driven web flasher + GitHub Actions build/deploy pipeline.
Changes:
- Add
BOARD_TYPE_TDECKwith board-specific defaults (display, I2C, input pins) and newHAS_KEYBOARDcapability in Kconfig + sdkconfig defaults. - Implement T-Deck-specific power (battery ADC + backlight + keyboard backlight) and input (I2C keyboard + GPIO trackball) integrations.
- Add GitHub Actions build + artifact publishing and a browser-based flasher UI that can flash latest CI artifacts or uploaded ZIP bundles.
Reviewed changes
Copilot reviewed 19 out of 23 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/switch_to.sh | Adds tdeck config selection for build switching script. |
| main/ui/mnemonic.c | Adjusts word-entry keyboard layout for devices with a physical keyboard; removes passphrase confirm UI activity. |
| main/ui/keyboard.c | Updates on-screen keyboard row layout to match physical QWERTY when CONFIG_HAS_KEYBOARD. |
| main/ui/digit_entry.c | Adds physical keyboard support for digit entry and introduces dual-base event waiting. |
| main/ui/dashboard.c | Enables display brightness/orientation options for T-Deck in display settings menu. |
| main/process/ota_defines.h | Adds OTA board-type string mapping for T-Deck. |
| main/process/mnemonic.c | Improves physical keyboard handling for mnemonic entry and changes passphrase confirmation to blind re-entry with sensitive buffers. |
| main/process/dashboard.c | Enables brightness settings and battery voltage display paths for T-Deck. |
| main/power/tdeck.inc | Adds T-Deck power implementation: backlight control, battery ADC reading, USB power inference, keyboard backlight linkage. |
| main/power.c | Wires T-Deck power implementation into board selection. |
| main/Kconfig.projbuild | Adds BOARD_TYPE_TDECK, HAS_KEYBOARD, and various T-Deck hardware defaults. |
| main/input/tdeck.inc | Adds T-Deck navigation implementation: I2C keyboard reader task + trackball ISR/task + press handling. |
| main/input.c | Includes T-Deck input implementation when CONFIG_BOARD_TYPE_TDECK. |
| main/gui.h | Declares new helper to wait for either of two event bases. |
| main/gui.c | Implements gui_activity_wait_event_of_either_base. |
| flasher/vendor/jszip-3.10.1.min.js | Adds JSZip dependency for reading firmware ZIP bundles in the browser. |
| flasher/index.html | Adds a full web flasher UI (CI firmware fetch + custom ZIP) and optional serial monitor. |
| flasher/branding/logo.svg | Adds branding asset for the web flasher. |
| configs/sdkconfig_display_tdeck.defaults | Adds standard T-Deck sdkconfig defaults for building firmware. |
| configs/sdkconfig_display_tdeck_debug.defaults | Adds debug T-Deck sdkconfig defaults (USB-Serial-JTAG console). |
| .gitignore | Ignores generated flasher/firmware/ content. |
| .github/workflows/build.yml | Adds CI build matrix for T-Deck + deploy-to-gh-pages of the flasher site and firmware artifacts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+2772
to
+2793
| bool gui_activity_wait_event_of_either_base(gui_activity_t* activity, const char* event_base1, | ||
| const char* event_base2, esp_event_base_t* trigger_event_base, int32_t* trigger_event_id, | ||
| void** trigger_event_data, const TickType_t max_wait) | ||
| { | ||
| JADE_ASSERT(activity); | ||
| JADE_ASSERT(event_base1); | ||
| JADE_ASSERT(event_base2); | ||
|
|
||
| // create a new wait-event-data structure and attach to the activity, which takes ownership | ||
| wait_event_data_t* const wait_event_data = gui_activity_make_wait_event_data(activity); | ||
| JADE_ASSERT(wait_event_data); | ||
|
|
||
| // register both bases against the same wait data so either can wake the caller | ||
| gui_activity_register_event(activity, event_base1, ESP_EVENT_ANY_ID, sync_wait_event_handler, wait_event_data); | ||
| gui_activity_register_event(activity, event_base2, ESP_EVENT_ANY_ID, sync_wait_event_handler, wait_event_data); | ||
|
|
||
| // immediately start waiting | ||
| const esp_err_t ret | ||
| = sync_wait_event(wait_event_data, trigger_event_base, trigger_event_id, trigger_event_data, max_wait); | ||
|
|
||
| return ret == ESP_OK; | ||
| } |
| @@ -394,7 +394,7 @@ gui_activity_t* make_display_settings_activity(void) | |||
|
|
|||
| // NOTE: Only Jade v1.1's and v2's have brightness controls | |||
| @@ -1703,7 +1703,7 @@ static void handle_view_otps(void) | |||
|
|
|||
| // NOTE: Only Jade v1.1's and v2's have brightness controls | |||
| @@ -2281,7 +2281,7 @@ static void handle_settings(const bool startup_menu) | |||
|
|
|||
| // NOTE: Only Jade v1.1's and v2's have brightness controls | |||
| BOARD_TYPE_M5_BLACK_GRAY || BOARD_TYPE_TTGO_TWATCHS3 || BOARD_TYPE_WS_TOUCH_LCD2 | ||
| BOARD_TYPE_M5_BLACK_GRAY || BOARD_TYPE_TTGO_TWATCHS3 || BOARD_TYPE_WS_TOUCH_LCD2 || BOARD_TYPE_TDECK | ||
| help | ||
| Invert the colors in the dipslay. Some devices may have inverted colors depending on revision |
Comment on lines
+54
to
+56
| deploy: | ||
| if: github.event_name == 'push' | ||
| needs: build |
Comment on lines
+146
to
+148
| <p style="font-size:13px;color:#8b949e;margin-bottom:12px"> | ||
| Downloads the latest firmware built from the <code>T-Deck-Plus</code> branch. | ||
| </p> |
Comment on lines
+299
to
+310
| function serialWrite(text) { | ||
| const last = serialDiv.lastChild; | ||
| if (last && last.nodeType === Node.TEXT_NODE) { | ||
| last.textContent += text; | ||
| } else { | ||
| serialDiv.appendChild(document.createTextNode(text)); | ||
| } | ||
| serialDiv.scrollTop = serialDiv.scrollHeight; | ||
| if (serialDiv.children.length > 500) { | ||
| serialDiv.removeChild(serialDiv.firstChild); | ||
| } | ||
| } |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
This pull request adds support for the LilyGO T-Deck hardware variant to the project. It introduces new configuration files for both normal and debug builds, updates the build system to handle T-Deck firmware, and extends the Kconfig system with the necessary board-specific settings and options. The changes ensure that T-Deck is properly recognized and configured in both the build pipeline and device configuration.
T-Deck hardware support:
BOARD_TYPE_TDECKtomain/Kconfig.projbuild, including configuration for display, input pins, and enabling features like battery and keyboard support. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16]Build and deployment pipeline:
.github/workflows/build.ymlto automate building and artifact deployment for both normal and debug T-Deck firmware variants.Board-specific configuration files:
configs/sdkconfig_display_tdeck.defaultsfor standard T-Deck builds andconfigs/sdkconfig_display_tdeck_debug.defaultsfor debug builds, specifying all relevant hardware and feature flags. [1] [2]