Skip to content

feat: Add capacitive touch controls for Tidbyt Gen 2#130

Merged
tavdog merged 2 commits intotronbyt:mainfrom
wurtz:main
Feb 8, 2026
Merged

feat: Add capacitive touch controls for Tidbyt Gen 2#130
tavdog merged 2 commits intotronbyt:mainfrom
wurtz:main

Conversation

@wurtz
Copy link
Copy Markdown
Contributor

@wurtz wurtz commented Feb 5, 2026

Implements touch gestures on GPIO33 (TOUCH_PAD_NUM8):

  • TAP: Skip to next app
  • DOUBLE TAP: Reserved for future use
  • HOLD (2s): Toggle display on/off

Features:

  • Adaptive baseline tracking to handle display EMI drift
  • Late tap detection to prevent accidental skips during double-tap
  • Fast warmup period (5s) for quicker calibration on boot
  • Debug logging (can be disabled via TOUCH_DEBUG_ENABLED)

Implements touch gestures on GPIO33 (TOUCH_PAD_NUM8):
- TAP: Skip to next app
- DOUBLE TAP: Reserved for future use
- HOLD (2s): Toggle display on/off

Features:
- Adaptive baseline tracking to handle display EMI drift
- Late tap detection to prevent accidental skips during double-tap
- Fast warmup period (5s) for quicker calibration on boot
- Debug logging (can be disabled via TOUCH_DEBUG_ENABLED)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @wurtz, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces capacitive touch control functionality to the Tidbyt Gen 2, allowing users to interact with the device through simple gestures. It integrates a new touch control module that handles gesture detection, adaptive baseline tracking for environmental stability, and provides actions such as navigating applications and managing display power.

Highlights

  • Capacitive Touch Controls: Implements new capacitive touch gestures (TAP, HOLD) on GPIO33 for the Tidbyt Gen 2 device, enabling direct user interaction.
  • Adaptive Baseline Tracking: Introduces an adaptive baseline tracking mechanism to effectively handle display EMI drift and other environmental factors, ensuring reliable touch detection.
  • Gesture Functionality: A single TAP gesture now skips to the next application, while a HOLD gesture (2 seconds) toggles the display power on and off.
  • Improved Responsiveness and Accuracy: Features a fast 5-second warmup period for quicker calibration on boot and incorporates late tap detection to prevent accidental skips during potential double-tap attempts.
  • Debug Logging: Includes optional debug logging for touch control events, which can be enabled via TOUCH_DEBUG_ENABLED.
Changelog
  • main/CMakeLists.txt
    • Added touch_control.c to the build system to include the new touch control module.
  • main/main.c
    • Included the new touch_control.h header for touch control functionality.
    • Introduced state variables display_power_on and saved_brightness to manage display state.
    • Declared and implemented handle_touch_event to process detected touch gestures.
    • Integrated touch_control_init() into the app_main function for startup initialization of touch controls.
    • Modified the main loop to continuously poll for touch events using touch_control_check() and dispatch them to handle_touch_event.
  • main/touch_control.c
    • New source file implementing the core logic for capacitive touch sensing and gesture recognition.
    • Features a Finite State Machine (FSM) to distinguish between tap, double-tap (reserved), and hold gestures.
    • Implements adaptive baseline tracking with fast warmup to ensure robust touch detection despite environmental changes.
    • Provides functions for initialization, calibration, event checking, and debug output.
  • main/touch_control.h
    • New header file defining the public interface for the touch control module.
    • Declares touch_event_t enum for different gesture types.
    • Defines constants for the main touch pad (GPIO33), default threshold, debounce time, and debug enablement.
    • Includes function prototypes for the touch control API.
Activity
  • The pull request was created by wurtz to add a new feature. No further activity (comments, reviews, etc.) is indicated in the provided context.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces capacitive touch controls for Tidbyt Gen 2, adding gestures for skipping apps and toggling the display. The implementation uses an adaptive baseline for touch detection, which is a solid approach.

My review has identified a few key areas for improvement:

  • The touch polling in the HTTP mode is not responsive and needs to be reworked to match the responsiveness of the websocket mode.
  • There's a bug in the display power-off logic that causes the user's brightness setting to be lost.
  • The new touch_control module contains some unused code and inconsistent comments that should be cleaned up for better maintainability.

Details and suggestions are provided in the specific comments.

Comment thread main/main.c
Comment on lines +810 to +814
// Check for touch events
touch_event_t touch_event = touch_control_check();
if (touch_event != TOUCH_EVENT_NONE) {
handle_touch_event(touch_event);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation only checks for touch events once per image cycle in the HTTP loop. This will lead to an unresponsive UI, as the loop can be blocked for app_dwell_secs (plus fetch time). To fix this, touch events should be polled frequently, similar to the change made in the websocket loop. Consider refactoring the main HTTP loop to replace long blocking waits with shorter, repeated delays that include a touch check.

Comment thread main/main.c
isAnimating = 1;
} else {
ESP_LOGI(TAG, "HOLD - Display OFF");
saved_brightness = 30;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

When turning the display off, the current brightness level is not saved. Instead, saved_brightness is hardcoded to 30. This means any brightness level set by the user will be lost when the display is toggled off and on again. The current brightness should be read and stored in saved_brightness before setting the display brightness to 0. This may require a new function like display_get_brightness().

Comment thread main/touch_control.c
Comment on lines +37 to +50
typedef struct {
uint16_t threshold;
uint32_t debounce_ms;
bool initialized;
uint16_t baseline;
float adaptive_baseline; // Floating point for smooth adaptation
uint32_t last_baseline_update;
uint32_t init_time; // Time of initialization for warmup period
touch_fsm_state_t state;
uint32_t touch_start_time;
uint32_t release_time;
uint32_t last_event_time;
bool is_late_tap; // True if current touch was too late for double-tap (will be swallowed)
} touch_state_t;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The threshold and debounce_ms fields in the touch_state_t struct are initialized but never used in the touch detection logic. The detection relies on other constants like TOUCH_DROP_THRESHOLD. Consequently, the public functions touch_control_set_threshold, touch_control_get_threshold, and touch_control_set_debounce are operating on unused variables, making them dead code. This is misleading and can cause confusion for future maintenance. Please remove these unused fields and their corresponding functions from both the .c and .h files.

Comment thread main/main.c

// Touch control state
static bool display_power_on = true;
static uint8_t saved_brightness = 30;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The magic number 30 is used to initialize saved_brightness. To improve maintainability and consistency, please use the DISPLAY_DEFAULT_BRIGHTNESS constant, which is defined in display.h and already included.

static uint8_t saved_brightness = DISPLAY_DEFAULT_BRIGHTNESS;

Comment thread main/touch_control.c
*
* Gestures:
* - Single tap: Next app
* - Double tap: Cycle brightness (10% -> 25% -> 50% -> 75%)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment here states that a double tap is for cycling brightness, but the implementation in main.c has this action as 'reserved for future use'. The PR description also says it's reserved. Please update this comment and the corresponding one in touch_control.h to match the actual implementation and avoid confusion.

 *   - Double tap: (Reserved for future use)

@tavdog
Copy link
Copy Markdown
Member

tavdog commented Feb 6, 2026

We'll need to ifdef more precisecly so that all devices except Gen2 will not implement the button press code.
And a small bug is that if you turn off the display with the button, then the server turns the screen back on with a brightness command the device still thinks the screen is off and the single press stops working.

- Add #ifdef CONFIG_BOARD_TIDBYT_GEN2 guards around all touch code
- Conditionally compile touch_control.c only for Gen2 in CMakeLists
- Non-Gen2 devices use original 5s delay instead of touch polling
- Fix display_power_on sync when server sends brightness command

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@tavdog tavdog merged commit 5a7e4ed into tronbyt:main Feb 8, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants