From 5c2ebf4eee5978d2acac0a8dd3bc4c179010c536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 25 Jul 2025 17:31:22 +0200 Subject: [PATCH 1/9] feat(touch): Support all touch versions in NG driver --- cores/esp32/esp32-hal-touch-ng.c | 133 +++++-- cores/esp32/esp32-hal-touch-ng.h | 42 ++- cores/esp32/esp32-hal-touch.c | 329 ------------------ cores/esp32/esp32-hal-touch.h | 103 ------ cores/esp32/esp32-hal.h | 1 - .../Touch/TouchButton/TouchButton.ino | 57 +-- .../ESP32/examples/Touch/TouchButton/ci.json | 2 +- .../Touch/TouchButtonV2/TouchButtonV2.ino | 51 --- .../examples/Touch/TouchButtonV2/ci.json | 5 - tests/validation/touch/touch.ino | 13 +- 10 files changed, 189 insertions(+), 547 deletions(-) delete mode 100644 cores/esp32/esp32-hal-touch.c delete mode 100644 cores/esp32/esp32-hal-touch.h delete mode 100644 libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino delete mode 100644 libraries/ESP32/examples/Touch/TouchButtonV2/ci.json diff --git a/cores/esp32/esp32-hal-touch-ng.c b/cores/esp32/esp32-hal-touch-ng.c index 888a299ec0c..392f404bae6 100644 --- a/cores/esp32/esp32-hal-touch-ng.c +++ b/cores/esp32/esp32-hal-touch-ng.c @@ -14,9 +14,8 @@ #include "soc/soc_caps.h" #if SOC_TOUCH_SENSOR_SUPPORTED -#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 for now +//#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 for now -#include "driver/touch_sens.h" #include "esp32-hal-touch-ng.h" #include "esp32-hal-periman.h" @@ -37,11 +36,24 @@ typedef struct { static TouchInterruptHandle_t __touchInterruptHandlers[SOC_TOUCH_SENSOR_NUM] = { 0, }; - -static uint8_t _sample_num = 1; +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +static uint8_t _sample_num = 1; // only one sample configuration supported +static float _duration_ms = 5.0f; +static touch_volt_lim_l_t _volt_low = TOUCH_VOLT_LIM_L_0V5; +static touch_volt_lim_h_t _volt_high = TOUCH_VOLT_LIM_H_1V7; +static touch_intr_trig_mode_t _intr_trig_mode = TOUCH_INTR_TRIG_ON_BELOW_THRESH; +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 +static uint8_t _sample_num = 1; // only one sample configuration supported +static float _duration_ms = 500.0f; +static touch_volt_lim_l_t _volt_low = TOUCH_VOLT_LIM_L_0V5; +static touch_volt_lim_h_t _volt_high = TOUCH_VOLT_LIM_H_2V2; +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 +static uint8_t _sample_num = 1; // TODO: can be extended to multiple samples static uint32_t _div_num = 1; static uint8_t _coarse_freq_tune = 1; static uint8_t _fine_freq_tune = 1; +#endif + static uint8_t used_pads = 0; static uint32_t __touchSleepTime = 256; @@ -156,15 +168,28 @@ bool touchBenchmarkThreshold(uint8_t pad) { // Reconfigure passed pad with new threshold uint32_t benchmark[_sample_num] = {}; + #if SOC_TOUCH_SUPPORT_BENCHMARK // ESP32S2, ESP32S3,ESP32P4 if (touch_channel_read_data(touch_channel_handle[pad], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark) != ESP_OK) { log_e("Touch channel read data failed!"); return false; } + #else + if (touch_channel_read_data(touch_channel_handle[pad], TOUCH_CHAN_DATA_TYPE_SMOOTH, benchmark) != ESP_OK) { + log_e("Touch channel read data failed!"); + return false; + } + #endif + /* Calculate the proper active thresholds regarding the initial benchmark */ - touch_channel_config_t chan_cfg = {}; + touch_channel_config_t chan_cfg = TOUCH_CHANNEL_DEFAULT_CONFIG(); for (int i = 0; i < _sample_num; i++) { +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + chan_cfg.abs_active_thresh[i] = (uint32_t)(benchmark[i] * (1 - s_thresh2bm_ratio)); + log_v("Configured [CH %d] sample %d: benchmark = %"PRIu32", threshold = %"PRIu32"\t", pad, i, benchmark[i], chan_cfg.abs_active_thresh[i]); +#else chan_cfg.active_thresh[i] = (uint32_t)(benchmark[i] * s_thresh2bm_ratio); - log_v("Configured [CH %d] sample %d: benchmark = %" PRIu32 ", threshold = %" PRIu32 "\t", pad, i, benchmark[i], chan_cfg.active_thresh[i]); + log_v("Configured [CH %d] sample %d: benchmark = %"PRIu32", threshold = %"PRIu32"\t", pad, i, benchmark[i], chan_cfg.active_thresh[i]); +#endif } /* Update the channel configuration */ if (touch_sensor_reconfig_channel(touch_channel_handle[pad], &chan_cfg) != ESP_OK) { @@ -198,21 +223,40 @@ static void __touchInit() { return; } // Support only one sample configuration for now - touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG(_div_num, _coarse_freq_tune, _fine_freq_tune); +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V1_DEFAULT_SAMPLE_CONFIG(_duration_ms, _volt_low, _volt_high); +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 + touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V2_DEFAULT_SAMPLE_CONFIG(_duration_ms, _volt_low, _volt_high); +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 + touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG(_sample_num, _div_num, _coarse_freq_tune, _fine_freq_tune); +#endif touch_sensor_sample_config_t sample_cfg[_sample_num] = {}; sample_cfg[0] = single_sample_cfg; - /* Allocate new touch controller handle */ touch_sensor_config_t sens_cfg = { +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + .power_on_wait_us = __touchSleepTime, + .meas_interval_us = __touchMeasureTime, + .intr_trig_mode = _intr_trig_mode, + .intr_trig_group = TOUCH_INTR_TRIG_GROUP_BOTH, + .sample_cfg_num = _sample_num, + .sample_cfg = sample_cfg, +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 + .power_on_wait_us = __touchSleepTime, + .meas_interval_us = __touchMeasureTime, + .max_meas_time_us = 0, + .sample_cfg_num = _sample_num, + .sample_cfg = sample_cfg, +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 .power_on_wait_us = __touchSleepTime, .meas_interval_us = __touchMeasureTime, .max_meas_time_us = 0, .output_mode = TOUCH_PAD_OUT_AS_CLOCK, .sample_cfg_num = _sample_num, .sample_cfg = sample_cfg, +#endif }; - // touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(_sample_num, sample_cfg); if (touch_sensor_new_controller(&sens_cfg, &touch_sensor_handle) != ESP_OK) { goto err; } @@ -225,14 +269,10 @@ static void __touchInit() { } /* Register the touch sensor on_active and on_inactive callbacks */ - touch_event_callbacks_t callbacks = { - .on_active = __touchOnActiveISR, - .on_inactive = __touchOnInactiveISR, - .on_measure_done = NULL, - .on_scan_done = NULL, - .on_timeout = NULL, - .on_proximity_meas_done = NULL, - }; + touch_event_callbacks_t callbacks = {0}; + callbacks.on_active = __touchOnActiveISR; + callbacks.on_inactive = __touchOnInactiveISR; + if (touch_sensor_register_callbacks(touch_sensor_handle, &callbacks, NULL) != ESP_OK) { goto err; } @@ -253,10 +293,8 @@ static void __touchChannelInit(int pad) { // Initial setup with default Threshold __touchInterruptHandlers[pad].fn = NULL; - touch_channel_config_t chan_cfg = { - .active_thresh = {1000} // default threshold, will be updated after benchmark - }; - + touch_channel_config_t chan_cfg = TOUCH_CHANNEL_DEFAULT_CONFIG(); + if (!touchStop() || !touchDisable()) { log_e("Touch sensor stop and disable failed!"); return; @@ -323,8 +361,21 @@ static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Ar __touchInterruptHandlers[pad].arg = NULL; } else { // attach ISR User Call - __touchInit(); - __touchChannelInit(pad); + if (perimanGetPinBus(pin, ESP32_BUS_TYPE_TOUCH) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_TOUCH, touchDetachBus); + if (!perimanClearPinBus(pin)) { + log_e("Failed to clear pin bus"); + return; + } + __touchInit(); + __touchChannelInit(pad); + + if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_TOUCH, (void *)(pin + 1), -1, pad)) { + touchDetachBus((void *)(pin + 1)); + log_e("Failed to set bus to Peripheral manager"); + return; + } + } __touchInterruptHandlers[pad].fn = userFunc; __touchInterruptHandlers[pad].callWithArgs = callWithArgs; __touchInterruptHandlers[pad].arg = Args; @@ -338,7 +389,11 @@ static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Ar touch_channel_config_t chan_cfg = {}; for (int i = 0; i < _sample_num; i++) { +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + chan_cfg.abs_active_thresh[i] = threshold; +#else chan_cfg.active_thresh[i] = threshold; +#endif } if (touch_sensor_reconfig_channel(touch_channel_handle[pad], &chan_cfg) != ESP_OK) { @@ -375,7 +430,6 @@ bool touchInterruptGetLastStatus(uint8_t pin) { if (pad < 0) { return false; } - return __touchInterruptHandlers[pad].lastStatusIsPressed; } @@ -405,9 +459,13 @@ void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold) { touch_sleep_config_t deep_slp_cfg = { .slp_wakeup_lvl = TOUCH_DEEP_SLEEP_WAKEUP, +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + .deep_slp_sens_cfg = NULL, // Use the original touch sensor configuration +#else // SOC_TOUCH_SENSOR_VERSION 2 and 3// ESP32S2, ESP32S3, ESP32P4 .deep_slp_chan = touch_channel_handle[pad], .deep_slp_thresh = {threshold}, .deep_slp_sens_cfg = NULL, // Use the original touch sensor configuration +#endif }; // Register the deep sleep wake-up @@ -434,6 +492,20 @@ void touchSetTiming(float measure, uint32_t sleep) { __touchMeasureTime = measure; } +#if SOC_TOUCH_SENSOR_VERSION == 1 || SOC_TOUCH_SENSOR_VERSION == 2 // ESP32, ESP32S2, ESP32S3 + +void touchSetConfig(float duration_ms, touch_volt_lim_l_t volt_low, touch_volt_lim_h_t volt_high) { + if (initialized) { + log_e("Touch sensor already initialized. Cannot set configuration."); + return; + } + _duration_ms = duration_ms; + _volt_low = volt_low; + _volt_high = volt_high; +} + +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 + void touchSetConfig(uint32_t div_num, uint8_t coarse_freq_tune, uint8_t fine_freq_tune) { if (initialized) { log_e("Touch sensor already initialized. Cannot set configuration."); @@ -443,11 +515,22 @@ void touchSetConfig(uint32_t div_num, uint8_t coarse_freq_tune, uint8_t fine_fre _coarse_freq_tune = coarse_freq_tune; _fine_freq_tune = fine_freq_tune; } +#endif + +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +void touchInterruptSetThresholdDirection(bool mustbeLower) { + if (mustbeLower) { + _intr_trig_mode = TOUCH_INTR_TRIG_ON_BELOW_THRESH; + } else { + _intr_trig_mode = TOUCH_INTR_TRIG_ON_ABOVE_THRESH; + } +} +#endif extern touch_value_t touchRead(uint8_t) __attribute__((weak, alias("__touchRead"))); extern void touchAttachInterrupt(uint8_t, voidFuncPtr, touch_value_t) __attribute__((weak, alias("__touchAttachInterrupt"))); extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, touch_value_t) __attribute__((weak, alias("__touchAttachArgsInterrupt"))); extern void touchDetachInterrupt(uint8_t) __attribute__((weak, alias("__touchDettachInterrupt"))); -#endif /* SOC_TOUCH_SENSOR_VERSION == 3 */ +//#endif /* SOC_TOUCH_SENSOR_VERSION == 3 */ #endif /* SOC_TOUCH_SENSOR_SUPPORTED */ diff --git a/cores/esp32/esp32-hal-touch-ng.h b/cores/esp32/esp32-hal-touch-ng.h index 0d4eb79ac58..23c00983092 100644 --- a/cores/esp32/esp32-hal-touch-ng.h +++ b/cores/esp32/esp32-hal-touch-ng.h @@ -22,13 +22,32 @@ #include "soc/soc_caps.h" #if SOC_TOUCH_SENSOR_SUPPORTED -#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 #ifdef __cplusplus extern "C" { #endif #include "esp32-hal.h" +#include "driver/touch_sens.h" + +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#define TOUCH_CHANNEL_DEFAULT_CONFIG() { \ + .abs_active_thresh = {1000}, \ + .charge_speed = TOUCH_CHARGE_SPEED_7, \ + .init_charge_volt = TOUCH_INIT_CHARGE_VOLT_DEFAULT, \ + .group = TOUCH_CHAN_TRIG_GROUP_BOTH, \ +} +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32-S2 & ESP32-S3 +#define TOUCH_CHANNEL_DEFAULT_CONFIG() { \ + .active_thresh = {2000}, \ + .charge_speed = TOUCH_CHARGE_SPEED_7, \ + .init_charge_volt = TOUCH_INIT_CHARGE_VOLT_DEFAULT, \ +} +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32-P4 +#define TOUCH_CHANNEL_DEFAULT_CONFIG() { \ + .active_thresh = {1000}, \ +} +#endif typedef uint32_t touch_value_t; @@ -40,11 +59,31 @@ typedef uint32_t touch_value_t; **/ void touchSetTiming(float measure, uint32_t sleep); +#if SOC_TOUCH_SENSOR_VERSION == 1 || SOC_TOUCH_SENSOR_VERSION == 2 // ESP32, ESP32S2, ESP32S3 +/* + * @param[in] duration_ms The measurement duration of the touch channel + * @param[in] volt_low The low voltage limit of the touch channel + * @param[in] volt_high The high voltage limit of the touch channel + */ +void touchSetConfig(float duration_ms, touch_volt_lim_l_t volt_low, touch_volt_lim_h_t volt_high); + +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 /* * Tune the touch pad frequency. * Note: Must be called before setting up touch pads */ void touchSetConfig(uint32_t _div_num, uint8_t coarse_freq_tune, uint8_t fine_freq_tune); +#endif + +#if SOC_TOUCH_SENSOR_VERSION == 1 +/* + * Specific functions to ESP32 + * Tells the driver if it shall activate the ISR if the sensor is Lower or Higher than the Threshold + * Default if Lower. + * Note: Must be called before setting up touch pads + **/ +void touchInterruptSetThresholdDirection(bool mustbeLower); +#endif /* * Read touch pad value. @@ -86,6 +125,5 @@ void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold); } #endif -#endif /* SOC_TOUCH_SENSOR_VERSION == 3 */ #endif /* SOC_TOUCH_SENSOR_SUPPORTED */ #endif /* MAIN_ESP32_HAL_TOUCH_H_ */ diff --git a/cores/esp32/esp32-hal-touch.c b/cores/esp32/esp32-hal-touch.c deleted file mode 100644 index 701bf6d16c9..00000000000 --- a/cores/esp32/esp32-hal-touch.c +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include "soc/soc_caps.h" - -#if SOC_TOUCH_SENSOR_SUPPORTED -#if SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32, ESP32S2, ESP32S3 - -#include "driver/touch_sensor.h" -#include "esp32-hal-touch.h" -#include "esp32-hal-periman.h" - -/* - Internal Private Touch Data Structure and Functions -*/ - -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 -static uint16_t __touchSleepCycles = 0x1000; -static uint16_t __touchMeasureCycles = 0x1000; -#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 -static uint16_t __touchSleepCycles = TOUCH_PAD_SLEEP_CYCLE_DEFAULT; -static uint16_t __touchMeasureCycles = TOUCH_PAD_MEASURE_CYCLE_DEFAULT; -#endif - -typedef void (*voidFuncPtr)(void); -typedef void (*voidArgFuncPtr)(void *); - -typedef struct { - voidFuncPtr fn; - bool callWithArgs; - void *arg; -#if SOC_TOUCH_SENSOR_VERSION == 2 // Only for ESP32S2 and ESP32S3 - bool lastStatusIsPressed; -#endif -} TouchInterruptHandle_t; - -static TouchInterruptHandle_t __touchInterruptHandlers[SOC_TOUCH_SENSOR_NUM] = { - 0, -}; - -static uint8_t used_pads = 0; -static bool initialized = false; -static bool channels_initialized[SOC_TOUCH_SENSOR_NUM] = {false}; - -static void ARDUINO_ISR_ATTR __touchISR(void *arg) { -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 - uint32_t pad_intr = touch_pad_get_status(); - //clear interrupt - touch_pad_clear_status(); - // call Pad ISR User callback - for (int i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) { - if ((pad_intr >> i) & 0x01) { - if (__touchInterruptHandlers[i].fn) { - // keeping backward compatibility with "void cb(void)" and with new "void cb(vooid *)" - if (__touchInterruptHandlers[i].callWithArgs) { - ((voidArgFuncPtr)__touchInterruptHandlers[i].fn)(__touchInterruptHandlers[i].arg); - } else { - __touchInterruptHandlers[i].fn(); - } - } - } - } -#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 - touch_pad_intr_mask_t evt = touch_pad_read_intr_status_mask(); - uint8_t pad_num = touch_pad_get_current_meas_channel(); - if (evt & TOUCH_PAD_INTR_MASK_ACTIVE) { - // touch has been pressed / touched - __touchInterruptHandlers[pad_num].lastStatusIsPressed = true; - } - if (evt & TOUCH_PAD_INTR_MASK_INACTIVE) { - // touch has been released / untouched - __touchInterruptHandlers[pad_num].lastStatusIsPressed = false; - } - if (__touchInterruptHandlers[pad_num].fn) { - // keeping backward compatibility with "void cb(void)" and with new "void cb(vooid *)" - if (__touchInterruptHandlers[pad_num].callWithArgs) { - ((voidArgFuncPtr)__touchInterruptHandlers[pad_num].fn)(__touchInterruptHandlers[pad_num].arg); - } else { - __touchInterruptHandlers[pad_num].fn(); - } - } -#endif -} - -static void __touchSetCycles(uint16_t measure, uint16_t sleep) { - __touchSleepCycles = sleep; - __touchMeasureCycles = measure; -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 - touch_pad_set_measurement_clock_cycles(measure); -#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 - touch_pad_set_charge_discharge_times(measure); -#endif - touch_pad_set_measurement_interval(sleep); -} - -static bool touchDetachBus(void *pin) { - int8_t pad = digitalPinToTouchChannel((int)(pin - 1)); - channels_initialized[pad] = false; - used_pads--; - if (used_pads == 0) { - if (touch_pad_deinit() != ESP_OK) //deinit touch module, as no pads are used - { - log_e("Touch module deinit failed!"); - return false; - } - initialized = false; - } - return true; -} - -static void __touchInit() { - if (initialized) { - return; - } - - esp_err_t err = ESP_OK; - -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 - err = touch_pad_init(); - if (err != ESP_OK) { - goto err; - } - // the next two lines will drive the touch reading values -- both will return ESP_OK - touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V); - touch_pad_set_measurement_clock_cycles(__touchMeasureCycles); - touch_pad_set_measurement_interval(__touchSleepCycles); - // Touch Sensor Timer initiated - touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); // returns ESP_OK - err = touch_pad_filter_start(10); - if (err != ESP_OK) { - goto err; - } - // keep ISR activated - it can run all together (ISR + touchRead()) - err = touch_pad_isr_register(__touchISR, NULL); - if (err != ESP_OK) { - goto err; - } - touch_pad_intr_enable(); // returns ESP_OK -#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 - err = touch_pad_init(); - if (err != ESP_OK) { - goto err; - } - // the next lines will drive the touch reading values -- all os them return ESP_OK - touch_pad_set_charge_discharge_times(__touchMeasureCycles); - touch_pad_set_measurement_interval(__touchSleepCycles); - touch_pad_set_voltage(TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD); - touch_pad_set_idle_channel_connect(TOUCH_PAD_IDLE_CH_CONNECT_DEFAULT); - touch_pad_denoise_t denoise = { - .grade = TOUCH_PAD_DENOISE_BIT4, - .cap_level = TOUCH_PAD_DENOISE_CAP_L4, - }; - touch_pad_denoise_set_config(&denoise); - touch_pad_denoise_enable(); - // Touch Sensor Timer initiated - touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); // returns ESP_OK - touch_pad_fsm_start(); // returns ESP_OK - //ISR setup moved to __touchChannelInit -#endif - initialized = true; - return; -err: - log_e(" Touch sensor initialization error."); - initialized = false; - return; -} - -static void __touchChannelInit(int pad) { - if (channels_initialized[pad]) { - return; - } - -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 - // Initial no Threshold and setup - __touchInterruptHandlers[pad].fn = NULL; - touch_pad_config(pad, TOUCH_PAD_THRESHOLD_MAX); // returns ESP_OK -#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 - // Initial no Threshold and setup - __touchInterruptHandlers[pad].fn = NULL; - touch_pad_config(pad); // returns ESP_OK - // keep ISR activated - it can run all together (ISR + touchRead()) - esp_err_t err = touch_pad_isr_register(__touchISR, NULL, TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE); - if (err != ESP_OK) { - log_e(" Touch sensor initialization error."); - return; - } - touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE); // returns ESP_OK -#endif - - channels_initialized[pad] = true; - used_pads++; - delay(20); //delay needed before reading from touch channel after config -} - -static touch_value_t __touchRead(uint8_t pin) { - int8_t pad = digitalPinToTouchChannel(pin); - if (pad < 0) { - log_e(" No touch pad on selected pin!"); - return 0; - } - - if (perimanGetPinBus(pin, ESP32_BUS_TYPE_TOUCH) == NULL) { - perimanSetBusDeinit(ESP32_BUS_TYPE_TOUCH, touchDetachBus); - if (!perimanClearPinBus(pin)) { - return 0; - } - __touchInit(); - __touchChannelInit(pad); - - if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_TOUCH, (void *)(pin + 1), -1, pad)) { - touchDetachBus((void *)(pin + 1)); - return 0; - } - } - - touch_value_t touch_value; - touch_pad_read_raw_data(pad, &touch_value); - - return touch_value; -} - -static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Args, touch_value_t threshold, bool callWithArgs) { - int8_t pad = digitalPinToTouchChannel(pin); - if (pad < 0) { - log_e(" No touch pad on selected pin!"); - return; - } - - if (userFunc == NULL) { - // detach ISR User Call - __touchInterruptHandlers[pad].fn = NULL; - threshold = TOUCH_PAD_THRESHOLD_MAX; // deactivate the ISR with SOC_TOUCH_PAD_THRESHOLD_MAX - } else { - // attach ISR User Call - __touchInit(); - __touchChannelInit(pad); - __touchInterruptHandlers[pad].fn = userFunc; - __touchInterruptHandlers[pad].callWithArgs = callWithArgs; - __touchInterruptHandlers[pad].arg = Args; - } - - touch_pad_set_thresh(pad, threshold); -} - -// it keeps backwards compatibility -static void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), touch_value_t threshold) { - __touchConfigInterrupt(pin, userFunc, NULL, threshold, false); -} - -// new additional version of the API with User Args -static void __touchAttachArgsInterrupt(uint8_t pin, void (*userFunc)(void), void *args, touch_value_t threshold) { - __touchConfigInterrupt(pin, userFunc, args, threshold, true); -} - -// new additional API to detach touch ISR -static void __touchDettachInterrupt(uint8_t pin) { - __touchConfigInterrupt(pin, NULL, NULL, 0, false); // userFunc as NULL acts as detaching -} - -/* - External Public Touch API Functions -*/ - -#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC -void touchInterruptSetThresholdDirection(bool mustbeLower) { - if (mustbeLower) { - touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW); - } else { - touch_pad_set_trigger_mode(TOUCH_TRIGGER_ABOVE); - } -} -#elif SOC_TOUCH_SENSOR_VERSION == 2 // Only for ESP32S2 and ESP32S3 -// returns true if touch pad has been and continues pressed and false otherwise -bool touchInterruptGetLastStatus(uint8_t pin) { - int8_t pad = digitalPinToTouchChannel(pin); - if (pad < 0) { - return false; - } - - return __touchInterruptHandlers[pad].lastStatusIsPressed; -} -#endif - -void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold) { - int8_t pad = digitalPinToTouchChannel(pin); - if (pad < 0) { - log_e(" No touch pad on selected pin!"); - return; - } - - if (perimanGetPinBus(pin, ESP32_BUS_TYPE_TOUCH) == NULL) { - perimanSetBusDeinit(ESP32_BUS_TYPE_TOUCH, touchDetachBus); - __touchInit(); - __touchChannelInit(pad); - if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_TOUCH, (void *)(pin + 1), -1, pad)) { - log_e("Failed to set bus to Peripheral manager"); - touchDetachBus((void *)(pin + 1)); - return; - } - } -#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC - touch_pad_set_thresh(pad, threshold); - -#elif SOC_TOUCH_SENSOR_VERSION == 2 - touch_pad_sleep_channel_enable(pad, true); - touch_pad_sleep_set_threshold(pad, threshold); - -#endif - esp_sleep_enable_touchpad_wakeup(); -} - -extern touch_value_t touchRead(uint8_t) __attribute__((weak, alias("__touchRead"))); -extern void touchAttachInterrupt(uint8_t, voidFuncPtr, touch_value_t) __attribute__((weak, alias("__touchAttachInterrupt"))); -extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, touch_value_t) __attribute__((weak, alias("__touchAttachArgsInterrupt"))); -extern void touchDetachInterrupt(uint8_t) __attribute__((weak, alias("__touchDettachInterrupt"))); -extern void touchSetCycles(uint16_t, uint16_t) __attribute__((weak, alias("__touchSetCycles"))); - -#endif /* SOC_TOUCH_SENSOR_VERSION <= 2 */ -#endif /* SOC_TOUCH_SENSOR_SUPPORTED */ diff --git a/cores/esp32/esp32-hal-touch.h b/cores/esp32/esp32-hal-touch.h deleted file mode 100644 index 4b06c7db766..00000000000 --- a/cores/esp32/esp32-hal-touch.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - Arduino.h - Main include file for the Arduino SDK - Copyright (c) 2005-2013 Arduino Team. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef MAIN_ESP32_HAL_TOUCH_H_ -#define MAIN_ESP32_HAL_TOUCH_H_ - -#include "soc/soc_caps.h" -#if SOC_TOUCH_SENSOR_SUPPORTED -#if SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32 ESP32S2 ESP32S3 - -#ifdef __cplusplus -extern "C" { -#endif - -#include "esp32-hal.h" - -#if !SOC_TOUCH_SENSOR_SUPPORTED -#error Touch IDF driver Not supported! -#endif - -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 -typedef uint16_t touch_value_t; -#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2 ESP32S3 -typedef uint32_t touch_value_t; -#endif - -/* - * Set cycles that measurement operation takes - * The result from touchRead, threshold and detection - * accuracy depend on these values. Defaults are - * 0x1000 for measure and 0x1000 for sleep. - * With default values touchRead takes 0.5ms - * */ -void touchSetCycles(uint16_t measure, uint16_t sleep); - -/* - * Read touch pad (for ESP32 values close to 0 mean touch detected / - * for ESP32-S2/S3 higher values mean touch detected) - * You can use this method to chose a good threshold value - * to use as value for touchAttachInterrupt - * */ -touch_value_t touchRead(uint8_t pin); - -/* - * Set function to be called if touch pad value falls (ESP32) - * below the given threshold / rises (ESP32-S2/S3) by given increment (threshold). - * Use touchRead to determine a proper threshold between touched and untouched state - * */ -void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), touch_value_t threshold); -void touchAttachInterruptArg(uint8_t pin, void (*userFunc)(void *), void *arg, touch_value_t threshold); -void touchDetachInterrupt(uint8_t pin); - -/* - * Specific functions to ESP32 - * Tells the driver if it shall activate the ISR if the sensor is Lower or Higher than the Threshold - * Default if Lower. - **/ - -#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC -void touchInterruptSetThresholdDirection(bool mustbeLower); -#endif - -/* - * Specific functions to ESP32-S2 and ESP32-S3 - * Returns true when the latest ISR status for the Touchpad is that it is touched (Active) - * and false when the Touchpad is untoouched (Inactive) - * This function can be used in conjunction with ISR User callback in order to take action - * as soon as the touchpad is touched and/or released - **/ - -#if SOC_TOUCH_SENSOR_VERSION == 2 // Only for ESP32S2 and ESP32S3 -// returns true if touch pad has been and continues pressed and false otherwise -bool touchInterruptGetLastStatus(uint8_t pin); -#endif - -/* - * Setup touch pad wake up from deep sleep with given threshold. - **/ -void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold); - -#ifdef __cplusplus -} -#endif - -#endif /* SOC_TOUCH_SENSOR_VERSION <= 2 */ -#endif /* SOC_TOUCH_SENSOR_SUPPORTED */ -#endif /* MAIN_ESP32_HAL_TOUCH_H_ */ diff --git a/cores/esp32/esp32-hal.h b/cores/esp32/esp32-hal.h index 5ed99aeb205..e2ca9309fe0 100644 --- a/cores/esp32/esp32-hal.h +++ b/cores/esp32/esp32-hal.h @@ -86,7 +86,6 @@ void yield(void); #include "esp32-hal-matrix.h" #include "esp32-hal-uart.h" #include "esp32-hal-gpio.h" -#include "esp32-hal-touch.h" #include "esp32-hal-touch-ng.h" #include "esp32-hal-dac.h" #include "esp32-hal-adc.h" diff --git a/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino b/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino index 43f3bc36592..8ebe2f00cbc 100644 --- a/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino +++ b/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino @@ -3,44 +3,53 @@ This is an example how to use Touch Intrrerupts The sketch will tell when it is touched and then released as like a push-button -This method based on touchInterruptSetThresholdDirection() is only available for ESP32 +This method based on touchInterruptGetLastStatus() */ #include "Arduino.h" -int threshold = 40; -bool touchActive = false; -bool lastTouchActive = false; -bool testingLower = true; - -void gotTouchEvent() { - if (lastTouchActive != testingLower) { - touchActive = !touchActive; - testingLower = !testingLower; - // Touch ISR will be inverted: Lower <--> Higher than the Threshold after ISR event is noticed - touchInterruptSetThresholdDirection(testingLower); - } +int threshold = 0; // if 0 is used, benchmark value is used. Its by default 1,5% change, can be changed by touchSetDefaultThreshold(float percentage) +bool touch1detected = false; +bool touch2detected = false; + +void gotTouch1() { + touch1detected = true; +} + +void gotTouch2() { + touch2detected = true; } void setup() { Serial.begin(115200); delay(1000); // give me time to bring up serial monitor - Serial.println("ESP32 Touch Interrupt Test"); - touchAttachInterrupt(T2, gotTouchEvent, threshold); - // Touch ISR will be activated when touchRead is lower than the Threshold - touchInterruptSetThresholdDirection(testingLower); + //Optional: Set the threshold to 5% of the benchmark value. Only effective if threshold = 0. + touchSetDefaultThreshold(5); + + //Set the touch pads + Serial.println("\n ESP32 Touch Interrupt Test\n"); + touchAttachInterrupt(T0, gotTouch1, threshold); + touchAttachInterrupt(T2, gotTouch2, threshold); } void loop() { - if (lastTouchActive != touchActive) { - lastTouchActive = touchActive; - if (touchActive) { - Serial.println(" ---- Touch was Pressed"); + if (touch1detected) { + touch1detected = false; + if (touchInterruptGetLastStatus(T1)) { + Serial.println(" --- T1 Touched"); } else { - Serial.println(" ---- Touch was Released"); + Serial.println(" --- T1 Released"); } } - Serial.printf("T2 pin2 = %d \n", touchRead(T2)); - delay(125); + if (touch2detected) { + touch2detected = false; + if (touchInterruptGetLastStatus(T2)) { + Serial.println(" --- T2 Touched"); + } else { + Serial.println(" --- T2 Released"); + } + } + + delay(80); } diff --git a/libraries/ESP32/examples/Touch/TouchButton/ci.json b/libraries/ESP32/examples/Touch/TouchButton/ci.json index cec76a84f9d..c0ecf9fc0a5 100644 --- a/libraries/ESP32/examples/Touch/TouchButton/ci.json +++ b/libraries/ESP32/examples/Touch/TouchButton/ci.json @@ -1,5 +1,5 @@ { "requires": [ - "CONFIG_SOC_TOUCH_VERSION_1=y" + "CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y" ] } diff --git a/libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino b/libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino deleted file mode 100644 index df9b3f41149..00000000000 --- a/libraries/ESP32/examples/Touch/TouchButtonV2/TouchButtonV2.ino +++ /dev/null @@ -1,51 +0,0 @@ -/* - -This is an example how to use Touch Intrrerupts -The sketch will tell when it is touched and then released as like a push-button - -This method based on touchInterruptGetLastStatus() is only available for ESP32 S2 and S3 -*/ - -#include "Arduino.h" - -int threshold = 1500; // ESP32S2 -bool touch1detected = false; -bool touch2detected = false; - -void gotTouch1() { - touch1detected = true; -} - -void gotTouch2() { - touch2detected = true; -} - -void setup() { - Serial.begin(115200); - delay(1000); // give me time to bring up serial monitor - - Serial.println("\n ESP32 Touch Interrupt Test\n"); - touchAttachInterrupt(T1, gotTouch1, threshold); - touchAttachInterrupt(T2, gotTouch2, threshold); -} - -void loop() { - if (touch1detected) { - touch1detected = false; - if (touchInterruptGetLastStatus(T1)) { - Serial.println(" --- T1 Touched"); - } else { - Serial.println(" --- T1 Released"); - } - } - if (touch2detected) { - touch2detected = false; - if (touchInterruptGetLastStatus(T2)) { - Serial.println(" --- T2 Touched"); - } else { - Serial.println(" --- T2 Released"); - } - } - - delay(80); -} diff --git a/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json b/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json deleted file mode 100644 index 2710fa7940e..00000000000 --- a/libraries/ESP32/examples/Touch/TouchButtonV2/ci.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "requires": [ - "CONFIG_SOC_TOUCH_VERSION_2=y" - ] -} diff --git a/tests/validation/touch/touch.ino b/tests/validation/touch/touch.ino index 97aac8a65e6..2e5910fbb26 100644 --- a/tests/validation/touch/touch.ino +++ b/tests/validation/touch/touch.ino @@ -1,10 +1,6 @@ #include #include "soc/soc_caps.h" -#include "driver/touch_pad.h" - -#if SOC_TOUCH_SENSOR_VERSION == 3 #include "hal/touch_sensor_ll.h" -#endif #if CONFIG_IDF_TARGET_ESP32 @@ -82,7 +78,7 @@ void gotTouch2() { */ static void test_press_fake(touch_pad_t pad_num) { #if SOC_TOUCH_SENSOR_VERSION <= 2 - touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_1, TOUCH_PAD_TIE_OPT_DEFAULT); + touch_ll_set_charge_speed(pad_num,TOUCH_CHARGE_SPEED_4); #else touch_ll_set_internal_capacitor(0x7f); #endif @@ -93,7 +89,7 @@ static void test_press_fake(touch_pad_t pad_num) { */ static void test_release_fake(touch_pad_t pad_num) { #if SOC_TOUCH_SENSOR_VERSION <= 2 - touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT); + touch_ll_set_charge_speed(pad_num, TOUCH_CHARGE_SPEED_7); #else touch_ll_set_internal_capacitor(0); #endif @@ -192,6 +188,11 @@ void setup() { UNITY_BEGIN(); RUN_TEST(test_touch_read); + +#if SOC_TOUCH_SENSOR_VERSION == 3 + touch_ll_enable_internal_capacitor(true); +#endif + RUN_TEST(test_touch_interrtupt); RUN_TEST(test_touch_errors); UNITY_END(); From 41287a37b8a277fa1379c7d87031157074b05525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 25 Jul 2025 18:29:35 +0200 Subject: [PATCH 2/9] fix(ci): Update touch test --- tests/validation/touch/touch.ino | 52 +++++++------------------------- 1 file changed, 11 insertions(+), 41 deletions(-) diff --git a/tests/validation/touch/touch.ino b/tests/validation/touch/touch.ino index 2e5910fbb26..315df0a5ee2 100644 --- a/tests/validation/touch/touch.ino +++ b/tests/validation/touch/touch.ino @@ -43,21 +43,14 @@ uint8_t TOUCH_GPIOS[] = {2, 3, 4, 5, 6 /*, 7, 8, 9, 10, 11, 12 ,13, 14, 15*/}; #define NO_TOUCH_GPIO 17 #endif +#define INTERRUPT_THRESHOLD 0 // Use benchmarked threshold + #if CONFIG_IDF_TARGET_ESP32 -#define RELEASED_VALUE 75 //75+ read value to pass test -#define PRESSED_VALUE 20 //20- read value to pass test -#define INTERRUPT_THRESHOLD 40 -#elif CONFIG_IDF_TARGET_ESP32S2 -#define RELEASED_VALUE 10000 //10000- read value to pass test -#define PRESSED_VALUE 42000 //40000+ read value to pass test -#define INTERRUPT_THRESHOLD 30000 -#elif CONFIG_IDF_TARGET_ESP32S3 -#define RELEASED_VALUE 25000 //25000- read value to pass test -#define PRESSED_VALUE 90000 //90000+ read value to pass test -#define INTERRUPT_THRESHOLD 80000 -#elif CONFIG_IDF_TARGET_ESP32P4 +#define PRESSED_VALUE_DIFFERENCE 200 //-200 read value difference against the unpressed value +#elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32S2 +#define PRESSED_VALUE_DIFFERENCE 2000 //2000+ read value difference against the unpressed value +#elif CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #define PRESSED_VALUE_DIFFERENCE 200 //200+ read value difference against the unpressed value -#define INTERRUPT_THRESHOLD 0 // Use benchmarked threshold #else #error Test not currently supported on this chip. Please adjust and try again! #endif @@ -109,31 +102,6 @@ void tearDown(void) { * Test Touch read on all available channels - compare values if reading is right */ void test_touch_read(void) { - -#if SOC_TOUCH_SENSOR_VERSION <= 2 - //TEST RELEASE STATE - for (int i = 0; i < sizeof(TOUCH_GPIOS); i++) { -#ifdef CONFIG_IDF_TARGET_ESP32 - TEST_ASSERT_GREATER_THAN(RELEASED_VALUE, touchRead(TOUCH_GPIOS[i])); -#else - TEST_ASSERT_LESS_THAN(RELEASED_VALUE, touchRead(TOUCH_GPIOS[i])); -#endif - } - - // TEST PRESS STATE - for (int j = 0; j < TEST_TOUCH_CHANNEL; j++) { - test_press_fake(touch_list[j]); - } - delay(100); - - for (int k = 0; k < sizeof(TOUCH_GPIOS); k++) { -#ifdef CONFIG_IDF_TARGET_ESP32 - TEST_ASSERT_LESS_THAN(PRESSED_VALUE, touchRead(TOUCH_GPIOS[k])); -#else - TEST_ASSERT_GREATER_THAN(PRESSED_VALUE, touchRead(TOUCH_GPIOS[k])); -#endif - } -#else //TOUCH V3 //TEST RELEASE STATE touch_value_t touch_unpressed[sizeof(TOUCH_GPIOS)]; for (int i = 0; i < sizeof(TOUCH_GPIOS); i++) { @@ -151,11 +119,14 @@ void test_touch_read(void) { touch_pressed[k] = touchRead(TOUCH_GPIOS[k]); } - // COMPARE PRESSED > UNPRESSED + // COMPARE PRESSED <-> UNPRESSED for (int l = 0; l < sizeof(TOUCH_GPIOS); l++) { +#if CONFIG_IDF_TARGET_ESP32 + TEST_ASSERT_LESS_THAN((touch_unpressed[l] - PRESSED_VALUE_DIFFERENCE), touch_pressed[l]); +#else TEST_ASSERT_GREATER_THAN((touch_unpressed[l] + PRESSED_VALUE_DIFFERENCE), touch_pressed[l]); - } #endif + } } void test_touch_interrtupt(void) { @@ -166,7 +137,6 @@ void test_touch_interrtupt(void) { test_press_fake(touch_list[0]); test_press_fake(touch_list[1]); - delay(300); touchDetachInterrupt(TOUCH_GPIOS[0]); touchDetachInterrupt(TOUCH_GPIOS[1]); From 0a3658044fa78c1f770b34c051d11855e8e25886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 25 Jul 2025 18:42:28 +0200 Subject: [PATCH 3/9] fix(touch): Update example and fix config --- cores/esp32/esp32-hal-touch-ng.c | 4 +--- .../examples/Touch/TouchInterrupt/TouchInterrupt.ino | 10 +++++----- libraries/ESP32/examples/Touch/TouchRead/TouchRead.ino | 4 ++-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/cores/esp32/esp32-hal-touch-ng.c b/cores/esp32/esp32-hal-touch-ng.c index 392f404bae6..479427861a3 100644 --- a/cores/esp32/esp32-hal-touch-ng.c +++ b/cores/esp32/esp32-hal-touch-ng.c @@ -14,7 +14,6 @@ #include "soc/soc_caps.h" #if SOC_TOUCH_SENSOR_SUPPORTED -//#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 for now #include "esp32-hal-touch-ng.h" #include "esp32-hal-periman.h" @@ -228,7 +227,7 @@ static void __touchInit() { #elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V2_DEFAULT_SAMPLE_CONFIG(_duration_ms, _volt_low, _volt_high); #elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 - touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG(_sample_num, _div_num, _coarse_freq_tune, _fine_freq_tune); + touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG(_div_num, _coarse_freq_tune, _fine_freq_tune); #endif touch_sensor_sample_config_t sample_cfg[_sample_num] = {}; sample_cfg[0] = single_sample_cfg; @@ -532,5 +531,4 @@ extern void touchAttachInterrupt(uint8_t, voidFuncPtr, touch_value_t) __attribut extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, touch_value_t) __attribute__((weak, alias("__touchAttachArgsInterrupt"))); extern void touchDetachInterrupt(uint8_t) __attribute__((weak, alias("__touchDettachInterrupt"))); -//#endif /* SOC_TOUCH_SENSOR_VERSION == 3 */ #endif /* SOC_TOUCH_SENSOR_SUPPORTED */ diff --git a/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino b/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino index 3b4e5f0b9e9..08e10dc0fac 100644 --- a/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino +++ b/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino @@ -3,11 +3,7 @@ This is an example how to use Touch Intrrerupts The bigger the threshold, the more sensible is the touch */ -#if CONFIG_IDF_TARGET_ESP32P4 -int threshold = 0; // when 0 is used, the benchmarked value will be used -#else -int threshold = 40; -#endif +int threshold = 0; // if 0 is used, benchmark value is used. Its by default 1,5% change, can be changed by touchSetDefaultThreshold(float percentage) bool touch1detected = false; bool touch2detected = false; @@ -23,6 +19,10 @@ void gotTouch2() { void setup() { Serial.begin(115200); delay(1000); // give me time to bring up serial monitor + + //Optional: Set the threshold to 5% of the benchmark value. Only effective if threshold = 0. + touchSetDefaultThreshold(5); + Serial.println("ESP32 Touch Interrupt Test"); touchAttachInterrupt(T2, gotTouch1, threshold); touchAttachInterrupt(T3, gotTouch2, threshold); diff --git a/libraries/ESP32/examples/Touch/TouchRead/TouchRead.ino b/libraries/ESP32/examples/Touch/TouchRead/TouchRead.ino index 8e93ba44691..ba221f3048f 100644 --- a/libraries/ESP32/examples/Touch/TouchRead/TouchRead.ino +++ b/libraries/ESP32/examples/Touch/TouchRead/TouchRead.ino @@ -1,5 +1,5 @@ // ESP32 Touch Test -// Just test touch pin - Touch0 is T0 which is on GPIO 4. +// Just test touch pin - Touch2 is T2 which is on GPIO 2. void setup() { Serial.begin(115200); @@ -8,6 +8,6 @@ void setup() { } void loop() { - Serial.println(touchRead(T1)); // get value using T0 + Serial.println(touchRead(T2)); // get value using T2 delay(1000); } From 09336ac7f73cc96491b98307a1e5e7f5e95898b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 25 Jul 2025 18:45:32 +0200 Subject: [PATCH 4/9] fix(touch): Use correct type --- cores/esp32/esp32-hal-touch-ng.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cores/esp32/esp32-hal-touch-ng.c b/cores/esp32/esp32-hal-touch-ng.c index 479427861a3..c3c5919a02d 100644 --- a/cores/esp32/esp32-hal-touch-ng.c +++ b/cores/esp32/esp32-hal-touch-ng.c @@ -43,7 +43,7 @@ static touch_volt_lim_h_t _volt_high = TOUCH_VOLT_LIM_H_1V7; static touch_intr_trig_mode_t _intr_trig_mode = TOUCH_INTR_TRIG_ON_BELOW_THRESH; #elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 static uint8_t _sample_num = 1; // only one sample configuration supported -static float _duration_ms = 500.0f; +static uint32_t _chg_times = 500; static touch_volt_lim_l_t _volt_low = TOUCH_VOLT_LIM_L_0V5; static touch_volt_lim_h_t _volt_high = TOUCH_VOLT_LIM_H_2V2; #elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 @@ -225,7 +225,7 @@ static void __touchInit() { #if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V1_DEFAULT_SAMPLE_CONFIG(_duration_ms, _volt_low, _volt_high); #elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 - touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V2_DEFAULT_SAMPLE_CONFIG(_duration_ms, _volt_low, _volt_high); + touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V2_DEFAULT_SAMPLE_CONFIG(_chg_times, _volt_low, _volt_high); #elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 touch_sensor_sample_config_t single_sample_cfg = TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG(_div_num, _coarse_freq_tune, _fine_freq_tune); #endif From 399094d2f805e63fefc093094624ae895d09ab02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 25 Jul 2025 18:49:01 +0200 Subject: [PATCH 5/9] fix(touch): Remove old driver from cmake --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c9800dfe2b..34b1c3e77fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,6 @@ set(CORE_SRCS cores/esp32/esp32-hal-time.c cores/esp32/esp32-hal-timer.c cores/esp32/esp32-hal-tinyusb.c - cores/esp32/esp32-hal-touch.c cores/esp32/esp32-hal-touch-ng.c cores/esp32/esp32-hal-uart.c cores/esp32/esp32-hal-rmt.c From ec720a8e8d133e12466a63bdd2382fe5e46fd5f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 25 Jul 2025 18:52:46 +0200 Subject: [PATCH 6/9] fix(touch): Update touchSetConfig for S2 and S3 --- cores/esp32/esp32-hal-touch-ng.c | 15 ++++++++++++--- cores/esp32/esp32-hal-touch-ng.h | 10 +++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/cores/esp32/esp32-hal-touch-ng.c b/cores/esp32/esp32-hal-touch-ng.c index c3c5919a02d..357db07746b 100644 --- a/cores/esp32/esp32-hal-touch-ng.c +++ b/cores/esp32/esp32-hal-touch-ng.c @@ -491,8 +491,7 @@ void touchSetTiming(float measure, uint32_t sleep) { __touchMeasureTime = measure; } -#if SOC_TOUCH_SENSOR_VERSION == 1 || SOC_TOUCH_SENSOR_VERSION == 2 // ESP32, ESP32S2, ESP32S3 - +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 void touchSetConfig(float duration_ms, touch_volt_lim_l_t volt_low, touch_volt_lim_h_t volt_high) { if (initialized) { log_e("Touch sensor already initialized. Cannot set configuration."); @@ -503,8 +502,18 @@ void touchSetConfig(float duration_ms, touch_volt_lim_l_t volt_low, touch_volt_l _volt_high = volt_high; } -#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 +void touchSetConfig(uint32_t chg_times, touch_volt_lim_l_t volt_low, touch_volt_lim_h_t volt_high) { + if (initialized) { + log_e("Touch sensor already initialized. Cannot set configuration."); + return; + } + _chg_times = chg_times; + _volt_low = volt_low; + _volt_high = volt_high; +} +#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 void touchSetConfig(uint32_t div_num, uint8_t coarse_freq_tune, uint8_t fine_freq_tune) { if (initialized) { log_e("Touch sensor already initialized. Cannot set configuration."); diff --git a/cores/esp32/esp32-hal-touch-ng.h b/cores/esp32/esp32-hal-touch-ng.h index 23c00983092..fba69db4ec7 100644 --- a/cores/esp32/esp32-hal-touch-ng.h +++ b/cores/esp32/esp32-hal-touch-ng.h @@ -59,7 +59,7 @@ typedef uint32_t touch_value_t; **/ void touchSetTiming(float measure, uint32_t sleep); -#if SOC_TOUCH_SENSOR_VERSION == 1 || SOC_TOUCH_SENSOR_VERSION == 2 // ESP32, ESP32S2, ESP32S3 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 /* * @param[in] duration_ms The measurement duration of the touch channel * @param[in] volt_low The low voltage limit of the touch channel @@ -67,6 +67,14 @@ void touchSetTiming(float measure, uint32_t sleep); */ void touchSetConfig(float duration_ms, touch_volt_lim_l_t volt_low, touch_volt_lim_h_t volt_high); +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 +/* + * @param[in] chg_times The charge times of the touch channel + * @param[in] volt_low The low voltage limit of the touch channel + * @param[in] volt_high The high voltage limit of the touch channel + */ +void touchSetConfig(uint32_t chg_times, touch_volt_lim_l_t volt_low, touch_volt_lim_h_t volt_high); + #elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 /* * Tune the touch pad frequency. From 7143d08112615b1287a0f3c3da662e0ee665236c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 25 Jul 2025 19:10:47 +0200 Subject: [PATCH 7/9] fix(touch): Revert old touch driver for older IDF --- cores/esp32/esp32-hal-touch-ng.c | 2 + cores/esp32/esp32-hal-touch-ng.h | 3 + cores/esp32/esp32-hal-touch.c | 329 +++++++++++++++++++++++++++++++ cores/esp32/esp32-hal-touch.h | 104 ++++++++++ cores/esp32/esp32-hal.h | 1 + 5 files changed, 439 insertions(+) create mode 100644 cores/esp32/esp32-hal-touch.c create mode 100644 cores/esp32/esp32-hal-touch.h diff --git a/cores/esp32/esp32-hal-touch-ng.c b/cores/esp32/esp32-hal-touch-ng.c index 357db07746b..8a550f01be8 100644 --- a/cores/esp32/esp32-hal-touch-ng.c +++ b/cores/esp32/esp32-hal-touch-ng.c @@ -14,6 +14,7 @@ #include "soc/soc_caps.h" #if SOC_TOUCH_SENSOR_SUPPORTED +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3 #include "esp32-hal-touch-ng.h" #include "esp32-hal-periman.h" @@ -540,4 +541,5 @@ extern void touchAttachInterrupt(uint8_t, voidFuncPtr, touch_value_t) __attribut extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, touch_value_t) __attribute__((weak, alias("__touchAttachArgsInterrupt"))); extern void touchDetachInterrupt(uint8_t) __attribute__((weak, alias("__touchDettachInterrupt"))); +#endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3 */ #endif /* SOC_TOUCH_SENSOR_SUPPORTED */ diff --git a/cores/esp32/esp32-hal-touch-ng.h b/cores/esp32/esp32-hal-touch-ng.h index fba69db4ec7..ee5ff23b9fa 100644 --- a/cores/esp32/esp32-hal-touch-ng.h +++ b/cores/esp32/esp32-hal-touch-ng.h @@ -21,7 +21,9 @@ #define MAIN_ESP32_HAL_TOUCH_NEW_H_ #include "soc/soc_caps.h" + #if SOC_TOUCH_SENSOR_SUPPORTED +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3 #ifdef __cplusplus extern "C" { @@ -133,5 +135,6 @@ void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold); } #endif +#endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3 */ #endif /* SOC_TOUCH_SENSOR_SUPPORTED */ #endif /* MAIN_ESP32_HAL_TOUCH_H_ */ diff --git a/cores/esp32/esp32-hal-touch.c b/cores/esp32/esp32-hal-touch.c new file mode 100644 index 00000000000..cc158aee634 --- /dev/null +++ b/cores/esp32/esp32-hal-touch.c @@ -0,0 +1,329 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "soc/soc_caps.h" + +#if SOC_TOUCH_SENSOR_SUPPORTED +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0) && SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32, ESP32S2, ESP32S3 + +#include "driver/touch_sensor.h" +#include "esp32-hal-touch.h" +#include "esp32-hal-periman.h" + +/* + Internal Private Touch Data Structure and Functions +*/ + +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +static uint16_t __touchSleepCycles = 0x1000; +static uint16_t __touchMeasureCycles = 0x1000; +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 +static uint16_t __touchSleepCycles = TOUCH_PAD_SLEEP_CYCLE_DEFAULT; +static uint16_t __touchMeasureCycles = TOUCH_PAD_MEASURE_CYCLE_DEFAULT; +#endif + +typedef void (*voidFuncPtr)(void); +typedef void (*voidArgFuncPtr)(void *); + +typedef struct { + voidFuncPtr fn; + bool callWithArgs; + void *arg; +#if SOC_TOUCH_SENSOR_VERSION == 2 // Only for ESP32S2 and ESP32S3 + bool lastStatusIsPressed; +#endif +} TouchInterruptHandle_t; + +static TouchInterruptHandle_t __touchInterruptHandlers[SOC_TOUCH_SENSOR_NUM] = { + 0, +}; + +static uint8_t used_pads = 0; +static bool initialized = false; +static bool channels_initialized[SOC_TOUCH_SENSOR_NUM] = {false}; + +static void ARDUINO_ISR_ATTR __touchISR(void *arg) { +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + uint32_t pad_intr = touch_pad_get_status(); + //clear interrupt + touch_pad_clear_status(); + // call Pad ISR User callback + for (int i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) { + if ((pad_intr >> i) & 0x01) { + if (__touchInterruptHandlers[i].fn) { + // keeping backward compatibility with "void cb(void)" and with new "void cb(vooid *)" + if (__touchInterruptHandlers[i].callWithArgs) { + ((voidArgFuncPtr)__touchInterruptHandlers[i].fn)(__touchInterruptHandlers[i].arg); + } else { + __touchInterruptHandlers[i].fn(); + } + } + } + } +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 + touch_pad_intr_mask_t evt = touch_pad_read_intr_status_mask(); + uint8_t pad_num = touch_pad_get_current_meas_channel(); + if (evt & TOUCH_PAD_INTR_MASK_ACTIVE) { + // touch has been pressed / touched + __touchInterruptHandlers[pad_num].lastStatusIsPressed = true; + } + if (evt & TOUCH_PAD_INTR_MASK_INACTIVE) { + // touch has been released / untouched + __touchInterruptHandlers[pad_num].lastStatusIsPressed = false; + } + if (__touchInterruptHandlers[pad_num].fn) { + // keeping backward compatibility with "void cb(void)" and with new "void cb(vooid *)" + if (__touchInterruptHandlers[pad_num].callWithArgs) { + ((voidArgFuncPtr)__touchInterruptHandlers[pad_num].fn)(__touchInterruptHandlers[pad_num].arg); + } else { + __touchInterruptHandlers[pad_num].fn(); + } + } +#endif +} + +static void __touchSetCycles(uint16_t measure, uint16_t sleep) { + __touchSleepCycles = sleep; + __touchMeasureCycles = measure; +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + touch_pad_set_measurement_clock_cycles(measure); +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 + touch_pad_set_charge_discharge_times(measure); +#endif + touch_pad_set_measurement_interval(sleep); +} + +static bool touchDetachBus(void *pin) { + int8_t pad = digitalPinToTouchChannel((int)(pin - 1)); + channels_initialized[pad] = false; + used_pads--; + if (used_pads == 0) { + if (touch_pad_deinit() != ESP_OK) //deinit touch module, as no pads are used + { + log_e("Touch module deinit failed!"); + return false; + } + initialized = false; + } + return true; +} + +static void __touchInit() { + if (initialized) { + return; + } + + esp_err_t err = ESP_OK; + +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + err = touch_pad_init(); + if (err != ESP_OK) { + goto err; + } + // the next two lines will drive the touch reading values -- both will return ESP_OK + touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V); + touch_pad_set_measurement_clock_cycles(__touchMeasureCycles); + touch_pad_set_measurement_interval(__touchSleepCycles); + // Touch Sensor Timer initiated + touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); // returns ESP_OK + err = touch_pad_filter_start(10); + if (err != ESP_OK) { + goto err; + } + // keep ISR activated - it can run all together (ISR + touchRead()) + err = touch_pad_isr_register(__touchISR, NULL); + if (err != ESP_OK) { + goto err; + } + touch_pad_intr_enable(); // returns ESP_OK +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 + err = touch_pad_init(); + if (err != ESP_OK) { + goto err; + } + // the next lines will drive the touch reading values -- all os them return ESP_OK + touch_pad_set_charge_discharge_times(__touchMeasureCycles); + touch_pad_set_measurement_interval(__touchSleepCycles); + touch_pad_set_voltage(TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD); + touch_pad_set_idle_channel_connect(TOUCH_PAD_IDLE_CH_CONNECT_DEFAULT); + touch_pad_denoise_t denoise = { + .grade = TOUCH_PAD_DENOISE_BIT4, + .cap_level = TOUCH_PAD_DENOISE_CAP_L4, + }; + touch_pad_denoise_set_config(&denoise); + touch_pad_denoise_enable(); + // Touch Sensor Timer initiated + touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); // returns ESP_OK + touch_pad_fsm_start(); // returns ESP_OK + //ISR setup moved to __touchChannelInit +#endif + initialized = true; + return; +err: + log_e(" Touch sensor initialization error."); + initialized = false; + return; +} + +static void __touchChannelInit(int pad) { + if (channels_initialized[pad]) { + return; + } + +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 + // Initial no Threshold and setup + __touchInterruptHandlers[pad].fn = NULL; + touch_pad_config(pad, TOUCH_PAD_THRESHOLD_MAX); // returns ESP_OK +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 + // Initial no Threshold and setup + __touchInterruptHandlers[pad].fn = NULL; + touch_pad_config(pad); // returns ESP_OK + // keep ISR activated - it can run all together (ISR + touchRead()) + esp_err_t err = touch_pad_isr_register(__touchISR, NULL, TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE); + if (err != ESP_OK) { + log_e(" Touch sensor initialization error."); + return; + } + touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE); // returns ESP_OK +#endif + + channels_initialized[pad] = true; + used_pads++; + delay(20); //delay needed before reading from touch channel after config +} + +static touch_value_t __touchRead(uint8_t pin) { + int8_t pad = digitalPinToTouchChannel(pin); + if (pad < 0) { + log_e(" No touch pad on selected pin!"); + return 0; + } + + if (perimanGetPinBus(pin, ESP32_BUS_TYPE_TOUCH) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_TOUCH, touchDetachBus); + if (!perimanClearPinBus(pin)) { + return 0; + } + __touchInit(); + __touchChannelInit(pad); + + if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_TOUCH, (void *)(pin + 1), -1, pad)) { + touchDetachBus((void *)(pin + 1)); + return 0; + } + } + + touch_value_t touch_value; + touch_pad_read_raw_data(pad, &touch_value); + + return touch_value; +} + +static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Args, touch_value_t threshold, bool callWithArgs) { + int8_t pad = digitalPinToTouchChannel(pin); + if (pad < 0) { + log_e(" No touch pad on selected pin!"); + return; + } + + if (userFunc == NULL) { + // detach ISR User Call + __touchInterruptHandlers[pad].fn = NULL; + threshold = TOUCH_PAD_THRESHOLD_MAX; // deactivate the ISR with SOC_TOUCH_PAD_THRESHOLD_MAX + } else { + // attach ISR User Call + __touchInit(); + __touchChannelInit(pad); + __touchInterruptHandlers[pad].fn = userFunc; + __touchInterruptHandlers[pad].callWithArgs = callWithArgs; + __touchInterruptHandlers[pad].arg = Args; + } + + touch_pad_set_thresh(pad, threshold); +} + +// it keeps backwards compatibility +static void __touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), touch_value_t threshold) { + __touchConfigInterrupt(pin, userFunc, NULL, threshold, false); +} + +// new additional version of the API with User Args +static void __touchAttachArgsInterrupt(uint8_t pin, void (*userFunc)(void), void *args, touch_value_t threshold) { + __touchConfigInterrupt(pin, userFunc, args, threshold, true); +} + +// new additional API to detach touch ISR +static void __touchDettachInterrupt(uint8_t pin) { + __touchConfigInterrupt(pin, NULL, NULL, 0, false); // userFunc as NULL acts as detaching +} + +/* + External Public Touch API Functions +*/ + +#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC +void touchInterruptSetThresholdDirection(bool mustbeLower) { + if (mustbeLower) { + touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW); + } else { + touch_pad_set_trigger_mode(TOUCH_TRIGGER_ABOVE); + } +} +#elif SOC_TOUCH_SENSOR_VERSION == 2 // Only for ESP32S2 and ESP32S3 +// returns true if touch pad has been and continues pressed and false otherwise +bool touchInterruptGetLastStatus(uint8_t pin) { + int8_t pad = digitalPinToTouchChannel(pin); + if (pad < 0) { + return false; + } + + return __touchInterruptHandlers[pad].lastStatusIsPressed; +} +#endif + +void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold) { + int8_t pad = digitalPinToTouchChannel(pin); + if (pad < 0) { + log_e(" No touch pad on selected pin!"); + return; + } + + if (perimanGetPinBus(pin, ESP32_BUS_TYPE_TOUCH) == NULL) { + perimanSetBusDeinit(ESP32_BUS_TYPE_TOUCH, touchDetachBus); + __touchInit(); + __touchChannelInit(pad); + if (!perimanSetPinBus(pin, ESP32_BUS_TYPE_TOUCH, (void *)(pin + 1), -1, pad)) { + log_e("Failed to set bus to Peripheral manager"); + touchDetachBus((void *)(pin + 1)); + return; + } + } +#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC + touch_pad_set_thresh(pad, threshold); + +#elif SOC_TOUCH_SENSOR_VERSION == 2 + touch_pad_sleep_channel_enable(pad, true); + touch_pad_sleep_set_threshold(pad, threshold); + +#endif + esp_sleep_enable_touchpad_wakeup(); +} + +extern touch_value_t touchRead(uint8_t) __attribute__((weak, alias("__touchRead"))); +extern void touchAttachInterrupt(uint8_t, voidFuncPtr, touch_value_t) __attribute__((weak, alias("__touchAttachInterrupt"))); +extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, touch_value_t) __attribute__((weak, alias("__touchAttachArgsInterrupt"))); +extern void touchDetachInterrupt(uint8_t) __attribute__((weak, alias("__touchDettachInterrupt"))); +extern void touchSetCycles(uint16_t, uint16_t) __attribute__((weak, alias("__touchSetCycles"))); + +#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0) && SOC_TOUCH_SENSOR_VERSION <= 2 */ +#endif /* SOC_TOUCH_SENSOR_SUPPORTED */ \ No newline at end of file diff --git a/cores/esp32/esp32-hal-touch.h b/cores/esp32/esp32-hal-touch.h new file mode 100644 index 00000000000..709691ef658 --- /dev/null +++ b/cores/esp32/esp32-hal-touch.h @@ -0,0 +1,104 @@ +/* + Arduino.h - Main include file for the Arduino SDK + Copyright (c) 2005-2013 Arduino Team. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MAIN_ESP32_HAL_TOUCH_H_ +#define MAIN_ESP32_HAL_TOUCH_H_ + +#include "soc/soc_caps.h" + +#if SOC_TOUCH_SENSOR_SUPPORTED +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0) && SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32, ESP32S2, ESP32S3 + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp32-hal.h" + +#if !SOC_TOUCH_SENSOR_SUPPORTED +#error Touch IDF driver Not supported! +#endif + +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +typedef uint16_t touch_value_t; +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2 ESP32S3 +typedef uint32_t touch_value_t; +#endif + +/* + * Set cycles that measurement operation takes + * The result from touchRead, threshold and detection + * accuracy depend on these values. Defaults are + * 0x1000 for measure and 0x1000 for sleep. + * With default values touchRead takes 0.5ms + * */ +void touchSetCycles(uint16_t measure, uint16_t sleep); + +/* + * Read touch pad (for ESP32 values close to 0 mean touch detected / + * for ESP32-S2/S3 higher values mean touch detected) + * You can use this method to chose a good threshold value + * to use as value for touchAttachInterrupt + * */ +touch_value_t touchRead(uint8_t pin); + +/* + * Set function to be called if touch pad value falls (ESP32) + * below the given threshold / rises (ESP32-S2/S3) by given increment (threshold). + * Use touchRead to determine a proper threshold between touched and untouched state + * */ +void touchAttachInterrupt(uint8_t pin, void (*userFunc)(void), touch_value_t threshold); +void touchAttachInterruptArg(uint8_t pin, void (*userFunc)(void *), void *arg, touch_value_t threshold); +void touchDetachInterrupt(uint8_t pin); + +/* + * Specific functions to ESP32 + * Tells the driver if it shall activate the ISR if the sensor is Lower or Higher than the Threshold + * Default if Lower. + **/ + +#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC +void touchInterruptSetThresholdDirection(bool mustbeLower); +#endif + +/* + * Specific functions to ESP32-S2 and ESP32-S3 + * Returns true when the latest ISR status for the Touchpad is that it is touched (Active) + * and false when the Touchpad is untoouched (Inactive) + * This function can be used in conjunction with ISR User callback in order to take action + * as soon as the touchpad is touched and/or released + **/ + +#if SOC_TOUCH_SENSOR_VERSION == 2 // Only for ESP32S2 and ESP32S3 +// returns true if touch pad has been and continues pressed and false otherwise +bool touchInterruptGetLastStatus(uint8_t pin); +#endif + +/* + * Setup touch pad wake up from deep sleep with given threshold. + **/ +void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold); + +#ifdef __cplusplus +} +#endif + +#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0) && SOC_TOUCH_SENSOR_VERSION <= 2 */ +#endif /* SOC_TOUCH_SENSOR_SUPPORTED */ +#endif /* MAIN_ESP32_HAL_TOUCH_H_ */ diff --git a/cores/esp32/esp32-hal.h b/cores/esp32/esp32-hal.h index e2ca9309fe0..5ed99aeb205 100644 --- a/cores/esp32/esp32-hal.h +++ b/cores/esp32/esp32-hal.h @@ -86,6 +86,7 @@ void yield(void); #include "esp32-hal-matrix.h" #include "esp32-hal-uart.h" #include "esp32-hal-gpio.h" +#include "esp32-hal-touch.h" #include "esp32-hal-touch-ng.h" #include "esp32-hal-dac.h" #include "esp32-hal-adc.h" From f691a428270247ec893daf2bf315532c7e037695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 25 Jul 2025 19:14:11 +0200 Subject: [PATCH 8/9] fix(touch): Add missing include --- cores/esp32/esp32-hal-touch-ng.c | 1 + cores/esp32/esp32-hal-touch-ng.h | 1 + cores/esp32/esp32-hal-touch.c | 1 + cores/esp32/esp32-hal-touch.h | 1 + 4 files changed, 4 insertions(+) diff --git a/cores/esp32/esp32-hal-touch-ng.c b/cores/esp32/esp32-hal-touch-ng.c index 8a550f01be8..483a444b4a0 100644 --- a/cores/esp32/esp32-hal-touch-ng.c +++ b/cores/esp32/esp32-hal-touch-ng.c @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. #include "soc/soc_caps.h" +#include "esp_idf_version.h" #if SOC_TOUCH_SENSOR_SUPPORTED #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3 diff --git a/cores/esp32/esp32-hal-touch-ng.h b/cores/esp32/esp32-hal-touch-ng.h index ee5ff23b9fa..988fdccda00 100644 --- a/cores/esp32/esp32-hal-touch-ng.h +++ b/cores/esp32/esp32-hal-touch-ng.h @@ -21,6 +21,7 @@ #define MAIN_ESP32_HAL_TOUCH_NEW_H_ #include "soc/soc_caps.h" +#include "esp_idf_version.h" #if SOC_TOUCH_SENSOR_SUPPORTED #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) || SOC_TOUCH_SENSOR_VERSION == 3 diff --git a/cores/esp32/esp32-hal-touch.c b/cores/esp32/esp32-hal-touch.c index cc158aee634..e611fa557f1 100644 --- a/cores/esp32/esp32-hal-touch.c +++ b/cores/esp32/esp32-hal-touch.c @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. #include "soc/soc_caps.h" +#include "esp_idf_version.h" #if SOC_TOUCH_SENSOR_SUPPORTED #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0) && SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32, ESP32S2, ESP32S3 diff --git a/cores/esp32/esp32-hal-touch.h b/cores/esp32/esp32-hal-touch.h index 709691ef658..44c99dce206 100644 --- a/cores/esp32/esp32-hal-touch.h +++ b/cores/esp32/esp32-hal-touch.h @@ -21,6 +21,7 @@ #define MAIN_ESP32_HAL_TOUCH_H_ #include "soc/soc_caps.h" +#include "esp_idf_version.h" #if SOC_TOUCH_SENSOR_SUPPORTED #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 5, 0) && SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32, ESP32S2, ESP32S3 From 04459faf480c9fc81043741c6f277276485ccdfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Fri, 25 Jul 2025 19:49:14 +0200 Subject: [PATCH 9/9] fix(touch): Update test and example --- CMakeLists.txt | 1 + .../examples/Touch/TouchButton/TouchButton.ino | 2 +- tests/validation/touch/touch.ino | 17 +++++++++++------ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 34b1c3e77fb..3c9800dfe2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ set(CORE_SRCS cores/esp32/esp32-hal-time.c cores/esp32/esp32-hal-timer.c cores/esp32/esp32-hal-tinyusb.c + cores/esp32/esp32-hal-touch.c cores/esp32/esp32-hal-touch-ng.c cores/esp32/esp32-hal-uart.c cores/esp32/esp32-hal-rmt.c diff --git a/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino b/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino index 8ebe2f00cbc..ac2b641be40 100644 --- a/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino +++ b/libraries/ESP32/examples/Touch/TouchButton/TouchButton.ino @@ -29,7 +29,7 @@ void setup() { //Set the touch pads Serial.println("\n ESP32 Touch Interrupt Test\n"); - touchAttachInterrupt(T0, gotTouch1, threshold); + touchAttachInterrupt(T1, gotTouch1, threshold); touchAttachInterrupt(T2, gotTouch2, threshold); } diff --git a/tests/validation/touch/touch.ino b/tests/validation/touch/touch.ino index 315df0a5ee2..abe450a27ab 100644 --- a/tests/validation/touch/touch.ino +++ b/tests/validation/touch/touch.ino @@ -4,28 +4,30 @@ #if CONFIG_IDF_TARGET_ESP32 -#define TEST_TOUCH_CHANNEL (9) +#define TEST_TOUCH_CHANNEL (7) static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = { TOUCH_PAD_NUM0, //TOUCH_PAD_NUM1 is GPIO0, for download. - TOUCH_PAD_NUM2, TOUCH_PAD_NUM3, TOUCH_PAD_NUM4, TOUCH_PAD_NUM5, TOUCH_PAD_NUM6, TOUCH_PAD_NUM7, TOUCH_PAD_NUM8, TOUCH_PAD_NUM9 + TOUCH_PAD_NUM2, TOUCH_PAD_NUM3, TOUCH_PAD_NUM4, TOUCH_PAD_NUM5, TOUCH_PAD_NUM6, TOUCH_PAD_NUM7 /*,TOUCH_PAD_NUM8, TOUCH_PAD_NUM9*/ }; -uint8_t TOUCH_GPIOS[] = {4, 2, 15, 13, 12, 14, 27, 33, 32}; +uint8_t TOUCH_GPIOS[] = {4,/* 0,*/ 2, 15, 13, 12, 14, 27/*, 33, 32*/}; #define NO_TOUCH_GPIO 25 #elif (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3) -#define TEST_TOUCH_CHANNEL (12) //14 +#define TEST_TOUCH_CHANNEL (9) //14 static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = { TOUCH_PAD_NUM1, TOUCH_PAD_NUM2, TOUCH_PAD_NUM3, TOUCH_PAD_NUM4, TOUCH_PAD_NUM5, TOUCH_PAD_NUM6, TOUCH_PAD_NUM7, - TOUCH_PAD_NUM8, TOUCH_PAD_NUM9, TOUCH_PAD_NUM10, TOUCH_PAD_NUM11, TOUCH_PAD_NUM12 + TOUCH_PAD_NUM8, /*TOUCH_PAD_NUM9,*/ TOUCH_PAD_NUM10 + //TOUCH_PAD_NUM11, //Wrong reading + //TOUCH_PAD_NUM12, //Wrong reading //TOUCH_PAD_NUM13, //Wrong reading //TOUCH_PAD_NUM14 }; -uint8_t TOUCH_GPIOS[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 /*,13,14*/}; +uint8_t TOUCH_GPIOS[] = {1, 2, 3, 4, 5, 6, 7, 8,/*9,*/ 10/*, 11, 12, 13, 14*/}; #define NO_TOUCH_GPIO 17 @@ -120,6 +122,9 @@ void test_touch_read(void) { } // COMPARE PRESSED <-> UNPRESSED + for (int l = 0; l < sizeof(TOUCH_GPIOS); l++) { + log_v("Touch %d: %d -> %d", TOUCH_GPIOS[l], touch_unpressed[l], touch_pressed[l]); + } for (int l = 0; l < sizeof(TOUCH_GPIOS); l++) { #if CONFIG_IDF_TARGET_ESP32 TEST_ASSERT_LESS_THAN((touch_unpressed[l] - PRESSED_VALUE_DIFFERENCE), touch_pressed[l]);