Skip to content

Commit 5a7e4ed

Browse files
wurtzclaude
andauthored
feat: Add capacitive touch controls for Tidbyt Gen 2 (#130)
* feat: Add capacitive touch controls for Tidbyt Gen 2 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> * fix: Guard touch code for Gen2 only, fix display state sync - 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> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent d3866c7 commit 5a7e4ed

4 files changed

Lines changed: 480 additions & 13 deletions

File tree

main/CMakeLists.txt

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,25 @@ if(NOT DEFINED VAL_REMOTE_URL)
1212
set(VAL_REMOTE_URL "XplaceholderREMOTEURL___________________________________________________________________________________________________________")
1313
endif()
1414

15-
idf_component_register(SRCS "main.c"
16-
"display.cpp"
17-
"flash.c"
18-
"gfx.c"
19-
"ota.c"
20-
"remote.c"
21-
"wifi.c"
22-
"ap.c"
23-
"nvs_settings.c"
24-
"dns_wrapper.c"
25-
"syslog.c"
26-
"sntp.c"
15+
# Conditionally include touch_control.c only for Tidbyt Gen2
16+
set(SRCS "main.c"
17+
"display.cpp"
18+
"flash.c"
19+
"gfx.c"
20+
"ota.c"
21+
"remote.c"
22+
"wifi.c"
23+
"ap.c"
24+
"nvs_settings.c"
25+
"dns_wrapper.c"
26+
"syslog.c"
27+
"sntp.c")
28+
29+
if(CONFIG_BOARD_TIDBYT_GEN2)
30+
list(APPEND SRCS "touch_control.c")
31+
endif()
32+
33+
idf_component_register(SRCS ${SRCS}
2734
INCLUDE_DIRS ".")
2835

2936
idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=esp_getaddrinfo" APPEND)

main/main.c

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#include "sdkconfig.h"
2323
#include "sntp.h"
2424
#include "syslog.h"
25+
#ifdef CONFIG_BOARD_TIDBYT_GEN2
26+
#include "touch_control.h"
27+
#endif
2528
#include "version.h"
2629
#include "wifi.h"
2730

@@ -54,6 +57,13 @@ static bool button_boot = false;
5457
static bool first_ws_image_received = false;
5558
static bool config_received = false;
5659

60+
#ifdef CONFIG_BOARD_TIDBYT_GEN2
61+
// Touch control state
62+
static bool display_power_on = true;
63+
static uint8_t saved_brightness = 30;
64+
static void handle_touch_event(touch_event_t event);
65+
#endif
66+
5767
static void config_saved_callback(void) {
5868
config_received = true;
5969
ESP_LOGI(TAG, "Configuration saved - signaling main task");
@@ -201,6 +211,11 @@ static void websocket_event_handler(void* handler_args, esp_event_base_t base,
201211
brightness_value = DISPLAY_MAX_BRIGHTNESS;
202212
display_set_brightness((uint8_t)brightness_value);
203213
ESP_LOGI(TAG, "Updated brightness to %d", brightness_value);
214+
#ifdef CONFIG_BOARD_TIDBYT_GEN2
215+
// Sync touch control state - server brightness command means display is on
216+
display_power_on = true;
217+
saved_brightness = (uint8_t)brightness_value;
218+
#endif
204219
}
205220

206221
// Check for "ota_url"
@@ -496,6 +511,19 @@ void app_main(void) {
496511
}
497512
esp_register_shutdown_handler(&display_shutdown);
498513

514+
#ifdef CONFIG_BOARD_TIDBYT_GEN2
515+
// Initialize touch controls (GPIO33 on Tidbyt Gen2)
516+
ESP_LOGI(TAG, "Initializing touch control...");
517+
esp_err_t touch_ret = touch_control_init();
518+
if (touch_ret == ESP_OK) {
519+
ESP_LOGI(TAG, "Touch control ready on GPIO33");
520+
touch_control_debug_all_pads();
521+
} else {
522+
ESP_LOGW(TAG, "Touch control init failed: %s (continuing without touch)",
523+
esp_err_to_name(touch_ret));
524+
}
525+
#endif
526+
499527
// Start the AP web server now that display memory is allocated
500528
if (nvs_get_ap_mode()) {
501529
ESP_LOGI(TAG, "Starting AP Web Server...");
@@ -692,7 +720,20 @@ void app_main(void) {
692720
}
693721

694722
wifi_health_check();
695-
vTaskDelay(pdMS_TO_TICKS(5000)); // check every 5s
723+
724+
#ifdef CONFIG_BOARD_TIDBYT_GEN2
725+
// Poll touch frequently for 5 seconds (50ms intervals = 100 checks)
726+
// This allows proper gesture detection while keeping health checks at 5s
727+
for (int i = 0; i < 100; i++) {
728+
touch_event_t touch_event = touch_control_check();
729+
if (touch_event != TOUCH_EVENT_NONE) {
730+
handle_touch_event(touch_event);
731+
}
732+
vTaskDelay(pdMS_TO_TICKS(50)); // 50ms = responsive touch
733+
}
734+
#else
735+
vTaskDelay(pdMS_TO_TICKS(5000)); // 5 second health check interval
736+
#endif
696737
}
697738
} else {
698739
// normal http
@@ -778,7 +819,62 @@ void app_main(void) {
778819
isAnimating = 1;
779820
}
780821
}
822+
823+
#ifdef CONFIG_BOARD_TIDBYT_GEN2
824+
// Check for touch events
825+
touch_event_t touch_event = touch_control_check();
826+
if (touch_event != TOUCH_EVENT_NONE) {
827+
handle_touch_event(touch_event);
828+
}
829+
#endif
830+
781831
wifi_health_check();
782832
}
783833
}
784834
}
835+
836+
#ifdef CONFIG_BOARD_TIDBYT_GEN2
837+
/**
838+
* Handle touch events from the single touch pad
839+
* TAP = skip to next app
840+
* DOUBLE_TAP = (reserved for future use)
841+
* HOLD = toggle display power on/off
842+
*/
843+
static void handle_touch_event(touch_event_t event) {
844+
ESP_LOGI(TAG, "Touch event: %s", touch_event_to_string(event));
845+
846+
switch (event) {
847+
case TOUCH_EVENT_TAP:
848+
if (display_power_on) {
849+
ESP_LOGI(TAG, "TAP - skip to next app");
850+
isAnimating = -1;
851+
} else {
852+
ESP_LOGI(TAG, "TAP ignored - display is off (hold to turn on)");
853+
}
854+
break;
855+
856+
case TOUCH_EVENT_DOUBLE_TAP:
857+
// Reserved for future use
858+
ESP_LOGI(TAG, "DOUBLE TAP - no action assigned");
859+
break;
860+
861+
case TOUCH_EVENT_HOLD:
862+
display_power_on = !display_power_on;
863+
864+
if (display_power_on) {
865+
ESP_LOGI(TAG, "HOLD - Display ON");
866+
display_set_brightness(saved_brightness);
867+
isAnimating = 1;
868+
} else {
869+
ESP_LOGI(TAG, "HOLD - Display OFF");
870+
saved_brightness = 30;
871+
display_set_brightness(0);
872+
isAnimating = 0;
873+
}
874+
break;
875+
876+
default:
877+
break;
878+
}
879+
}
880+
#endif

0 commit comments

Comments
 (0)