1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-15 17:52:19 +01:00
This commit is contained in:
J. Nick Koston
2025-06-12 16:30:41 -05:00
parent 3adcae783c
commit f7afcb3b24
2 changed files with 16 additions and 0 deletions

View File

@@ -82,6 +82,13 @@ class ESP32TouchComponent : public Component {
// ESP32 v1 specific // ESP32 v1 specific
static void touch_isr_handler(void *arg); static void touch_isr_handler(void *arg);
QueueHandle_t touch_queue_{nullptr}; QueueHandle_t touch_queue_{nullptr};
// Design note: last_touch_time_ does not require synchronization primitives because:
// 1. ESP32 guarantees atomic 32-bit aligned reads/writes
// 2. ISR only writes timestamps, main loop only reads (except sentinel value 1)
// 3. Timing tolerance allows for occasional stale reads (50ms check interval)
// 4. Queue operations provide implicit memory barriers
// Using atomic/critical sections would add overhead without meaningful benefit
uint32_t last_touch_time_[TOUCH_PAD_MAX] = {0}; uint32_t last_touch_time_[TOUCH_PAD_MAX] = {0};
uint32_t release_timeout_ms_{1500}; uint32_t release_timeout_ms_{1500};
uint32_t release_check_interval_ms_{50}; uint32_t release_check_interval_ms_{50};

View File

@@ -72,6 +72,9 @@ void ESP32TouchComponent::setup() {
} }
// Calculate release timeout based on sleep cycle // Calculate release timeout based on sleep cycle
// Design note: ESP32 v1 hardware limitation - interrupts only fire on touch (not release)
// We must use timeout-based detection for release events
// Formula: 3 sleep cycles converted to ms, with 100ms minimum
uint32_t rtc_freq = rtc_clk_slow_freq_get_hz(); uint32_t rtc_freq = rtc_clk_slow_freq_get_hz();
this->release_timeout_ms_ = (this->sleep_cycle_ * 1000 * 3) / (rtc_freq * 2); this->release_timeout_ms_ = (this->sleep_cycle_ * 1000 * 3) / (rtc_freq * 2);
if (this->release_timeout_ms_ < 100) { if (this->release_timeout_ms_ < 100) {
@@ -151,6 +154,12 @@ void ESP32TouchComponent::loop() {
touch_pad_t pad = child->get_touch_pad(); touch_pad_t pad = child->get_touch_pad();
uint32_t last_time = this->last_touch_time_[pad]; uint32_t last_time = this->last_touch_time_[pad];
// Design note: Sentinel value pattern explanation
// - 0: Never touched since boot (waiting for initial timeout)
// - 1: Initial OFF state has been published (prevents repeated publishes)
// - >1: Actual timestamp of last touch event
// This avoids needing a separate boolean flag for initial state tracking
// If we've never seen this pad touched (last_time == 0) and enough time has passed // If we've never seen this pad touched (last_time == 0) and enough time has passed
// since startup, publish OFF state and mark as published with value 1 // since startup, publish OFF state and mark as published with value 1
if (last_time == 0 && now > this->release_timeout_ms_) { if (last_time == 0 && now > this->release_timeout_ms_) {