src.nth.io/

summaryrefslogtreecommitdiff
path: root/main/touch.c
diff options
context:
space:
mode:
authorLuke Hoersten <[email protected]>2026-06-14 16:41:03 -0500
committerLuke Hoersten <[email protected]>2026-06-14 16:41:03 -0500
commitc6ce4b3f46a1f1adf700306dadc9034a6a2ac0d3 (patch)
tree3bd6f0a3c2eea8b0095bd05549cae650fe166b40 /main/touch.c
parent6c1a26bdae63d152caa45023e8255561a22fc0e2 (diff)
M3 done: drop boot test, fold BOOT button into touch long-press
The Waveshare ESP32-P4-ETH board exposes BOOT on GPIO 35, but at runtime that pin is owned by the EMAC TXD1 signal. No usable GPIO is wired to a separate user button, so the BOOT-button task could never fire. Move both BOOT-button behaviours onto the touch panel: - ≥1.5s hold → 15s identity overlay (was BOOT short-press) - ≥5s hold → factory reset (was BOOT long-hold) Short tap (<500ms) still toggles wake/sleep. Long-press fires while the finger is still down so the user gets immediate feedback at each threshold. Also strip the R/G/B 6 s boot test sequence — the panel now renders correctly, so it's no longer useful diagnostically. Boot subsystem flags drop the trailing B column: [EMHDJT].
Diffstat (limited to 'main/touch.c')
-rw-r--r--main/touch.c103
1 files changed, 60 insertions, 43 deletions
diff --git a/main/touch.c b/main/touch.c
index 4d8003f..6b4e035 100644
--- a/main/touch.c
+++ b/main/touch.c
@@ -5,12 +5,14 @@
#include "driver/i2c_master.h"
#include "esp_check.h"
#include "esp_log.h"
+#include "esp_system.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "display.h"
#include "local_screens.h"
+#include "nvs_config.h"
#include "state_machine.h"
#include "viewport_state.h"
@@ -19,18 +21,15 @@ static const char *TAG = "touch";
#define FT5426_ADDR 0x38
#define FT5426_I2C_FREQ_HZ 400000
-// FT5x06/FT5426 register map (subset).
#define FT_REG_DEV_MODE 0x00
-#define FT_REG_GEST_ID 0x01
-#define FT_REG_TD_STATUS 0x02 // low 4 bits = touch count
-#define FT_REG_P1_XH 0x03 // X high (bits 0..3) + event flag (bits 6..7)
-#define FT_REG_P1_XL 0x04
-#define FT_REG_P1_YH 0x05
-#define FT_REG_P1_YL 0x06
+#define FT_REG_TD_STATUS 0x02
+#define FT_REG_P1_XH 0x03
#define POLL_PERIOD_MS 30
-#define TAP_MAX_MS 500
-#define TAP_MAX_MOVE_PX 25
+#define TAP_MAX_MS 500 // < this on release = short tap (toggle)
+#define LONG_PRESS_MS 1500 // ≥ this while held = identity overlay
+#define FACTORY_RESET_MS 5000 // ≥ this while held = factory reset
+#define OVERLAY_MS 15000
#define TAP_DEBOUNCE_MS 150
static i2c_master_dev_handle_t s_dev;
@@ -41,12 +40,37 @@ static esp_err_t ft_read(uint8_t reg, uint8_t *buf, size_t n)
return i2c_master_transmit_receive(s_dev, &reg, 1, buf, n, 50);
}
+static void on_short_tap(void)
+{
+ if (local_screens_overlay_active()) local_screens_overlay_dismiss();
+ viewport_run_state_t target =
+ (state_machine_current() == VIEWPORT_STATE_AWAKE)
+ ? VIEWPORT_STATE_ASLEEP
+ : VIEWPORT_STATE_AWAKE;
+ ESP_LOGI(TAG, "tap -> %s", target == VIEWPORT_STATE_AWAKE ? "wake" : "sleep");
+ state_machine_set_local(target);
+}
+
+static void on_long_press(void)
+{
+ ESP_LOGI(TAG, "long-press → identity overlay for %dms", OVERLAY_MS);
+ if (display_is_up()) local_screens_overlay(OVERLAY_MS);
+}
+
+static void on_factory_reset(void)
+{
+ ESP_LOGW(TAG, "very-long-press %dms → factory reset", FACTORY_RESET_MS);
+ nvs_config_reset();
+ vTaskDelay(pdMS_TO_TICKS(200));
+ esp_restart();
+}
+
static void touch_task(void *arg)
{
bool was_down = false;
uint64_t down_us = 0;
- uint16_t down_x = 0;
- uint16_t down_y = 0;
+ bool long_fired = false;
+ bool reset_fired = false;
uint64_t last_tap_us = 0;
uint8_t buf[7];
@@ -54,43 +78,36 @@ static void touch_task(void *arg)
vTaskDelay(pdMS_TO_TICKS(POLL_PERIOD_MS));
if (ft_read(FT_REG_DEV_MODE, buf, sizeof(buf)) != ESP_OK) continue;
-
uint8_t touches = buf[FT_REG_TD_STATUS] & 0x0F;
+ uint64_t now = (uint64_t)esp_timer_get_time();
+
if (touches > 0) {
- // Always capture P1; we only care about taps, not multi-touch.
- uint16_t x = ((buf[FT_REG_P1_XH] & 0x0F) << 8) | buf[FT_REG_P1_XL];
- uint16_t y = ((buf[FT_REG_P1_YH] & 0x0F) << 8) | buf[FT_REG_P1_YL];
if (!was_down) {
- was_down = true;
- down_us = (uint64_t)esp_timer_get_time();
- down_x = x;
- down_y = y;
+ was_down = true;
+ down_us = now;
+ long_fired = false;
+ reset_fired = false;
+ } else {
+ uint64_t held_ms = (now - down_us) / 1000ULL;
+ if (!long_fired && held_ms >= LONG_PRESS_MS) {
+ long_fired = true;
+ on_long_press();
+ }
+ if (!reset_fired && held_ms >= FACTORY_RESET_MS) {
+ reset_fired = true;
+ on_factory_reset(); // does not return
+ }
}
} else if (was_down) {
- // Release: was-down → up.
was_down = false;
- uint64_t now = (uint64_t)esp_timer_get_time();
-
+ uint64_t held_ms = (now - down_us) / 1000ULL;
if (now - last_tap_us < (uint64_t)TAP_DEBOUNCE_MS * 1000ULL) continue;
- uint64_t dt_ms = (now - down_us) / 1000ULL;
- // No reliable last position from the burst; use down coordinates
- // for the duration check, ignore movement check beyond the down
- // capture. Good enough for tap-vs-press.
- (void)down_x; (void)down_y; (void)TAP_MAX_MOVE_PX;
-
- if (dt_ms > 0 && dt_ms <= TAP_MAX_MS) {
+ // Short tap only fires on release; long-press already fired
+ // while the finger was still down.
+ if (!long_fired && held_ms > 0 && held_ms <= TAP_MAX_MS) {
last_tap_us = now;
- // Cancel any BOOT-button identity overlay so a tap-to-sleep
- // doesn't fight the overlay timer trying to restore content.
- if (local_screens_overlay_active()) local_screens_overlay_dismiss();
- viewport_run_state_t target =
- (state_machine_current() == VIEWPORT_STATE_AWAKE)
- ? VIEWPORT_STATE_ASLEEP
- : VIEWPORT_STATE_AWAKE;
- ESP_LOGI(TAG, "tap (%lu ms) -> %s", (unsigned long)dt_ms,
- target == VIEWPORT_STATE_AWAKE ? "wake" : "sleep");
- state_machine_set_local(target);
+ on_short_tap();
}
}
}
@@ -112,15 +129,15 @@ esp_err_t touch_init(void)
ESP_RETURN_ON_ERROR(i2c_master_bus_add_device(bus, &cfg, &s_dev),
TAG, "i2c add FT5426");
- // Sanity poll: read device mode.
uint8_t dev_mode = 0;
esp_err_t err = ft_read(FT_REG_DEV_MODE, &dev_mode, 1);
if (err != ESP_OK) {
- ESP_LOGE(TAG, "FT5426 @0x38 unreachable (%s) — check INT jumper",
- esp_err_to_name(err));
+ ESP_LOGE(TAG, "FT5426 @0x38 unreachable (%s)", esp_err_to_name(err));
return err;
}
- ESP_LOGI(TAG, "FT5426 ack'd (dev_mode=0x%02x)", dev_mode);
+ ESP_LOGI(TAG, "FT5426 ack'd (dev_mode=0x%02x); "
+ "tap=toggle, %dms hold=ID overlay, %dms hold=factory reset",
+ dev_mode, LONG_PRESS_MS, FACTORY_RESET_MS);
BaseType_t ok = xTaskCreate(touch_task, "touch", 3072, NULL, 4, &s_task);
return (ok == pdPASS) ? ESP_OK : ESP_FAIL;