diff --git a/CMakeLists.txt b/CMakeLists.txt index a06f815c9d8..6688a97803d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ set(CORE_SRCS 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 cores/esp32/Esp.cpp @@ -317,6 +318,10 @@ if(NOT CONFIG_ARDUINO_SELECTIVE_COMPILATION OR CONFIG_ARDUINO_SELECTIVE_OpenThre endif() endif() +if(IDF_TARGET STREQUAL "esp32p4") + list(APPEND requires esp_driver_touch_sens) +endif() + idf_component_register(INCLUDE_DIRS ${includedirs} PRIV_INCLUDE_DIRS ${priv_includes} SRCS ${srcs} REQUIRES ${requires} PRIV_REQUIRES ${priv_requires}) if(NOT CONFIG_FREERTOS_HZ EQUAL 1000 AND NOT "$ENV{ARDUINO_SKIP_TICK_CHECK}") diff --git a/cores/esp32/esp32-hal-touch-ng.c b/cores/esp32/esp32-hal-touch-ng.c new file mode 100644 index 00000000000..888a299ec0c --- /dev/null +++ b/cores/esp32/esp32-hal-touch-ng.c @@ -0,0 +1,453 @@ +// Copyright 2024 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 == 3 // ESP32P4 for now + +#include "driver/touch_sens.h" +#include "esp32-hal-touch-ng.h" +#include "esp32-hal-periman.h" + +/* + Internal Private Touch Data Structure and Functions +*/ + +typedef void (*voidFuncPtr)(void); +typedef void (*voidArgFuncPtr)(void *); + +typedef struct { + voidFuncPtr fn; + bool callWithArgs; + void *arg; + bool lastStatusIsPressed; +} TouchInterruptHandle_t; + +static TouchInterruptHandle_t __touchInterruptHandlers[SOC_TOUCH_SENSOR_NUM] = { + 0, +}; + +static uint8_t _sample_num = 1; +static uint32_t _div_num = 1; +static uint8_t _coarse_freq_tune = 1; +static uint8_t _fine_freq_tune = 1; +static uint8_t used_pads = 0; + +static uint32_t __touchSleepTime = 256; +static float __touchMeasureTime = 32.0f; + +static touch_sensor_config_t sensor_config; + +static bool initialized = false; +static bool enabled = false; +static bool running = false; +static bool channels_initialized[SOC_TOUCH_SENSOR_NUM] = {false}; + +static touch_sensor_handle_t touch_sensor_handle = NULL; +static touch_channel_handle_t touch_channel_handle[SOC_TOUCH_SENSOR_NUM] = {}; + +// Active threshold to benchmark ratio. (i.e., touch will be activated when data >= benchmark * (1 + ratio)) +static float s_thresh2bm_ratio = 0.015f; // 1.5% for all channels + +static bool ARDUINO_ISR_ATTR __touchOnActiveISR(touch_sensor_handle_t sens_handle, const touch_active_event_data_t *event, void *user_ctx) { + uint8_t pad_num = (uint8_t)event->chan_id; + __touchInterruptHandlers[pad_num].lastStatusIsPressed = true; + if (__touchInterruptHandlers[pad_num].fn) { + // keeping backward compatibility with "void cb(void)" and with new "void cb(void *)" + if (__touchInterruptHandlers[pad_num].callWithArgs) { + ((voidArgFuncPtr)__touchInterruptHandlers[pad_num].fn)(__touchInterruptHandlers[pad_num].arg); + } else { + __touchInterruptHandlers[pad_num].fn(); + } + } + return false; +} + +static bool ARDUINO_ISR_ATTR __touchOnInactiveISR(touch_sensor_handle_t sens_handle, const touch_inactive_event_data_t *event, void *user_ctx) { + uint8_t pad_num = (uint8_t)event->chan_id; + __touchInterruptHandlers[pad_num].lastStatusIsPressed = false; + if (__touchInterruptHandlers[pad_num].fn) { + // keeping backward compatibility with "void cb(void)" and with new "void cb(void *)" + if (__touchInterruptHandlers[pad_num].callWithArgs) { + ((voidArgFuncPtr)__touchInterruptHandlers[pad_num].fn)(__touchInterruptHandlers[pad_num].arg); + } else { + __touchInterruptHandlers[pad_num].fn(); + } + } + return false; +} + +bool touchStop() { + if (!running) { // Already stopped + return true; + } + if (touch_sensor_stop_continuous_scanning(touch_sensor_handle) != ESP_OK) { + log_e("Touch sensor stop scanning failed!"); + return false; + } + running = false; + return true; +} + +bool touchDisable() { + if (!enabled) { // Already disabled + return true; + } + if (!running && (touch_sensor_disable(touch_sensor_handle) != ESP_OK)) { + log_e("Touch sensor still running or disable failed!"); + return false; + } + enabled = false; + return true; +} + +bool touchStart() { + if (running) { // Already running + return true; + } + if (enabled && (touch_sensor_start_continuous_scanning(touch_sensor_handle) != ESP_OK)) { + log_e("Touch sensor not enabled or failed to start continuous scanning failed!"); + return false; + } + running = true; + return true; +} + +bool touchEnable() { + if (enabled) { // Already enabled + return true; + } + if (touch_sensor_enable(touch_sensor_handle) != ESP_OK) { + log_e("Touch sensor enable failed!"); + return false; + } + enabled = true; + return true; +} + +bool touchBenchmarkThreshold(uint8_t pad) { + if (!touchEnable()) { + return false; + } + + /* Scan the enabled touch channels for several times, to make sure the initial channel data is stable */ + for (int i = 0; i < 3; i++) { + if (touch_sensor_trigger_oneshot_scanning(touch_sensor_handle, 2000) != ESP_OK) { + log_e("Touch sensor trigger oneshot scanning failed!"); + return false; + } + } + + /* Disable the touch channel to rollback the state */ + if (!touchDisable()) { + return false; + } + + // Reconfigure passed pad with new threshold + uint32_t benchmark[_sample_num] = {}; + 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; + } + /* Calculate the proper active thresholds regarding the initial benchmark */ + touch_channel_config_t chan_cfg = {}; + for (int i = 0; i < _sample_num; i++) { + 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]); + } + /* Update the channel configuration */ + if (touch_sensor_reconfig_channel(touch_channel_handle[pad], &chan_cfg) != ESP_OK) { + log_e("Touch sensor threshold reconfig channel failed!"); + return false; + } + return true; +} + +static bool touchDetachBus(void *pin) { + int8_t pad = digitalPinToTouchChannel((int)(pin - 1)); + channels_initialized[pad] = false; + //disable touch pad and delete the channel + touch_sensor_del_channel(touch_channel_handle[pad]); + used_pads--; + if (used_pads == 0) { + touchStop(); + touchDisable(); + if (touch_sensor_del_controller(touch_sensor_handle) != 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; + } + // 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); + 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 = { + .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, + }; + + // 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; + } + + sensor_config = sens_cfg; + /* Configure the touch sensor filter */ + touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG(); + if (touch_sensor_config_filter(touch_sensor_handle, &filter_cfg) != ESP_OK) { + goto err; + } + + /* 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, + }; + if (touch_sensor_register_callbacks(touch_sensor_handle, &callbacks, NULL) != ESP_OK) { + goto err; + } + + initialized = true; + return; +err: + log_e(" Touch sensor initialization error."); + initialized = false; + return; +} + +static void __touchChannelInit(int pad) { + if (channels_initialized[pad]) { + return; + } + + // 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 + }; + + if (!touchStop() || !touchDisable()) { + log_e("Touch sensor stop and disable failed!"); + return; + } + + if (touch_sensor_new_channel(touch_sensor_handle, pad, &chan_cfg, &touch_channel_handle[pad]) != ESP_OK) { + log_e("Touch sensor new channel failed!"); + return; + } + + // Benchmark active threshold and reconfigure pad + if (!touchBenchmarkThreshold(pad)) { + log_e("Touch sensor benchmark threshold failed!"); + return; + } + + channels_initialized[pad] = true; + used_pads++; + + if (!touchEnable() || !touchStart()) { + log_e("Touch sensor enable and start failed!"); + } +} + +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; + } + } + + uint32_t touch_read[_sample_num] = {}; + touch_channel_read_data(touch_channel_handle[pad], TOUCH_CHAN_DATA_TYPE_SMOOTH, touch_read); + touch_value_t touch_value = touch_read[0]; // only one sample configuration for now + + return touch_value; +} + +static void __touchConfigInterrupt(uint8_t pin, void (*userFunc)(void), void *Args, bool callWithArgs, touch_value_t threshold) { + 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; + __touchInterruptHandlers[pad].callWithArgs = false; + __touchInterruptHandlers[pad].arg = NULL; + } else { + // attach ISR User Call + __touchInit(); + __touchChannelInit(pad); + __touchInterruptHandlers[pad].fn = userFunc; + __touchInterruptHandlers[pad].callWithArgs = callWithArgs; + __touchInterruptHandlers[pad].arg = Args; + } + + if (threshold != 0) { + if (!touchStop() || !touchDisable()) { + log_e("Touch sensor stop and disable failed!"); + return; + } + + touch_channel_config_t chan_cfg = {}; + for (int i = 0; i < _sample_num; i++) { + chan_cfg.active_thresh[i] = threshold; + } + + if (touch_sensor_reconfig_channel(touch_channel_handle[pad], &chan_cfg) != ESP_OK) { + log_e("Touch sensor threshold reconfig channel failed!"); + } + + if (!touchEnable() || !touchStart()) { + log_e("Touch sensor enable and start failed!"); + } + } +} + +// 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 +// */ + +bool touchInterruptGetLastStatus(uint8_t pin) { + int8_t pad = digitalPinToTouchChannel(pin); + if (pad < 0) { + return false; + } + + return __touchInterruptHandlers[pad].lastStatusIsPressed; +} + +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; + } + } + + log_v("Touch sensor deep sleep wake-up configuration for pad %d with threshold %d", pad, threshold); + if (!touchStop() || !touchDisable()) { + log_e("Touch sensor stop and disable failed!"); + return; + } + + touch_sleep_config_t deep_slp_cfg = { + .slp_wakeup_lvl = TOUCH_DEEP_SLEEP_WAKEUP, + .deep_slp_chan = touch_channel_handle[pad], + .deep_slp_thresh = {threshold}, + .deep_slp_sens_cfg = NULL, // Use the original touch sensor configuration + }; + + // Register the deep sleep wake-up + if (touch_sensor_config_sleep_wakeup(touch_sensor_handle, &deep_slp_cfg) != ESP_OK) { + log_e("Touch sensor deep sleep wake-up failed!"); + return; + } + + if (!touchEnable() || !touchStart()) { + log_e("Touch sensor enable and start failed!"); + } +} + +void touchSetDefaultThreshold(float percentage) { + s_thresh2bm_ratio = (float)percentage / 100.0f; +} + +void touchSetTiming(float measure, uint32_t sleep) { + if (initialized) { + log_e("Touch sensor already initialized. Cannot set cycles."); + return; + } + __touchSleepTime = sleep; + __touchMeasureTime = measure; +} + +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."); + return; + } + _div_num = div_num; + _coarse_freq_tune = coarse_freq_tune; + _fine_freq_tune = fine_freq_tune; +} + +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_SUPPORTED */ diff --git a/cores/esp32/esp32-hal-touch-ng.h b/cores/esp32/esp32-hal-touch-ng.h new file mode 100644 index 00000000000..0d4eb79ac58 --- /dev/null +++ b/cores/esp32/esp32-hal-touch-ng.h @@ -0,0 +1,91 @@ +/* + 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_NEW_H_ +#define MAIN_ESP32_HAL_TOUCH_NEW_H_ + +#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" + +typedef uint32_t touch_value_t; + +/* + * Set time in us that measurement operation takes + * The result from touchRead, threshold and detection + * accuracy depend on these values. + * Note: must be called before setting up touch pads + **/ +void touchSetTiming(float measure, uint32_t sleep); + +/* + * 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); + +/* + * Read touch pad value. + * 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 rises 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); + +/* + * 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. + **/ +bool touchInterruptGetLastStatus(uint8_t pin); + +/* + * Set the default threshold for touch pads. + * The threshold is a percentage of the benchmark value. + * The default value is 1.5%. + **/ +void touchSetDefaultThreshold(float percentage); + +/* + * Setup touch pad wake up from deep sleep /light sleep with given threshold. + * When light sleep is used, all used touch pads will be able to wake up the chip. + **/ +void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold); + +#ifdef __cplusplus +} +#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 index 93e0cb1c4ac..701bf6d16c9 100644 --- a/cores/esp32/esp32-hal-touch.c +++ b/cores/esp32/esp32-hal-touch.c @@ -14,10 +14,8 @@ #include "soc/soc_caps.h" #if SOC_TOUCH_SENSOR_SUPPORTED -#if SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 -// ToDo: Implement touch sensor for ESP32P4 -#warning "Touch sensor not implemented for ESP32P4 yet" -#else +#if SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32, ESP32S2, ESP32S3 + #include "driver/touch_sensor.h" #include "esp32-hal-touch.h" #include "esp32-hal-periman.h" @@ -26,10 +24,10 @@ Internal Private Touch Data Structure and Functions */ -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#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, ESP32P4 +#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 @@ -55,7 +53,7 @@ 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 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 uint32_t pad_intr = touch_pad_get_status(); //clear interrupt touch_pad_clear_status(); @@ -97,7 +95,7 @@ static void ARDUINO_ISR_ATTR __touchISR(void *arg) { static void __touchSetCycles(uint16_t measure, uint16_t sleep) { __touchSleepCycles = sleep; __touchMeasureCycles = measure; -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#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); @@ -127,7 +125,7 @@ static void __touchInit() { esp_err_t err = ESP_OK; -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 err = touch_pad_init(); if (err != ESP_OK) { goto err; @@ -147,7 +145,7 @@ static void __touchInit() { if (err != ESP_OK) { goto err; } - touch_pad_intr_enable(); // returns ESP_OK + touch_pad_intr_enable(); // returns ESP_OK #elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 err = touch_pad_init(); if (err != ESP_OK) { @@ -169,7 +167,6 @@ static void __touchInit() { touch_pad_fsm_start(); // returns ESP_OK //ISR setup moved to __touchChannelInit #endif - initialized = true; return; err: @@ -183,11 +180,11 @@ static void __touchChannelInit(int pad) { return; } -#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32 +#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 +#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2, ESP32S3 // Initial no Threshold and setup __touchInterruptHandlers[pad].fn = NULL; touch_pad_config(pad); // returns ESP_OK @@ -274,7 +271,7 @@ static void __touchDettachInterrupt(uint8_t pin) { External Public Touch API Functions */ -#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC +#if SOC_TOUCH_SENSOR_VERSION == 1 // Only for ESP32 SoC void touchInterruptSetThresholdDirection(bool mustbeLower) { if (mustbeLower) { touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW); @@ -328,5 +325,5 @@ extern void touchAttachInterruptArg(uint8_t, voidArgFuncPtr, void *, touch_value 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 == 3 */ +#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 index cc140d81bb0..4b06c7db766 100644 --- a/cores/esp32/esp32-hal-touch.h +++ b/cores/esp32/esp32-hal-touch.h @@ -22,6 +22,7 @@ #include "soc/soc_caps.h" #if SOC_TOUCH_SENSOR_SUPPORTED +#if SOC_TOUCH_SENSOR_VERSION <= 2 // ESP32 ESP32S2 ESP32S3 #ifdef __cplusplus extern "C" { @@ -37,8 +38,6 @@ extern "C" { typedef uint16_t touch_value_t; #elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32S2 ESP32S3 typedef uint32_t touch_value_t; -#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32P4 -typedef uint32_t touch_value_t; #endif /* @@ -99,5 +98,6 @@ void touchSleepWakeUpEnable(uint8_t pin, touch_value_t threshold); } #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 60350ae960b..d80bf2f15de 100644 --- a/cores/esp32/esp32-hal.h +++ b/cores/esp32/esp32-hal.h @@ -74,6 +74,7 @@ void yield(void); #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" #include "esp32-hal-spi.h" diff --git a/cores/esp32/io_pin_remap.h b/cores/esp32/io_pin_remap.h index 73789a585e3..10f11a5bf4c 100644 --- a/cores/esp32/io_pin_remap.h +++ b/cores/esp32/io_pin_remap.h @@ -106,7 +106,7 @@ int8_t gpioNumberToDigitalPin(int8_t gpioNumber); #define spiAttachMOSI(spi, mosi) spiAttachMOSI(spi, digitalPinToGPIONumber(mosi)) #define spiAttachSS(spi, cs_num, ss) spiAttachSS(spi, cs_num, digitalPinToGPIONumber(ss)) -// cores/esp32/esp32-hal-touch.h +// cores/esp32/esp32-hal-touch.h && cores/esp32/esp32-hal-touch-ng.h #define touchInterruptGetLastStatus(pin) touchInterruptGetLastStatus(digitalPinToGPIONumber(pin)) #define touchRead(pin) touchRead(digitalPinToGPIONumber(pin)) #define touchAttachInterruptArg(pin, userFunc, arg, threshold) touchAttachInterruptArg(digitalPinToGPIONumber(pin), userFunc, arg, threshold) diff --git a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino index 5aacf1baaf0..9d2b248ba44 100644 --- a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino +++ b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/TouchWakeUp.ino @@ -15,9 +15,11 @@ Pranav Cherukupalli */ #if CONFIG_IDF_TARGET_ESP32 -#define THRESHOLD 40 /* Greater the value, more the sensitivity */ -#else //ESP32-S2 and ESP32-S3 + default for other chips (to be adjusted) */ +#define THRESHOLD 40 /* Greater the value, more the sensitivity */ +#elif (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3) #define THRESHOLD 5000 /* Lower the value, more the sensitivity */ +#else // ESP32-P4 + default for other chips (to be adjusted) */ +#define THRESHOLD 500 /* Lower the value, more the sensitivity */ #endif RTC_DATA_ATTR int bootCount = 0; @@ -88,7 +90,7 @@ void setup() { touchSleepWakeUpEnable(T3, THRESHOLD); touchSleepWakeUpEnable(T7, THRESHOLD); -#else //ESP32-S2 + ESP32-S3 +#else //ESP32-S2 + ESP32-S3 + ESP32-P4 //Setup sleep wakeup on Touch Pad 3 (GPIO3) touchSleepWakeUpEnable(T3, THRESHOLD); diff --git a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/ci.json b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/ci.json index cd679adefad..25c42144223 100644 --- a/libraries/ESP32/examples/DeepSleep/TouchWakeUp/ci.json +++ b/libraries/ESP32/examples/DeepSleep/TouchWakeUp/ci.json @@ -2,7 +2,6 @@ "targets": { "esp32c3": false, "esp32c6": false, - "esp32h2": false, - "esp32p4": false + "esp32h2": false } } diff --git a/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino b/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino index 0f0880902fb..3b4e5f0b9e9 100644 --- a/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino +++ b/libraries/ESP32/examples/Touch/TouchInterrupt/TouchInterrupt.ino @@ -3,7 +3,12 @@ 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 + bool touch1detected = false; bool touch2detected = false; diff --git a/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json b/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json index 4363987f4d6..c0ecf9fc0a5 100644 --- a/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json +++ b/libraries/ESP32/examples/Touch/TouchInterrupt/ci.json @@ -1,8 +1,5 @@ { "requires": [ "CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y" - ], - "targets": { - "esp32p4": false - } + ] } diff --git a/libraries/ESP32/examples/Touch/TouchRead/ci.json b/libraries/ESP32/examples/Touch/TouchRead/ci.json index 4363987f4d6..c0ecf9fc0a5 100644 --- a/libraries/ESP32/examples/Touch/TouchRead/ci.json +++ b/libraries/ESP32/examples/Touch/TouchRead/ci.json @@ -1,8 +1,5 @@ { "requires": [ "CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y" - ], - "targets": { - "esp32p4": false - } + ] } diff --git a/tests/validation/touch/ci.json b/tests/validation/touch/ci.json index 1abbabeae0c..855e9bd964d 100644 --- a/tests/validation/touch/ci.json +++ b/tests/validation/touch/ci.json @@ -5,8 +5,5 @@ }, "requires": [ "CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y" - ], - "targets": { - "esp32p4": false - } + ] } diff --git a/tests/validation/touch/touch.ino b/tests/validation/touch/touch.ino index 60f6e7f7966..97aac8a65e6 100644 --- a/tests/validation/touch/touch.ino +++ b/tests/validation/touch/touch.ino @@ -2,6 +2,10 @@ #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 #define TEST_TOUCH_CHANNEL (9) @@ -15,11 +19,7 @@ uint8_t TOUCH_GPIOS[] = {4, 2, 15, 13, 12, 14, 27, 33, 32}; #define NO_TOUCH_GPIO 25 -#define RELEASED_VALUE 75 //75+ read value to pass test -#define PRESSED_VALUE 20 //20- read value to pass test -#define INTERRUPT_THRESHOLD 40 - -#else //ESP32S2 and ESP32S3 +#elif (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3) #define TEST_TOUCH_CHANNEL (12) //14 static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = { @@ -33,7 +33,25 @@ uint8_t TOUCH_GPIOS[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 /*,13,14*/}; #define NO_TOUCH_GPIO 17 -#if CONFIG_IDF_TARGET_ESP32S2 +#else //ESP32P4 + +#define TEST_TOUCH_CHANNEL (5) //14 +static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = { + TOUCH_PAD_NUM0, 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_NUM13*/ +}; + +uint8_t TOUCH_GPIOS[] = {2, 3, 4, 5, 6 /*, 7, 8, 9, 10, 11, 12 ,13, 14, 15*/}; + +#define NO_TOUCH_GPIO 17 +#endif + +#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 @@ -41,12 +59,13 @@ uint8_t TOUCH_GPIOS[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 /*,13,14*/}; #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 +#define INTERRUPT_THRESHOLD 0 // Use benchmarked threshold #else #error Test not currently supported on this chip. Please adjust and try again! #endif -#endif - bool touch1detected = false; bool touch2detected = false; @@ -59,17 +78,25 @@ void gotTouch2() { } /* - * Change the slope to get larger value from touch sensor. + * Change the slope to get larger value from touch sensor. (Capacitor for ESP32P4) */ 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); +#else + touch_ll_set_internal_capacitor(0x7f); +#endif } /* - * Change the slope to get smaller value from touch sensor. + * Change the slope to get smaller value from touch sensor. (Capacitor for ESP32P4) */ 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); +#else + touch_ll_set_internal_capacitor(0); +#endif } /* These functions are intended to be called before and after each test. */ @@ -87,6 +114,7 @@ void tearDown(void) { */ 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 @@ -109,6 +137,29 @@ void test_touch_read(void) { 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++) { + touch_unpressed[i] = touchRead(TOUCH_GPIOS[i]); + } + + // TEST PRESS STATE + for (int j = 0; j < TEST_TOUCH_CHANNEL; j++) { + test_press_fake(touch_list[j]); + } + delay(100); + + touch_value_t touch_pressed[sizeof(TOUCH_GPIOS)]; + for (int k = 0; k < sizeof(TOUCH_GPIOS); k++) { + touch_pressed[k] = touchRead(TOUCH_GPIOS[k]); + } + + // COMPARE PRESSED > UNPRESSED + for (int l = 0; l < sizeof(TOUCH_GPIOS); l++) { + TEST_ASSERT_GREATER_THAN((touch_unpressed[l] + PRESSED_VALUE_DIFFERENCE), touch_pressed[l]); + } +#endif } void test_touch_interrtupt(void) { @@ -146,4 +197,6 @@ void setup() { UNITY_END(); } -void loop() {} +void loop() { + delay(10); +}