From fd7b80833cc98f539c3c8628e0444521b4034a5e Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Wed, 8 Jan 2025 13:06:05 +0800 Subject: [PATCH] feat(touch): support touch v1 in new touch driver --- .../touch_sensor_v1/sdkconfig.defaults | 1 + .../esp32/include/driver/touch_sensor.h | 386 +--------------- .../include/driver/touch_sensor_legacy.h | 385 ++++++++++++++++ .../driver/touch_sensor/esp32/touch_sensor.c | 20 +- .../touch_sensor/esp32s2/touch_sensor.c | 2 +- .../touch_sensor/esp32s3/touch_sensor.c | 2 +- .../esp_driver_touch_sens/CMakeLists.txt | 16 +- .../common/touch_sens_common.c | 68 ++- .../common/touch_sens_private.h | 39 +- .../include/driver/touch_version_types.h | 298 +++++++++++- .../hw_ver1/touch_version_specific.c | 368 +++++++++++++++ .../include/driver/touch_version_types.h | 2 +- .../hw_ver2/touch_version_specific.c | 29 +- .../include/driver/touch_version_types.h | 27 +- .../hw_ver3/touch_version_specific.c | 32 +- .../include/driver/touch_sens.h | 60 ++- .../include/driver/touch_sens_types.h | 10 +- .../include/esp_private/touch_sens_helper.h | 45 -- components/esp_driver_touch_sens/linker.lf | 5 +- components/esp_hw_support/include/esp_sleep.h | 2 +- components/esp_hw_support/sleep_modes.c | 26 +- components/hal/CMakeLists.txt | 8 +- .../hal/esp32/include/hal/touch_sensor_ll.h | 427 +++++++++++++++++- .../hal/esp32p4/include/hal/touch_sensor_ll.h | 20 +- .../hal/esp32s2/include/hal/touch_sensor_ll.h | 39 +- components/hal/esp32s2/touch_sensor_hal.c | 2 +- .../hal/esp32s3/include/hal/touch_sensor_ll.h | 40 +- components/hal/esp32s3/touch_sensor_hal.c | 2 +- components/hal/include/hal/touch_sens_hal.h | 34 +- components/hal/include/hal/touch_sens_types.h | 120 ++--- components/hal/touch_sens_hal.c | 39 +- .../soc/esp32/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32/include/soc/soc_caps.h | 4 +- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32p4/include/soc/soc_caps.h | 1 + .../esp32s2/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32s2/include/soc/soc_caps.h | 3 +- .../esp32s3/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32s3/include/soc/soc_caps.h | 3 +- 39 files changed, 1950 insertions(+), 631 deletions(-) create mode 100644 components/driver/touch_sensor/esp32/include/driver/touch_sensor_legacy.h create mode 100644 components/esp_driver_touch_sens/hw_ver1/touch_version_specific.c delete mode 100644 components/esp_driver_touch_sens/include/esp_private/touch_sens_helper.h diff --git a/components/driver/test_apps/touch_sensor_v1/sdkconfig.defaults b/components/driver/test_apps/touch_sensor_v1/sdkconfig.defaults index fa8ac618b9..d4c3325166 100644 --- a/components/driver/test_apps/touch_sensor_v1/sdkconfig.defaults +++ b/components/driver/test_apps/touch_sensor_v1/sdkconfig.defaults @@ -1,2 +1,3 @@ CONFIG_FREERTOS_HZ=1000 CONFIG_ESP_TASK_WDT_EN=n +CONFIG_TOUCH_SUPPRESS_DEPRECATE_WARN=y diff --git a/components/driver/touch_sensor/esp32/include/driver/touch_sensor.h b/components/driver/touch_sensor/esp32/include/driver/touch_sensor.h index c1a6f759f2..18d5b32988 100644 --- a/components/driver/touch_sensor/esp32/include/driver/touch_sensor.h +++ b/components/driver/touch_sensor/esp32/include/driver/touch_sensor.h @@ -1,385 +1,17 @@ /* - * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - -#include "driver/touch_sensor_common.h" - -/** - * @brief Configure touch pad interrupt threshold. - * - * @note If FSM mode is set to TOUCH_FSM_MODE_TIMER, this function will be blocked for one measurement cycle and wait for data to be valid. - * - * @param touch_num touch pad index - * @param threshold interrupt threshold, - * - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG if argument wrong - * - ESP_FAIL if touch pad not initialized - */ -esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold); - -/** - * @brief get touch sensor counter value. - * Each touch sensor has a counter to count the number of charge/discharge cycles. - * When the pad is not 'touched', we can get a number of the counter. - * When the pad is 'touched', the value in counter will get smaller because of the larger equivalent capacitance. - * - * @note This API requests hardware measurement once. If IIR filter mode is enabled, - * please use 'touch_pad_read_raw_data' interface instead. - * - * @param touch_num touch pad index - * @param touch_value pointer to accept touch sensor value - * - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG Touch pad parameter error - * - ESP_ERR_INVALID_STATE This touch pad hardware connection is error, the value of "touch_value" is 0. - * - ESP_FAIL Touch pad not initialized - */ -esp_err_t touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value); - -/** - * @brief get filtered touch sensor counter value by IIR filter. - * - * @note touch_pad_filter_start has to be called before calling touch_pad_read_filtered. - * This function can be called from ISR - * - * @param touch_num touch pad index - * @param touch_value pointer to accept touch sensor value - * - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG Touch pad parameter error - * - ESP_ERR_INVALID_STATE This touch pad hardware connection is error, the value of "touch_value" is 0. - * - ESP_FAIL Touch pad not initialized - */ -esp_err_t touch_pad_read_filtered(touch_pad_t touch_num, uint16_t *touch_value); - -/** - * @brief get raw data (touch sensor counter value) from IIR filter process. - * Need not request hardware measurements. - * - * @note touch_pad_filter_start has to be called before calling touch_pad_read_raw_data. - * This function can be called from ISR - * - * @param touch_num touch pad index - * @param touch_value pointer to accept touch sensor value - * - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG Touch pad parameter error - * - ESP_ERR_INVALID_STATE This touch pad hardware connection is error, the value of "touch_value" is 0. - * - ESP_FAIL Touch pad not initialized - */ -esp_err_t touch_pad_read_raw_data(touch_pad_t touch_num, uint16_t *touch_value); - -/** - * @brief Callback function that is called after each IIR filter calculation. - * @note This callback is called in timer task in each filtering cycle. - * @note This callback should not be blocked. - * @param raw_value The latest raw data(touch sensor counter value) that - * points to all channels(raw_value[0..TOUCH_PAD_MAX-1]). - * @param filtered_value The latest IIR filtered data(calculated from raw data) that - * points to all channels(filtered_value[0..TOUCH_PAD_MAX-1]). - * - */ -typedef void (* filter_cb_t)(uint16_t *raw_value, uint16_t *filtered_value); - -/** - * @brief Register the callback function that is called after each IIR filter calculation. - * @note The 'read_cb' callback is called in timer task in each filtering cycle. - * @param read_cb Pointer to filtered callback function. - * If the argument passed in is NULL, the callback will stop. - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG set error - */ -esp_err_t touch_pad_set_filter_read_cb(filter_cb_t read_cb); - -/** - * @brief Register touch-pad ISR. - * The handler will be attached to the same CPU core that this function is running on. - * @param fn Pointer to ISR handler - * @param arg Parameter for ISR - * @return - * - ESP_OK Success ; - * - ESP_ERR_INVALID_ARG GPIO error - * - ESP_ERR_NO_MEM No memory - */ -esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg); - -/** - * @brief Set the clock cycles of each measurement - * @note This function will specify the clock cycles of each measurement - * and the clock is sourced from SOC_MOD_CLK_RTC_FAST, its default frequency is SOC_CLK_RC_FAST_FREQ_APPROX - * The touch sensor will record the charge and discharge times during these clock cycles as the final result (raw value) - * @note If clock cycles is too small, it may lead to inaccurate results. - * - * @param clock_cycle The clock cycles of each measurement - * measure_time = clock_cycle / SOC_CLK_RC_FAST_FREQ_APPROX, the maximum measure time is 0xffff / SOC_CLK_RC_FAST_FREQ_APPROX - * @return - * - ESP_OK Set the clock cycle success - */ -esp_err_t touch_pad_set_measurement_clock_cycles(uint16_t clock_cycle); - -/** - * @brief Get the clock cycles of each measurement - * - * @param clock_cycle The clock cycles of each measurement - * @return - * - ESP_OK Get the clock cycle success - * - ESP_ERR_INVALID_ARG The input parameter is NULL - */ -esp_err_t touch_pad_get_measurement_clock_cycles(uint16_t *clock_cycle); - -/** - * @brief Set the interval between two measurements - * @note The touch sensor will sleep between two measurements - * This function is to set the interval cycle - * And the interval is clocked from SOC_MOD_CLK_RTC_SLOW, its default frequency is SOC_CLK_RC_SLOW_FREQ_APPROX - * - * @param interval_cycle The interval between two measurements - * sleep_time = interval_cycle / SOC_CLK_RC_SLOW_FREQ_APPROX. - * The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function. - * @return - * - ESP_OK Set interval cycle success - */ -esp_err_t touch_pad_set_measurement_interval(uint16_t interval_cycle); - -/** - * @brief Get the interval between two measurements - * - * @param interval_cycle The interval between two measurements - * @return - * - ESP_OK Get interval cycle success - * - ESP_ERR_INVALID_ARG The input parameter is NULL - */ -esp_err_t touch_pad_get_measurement_interval(uint16_t *interval_cycle); - -/** - * @brief Set touch sensor measurement and sleep time. - * Excessive total time will slow down the touch response. - * Too small measurement time will not be sampled enough, resulting in inaccurate measurements. - * @note The touch sensor will count the number of charge/discharge cycles over a fixed period of time (specified as the second parameter). - * That means the number of cycles (raw value) will decrease as the capacity of the touch pad is increasing. - * @note The greater the duty cycle of the measurement time, the more system power is consumed. - * - * @param sleep_cycle The touch sensor will sleep after each measurement. - * sleep_cycle decide the interval between each measurement. - * t_sleep = sleep_cycle / SOC_CLK_RC_SLOW_FREQ_APPROX. - * The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function. - * @param meas_cycle The duration of the touch sensor measurement. - * t_meas = meas_cycle / SOC_CLK_RC_FAST_FREQ_APPROX, the maximum measure time is 0xffff / SOC_CLK_RC_FAST_FREQ_APPROX - * @return - * - ESP_OK on success - */ -esp_err_t touch_pad_set_meas_time(uint16_t sleep_cycle, uint16_t meas_cycle) -__attribute__((deprecated("please use 'touch_pad_set_measurement_clock_cycles' and 'touch_pad_set_measurement_interval' instead"))); - -/** - * @brief Get touch sensor measurement and sleep time - * @param sleep_cycle Pointer to accept sleep cycle number - * @param meas_cycle Pointer to accept measurement cycle count. - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_ARG The input parameter is NULL - */ -esp_err_t touch_pad_get_meas_time(uint16_t *sleep_cycle, uint16_t *meas_cycle) -__attribute__((deprecated("please use 'touch_pad_get_measurement_clock_cycles' and 'touch_pad_get_measurement_interval' instead"))); - -/** - * @brief Trigger a touch sensor measurement, only support in SW mode of FSM - * @return - * - ESP_OK on success - */ -esp_err_t touch_pad_sw_start(void); - -/** - * @brief Set touch sensor interrupt threshold - * @param touch_num touch pad index - * @param threshold threshold of touchpad count, refer to touch_pad_set_trigger_mode to see how to set trigger mode. - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_ARG if argument is wrong - */ -esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint16_t threshold); - -/** - * @brief Get touch sensor interrupt threshold - * @param touch_num touch pad index - * @param threshold pointer to accept threshold - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_ARG if argument is wrong - */ -esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint16_t *threshold); - -/** - * @brief Set touch sensor interrupt trigger mode. - * Interrupt can be triggered either when counter result is less than - * threshold or when counter result is more than threshold. - * @param mode touch sensor interrupt trigger mode - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_ARG if argument is wrong - */ -esp_err_t touch_pad_set_trigger_mode(touch_trigger_mode_t mode); - -/** - * @brief Get touch sensor interrupt trigger mode - * @param mode pointer to accept touch sensor interrupt trigger mode - * @return - * - ESP_OK on success - */ -esp_err_t touch_pad_get_trigger_mode(touch_trigger_mode_t *mode); - -/** - * @brief Set touch sensor interrupt trigger source. There are two sets of touch signals. - * Set1 and set2 can be mapped to several touch signals. Either set will be triggered - * if at least one of its touch signal is 'touched'. The interrupt can be configured to be generated - * if set1 is triggered, or only if both sets are triggered. - * @param src touch sensor interrupt trigger source - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_ARG if argument is wrong - */ -esp_err_t touch_pad_set_trigger_source(touch_trigger_src_t src); - -/** - * @brief Get touch sensor interrupt trigger source - * @param src pointer to accept touch sensor interrupt trigger source - * @return - * - ESP_OK on success - */ -esp_err_t touch_pad_get_trigger_source(touch_trigger_src_t *src); - -/** - * @brief Set touch sensor group mask. - * Touch pad module has two sets of signals, 'Touched' signal is triggered only if - * at least one of touch pad in this group is "touched". - * This function will set the register bits according to the given bitmask. - * @param set1_mask bitmask of touch sensor signal group1, it's a 10-bit value - * @param set2_mask bitmask of touch sensor signal group2, it's a 10-bit value - * @param en_mask bitmask of touch sensor work enable, it's a 10-bit value - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_ARG if argument is wrong - */ -esp_err_t touch_pad_set_group_mask(uint16_t set1_mask, uint16_t set2_mask, uint16_t en_mask); - -/** - * @brief Get touch sensor group mask. - * @param set1_mask pointer to accept bitmask of touch sensor signal group1, it's a 10-bit value - * @param set2_mask pointer to accept bitmask of touch sensor signal group2, it's a 10-bit value - * @param en_mask pointer to accept bitmask of touch sensor work enable, it's a 10-bit value - * @return - * - ESP_OK on success - */ -esp_err_t touch_pad_get_group_mask(uint16_t *set1_mask, uint16_t *set2_mask, uint16_t *en_mask); - -/** - * @brief Clear touch sensor group mask. - * Touch pad module has two sets of signals, Interrupt is triggered only if - * at least one of touch pad in this group is "touched". - * This function will clear the register bits according to the given bitmask. - * @param set1_mask bitmask touch sensor signal group1, it's a 10-bit value - * @param set2_mask bitmask touch sensor signal group2, it's a 10-bit value - * @param en_mask bitmask of touch sensor work enable, it's a 10-bit value - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_ARG if argument is wrong - */ -esp_err_t touch_pad_clear_group_mask(uint16_t set1_mask, uint16_t set2_mask, uint16_t en_mask); - -/** - * @brief To enable touch pad interrupt - * @return - * - ESP_OK on success - */ -esp_err_t touch_pad_intr_enable(void); - -/** - * @brief To disable touch pad interrupt - * @return - * - ESP_OK on success - */ -esp_err_t touch_pad_intr_disable(void); - -/** - * @brief To clear touch pad interrupt - * @return - * - ESP_OK on success - */ -esp_err_t touch_pad_intr_clear(void); - -/** - * @brief set touch pad filter calibration period, in ms. - * Need to call touch_pad_filter_start before all touch filter APIs - * @param new_period_ms filter period, in ms - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_STATE driver state error - * - ESP_ERR_INVALID_ARG parameter error - */ -esp_err_t touch_pad_set_filter_period(uint32_t new_period_ms); - -/** - * @brief get touch pad filter calibration period, in ms - * Need to call touch_pad_filter_start before all touch filter APIs - * @param p_period_ms pointer to accept period - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_STATE driver state error - * - ESP_ERR_INVALID_ARG parameter error - */ -esp_err_t touch_pad_get_filter_period(uint32_t *p_period_ms); - -/** - * @brief start touch pad filter function - * This API will start a filter to process the noise in order to prevent false triggering - * when detecting slight change of capacitance. - * Need to call touch_pad_filter_start before all touch filter APIs - * - * @note This filter uses FreeRTOS timer, which is dispatched from a task with - * priority 1 by default on CPU 0. So if some application task with higher priority - * takes a lot of CPU0 time, then the quality of data obtained from this filter will be affected. - * You can adjust FreeRTOS timer task priority in menuconfig. - * @param filter_period_ms filter calibration period, in ms - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG parameter error - * - ESP_ERR_NO_MEM No memory for driver - * - ESP_ERR_INVALID_STATE driver state error - */ -esp_err_t touch_pad_filter_start(uint32_t filter_period_ms); - -/** - * @brief stop touch pad filter function - * Need to call touch_pad_filter_start before all touch filter APIs - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_STATE driver state error - */ -esp_err_t touch_pad_filter_stop(void); - -/** - * @brief delete touch pad filter driver and release the memory - * Need to call touch_pad_filter_start before all touch filter APIs - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_STATE driver state error - */ -esp_err_t touch_pad_filter_delete(void); - -#ifdef __cplusplus -} +#include "sdkconfig.h" +#include "driver/touch_sensor_legacy.h" + +#if !CONFIG_TOUCH_SUPPRESS_DEPRECATE_WARN +#warning "This set of Touch APIs has been deprecated, \ +please include 'driver/touch_sens.h' instead. \ +if you want to keep using the old APIs and ignore this warning, \ +you can enable 'Suppress legacy driver deprecated warning' option under 'Touch Configuration' menu in Kconfig" #endif diff --git a/components/driver/touch_sensor/esp32/include/driver/touch_sensor_legacy.h b/components/driver/touch_sensor/esp32/include/driver/touch_sensor_legacy.h new file mode 100644 index 0000000000..a4aa9f6cad --- /dev/null +++ b/components/driver/touch_sensor/esp32/include/driver/touch_sensor_legacy.h @@ -0,0 +1,385 @@ +/* + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "driver/touch_sensor_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Configure touch pad interrupt threshold. + * + * @note If FSM mode is set to TOUCH_FSM_MODE_TIMER, this function will be blocked for one measurement cycle and wait for data to be valid. + * + * @param touch_num touch pad index + * @param threshold interrupt threshold, + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG if argument wrong + * - ESP_FAIL if touch pad not initialized + */ +esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold); + +/** + * @brief get touch sensor counter value. + * Each touch sensor has a counter to count the number of charge/discharge cycles. + * When the pad is not 'touched', we can get a number of the counter. + * When the pad is 'touched', the value in counter will get smaller because of the larger equivalent capacitance. + * + * @note This API requests hardware measurement once. If IIR filter mode is enabled, + * please use 'touch_pad_read_raw_data' interface instead. + * + * @param touch_num touch pad index + * @param touch_value pointer to accept touch sensor value + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Touch pad parameter error + * - ESP_ERR_INVALID_STATE This touch pad hardware connection is error, the value of "touch_value" is 0. + * - ESP_FAIL Touch pad not initialized + */ +esp_err_t touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value); + +/** + * @brief get filtered touch sensor counter value by IIR filter. + * + * @note touch_pad_filter_start has to be called before calling touch_pad_read_filtered. + * This function can be called from ISR + * + * @param touch_num touch pad index + * @param touch_value pointer to accept touch sensor value + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Touch pad parameter error + * - ESP_ERR_INVALID_STATE This touch pad hardware connection is error, the value of "touch_value" is 0. + * - ESP_FAIL Touch pad not initialized + */ +esp_err_t touch_pad_read_filtered(touch_pad_t touch_num, uint16_t *touch_value); + +/** + * @brief get raw data (touch sensor counter value) from IIR filter process. + * Need not request hardware measurements. + * + * @note touch_pad_filter_start has to be called before calling touch_pad_read_raw_data. + * This function can be called from ISR + * + * @param touch_num touch pad index + * @param touch_value pointer to accept touch sensor value + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Touch pad parameter error + * - ESP_ERR_INVALID_STATE This touch pad hardware connection is error, the value of "touch_value" is 0. + * - ESP_FAIL Touch pad not initialized + */ +esp_err_t touch_pad_read_raw_data(touch_pad_t touch_num, uint16_t *touch_value); + +/** + * @brief Callback function that is called after each IIR filter calculation. + * @note This callback is called in timer task in each filtering cycle. + * @note This callback should not be blocked. + * @param raw_value The latest raw data(touch sensor counter value) that + * points to all channels(raw_value[0..TOUCH_PAD_MAX-1]). + * @param filtered_value The latest IIR filtered data(calculated from raw data) that + * points to all channels(filtered_value[0..TOUCH_PAD_MAX-1]). + * + */ +typedef void (* filter_cb_t)(uint16_t *raw_value, uint16_t *filtered_value); + +/** + * @brief Register the callback function that is called after each IIR filter calculation. + * @note The 'read_cb' callback is called in timer task in each filtering cycle. + * @param read_cb Pointer to filtered callback function. + * If the argument passed in is NULL, the callback will stop. + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG set error + */ +esp_err_t touch_pad_set_filter_read_cb(filter_cb_t read_cb); + +/** + * @brief Register touch-pad ISR. + * The handler will be attached to the same CPU core that this function is running on. + * @param fn Pointer to ISR handler + * @param arg Parameter for ISR + * @return + * - ESP_OK Success ; + * - ESP_ERR_INVALID_ARG GPIO error + * - ESP_ERR_NO_MEM No memory + */ +esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg); + +/** + * @brief Set the clock cycles of each measurement + * @note This function will specify the clock cycles of each measurement + * and the clock is sourced from SOC_MOD_CLK_RTC_FAST, its default frequency is SOC_CLK_RC_FAST_FREQ_APPROX + * The touch sensor will record the charge and discharge times during these clock cycles as the final result (raw value) + * @note If clock cycles is too small, it may lead to inaccurate results. + * + * @param clock_cycle The clock cycles of each measurement + * measure_time = clock_cycle / SOC_CLK_RC_FAST_FREQ_APPROX, the maximum measure time is 0xffff / SOC_CLK_RC_FAST_FREQ_APPROX + * @return + * - ESP_OK Set the clock cycle success + */ +esp_err_t touch_pad_set_measurement_clock_cycles(uint16_t clock_cycle); + +/** + * @brief Get the clock cycles of each measurement + * + * @param clock_cycle The clock cycles of each measurement + * @return + * - ESP_OK Get the clock cycle success + * - ESP_ERR_INVALID_ARG The input parameter is NULL + */ +esp_err_t touch_pad_get_measurement_clock_cycles(uint16_t *clock_cycle); + +/** + * @brief Set the interval between two measurements + * @note The touch sensor will sleep between two measurements + * This function is to set the interval cycle + * And the interval is clocked from SOC_MOD_CLK_RTC_SLOW, its default frequency is SOC_CLK_RC_SLOW_FREQ_APPROX + * + * @param interval_cycle The interval between two measurements + * sleep_time = interval_cycle / SOC_CLK_RC_SLOW_FREQ_APPROX. + * The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function. + * @return + * - ESP_OK Set interval cycle success + */ +esp_err_t touch_pad_set_measurement_interval(uint16_t interval_cycle); + +/** + * @brief Get the interval between two measurements + * + * @param interval_cycle The interval between two measurements + * @return + * - ESP_OK Get interval cycle success + * - ESP_ERR_INVALID_ARG The input parameter is NULL + */ +esp_err_t touch_pad_get_measurement_interval(uint16_t *interval_cycle); + +/** + * @brief Set touch sensor measurement and sleep time. + * Excessive total time will slow down the touch response. + * Too small measurement time will not be sampled enough, resulting in inaccurate measurements. + * @note The touch sensor will count the number of charge/discharge cycles over a fixed period of time (specified as the second parameter). + * That means the number of cycles (raw value) will decrease as the capacity of the touch pad is increasing. + * @note The greater the duty cycle of the measurement time, the more system power is consumed. + * + * @param sleep_cycle The touch sensor will sleep after each measurement. + * sleep_cycle decide the interval between each measurement. + * t_sleep = sleep_cycle / SOC_CLK_RC_SLOW_FREQ_APPROX. + * The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function. + * @param meas_cycle The duration of the touch sensor measurement. + * t_meas = meas_cycle / SOC_CLK_RC_FAST_FREQ_APPROX, the maximum measure time is 0xffff / SOC_CLK_RC_FAST_FREQ_APPROX + * @return + * - ESP_OK on success + */ +esp_err_t touch_pad_set_meas_time(uint16_t sleep_cycle, uint16_t meas_cycle) +__attribute__((deprecated("please use 'touch_pad_set_measurement_clock_cycles' and 'touch_pad_set_measurement_interval' instead"))); + +/** + * @brief Get touch sensor measurement and sleep time + * @param sleep_cycle Pointer to accept sleep cycle number + * @param meas_cycle Pointer to accept measurement cycle count. + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG The input parameter is NULL + */ +esp_err_t touch_pad_get_meas_time(uint16_t *sleep_cycle, uint16_t *meas_cycle) +__attribute__((deprecated("please use 'touch_pad_get_measurement_clock_cycles' and 'touch_pad_get_measurement_interval' instead"))); + +/** + * @brief Trigger a touch sensor measurement, only support in SW mode of FSM + * @return + * - ESP_OK on success + */ +esp_err_t touch_pad_sw_start(void); + +/** + * @brief Set touch sensor interrupt threshold + * @param touch_num touch pad index + * @param threshold threshold of touchpad count, refer to touch_pad_set_trigger_mode to see how to set trigger mode. + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if argument is wrong + */ +esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint16_t threshold); + +/** + * @brief Get touch sensor interrupt threshold + * @param touch_num touch pad index + * @param threshold pointer to accept threshold + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if argument is wrong + */ +esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint16_t *threshold); + +/** + * @brief Set touch sensor interrupt trigger mode. + * Interrupt can be triggered either when counter result is less than + * threshold or when counter result is more than threshold. + * @param mode touch sensor interrupt trigger mode + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if argument is wrong + */ +esp_err_t touch_pad_set_trigger_mode(touch_trigger_mode_t mode); + +/** + * @brief Get touch sensor interrupt trigger mode + * @param mode pointer to accept touch sensor interrupt trigger mode + * @return + * - ESP_OK on success + */ +esp_err_t touch_pad_get_trigger_mode(touch_trigger_mode_t *mode); + +/** + * @brief Set touch sensor interrupt trigger source. There are two sets of touch signals. + * Set1 and set2 can be mapped to several touch signals. Either set will be triggered + * if at least one of its touch signal is 'touched'. The interrupt can be configured to be generated + * if set1 is triggered, or only if both sets are triggered. + * @param src touch sensor interrupt trigger source + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if argument is wrong + */ +esp_err_t touch_pad_set_trigger_source(touch_trigger_src_t src); + +/** + * @brief Get touch sensor interrupt trigger source + * @param src pointer to accept touch sensor interrupt trigger source + * @return + * - ESP_OK on success + */ +esp_err_t touch_pad_get_trigger_source(touch_trigger_src_t *src); + +/** + * @brief Set touch sensor group mask. + * Touch pad module has two sets of signals, 'Touched' signal is triggered only if + * at least one of touch pad in this group is "touched". + * This function will set the register bits according to the given bitmask. + * @param set1_mask bitmask of touch sensor signal group1, it's a 10-bit value + * @param set2_mask bitmask of touch sensor signal group2, it's a 10-bit value + * @param en_mask bitmask of touch sensor work enable, it's a 10-bit value + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if argument is wrong + */ +esp_err_t touch_pad_set_group_mask(uint16_t set1_mask, uint16_t set2_mask, uint16_t en_mask); + +/** + * @brief Get touch sensor group mask. + * @param set1_mask pointer to accept bitmask of touch sensor signal group1, it's a 10-bit value + * @param set2_mask pointer to accept bitmask of touch sensor signal group2, it's a 10-bit value + * @param en_mask pointer to accept bitmask of touch sensor work enable, it's a 10-bit value + * @return + * - ESP_OK on success + */ +esp_err_t touch_pad_get_group_mask(uint16_t *set1_mask, uint16_t *set2_mask, uint16_t *en_mask); + +/** + * @brief Clear touch sensor group mask. + * Touch pad module has two sets of signals, Interrupt is triggered only if + * at least one of touch pad in this group is "touched". + * This function will clear the register bits according to the given bitmask. + * @param set1_mask bitmask touch sensor signal group1, it's a 10-bit value + * @param set2_mask bitmask touch sensor signal group2, it's a 10-bit value + * @param en_mask bitmask of touch sensor work enable, it's a 10-bit value + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if argument is wrong + */ +esp_err_t touch_pad_clear_group_mask(uint16_t set1_mask, uint16_t set2_mask, uint16_t en_mask); + +/** + * @brief To enable touch pad interrupt + * @return + * - ESP_OK on success + */ +esp_err_t touch_pad_intr_enable(void); + +/** + * @brief To disable touch pad interrupt + * @return + * - ESP_OK on success + */ +esp_err_t touch_pad_intr_disable(void); + +/** + * @brief To clear touch pad interrupt + * @return + * - ESP_OK on success + */ +esp_err_t touch_pad_intr_clear(void); + +/** + * @brief set touch pad filter calibration period, in ms. + * Need to call touch_pad_filter_start before all touch filter APIs + * @param new_period_ms filter period, in ms + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE driver state error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t touch_pad_set_filter_period(uint32_t new_period_ms); + +/** + * @brief get touch pad filter calibration period, in ms + * Need to call touch_pad_filter_start before all touch filter APIs + * @param p_period_ms pointer to accept period + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE driver state error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t touch_pad_get_filter_period(uint32_t *p_period_ms); + +/** + * @brief start touch pad filter function + * This API will start a filter to process the noise in order to prevent false triggering + * when detecting slight change of capacitance. + * Need to call touch_pad_filter_start before all touch filter APIs + * + * @note This filter uses FreeRTOS timer, which is dispatched from a task with + * priority 1 by default on CPU 0. So if some application task with higher priority + * takes a lot of CPU0 time, then the quality of data obtained from this filter will be affected. + * You can adjust FreeRTOS timer task priority in menuconfig. + * @param filter_period_ms filter calibration period, in ms + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG parameter error + * - ESP_ERR_NO_MEM No memory for driver + * - ESP_ERR_INVALID_STATE driver state error + */ +esp_err_t touch_pad_filter_start(uint32_t filter_period_ms); + +/** + * @brief stop touch pad filter function + * Need to call touch_pad_filter_start before all touch filter APIs + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE driver state error + */ +esp_err_t touch_pad_filter_stop(void); + +/** + * @brief delete touch pad filter driver and release the memory + * Need to call touch_pad_filter_start before all touch filter APIs + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE driver state error + */ +esp_err_t touch_pad_filter_delete(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/driver/touch_sensor/esp32/touch_sensor.c b/components/driver/touch_sensor/esp32/touch_sensor.c index 1150e24e6f..8731a080da 100644 --- a/components/driver/touch_sensor/esp32/touch_sensor.c +++ b/components/driver/touch_sensor/esp32/touch_sensor.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,7 +17,7 @@ #include "esp_timer.h" #include "esp_intr_alloc.h" #include "driver/rtc_io.h" -#include "driver/touch_pad.h" +#include "driver/touch_sensor_legacy.h" #include "esp_private/rtc_ctrl.h" #include "driver/gpio.h" #include "esp_check.h" @@ -522,3 +522,19 @@ err: xSemaphoreGive(rtc_touch_mux); return ret; } + +#if !CONFIG_TOUCH_SKIP_LEGACY_CONFLICT_CHECK +/** + * @brief This function will be called during start up, to check that the new touch driver is not running along with the legacy touch driver + */ +static __attribute__((constructor)) void check_touch_driver_conflict(void) +{ + extern __attribute__((weak)) esp_err_t touch_sensor_new_controller(const void*, void *); + /* If the new Touch driver is linked, the weak function will point to the actual function in the new driver, otherwise it is NULL*/ + if ((void *)touch_sensor_new_controller != NULL) { + ESP_EARLY_LOGE("legacy_touch_driver", "CONFLICT! The new touch driver can't work along with the legacy touch driver"); + abort(); + } + ESP_EARLY_LOGW("legacy_touch_driver", "legacy touch driver is deprecated, please migrate to use driver/touch_sens.h"); +} +#endif //CONFIG_TOUCH_SKIP_LEGACY_CONFLICT_CHECK diff --git a/components/driver/touch_sensor/esp32s2/touch_sensor.c b/components/driver/touch_sensor/esp32s2/touch_sensor.c index f4ef21d5af..8bc29e71d0 100644 --- a/components/driver/touch_sensor/esp32s2/touch_sensor.c +++ b/components/driver/touch_sensor/esp32s2/touch_sensor.c @@ -608,7 +608,7 @@ esp_err_t touch_pad_sleep_get_channel_num(touch_pad_t *pad_num) { TOUCH_NULL_POINTER_CHECK(pad_num, "pad_num"); TOUCH_ENTER_CRITICAL(); - touch_hal_sleep_get_channel_num(pad_num); + touch_hal_sleep_get_channel_num((uint32_t *)pad_num); TOUCH_EXIT_CRITICAL(); return ESP_OK; } diff --git a/components/driver/touch_sensor/esp32s3/touch_sensor.c b/components/driver/touch_sensor/esp32s3/touch_sensor.c index cec9222fa6..968d0e73d6 100644 --- a/components/driver/touch_sensor/esp32s3/touch_sensor.c +++ b/components/driver/touch_sensor/esp32s3/touch_sensor.c @@ -581,7 +581,7 @@ esp_err_t touch_pad_sleep_get_channel_num(touch_pad_t *pad_num) { TOUCH_NULL_POINTER_CHECK(pad_num, "pad_num"); TOUCH_ENTER_CRITICAL(); - touch_hal_sleep_get_channel_num(pad_num); + touch_hal_sleep_get_channel_num((uint32_t *)pad_num); TOUCH_EXIT_CRITICAL(); return ESP_OK; } diff --git a/components/esp_driver_touch_sens/CMakeLists.txt b/components/esp_driver_touch_sens/CMakeLists.txt index d7f47492ad..7f77013a5e 100644 --- a/components/esp_driver_touch_sens/CMakeLists.txt +++ b/components/esp_driver_touch_sens/CMakeLists.txt @@ -6,17 +6,21 @@ endif() set(srcs) set(public_inc) +set(priv_require esp_driver_gpio) if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED) set(version_folder "hw_ver${CONFIG_SOC_TOUCH_SENSOR_VERSION}") - if(CONFIG_SOC_TOUCH_SENSOR_VERSION GREATER 1) - list(APPEND srcs "common/touch_sens_common.c" - "${version_folder}/touch_version_specific.c") - list(APPEND public_inc "include" "${version_folder}/include") - endif() + list(APPEND srcs "common/touch_sens_common.c" + "${version_folder}/touch_version_specific.c") + list(APPEND public_inc "include" "${version_folder}/include") +endif() + +# ESP32 need esp_timer to execute the software filter periodically +if(${target} STREQUAL "esp32") + list(APPEND priv_require esp_timer) endif() idf_component_register(SRCS ${srcs} - PRIV_REQUIRES esp_driver_gpio + PRIV_REQUIRES ${priv_require} INCLUDE_DIRS ${public_inc} ) diff --git a/components/esp_driver_touch_sens/common/touch_sens_common.c b/components/esp_driver_touch_sens/common/touch_sens_common.c index 505d776f8e..583b5b8d0f 100644 --- a/components/esp_driver_touch_sens/common/touch_sens_common.c +++ b/components/esp_driver_touch_sens/common/touch_sens_common.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +14,7 @@ #include "soc/touch_sensor_periph.h" #include "esp_private/gpio.h" #include "driver/touch_sens.h" +#include "esp_private/esp_gpio_reserve.h" #if SOC_TOUCH_SENSOR_VERSION <= 2 #include "esp_private/rtc_ctrl.h" @@ -21,7 +22,6 @@ #include "soc/interrupts.h" #include "esp_intr_alloc.h" #endif -#include "esp_private/touch_sens_helper.h" #if CONFIG_TOUCH_ENABLE_DEBUG_LOG // The local log level must be defined before including esp_log.h @@ -42,6 +42,9 @@ touch_sensor_handle_t g_touch = NULL; static void touch_channel_pin_init(int id) { gpio_num_t pin = touch_sensor_channel_io_map[id]; + if (esp_gpio_reserve(BIT64(pin)) & BIT64(pin)) { + ESP_LOGW(TAG, "The GPIO%d is conflict with other module", (int)pin); + } gpio_config_as_analog(pin); } @@ -145,18 +148,16 @@ esp_err_t touch_sensor_new_channel(touch_sensor_handle_t sens_handle, int chan_i ESP_GOTO_ON_FALSE(sens_handle->ch[chan_id], ESP_ERR_NO_MEM, err2, TAG, "No memory for touch channel"); sens_handle->ch[chan_id]->id = chan_id; sens_handle->ch[chan_id]->base = sens_handle; +#if SOC_TOUCH_SUPPORT_PROX_SENSING sens_handle->ch[chan_id]->prox_id = 0; +#endif /* Init the channel */ ESP_GOTO_ON_ERROR(touch_priv_config_channel(sens_handle->ch[chan_id], chan_cfg), err1, TAG, "Failed to configure the touch channel %d", chan_id); touch_channel_pin_init(chan_id); - - touch_chan_benchmark_config_t bm_cfg = {.do_reset = true}; TOUCH_ENTER_CRITICAL(TOUCH_PERIPH_LOCK); sens_handle->chan_mask |= 1 << chan_id; - /* Reset the benchmark to overwrite the legacy benchmark during the deep sleep */ - touch_priv_config_benchmark(sens_handle->ch[chan_id], &bm_cfg); TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK); *ret_chan_handle = sens_handle->ch[chan_id]; @@ -307,7 +308,12 @@ esp_err_t touch_sensor_start_continuous_scanning(touch_sensor_handle_t sens_hand ESP_GOTO_ON_FALSE_ISR(sens_handle->is_enabled, ESP_ERR_INVALID_STATE, err, TAG, "Please enable the touch sensor first"); ESP_GOTO_ON_FALSE_ISR(!sens_handle->is_started, ESP_ERR_INVALID_STATE, err, TAG, "Continuous scanning has started already"); - +#if SOC_TOUCH_SENSOR_VERSION == 1 + if (sens_handle->sw_filter_timer) { + ESP_GOTO_ON_ERROR_ISR(esp_timer_start_periodic(sens_handle->sw_filter_timer, sens_handle->timer_interval_ms * 1000), + err, TAG, "Failed to start the sw filter timer"); + } +#endif TOUCH_ENTER_CRITICAL_SAFE(TOUCH_PERIPH_LOCK); sens_handle->is_started = true; touch_ll_enable_fsm_timer(true); @@ -325,7 +331,11 @@ esp_err_t touch_sensor_stop_continuous_scanning(touch_sensor_handle_t sens_handl esp_err_t ret = ESP_OK; ESP_GOTO_ON_FALSE_ISR(sens_handle->is_started, ESP_ERR_INVALID_STATE, err, TAG, "Continuous scanning not started yet"); - +#if SOC_TOUCH_SENSOR_VERSION == 1 + if (sens_handle->sw_filter_timer) { + ESP_GOTO_ON_ERROR(esp_timer_stop(sens_handle->sw_filter_timer), err, TAG, "Failed to stop the timer"); + } +#endif TOUCH_ENTER_CRITICAL_SAFE(TOUCH_PERIPH_LOCK); touch_ll_stop_fsm_repeated_timer(); touch_ll_enable_fsm_timer(false); @@ -367,11 +377,13 @@ esp_err_t touch_sensor_trigger_oneshot_scanning(touch_sensor_handle_t sens_handl touch_ll_trigger_oneshot_measurement(); TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK); while (!touch_ll_is_measure_done()) { +#if SOC_TOUCH_SENSOR_VERSION >= 2 if (g_touch->is_meas_timeout) { g_touch->is_meas_timeout = false; ESP_LOGW(TAG, "The measurement time on channel %d exceed the limitation", i); break; } +#endif if (timeout_ms >= 0) { ESP_GOTO_ON_FALSE(xTaskGetTickCount() <= end_tick, ESP_ERR_TIMEOUT, err, TAG, "Wait for measurement done timeout"); } @@ -382,7 +394,12 @@ esp_err_t touch_sensor_trigger_oneshot_scanning(touch_sensor_handle_t sens_handl TOUCH_ENTER_CRITICAL(TOUCH_PERIPH_LOCK); touch_ll_channel_sw_measure_mask(0); TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK); - +#if SOC_TOUCH_SENSOR_VERSION == 1 + /* If software filter enabled, do the filter immediately after oneshot scanning */ + if (sens_handle->sw_filter_timer) { + touch_priv_execute_sw_filter(sens_handle); + } +#endif err: xSemaphoreGiveRecursive(sens_handle->mutex); TOUCH_ENTER_CRITICAL(TOUCH_PERIPH_LOCK); @@ -403,6 +420,11 @@ esp_err_t touch_sensor_register_callbacks(touch_sensor_handle_t sens_handle, con } ESP_RETURN_ON_FALSE(!user_ctx || esp_ptr_internal(user_ctx), ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM"); #endif +#if SOC_TOUCH_SENSOR_VERSION == 1 + if (sens_handle->data_filter_fn == NULL) { + ESP_RETURN_ON_FALSE(!(callbacks->on_active || callbacks->on_inactive), ESP_ERR_INVALID_STATE, TAG, "filter has not configured"); + } +#endif esp_err_t ret = ESP_OK; xSemaphoreTakeRecursive(sens_handle->mutex, portMAX_DELAY); @@ -424,14 +446,6 @@ esp_err_t touch_channel_read_data(touch_channel_handle_t chan_handle, touch_chan return touch_priv_channel_read_data(chan_handle, type, data); } -esp_err_t touch_channel_config_benchmark(touch_channel_handle_t chan_handle, const touch_chan_benchmark_config_t *benchmark_cfg) -{ - TOUCH_NULL_POINTER_CHECK_ISR(chan_handle); - TOUCH_NULL_POINTER_CHECK_ISR(benchmark_cfg); - touch_priv_config_benchmark(chan_handle, benchmark_cfg); - return ESP_OK; -} - /******************************************************************************/ /* Scope: Private APIs */ /******************************************************************************/ @@ -440,12 +454,30 @@ esp_err_t touch_sensor_get_channel_info(touch_channel_handle_t chan_handle, touc TOUCH_NULL_POINTER_CHECK(chan_handle); TOUCH_NULL_POINTER_CHECK(chan_info); xSemaphoreTakeRecursive(chan_handle->base->mutex, portMAX_DELAY); + memset(chan_info, 0, sizeof(touch_chan_info_t)); chan_info->chan_id = chan_handle->id; chan_info->chan_gpio = touch_sensor_channel_io_map[chan_handle->id]; - chan_info->flags.can_wake_dp_slp = chan_handle == chan_handle->base->deep_slp_chan; +#if SOC_TOUCH_SENSOR_VERSION == 1 + // All channels on V1 can wake up deep sleep + chan_info->flags.can_wake_dp_slp = true; + chan_info->abs_active_thresh[0] = touch_ll_get_chan_active_threshold(chan_handle->id); +#elif SOC_TOUCH_SENSOR_VERSION == 2 + chan_info->flags.can_wake_dp_slp = (!chan_handle->base->allow_pd) || (chan_handle == chan_handle->base->deep_slp_chan); + chan_info->active_thresh[0] = touch_ll_get_chan_active_threshold(chan_handle->id); +#elif SOC_TOUCH_SENSOR_VERSION == 3 + chan_info->flags.can_wake_dp_slp = (!chan_handle->base->allow_pd) || (chan_handle == chan_handle->base->deep_slp_chan); + for (int i = 0; i < TOUCH_SAMPLE_CFG_NUM; i++) { + chan_info->active_thresh[i] = touch_ll_get_chan_active_threshold(chan_handle->id, i); + } +#endif + +#if SOC_TOUCH_SUPPORT_PROX_SENSING chan_info->flags.is_proxi = chan_handle->prox_id > 0; +#endif +#if SOC_TOUCH_SUPPORT_WATERPROOF chan_info->flags.is_guard = chan_handle == chan_handle->base->guard_chan; chan_info->flags.is_shield = chan_handle == chan_handle->base->shield_chan; +#endif xSemaphoreGiveRecursive(chan_handle->base->mutex); return ESP_OK; } diff --git a/components/esp_driver_touch_sens/common/touch_sens_private.h b/components/esp_driver_touch_sens/common/touch_sens_private.h index c47c9567d3..dc45fd9c12 100644 --- a/components/esp_driver_touch_sens/common/touch_sens_private.h +++ b/components/esp_driver_touch_sens/common/touch_sens_private.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,9 @@ #include "esp_memory_utils.h" #include "esp_check.h" #include "sdkconfig.h" +#if SOC_TOUCH_SENSOR_VERSION == 1 +#include "esp_timer.h" +#endif #ifdef __cplusplus extern "C" { @@ -76,8 +79,16 @@ struct touch_sensor_s { intr_handle_t intr_handle; /*!< Interrupt handle */ touch_event_callbacks_t cbs; /*!< Event callbacks */ touch_channel_handle_t deep_slp_chan; /*!< The configured channel for depp sleep, will be NULL if not enable the deep sleep */ +#if SOC_TOUCH_SUPPORT_WATERPROOF touch_channel_handle_t guard_chan; /*!< The configured channel for the guard ring, will be NULL if not set */ touch_channel_handle_t shield_chan; /*!< The configured channel for the shield pad, will be NULL if not set */ +#endif +#if SOC_TOUCH_SENSOR_VERSION == 1 + uint32_t timer_interval_ms; /*!< Timer interval in milliseconds for software filter */ + esp_timer_handle_t sw_filter_timer; /*!< Software filter timer handle */ + touch_sw_filter_t data_filter_fn; /*!< Software filter function pointer */ + void *user_filter_ctx; /*!< User context that will pass to the software filter function */ +#endif SemaphoreHandle_t mutex; /*!< Mutex lock to ensure thread safety */ @@ -87,14 +98,18 @@ struct touch_sensor_s { struct { bool is_enabled : 1; /*!< Flag to indicate whether the scanning is enabled */ bool is_started : 1; /*!< Flag to indicate whether the scanning has started */ - bool is_meas_timeout : 1; /*!< Flag to indicate whether the measurement timeout, will force to stop the current measurement if the timeout is triggered */ bool sleep_en : 1; /*!< Flag to indicate whether the sleep wake-up feature is enabled */ +#if SOC_TOUCH_SENSOR_VERSION == 1 + bool is_below_trig; /*!< Whether the touch sensor interrupt will trigger below the trigger threshold */ +#else // SOC_TOUCH_SENSOR_VERSION >= 2 bool allow_pd : 1; /*!< Flag to indicate whether allow RTC_PERIPH power down during the sleep */ + bool is_meas_timeout : 1; /*!< Flag to indicate whether the measurement timeout, will force to stop the current measurement if the timeout is triggered */ bool waterproof_en : 1; /*!< Flag to indicate whether the water proof feature is enabled */ bool immersion_proof : 1; /*!< Flag to indicate whether to disable scanning when the guard ring is triggered */ bool proximity_en : 1; /*!< Flag to indicate whether the proximity sensing feature is enabled */ bool timeout_en : 1; /*!< Flag to indicate whether the measurement timeout feature (hardware timeout) is enabled */ bool denoise_en : 1; /*!< Flag to indicate whether the denoise channel feature is enabled */ +#endif }; uint32_t flags; }; @@ -107,6 +122,7 @@ struct touch_sensor_s { struct touch_channel_s { touch_sensor_handle_t base; /*!< The touch sensor controller handle */ int id; /*!< Touch channel id, the range is target-specific */ +#if SOC_TOUCH_SUPPORT_PROX_SENSING int prox_id; /*!< The proximity channel id + 1. It is 0 if not a proximity channel */ uint32_t prox_cnt; /*!< Cache the proximity measurement count, only takes effect when the channel is a proximity channel. * When this count reaches `touch_proximity_config_t::scan_times`, @@ -116,6 +132,12 @@ struct touch_channel_s { * The value will accumulate for each scanning until it reaches `touch_proximity_config_t::scan_times`. * This accumulated proximity value can be read via `touch_channel_read_data` when all scanning finished. */ +#endif +#if SOC_TOUCH_SENSOR_VERSION == 1 + uint32_t abs_thresh; /*!< Absolute threshold value that evaluate whether the channel is active */ + uint32_t smooth_data; /*!< The smoothed data value, which is filtered by the software filter */ + bool is_active; /*!< Flag to indicate whether the channel is active */ +#endif }; extern touch_sensor_handle_t g_touch; /*!< Global touch sensor controller handle for `esp_driver_touch_sens` use only */ @@ -190,15 +212,14 @@ esp_err_t touch_priv_deinit_controller(touch_sensor_handle_t sens_handle); */ esp_err_t touch_priv_channel_read_data(touch_channel_handle_t chan_handle, touch_chan_data_type_t type, uint32_t *data); +#if SOC_TOUCH_SENSOR_VERSION == 1 /** - * @brief Touch sensor channel benchmark set interface - * @note This is a private interface of `esp_driver_touch_sens` - * It should be implemented by each hardware version - * - * @param[in] chan_handle The channel handle - * @param[in] benchmark_cfg The benchmark operation + * @brief Execute software filter for once + * @note This is the implementation of the esp_timer callback + * @param[in] arg the touch sensor controller handle */ -void touch_priv_config_benchmark(touch_channel_handle_t chan_handle, const touch_chan_benchmark_config_t *benchmark_cfg); +void touch_priv_execute_sw_filter(void *arg); +#endif #ifdef __cplusplus } diff --git a/components/esp_driver_touch_sens/hw_ver1/include/driver/touch_version_types.h b/components/esp_driver_touch_sens/hw_ver1/include/driver/touch_version_types.h index 230a0df55e..1871b4f316 100644 --- a/components/esp_driver_touch_sens/hw_ver1/include/driver/touch_version_types.h +++ b/components/esp_driver_touch_sens/hw_ver1/include/driver/touch_version_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,4 +9,298 @@ * Version 1 includes ESP32 */ -#error "'esp_driver_touch_sens' does not support for ESP32 yet" +#pragma once + +#include "soc/soc_caps.h" +#include "driver/touch_sens_types.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TOUCH_MIN_CHAN_ID 0 /*!< The minimum available channel id of the touch pad */ +#define TOUCH_MAX_CHAN_ID 9 /*!< The maximum available channel id of the touch pad */ + +/** + * @brief Helper macro to the default configurations of the touch sensor controller + * + * @param[in] sample_cfg_number The number of the sample configurations, which can only be 1 here because there is only one sample configuration + * @param[in] sample_cfg_ptr The pointer to the sample configurations + */ +#define TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(sample_cfg_number, sample_cfg_ptr) { \ + .power_on_wait_us = 256, \ + .meas_interval_us = 320.0, \ + .intr_trig_mode = TOUCH_INTR_TRIG_ON_BELOW_THRESH, \ + .intr_trig_group = TOUCH_INTR_TRIG_GROUP_BOTH, \ + .sample_cfg_num = sample_cfg_number, \ + .sample_cfg = sample_cfg_ptr, \ +} + +/** + * @brief Helper macro to the default sample configurations + * @note This default configuration uses `sample frequency = clock frequency / 1` + * + * @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 + */ +#define TOUCH_SENSOR_V1_DEFAULT_SAMPLE_CONFIG(duration_ms, volt_low, volt_high) { \ + .charge_duration_ms = duration_ms, \ + .charge_volt_lim_h = volt_high, \ + .charge_volt_lim_l = volt_low, \ +} + +/** + * @brief Helper macro to the default filter configurations + * + */ +#define TOUCH_SENSOR_DEFAULT_FILTER_CONFIG() { \ + .interval_ms = 10, \ + .data_filter_fn = NULL, /* Set NULL to use default software filter */ \ +} + +/** + * @brief The data type of the touch channel + * + */ +typedef enum { + TOUCH_CHAN_DATA_TYPE_RAW, /*!< The raw data of the touch channel */ + TOUCH_CHAN_DATA_TYPE_SMOOTH, /*!< The smooth data of the touch channel (need to config software filter fist) */ +} touch_chan_data_type_t; + +/** + * @brief Touch channel trigger group + * + */ +typedef enum { + TOUCH_CHAN_TRIG_GROUP_1 = 0x01, /*!< Channel will be added to the interrupt trigger group 1 */ + TOUCH_CHAN_TRIG_GROUP_2 = 0x02, /*!< Channel will be added to the interrupt trigger group 2 */ + TOUCH_CHAN_TRIG_GROUP_BOTH = 0x03, /*!< Channel will be added to both interrupt trigger group 1 and 2 */ +} touch_chan_trig_group_t; + +/** + * @brief Sample configurations of the touch sensor + * + */ +typedef struct { + float charge_duration_ms; /*!< Charge duration time of one measurement on a touch channel */ + touch_volt_lim_h_t charge_volt_lim_h; /*!< The upper voltage limit while charging a touch pad. i.e., the touch controller won't charge the touch pad higher than this high voltage limitation. */ + touch_volt_lim_l_t charge_volt_lim_l; /*!< The lower voltage limit while discharging a touch pad. i.e., the touch controller won't discharge the touch pad lower than this low voltage limitation. */ +} touch_sensor_sample_config_t; + +/** + * @brief Configurations of the touch sensor controller + * + */ +typedef struct { + uint32_t power_on_wait_us; /*!< The waiting time between the channels power on and able to measure, to ensure the data stability */ + float meas_interval_us; /*!< Measurement interval of each channels */ + touch_intr_trig_mode_t intr_trig_mode; /*!< Interrupt trigger mode, the hardware touch interrupt can be triggered either above or below the absolute threshold */ + touch_intr_trig_group_t intr_trig_group; /*!< Which channel group can trigger the hardware touch interrupt */ + /* Touch sensor sample configuration */ + uint32_t sample_cfg_num; /*!< The sample configuration number that used for sampling, CANNOT exceed TOUCH_SAMPLE_CFG_NUM */ + touch_sensor_sample_config_t *sample_cfg; /*!< The array of this sample configuration configurations, the length should be specified in `touch_sensor_config_t::sample_cfg_num` */ +} touch_sensor_config_t; + +/** + * @brief Configurations of the touch sensor channel + * + */ +typedef struct { + uint32_t abs_active_thresh[TOUCH_SAMPLE_CFG_NUM]; /*!< The ablolute active threshould. The ``on_active`` and ``on_hw_active`` callback will trigger when + * - If touch_sensor_config_t::intr_trig_mode = TOUCH_INTR_TRIG_ON_BELOW_THRESH, the callback will keep triggering when the touch channel value below the threshold. + * - If touch_sensor_config_t::intr_trig_mode = TOUCH_INTR_TRIG_ON_ABOVE_THRESH, the callback will keep triggering when the touch channel value above the threshold. + */ + touch_charge_speed_t charge_speed; /*!< The speed of charging and discharging the touch pad, the higher the speed, the faster charging and discharging */ + touch_init_charge_volt_t init_charge_volt; /*!< The initial voltage before charging/discharging a touch pad */ + touch_chan_trig_group_t group; /*!< The channel group that the channel belongs to. The group will be used to trigger the interrupt */ +} touch_channel_config_t; + +/** + * @brief Touch software filter data + * + */ +typedef struct { + uint32_t prev_output; /*!< Previous output filtered data */ + uint32_t curr_input; /*!< Current input raw data that need to be filtered */ +} touch_sw_filter_data_t; + +/** + * @brief Touch software filter prototype + * @note Users can customize their own filter algorithm by this prototype + * @param[in] chan_handle The handle of the touch channel that need to be filtered + * @param[in] filter_data The data of the software filter + * @param[in] user_filter_ctx User customized filter context pointer + * @return + * - uint32_t The filtered data + */ +typedef uint32_t (*touch_sw_filter_t)(touch_channel_handle_t chan_handle, const touch_sw_filter_data_t *filter_data, void *user_filter_ctx); + +/** + * @brief The configuration of the software filter + * + */ +typedef struct { + uint32_t interval_ms; /*!< The software filter interval in milliseconds. + * The software filter will trigger periodically based on esp_timer + */ + touch_sw_filter_t data_filter_fn; /*!< The data filter function pointer. + * You can specify your own filter algorithm, or set NULL to use default software filter + */ + void *user_filter_ctx; /*!< User costomized filter context pointer. + * This pointer will be passed to the second parameter of `touch_sw_filter_t` . + * So that users can access their costomized filter context in the software filter function. + */ +} touch_sensor_filter_config_t; + +/** + * @brief Touch sensor configuration during the deep sleep + * @note Currently it is the same as the normal controller configuration. + * The deep sleep configuration only takes effect when the chip entered sleep, + * so that to update a more power efficient configuration. + * + */ +typedef touch_sensor_config_t touch_sensor_config_dslp_t; + +/** + * @brief Helper macro to the default light sleep wake-up configurations + * @note RTC_PERIPH will keep power on during the light sleep. + * Any enabled touch channel can wake-up the chip from light sleep. + */ +#define TOUCH_SENSOR_DEFAULT_LSLP_CONFIG() { \ + .slp_wakeup_lvl = TOUCH_LIGHT_SLEEP_WAKEUP, \ +} + +/** + * @brief Helper macro to the default deep sleep wake-up configurations + * @note RTC_PERIPH will keep power on during the deep sleep. + * Any enabled touch channel can wake-up the chip from deep sleep. + */ +#define TOUCH_SENSOR_DEFAULT_DSLP_CONFIG() { \ + .slp_wakeup_lvl = TOUCH_DEEP_SLEEP_WAKEUP, \ +} + +/** + * @brief Configuration of the touch sensor sleep function + * + */ +typedef struct { + touch_sleep_wakeup_level_t slp_wakeup_lvl; /*!< The sleep level that can be woke up by touch sensor. */ + touch_sensor_config_dslp_t *deep_slp_sens_cfg; /*!< Specify the touch sensor configuration during the deep sleep. + * Note that these configurations will no take effect immediately, + * they will be set automatically while the chip prepare to enter sleep. + * Set NULL to not change the configurations before entering sleep. + * The sleep configuration mainly aims at lower down the charging and measuring times, + * so that to save power consumption during the sleep. + * Only effective when the `touch_sleep_config_t::slp_wakeup_lvl` is `TOUCH_DEEP_SLEEP_WAKEUP` + */ +} touch_sleep_config_t; + +/** + * @brief Base event structure used in touch event queue + */ +typedef struct { + touch_channel_handle_t chan; /*!< the current triggered touch channel handle */ + int chan_id; /*!< the current triggered touch channel number */ +} touch_base_event_data_t; + +/** + * @brief Active event data + * @note Currently same as base event data + * + */ +typedef touch_base_event_data_t touch_active_event_data_t; + +/** + * @brief Inactive event data + * @note Currently same as base event data + * + */ +typedef touch_base_event_data_t touch_inactive_event_data_t; + +/** + * @brief Active event data + * + */ +typedef struct { + uint32_t active_mask; /*!< The current active channel mask. + * For the bits in the status mask, + * if the bit is set, the corresponding channel is active + * if the bit is cleared, the corresponding channel is inactive + */ +} touch_hw_active_event_data_t; + +/** + * @brief Touch sensor callbacks + * @note Set NULL for the unused callbacks. + * @note The Touch Sensor V1 hardware interrupt callback is different compare to other versions. + * To align the behavior of the `on_active` and `on_inactive`, they are added as the software filter callbacks. + * Please configure the software filter by `touch_sensor_config_filter` before using hardware interrupt. + * + */ +typedef struct { + union { + /** + * @brief Touch sensor on software active event callback. + * @note This callback is triggered by the software periodical filter. + * It callbacks when any touch channel is activated. + * @param[in] sens_handle Touch sensor controller handle, created from `touch_sensor_new_controller()` + * @param[in] event Touch sensor active event data + * @param[in] user_ctx User registered context, passed from `touch_sensor_register_callbacks()` + * + * @return Whether a high priority task has been waken up by this callback function + */ + bool (*on_sw_active)(touch_sensor_handle_t sens_handle, const touch_active_event_data_t *event, void *user_ctx); + /** + * @brief Touch sensor on software active event callback. (Alias of `on_sw_active` for compatibility) + * @note This callback is triggered by the software periodical filter. + * It callbacks when any touch channel is activated. + * @param[in] sens_handle Touch sensor controller handle, created from `touch_sensor_new_controller()` + * @param[in] event Touch sensor active event data + * @param[in] user_ctx User registered context, passed from `touch_sensor_register_callbacks()` + * + * @return Whether a high priority task has been waken up by this callback function + */ + bool (*on_active)(touch_sensor_handle_t sens_handle, const touch_active_event_data_t *event, void *user_ctx); + }; + + union { + /** + * @brief Touch sensor on software inactive event callback. + * @note This callback is triggered by the software periodical filter. + * It callbacks when any touch channel is de-activated. + * @param[in] sens_handle Touch sensor controller handle, created from `touch_sensor_new_controller()` + * @param[in] event Touch sensor active event data + * @param[in] user_ctx User registered context, passed from `touch_sensor_register_callbacks()` + * @return Whether a high priority task has been waken up by this callback function + */ + bool (*on_sw_inactive)(touch_sensor_handle_t sens_handle, const touch_inactive_event_data_t *event, void *user_ctx); + /** + * @brief Touch sensor on software inactive event callback. (Alias of `on_sw_active` for compatibility) + * @note This callback is triggered by the software periodical filter. + * It callbacks when any touch channel is de-activated. + * @param[in] sens_handle Touch sensor controller handle, created from `touch_sensor_new_controller()` + * @param[in] event Touch sensor active event data + * @param[in] user_ctx User registered context, passed from `touch_sensor_register_callbacks()` + * @return Whether a high priority task has been waken up by this callback function + */ + bool (*on_inactive)(touch_sensor_handle_t sens_handle, const touch_inactive_event_data_t *event, void *user_ctx); + }; + + /** + * @brief Touch sensor on hardware active interrupt event callback. + * @note This callback is triggered by the hardware interrupt. + * It callbacks every time when any of the touch channel below or above (depended on touch_sensor_config_t::intr_trig_mode) the threshold. + * @param[in] sens_handle Touch sensor controller handle, created from `touch_sensor_new_controller()` + * @param[in] event Touch sensor active event data + * @param[in] user_ctx User registered context, passed from `touch_sensor_register_callbacks()` + * + * @return Whether a high priority task has been waken up by this callback function + */ + bool (*on_hw_active)(touch_sensor_handle_t sens_handle, const touch_hw_active_event_data_t *event, void *user_ctx); +} touch_event_callbacks_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_driver_touch_sens/hw_ver1/touch_version_specific.c b/components/esp_driver_touch_sens/hw_ver1/touch_version_specific.c new file mode 100644 index 0000000000..1252f8833a --- /dev/null +++ b/components/esp_driver_touch_sens/hw_ver1/touch_version_specific.c @@ -0,0 +1,368 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief This file is only applicable to the touch hardware version1 + * Version 1 includes ESP32 + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "soc/soc_caps.h" +#include "soc/clk_tree_defs.h" +#include "soc/touch_sensor_periph.h" +#include "soc/rtc.h" +#include "hal/hal_utils.h" +#include "driver/touch_sens.h" +#include "esp_private/rtc_ctrl.h" +#include "esp_private/periph_ctrl.h" +#include "esp_clk_tree.h" +#include "esp_sleep.h" +#include "../../common/touch_sens_private.h" +#if CONFIG_TOUCH_ENABLE_DEBUG_LOG +// The local log level must be defined before including esp_log.h +// Set the maximum log level for this source file +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG +#endif +#include "esp_log.h" +#include "esp_check.h" + +static const char *TAG = "touch"; + +portMUX_TYPE g_touch_spinlock = portMUX_INITIALIZER_UNLOCKED; + +/****************************************************************************** + * Scope: touch v1 impl private * + ******************************************************************************/ +#define TOUCH_DEFAULT_SW_FILTER_COEFF TOUCH_SMOOTH_IIR_FILTER_2 + +static uint32_t s_touch_default_sw_iir_filter(touch_channel_handle_t chan_handle, const touch_sw_filter_data_t *filter_data, void *user_filter_ctx) +{ + /* Not used in the default filter algorithm */ + (void)chan_handle; + (void)user_filter_ctx; + /* If the previous data is 0, return current value directly */ + if (filter_data->prev_output == 0) { + return filter_data->curr_input; + } + return filter_data->prev_output - (filter_data->prev_output >> TOUCH_DEFAULT_SW_FILTER_COEFF) + + (filter_data->curr_input >> TOUCH_DEFAULT_SW_FILTER_COEFF); +} + +/****************************************************************************** + * Scope: touch driver private * + ******************************************************************************/ +void touch_priv_execute_sw_filter(void* arg) +{ + touch_sensor_handle_t sens_handle = (touch_sensor_handle_t)arg; + uint32_t chan_mask = sens_handle->chan_mask; + /* Read raw data and do the filtering */ + FOR_EACH_TOUCH_CHANNEL(i) { + touch_channel_handle_t chan_handle = sens_handle->ch[i]; + if (chan_handle) { + touch_sw_filter_data_t fdata = { + .prev_output = chan_handle->smooth_data, + }; + /* Read raw data */ + while (!touch_ll_is_measure_done()); + touch_ll_read_chan_data(chan_handle->id, TOUCH_LL_READ_RAW, &fdata.curr_input); + /* Do filtering */ + chan_handle->smooth_data = sens_handle->data_filter_fn(chan_handle, &fdata, sens_handle->user_filter_ctx); + } + /* Break if no more enabled channels */ + chan_mask >>= 1; + if (!chan_mask) { + break; + } + } + chan_mask = sens_handle->chan_mask; + /* Callback if the channel activated or de-activated */ + FOR_EACH_TOUCH_CHANNEL(i) { + touch_channel_handle_t chan_handle = sens_handle->ch[i]; + if (chan_handle) { + /* Prepare basic event data */ + touch_base_event_data_t base_edata = { + .chan = chan_handle, + .chan_id = chan_handle->id, + }; + bool is_below = chan_handle->smooth_data < chan_handle->abs_thresh; + /* Judge if the channel is active or inactive for now */ + bool is_active_now = sens_handle->is_below_trig ? is_below : !is_below; + /* Inactive before but now activated */ + if (!chan_handle->is_active && is_active_now) { + chan_handle->is_active = true; + if (sens_handle->cbs.on_active) { + sens_handle->cbs.on_active(sens_handle, &base_edata, sens_handle->user_ctx); + } + } + /* Active before but now de-activated */ + if (chan_handle->is_active && !is_active_now) { + chan_handle->is_active = false; + if (sens_handle->cbs.on_inactive) { + sens_handle->cbs.on_inactive(sens_handle, &base_edata, sens_handle->user_ctx); + } + } + } + /* Break if no more enabled channels */ + chan_mask >>= 1; + if (!chan_mask) { + break; + } + } +} + +void touch_priv_enable_module(bool enable) +{ + // Nothing to do + // No dedicate touch sensor clock gate or power domain need to operate +} + +void IRAM_ATTR touch_priv_default_intr_handler(void *arg) +{ + /* If the touch controller object has not been allocated, return directly */ + if (!g_touch) { + return; + } + bool need_yield = false; + touch_hw_active_event_data_t data; + // Only one `on_active` interrupt source, clear directly + touch_ll_interrupt_clear(TOUCH_LL_INTR_MASK_ALL); + touch_ll_get_active_channel_mask(&(data.active_mask)); + touch_ll_clear_active_channel_status(); + // Get the activated channels + if (g_touch->cbs.on_hw_active) { + need_yield |= g_touch->cbs.on_hw_active(g_touch, &data, g_touch->user_ctx); + } + + if (need_yield) { + portYIELD_FROM_ISR(); + } +} + +static esp_err_t s_touch_convert_to_hal_config(touch_sensor_handle_t sens_handle, const touch_sensor_config_t *sens_cfg, touch_hal_config_t *hal_cfg) +{ + TOUCH_NULL_POINTER_CHECK(sens_cfg); + TOUCH_NULL_POINTER_CHECK(hal_cfg); + TOUCH_NULL_POINTER_CHECK(hal_cfg->sample_cfg); + + ESP_RETURN_ON_FALSE(sens_cfg->sample_cfg_num && sens_cfg->sample_cfg, ESP_ERR_INVALID_ARG, TAG, + "at least one sample configuration required"); + ESP_RETURN_ON_FALSE(sens_cfg->sample_cfg_num <= TOUCH_SAMPLE_CFG_NUM, ESP_ERR_INVALID_ARG, TAG, + "at most %d sample configurations supported", (int)(TOUCH_SAMPLE_CFG_NUM)); + + /* Get the source clock frequency for the first time */ + if (!sens_handle->src_freq_hz) { + /* Touch sensor actually uses dynamic fast clock LP_DYN_FAST_CLK, but it will only switch to the slow clock during sleep, + * This driver only designed for wakeup case (sleep case should use ULP driver), so we only need to consider RTC_FAST here */ + esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_RTC_FAST, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &sens_handle->src_freq_hz); + ESP_LOGD(TAG, "touch rtc clock source: RTC_FAST, frequency: %"PRIu32" Hz", sens_handle->src_freq_hz); + } + + uint32_t src_freq_mhz = sens_handle->src_freq_hz / 1000000; + hal_cfg->power_on_wait_ticks = (uint32_t)sens_cfg->power_on_wait_us * src_freq_mhz; + hal_cfg->power_on_wait_ticks = hal_cfg->power_on_wait_ticks > TOUCH_LL_PAD_MEASURE_WAIT_MAX ? + TOUCH_LL_PAD_MEASURE_WAIT_MAX : hal_cfg->power_on_wait_ticks; + hal_cfg->meas_interval_ticks = (uint32_t)(sens_cfg->meas_interval_us * src_freq_mhz); + + sens_handle->is_below_trig = sens_cfg->intr_trig_mode == TOUCH_INTR_TRIG_ON_BELOW_THRESH; + hal_cfg->intr_trig_mode = sens_cfg->intr_trig_mode; + hal_cfg->intr_trig_group = sens_cfg->intr_trig_group; + hal_cfg->sample_cfg_num = sens_cfg->sample_cfg_num; // Only one sample cfg + + uint32_t charge_duration_ticks = (uint32_t)(sens_cfg->sample_cfg->charge_duration_ms * src_freq_mhz * 1000); + charge_duration_ticks = charge_duration_ticks > TOUCH_LL_CHARGE_DURATION_MAX ? + TOUCH_LL_CHARGE_DURATION_MAX : charge_duration_ticks; + hal_cfg->sample_cfg->charge_duration_ticks = charge_duration_ticks; + hal_cfg->sample_cfg->charge_volt_lim_h = sens_cfg->sample_cfg->charge_volt_lim_h; + hal_cfg->sample_cfg->charge_volt_lim_l = sens_cfg->sample_cfg->charge_volt_lim_l; + return ESP_OK; +} + +esp_err_t touch_priv_config_controller(touch_sensor_handle_t sens_handle, const touch_sensor_config_t *sens_cfg) +{ +#if CONFIG_TOUCH_ENABLE_DEBUG_LOG + esp_log_level_set(TAG, ESP_LOG_DEBUG); +#endif + /* Check and convert the configuration to hal configurations */ + touch_hal_sample_config_t hal_sample_cfg = {}; + touch_hal_config_t hal_cfg = { + .sample_cfg = &hal_sample_cfg, + }; + ESP_RETURN_ON_ERROR(s_touch_convert_to_hal_config(sens_handle, sens_cfg, &hal_cfg), + TAG, "parse the configuration failed due to the invalid configuration"); + sens_handle->sample_cfg_num = 1; // Only have one set of sampling configuration + + /* Configure the hardware */ + TOUCH_ENTER_CRITICAL(TOUCH_PERIPH_LOCK); + touch_hal_config_controller(&hal_cfg); + touch_ll_reset_trigger_groups(); + // Reset all channels' activate threshold according to the trigger mode in case of the mis-triggering even the channel is not enabled. + uint32_t rst_thresh = sens_cfg->intr_trig_mode == TOUCH_INTR_TRIG_ON_BELOW_THRESH ? 0 : TOUCH_LL_ACTIVE_THRESH_MAX; + FOR_EACH_TOUCH_CHANNEL(i) { + touch_ll_set_chan_active_threshold(i, rst_thresh); + } + TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK); + + return ESP_OK; +} + +esp_err_t touch_priv_config_channel(touch_channel_handle_t chan_handle, const touch_channel_config_t *chan_cfg) +{ + // Check the validation of the channel active threshold + ESP_RETURN_ON_FALSE(chan_cfg->abs_active_thresh[0] <= TOUCH_LL_ACTIVE_THRESH_MAX, ESP_ERR_INVALID_ARG, + TAG, "the active threshold out of range 0~%d", TOUCH_LL_ACTIVE_THRESH_MAX); + TOUCH_ENTER_CRITICAL(TOUCH_PERIPH_LOCK); + chan_handle->abs_thresh = chan_cfg->abs_active_thresh[0]; + touch_ll_set_chan_active_threshold(chan_handle->id, chan_cfg->abs_active_thresh[0]); + touch_ll_set_charge_speed(chan_handle->id, chan_cfg->charge_speed); + touch_ll_set_init_charge_voltage(chan_handle->id, chan_cfg->init_charge_volt); + if (chan_cfg->group & TOUCH_CHAN_TRIG_GROUP_1) { + touch_ll_config_trigger_group1(chan_handle->id, true); + } + if (chan_cfg->group & TOUCH_CHAN_TRIG_GROUP_2) { + touch_ll_config_trigger_group2(chan_handle->id, true); + } + TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK); + return ESP_OK; +} + +esp_err_t touch_priv_deinit_controller(touch_sensor_handle_t sens_handle) +{ + touch_ll_reset_trigger_groups(); + /* Disable the additional functions */ + if (sens_handle->sleep_en) { + touch_sensor_config_sleep_wakeup(sens_handle, NULL); + } + return ESP_OK; +} + +esp_err_t touch_priv_channel_read_data(touch_channel_handle_t chan_handle, touch_chan_data_type_t type, uint32_t *data) +{ + ESP_RETURN_ON_FALSE_ISR(type >= TOUCH_CHAN_DATA_TYPE_RAW && type <= TOUCH_CHAN_DATA_TYPE_SMOOTH, + ESP_ERR_INVALID_ARG, TAG, "The channel data type is invalid"); + ESP_RETURN_ON_FALSE_ISR(type == TOUCH_CHAN_DATA_TYPE_SMOOTH && chan_handle->base->data_filter_fn != NULL, + ESP_ERR_INVALID_STATE, TAG, "The software filter has not configured"); + TOUCH_ENTER_CRITICAL_SAFE(TOUCH_PERIPH_LOCK); + switch (type) { + default: // fall through + case TOUCH_CHAN_DATA_TYPE_RAW: + // Have to wait the measure done, otherwise it might read the un-finished data + while (!touch_ll_is_measure_done()); + touch_ll_read_chan_data(chan_handle->id, TOUCH_LL_READ_RAW, data); + break; + case TOUCH_CHAN_DATA_TYPE_SMOOTH: + *data = chan_handle->smooth_data; + break; + } + TOUCH_EXIT_CRITICAL_SAFE(TOUCH_PERIPH_LOCK); + return ESP_OK; +} + +/****************************************************************************** + * Scope: public APIs * + ******************************************************************************/ +esp_err_t touch_sensor_config_sleep_wakeup(touch_sensor_handle_t sens_handle, const touch_sleep_config_t *sleep_cfg) +{ + TOUCH_NULL_POINTER_CHECK(sens_handle); + + esp_err_t ret = ESP_OK; + int dp_slp_chan_id = -1; + touch_hal_sample_config_t hal_sample_cfg = {}; + touch_hal_config_t hal_cfg = { + .sample_cfg = &hal_sample_cfg, + }; + touch_hal_config_t *hal_cfg_ptr = NULL; + + xSemaphoreTakeRecursive(sens_handle->mutex, portMAX_DELAY); + ESP_GOTO_ON_FALSE(!sens_handle->is_enabled, ESP_ERR_INVALID_STATE, err, TAG, "Please disable the touch sensor first"); + + if (sleep_cfg) { + ESP_GOTO_ON_FALSE(sleep_cfg->slp_wakeup_lvl == TOUCH_LIGHT_SLEEP_WAKEUP || sleep_cfg->slp_wakeup_lvl == TOUCH_DEEP_SLEEP_WAKEUP, + ESP_ERR_INVALID_ARG, err, TAG, "Invalid sleep level"); + /* Enabled touch sensor as wake-up source */ + ESP_GOTO_ON_ERROR(esp_sleep_enable_touchpad_wakeup(), err, TAG, "Failed to enable touch sensor wakeup"); +#if SOC_PM_SUPPORT_RTC_PERIPH_PD + // Keep ESP_PD_DOMAIN_RTC_PERIPH power domain on during the light/deep sleep, so that to keep the touch sensor working + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); +#endif // SOC_PM_SUPPORT_RC_FAST_PD + + /* If set the deep sleep channel (i.e., enable deep sleep wake-up), + configure the deep sleep related settings. */ + if (sleep_cfg->slp_wakeup_lvl == TOUCH_DEEP_SLEEP_WAKEUP) { + /* Check and convert the configuration to hal configurations */ + if (sleep_cfg->deep_slp_sens_cfg) { + hal_cfg_ptr = &hal_cfg; + ESP_GOTO_ON_ERROR(s_touch_convert_to_hal_config(sens_handle, sleep_cfg->deep_slp_sens_cfg, hal_cfg_ptr), + err, TAG, "parse the configuration failed due to the invalid configuration"); + } + sens_handle->sleep_en = true; + } + } else { + /* Disable the touch sensor as wake-up source */ + esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TOUCHPAD); +#if SOC_PM_SUPPORT_RTC_PERIPH_PD + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO); +#endif // SOC_PM_SUPPORT_RC_FAST_PD + sens_handle->deep_slp_chan = NULL; + sens_handle->sleep_en = false; + } + + /* Save or update the sleep config */ + TOUCH_ENTER_CRITICAL(TOUCH_PERIPH_LOCK); + touch_hal_save_sleep_config(dp_slp_chan_id, hal_cfg_ptr, false); + TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK); + +err: + xSemaphoreGiveRecursive(sens_handle->mutex); + return ret; +} + +esp_err_t touch_sensor_config_filter(touch_sensor_handle_t sens_handle, const touch_sensor_filter_config_t *filter_cfg) +{ + TOUCH_NULL_POINTER_CHECK(sens_handle); + esp_err_t ret = ESP_OK; + + xSemaphoreTakeRecursive(sens_handle->mutex, portMAX_DELAY); + if (filter_cfg) { + ESP_GOTO_ON_FALSE(filter_cfg->interval_ms, ESP_ERR_INVALID_ARG, err, TAG, "Invalid timer interval"); + if (sens_handle->sw_filter_timer == NULL) { + esp_timer_create_args_t timer_cfg = { + .callback = touch_priv_execute_sw_filter, + .arg = sens_handle, + /* Choose TASK dispatch because the filter might involve float calculation, + and also reading the raw data might need to wait the measurement done */ + .dispatch_method = ESP_TIMER_TASK, + .name = "touch_v1_sw_filter_timer", + .skip_unhandled_events = true, + }; + ESP_GOTO_ON_ERROR(esp_timer_create(&timer_cfg, &(sens_handle->sw_filter_timer)), + err, TAG, "Failed to create the sw filter timer"); + } + sens_handle->timer_interval_ms = filter_cfg->interval_ms; + /* If user does not specify a filter, use the default filter instead */ + sens_handle->data_filter_fn = filter_cfg->data_filter_fn ? + filter_cfg->data_filter_fn : + s_touch_default_sw_iir_filter; + sens_handle->user_filter_ctx = filter_cfg->user_filter_ctx; + } else { + if (sens_handle->sw_filter_timer) { + ESP_GOTO_ON_ERROR(esp_timer_delete(sens_handle->sw_filter_timer), err, TAG, "Failed to delete the sw filter timer"); + } + sens_handle->data_filter_fn = NULL; + sens_handle->user_filter_ctx = NULL; + sens_handle->timer_interval_ms = 0; + FOR_EACH_TOUCH_CHANNEL(i) { + if (sens_handle->ch[i]) { + sens_handle->ch[i]->smooth_data = 0; + } + } + } +err: + xSemaphoreGiveRecursive(sens_handle->mutex); + return ret; +} diff --git a/components/esp_driver_touch_sens/hw_ver2/include/driver/touch_version_types.h b/components/esp_driver_touch_sens/hw_ver2/include/driver/touch_version_types.h index d5e7784b9c..a0c1f595a5 100644 --- a/components/esp_driver_touch_sens/hw_ver2/include/driver/touch_version_types.h +++ b/components/esp_driver_touch_sens/hw_ver2/include/driver/touch_version_types.h @@ -117,7 +117,7 @@ typedef struct { * */ typedef struct { - uint32_t active_thresh[TOUCH_SAMPLE_CFG_NUM]; /*!< The active threshold of each sample configuration, + uint32_t active_thresh[TOUCH_SAMPLE_CFG_NUM]; /*!< The relative active threshold of each sample configuration, * while the touch channel smooth value minus benchmark value exceed this threshold, * will be regarded as activated */ diff --git a/components/esp_driver_touch_sens/hw_ver2/touch_version_specific.c b/components/esp_driver_touch_sens/hw_ver2/touch_version_specific.c index fed6d3585d..31b7919240 100644 --- a/components/esp_driver_touch_sens/hw_ver2/touch_version_specific.c +++ b/components/esp_driver_touch_sens/hw_ver2/touch_version_specific.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -207,6 +207,9 @@ esp_err_t touch_priv_config_channel(touch_channel_handle_t chan_handle, const to touch_ll_set_charge_speed(chan_handle->id, chan_cfg->charge_speed); touch_ll_set_init_charge_voltage(chan_handle->id, chan_cfg->init_charge_volt); TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK); + touch_chan_benchmark_config_t bm_cfg = {.do_reset = true}; + /* Reset the benchmark to overwrite the legacy benchmark during the deep sleep */ + touch_channel_config_benchmark(chan_handle, &bm_cfg); return ESP_OK; } @@ -255,13 +258,6 @@ esp_err_t touch_priv_channel_read_data(touch_channel_handle_t chan_handle, touch return ESP_OK; } -void touch_priv_config_benchmark(touch_channel_handle_t chan_handle, const touch_chan_benchmark_config_t *benchmark_cfg) -{ - if (benchmark_cfg->do_reset) { - touch_ll_reset_chan_benchmark(BIT(chan_handle->id)); - } -} - /****************************************************************************** * Scope: public APIs * ******************************************************************************/ @@ -299,6 +295,16 @@ esp_err_t touch_sensor_config_filter(touch_sensor_handle_t sens_handle, const to return ret; } +esp_err_t touch_channel_config_benchmark(touch_channel_handle_t chan_handle, const touch_chan_benchmark_config_t *benchmark_cfg) +{ + TOUCH_NULL_POINTER_CHECK_ISR(chan_handle); + TOUCH_NULL_POINTER_CHECK_ISR(benchmark_cfg); + if (benchmark_cfg->do_reset) { + touch_ll_reset_chan_benchmark(BIT(chan_handle->id)); + } + return ESP_OK; +} + esp_err_t touch_sensor_config_sleep_wakeup(touch_sensor_handle_t sens_handle, const touch_sleep_config_t *sleep_cfg) { TOUCH_NULL_POINTER_CHECK(sens_handle); @@ -317,13 +323,18 @@ esp_err_t touch_sensor_config_sleep_wakeup(touch_sensor_handle_t sens_handle, co ESP_ERR_INVALID_ARG, err, TAG, "Invalid sleep level"); /* Enabled touch sensor as wake-up source */ ESP_GOTO_ON_ERROR(esp_sleep_enable_touchpad_wakeup(), err, TAG, "Failed to enable touch sensor wakeup"); - /* If set the deep sleep channel (i.e., enable deep sleep wake-up), configure the deep sleep related settings. */ if (sleep_cfg->slp_wakeup_lvl == TOUCH_DEEP_SLEEP_WAKEUP) { if (sleep_cfg->deep_slp_allow_pd) { ESP_GOTO_ON_FALSE(sleep_cfg->deep_slp_chan, ESP_ERR_INVALID_ARG, err, TAG, "deep sleep waken channel can't be NULL when allow RTC power down"); +#if CONFIG_IDF_TARGET_ESP32S2 + /* Workaround: In deep sleep, for ESP32S2, Power down the RTC_PERIPH will change the slope configuration of Touch sensor sleep pad. + * The configuration change will change the reading of the sleep pad, which will cause the touch wake-up sensor to trigger falsely. */ + slp_opt = ESP_PD_OPTION_ON; + ESP_LOGW(TAG, "Keep the RTC_PERIPH power on in case the false trigger"); +#endif } else { /* Keep the RTC_PERIPH power domain on in deep sleep */ slp_opt = ESP_PD_OPTION_ON; diff --git a/components/esp_driver_touch_sens/hw_ver3/include/driver/touch_version_types.h b/components/esp_driver_touch_sens/hw_ver3/include/driver/touch_version_types.h index a9f9f4d433..cb9e0bfb62 100644 --- a/components/esp_driver_touch_sens/hw_ver3/include/driver/touch_version_types.h +++ b/components/esp_driver_touch_sens/hw_ver3/include/driver/touch_version_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -41,6 +41,7 @@ extern "C" { /** * @brief Helper macro to the default sample configurations * @note This default configuration uses `sample frequency = clock frequency / 1` + * This helper macro mostly focus on the final result scaling * * @param[in] _div_num The division of the final data, used to scaling the final data * @param[in] coarse_freq_tune The coarse frequency tuning value @@ -57,6 +58,28 @@ extern "C" { .bypass_shield_output = false, \ } +/** + * @brief Helper macro to the default sample configurations + * @note This default configuration uses `sample frequency = clock frequency / 1` + * This helper macro mostly focus on the sawtooth wave frequency tuning + * Recommended for the frequency hopping usage + * + * @param[in] res The resistance of the RC filter + * @param[in] cap The capacitance of the RC filter + * @param[in] coarse_freq_tune The coarse frequency tuning value + * @param[in] fine_freq_tune The fine frequency tuning value + */ +#define TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG2(res, cap, coarse_freq_tune, fine_freq_tune) { \ + .div_num = 8, \ + .charge_times = 500, \ + .rc_filter_res = res, \ + .rc_filter_cap = cap, \ + .low_drv = fine_freq_tune, \ + .high_drv = coarse_freq_tune, \ + .bias_volt = 5, \ + .bypass_shield_output = false, \ +} + /** * @brief Helper macro to the default filter configurations * @@ -122,7 +145,7 @@ typedef struct { * */ typedef struct { - uint32_t active_thresh[TOUCH_SAMPLE_CFG_NUM]; /*!< The active threshold of each sample configuration, + uint32_t active_thresh[TOUCH_SAMPLE_CFG_NUM]; /*!< The relative active threshold of each sample configuration, * while the touch channel smooth value minus benchmark value exceed this threshold, * will be regarded as activated */ diff --git a/components/esp_driver_touch_sens/hw_ver3/touch_version_specific.c b/components/esp_driver_touch_sens/hw_ver3/touch_version_specific.c index a85f17aefa..0601a7bc88 100644 --- a/components/esp_driver_touch_sens/hw_ver3/touch_version_specific.c +++ b/components/esp_driver_touch_sens/hw_ver3/touch_version_specific.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,8 @@ #include "soc/clk_tree_defs.h" #include "soc/touch_sensor_periph.h" #include "soc/rtc.h" +#include "soc/chip_revision.h" +#include "hal/efuse_hal.h" #include "hal/hal_utils.h" #include "driver/touch_sens.h" #include "esp_private/rtc_ctrl.h" @@ -205,6 +207,9 @@ esp_err_t touch_priv_config_channel(touch_channel_handle_t chan_handle, const to touch_ll_set_chan_active_threshold(chan_handle->id, smp_cfg_id, chan_cfg->active_thresh[smp_cfg_id]); } TOUCH_EXIT_CRITICAL(TOUCH_PERIPH_LOCK); + touch_chan_benchmark_config_t bm_cfg = {.do_reset = true}; + /* Reset the benchmark to overwrite the legacy benchmark during the deep sleep */ + touch_channel_config_benchmark(chan_handle, &bm_cfg); return ESP_OK; } @@ -264,13 +269,6 @@ esp_err_t touch_priv_channel_read_data(touch_channel_handle_t chan_handle, touch return ESP_OK; } -void touch_priv_config_benchmark(touch_channel_handle_t chan_handle, const touch_chan_benchmark_config_t *benchmark_cfg) -{ - if (benchmark_cfg->do_reset) { - touch_ll_reset_chan_benchmark(BIT(chan_handle->id)); - } -} - /****************************************************************************** * Scope: public APIs * ******************************************************************************/ @@ -308,6 +306,16 @@ esp_err_t touch_sensor_config_filter(touch_sensor_handle_t sens_handle, const to return ret; } +esp_err_t touch_channel_config_benchmark(touch_channel_handle_t chan_handle, const touch_chan_benchmark_config_t *benchmark_cfg) +{ + TOUCH_NULL_POINTER_CHECK_ISR(chan_handle); + TOUCH_NULL_POINTER_CHECK_ISR(benchmark_cfg); + if (benchmark_cfg->do_reset) { + touch_ll_reset_chan_benchmark(BIT(chan_handle->id)); + } + return ESP_OK; +} + esp_err_t touch_sensor_config_sleep_wakeup(touch_sensor_handle_t sens_handle, const touch_sleep_config_t *sleep_cfg) { TOUCH_NULL_POINTER_CHECK(sens_handle); @@ -336,6 +344,14 @@ esp_err_t touch_sensor_config_sleep_wakeup(touch_sensor_handle_t sens_handle, co if (sleep_cfg->deep_slp_allow_pd) { ESP_GOTO_ON_FALSE(sleep_cfg->deep_slp_chan, ESP_ERR_INVALID_ARG, err, TAG, "deep sleep waken channel can't be NULL when allow RTC power down"); +#if CONFIG_IDF_TARGET_ESP32P4 + /* Due to esp32p4 eco0 hardware bug, if LP peripheral power domain is powerdowned in sleep, there will be a possibility of + * triggering the EFUSE_CRC reset, so disable the power-down of this power domain on lightsleep for ECO0 version. */ + if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) { + slp_opt = ESP_PD_OPTION_ON; + ESP_LOGW(TAG, "Keep the RTC_PERIPH power on"); + } +#endif } else { /* Keep the RTC_PERIPH power domain on in deep sleep */ slp_opt = ESP_PD_OPTION_ON; diff --git a/components/esp_driver_touch_sens/include/driver/touch_sens.h b/components/esp_driver_touch_sens/include/driver/touch_sens.h index c1e22d5713..6e32c1218d 100644 --- a/components/esp_driver_touch_sens/include/driver/touch_sens.h +++ b/components/esp_driver_touch_sens/include/driver/touch_sens.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -209,19 +209,6 @@ esp_err_t touch_sensor_trigger_oneshot_scanning(touch_sensor_handle_t sens_handl */ esp_err_t touch_sensor_register_callbacks(touch_sensor_handle_t sens_handle, const touch_event_callbacks_t *callbacks, void *user_ctx); -/** - * @brief Confiture the touch sensor benchmark for all the registered channels - * @note This function can be called no matter the touch sensor controller is enabled or not (i.e. ENABLED or SCANNING state). - * And it can also be called in ISR/callback context. - * - * @param[in] chan_handle Touch channel handle - * @param[in] benchmark_cfg The benchmark configurations - * @return - * - ESP_OK On success - * - ESP_ERR_INVALID_ARG NULL pointer - */ -esp_err_t touch_channel_config_benchmark(touch_channel_handle_t chan_handle, const touch_chan_benchmark_config_t *benchmark_cfg); - /** * @brief Read the touch channel data according to the types * @note This function can be called no matter the touch sensor controller is enabled or not (i.e. ENABLED or SCANNING state). @@ -242,6 +229,21 @@ esp_err_t touch_channel_config_benchmark(touch_channel_handle_t chan_handle, con */ esp_err_t touch_channel_read_data(touch_channel_handle_t chan_handle, touch_chan_data_type_t type, uint32_t *data); +#if SOC_TOUCH_SUPPORT_BENCHMARK +/** + * @brief Confiture the touch sensor benchmark for all the registered channels + * @note This function can be called no matter the touch sensor controller is enabled or not (i.e. ENABLED or SCANNING state). + * And it can also be called in ISR/callback context. + * + * @param[in] chan_handle Touch channel handle + * @param[in] benchmark_cfg The benchmark configurations + * @return + * - ESP_OK On success + * - ESP_ERR_INVALID_ARG NULL pointer + */ +esp_err_t touch_channel_config_benchmark(touch_channel_handle_t chan_handle, const touch_chan_benchmark_config_t *benchmark_cfg); +#endif // SOC_TOUCH_SUPPORT_BENCHMARK + #if SOC_TOUCH_SUPPORT_WATERPROOF /** * @brief Configure the touch sensor water proof channels @@ -309,6 +311,36 @@ esp_err_t touch_sensor_config_sleep_wakeup(touch_sensor_handle_t sens_handle, co esp_err_t touch_sensor_config_denoise_channel(touch_sensor_handle_t sens_handle, const touch_denoise_chan_config_t *denoise_cfg); #endif +/** + * @brief Touch channel information + * + */ +typedef struct { + int chan_id; /*!< Touch channel number */ + int chan_gpio; /*!< Corresponding GPIO of this channel */ + union { + uint32_t abs_active_thresh[TOUCH_SAMPLE_CFG_NUM]; /*!< The configured absolute threshould of this channel (only used for V1) */ + uint32_t active_thresh[TOUCH_SAMPLE_CFG_NUM]; /*!< The configured relative threshould of this channel (used except V1) */ + }; + struct { + uint32_t can_wake_dp_slp: 1; /*!< Whether this channel can wakeup from deep sleep */ + uint32_t is_proxi: 1; /*!< Whether this channel is used for proximity sensing */ + uint32_t is_guard: 1; /*!< Whether this channel is used for waterproof guard channel */ + uint32_t is_shield: 1; /*!< Whether this channel is used for waterproof shield channel */ + } flags; /*!< Channel sub-feature flags */ +} touch_chan_info_t; + +/** + * @brief Get the touch channel information by the channel handle + * + * @param[in] chan_handle Touch channel handle + * @param[out] chan_info Touch channel information + * @return + * - ESP_OK: Success to get the channel information + * - ESP_ERR_INVALID_ARG: NULL pointer + */ +esp_err_t touch_sensor_get_channel_info(touch_channel_handle_t chan_handle, touch_chan_info_t *chan_info); + #ifdef __cplusplus } #endif diff --git a/components/esp_driver_touch_sens/include/driver/touch_sens_types.h b/components/esp_driver_touch_sens/include/driver/touch_sens_types.h index 50ee1ae0c3..97e6bf9886 100644 --- a/components/esp_driver_touch_sens/include/driver/touch_sens_types.h +++ b/components/esp_driver_touch_sens/include/driver/touch_sens_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,8 +16,8 @@ extern "C" { #endif -#define TOUCH_TOTAL_CHAN_NUM SOC_TOUCH_SENSOR_NUM /*!< The total channel number of the touch sensor */ -#define TOUCH_SAMPLE_CFG_NUM SOC_TOUCH_SAMPLE_CFG_NUM /*!< The supported max sample configuration number */ +#define TOUCH_TOTAL_CHAN_NUM SOC_TOUCH_SENSOR_NUM /*!< The total channel number of the touch sensor */ +#define TOUCH_SAMPLE_CFG_NUM SOC_TOUCH_SAMPLE_CFG_NUM /*!< The supported max sample configuration number */ #if SOC_TOUCH_SUPPORT_PROX_SENSING #define TOUCH_PROXIMITY_CHAN_NUM SOC_TOUCH_PROXIMITY_CHANNEL_NUM /*!< The supported proximity channel number in proximity sensing mode */ #endif @@ -31,8 +31,8 @@ typedef enum { TOUCH_DEEP_SLEEP_WAKEUP, /*!< Enable the touch sensor to wake up the chip from deep sleep or light sleep */ } touch_sleep_wakeup_level_t; -typedef struct touch_sensor_s *touch_sensor_handle_t; /*!< The handle of touch sensor controller */ -typedef struct touch_channel_s *touch_channel_handle_t; /*!< The handle of touch channel */ +typedef struct touch_sensor_s *touch_sensor_handle_t; /*!< The handle of touch sensor controller */ +typedef struct touch_channel_s *touch_channel_handle_t; /*!< The handle of touch channel */ #ifdef __cplusplus } diff --git a/components/esp_driver_touch_sens/include/esp_private/touch_sens_helper.h b/components/esp_driver_touch_sens/include/esp_private/touch_sens_helper.h deleted file mode 100644 index 637a90336a..0000000000 --- a/components/esp_driver_touch_sens/include/esp_private/touch_sens_helper.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include -#include "esp_err.h" -#include "driver/touch_sens_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Touch channel information - * - */ -typedef struct { - int chan_id; /*!< Touch channel number */ - int chan_gpio; /*!< Corresponding GPIO of this channel */ - struct { - uint32_t can_wake_dp_slp: 1;/*!< Whether this channel can wakeup from deep sleep */ - uint32_t is_proxi: 1; /*!< Whether this channel is used for proximity sensing */ - uint32_t is_guard: 1; /*!< Whether this channel is used for waterproof guard channel */ - uint32_t is_shield: 1; /*!< Whether this channel is used for waterproof shield channel */ - } flags; /*!< Channel sub-feature flags */ -} touch_chan_info_t; - -/** - * @brief Get the touch channel information by the channel handle - * - * @param[in] chan_handle Touch channel handle - * @param[out] chan_info Touch channel information - * @return - * - ESP_OK: Success to get the channel information - * - ESP_ERR_INVALID_ARG: NULL pointer - */ -esp_err_t touch_sensor_get_channel_info(touch_channel_handle_t chan_handle, touch_chan_info_t *chan_info); - -#ifdef __cplusplus -} -#endif diff --git a/components/esp_driver_touch_sens/linker.lf b/components/esp_driver_touch_sens/linker.lf index 9dbc60f175..e10117c01b 100644 --- a/components/esp_driver_touch_sens/linker.lf +++ b/components/esp_driver_touch_sens/linker.lf @@ -5,6 +5,7 @@ entries: touch_sens_common: touch_sensor_start_continuous_scanning (noflash) touch_sens_common: touch_sensor_stop_continuous_scanning (noflash) touch_sens_common: touch_channel_read_data (noflash) - touch_sens_common: touch_channel_config_benchmark (noflash) touch_sens_version_specific: touch_priv_channel_read_data (noflash) - touch_sens_version_specific: touch_priv_config_benchmark (noflash) + if SOC_TOUCH_SUPPORT_BENCHMARK = y: + touch_sens_common: touch_channel_config_benchmark (noflash) + touch_sens_version_specific: touch_priv_config_benchmark (noflash) diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index f40f94ae3c..91407e98ca 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -214,7 +214,7 @@ esp_err_t esp_sleep_enable_touchpad_wakeup(void); * * @return touch pad which caused wakeup */ -touch_pad_t esp_sleep_get_touchpad_wakeup_status(void); +int esp_sleep_get_touchpad_wakeup_status(void); #endif // SOC_TOUCH_SENSOR_SUPPORTED /** diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index c872a0e067..9a7170ced0 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -63,7 +63,6 @@ #include "hal/wdt_hal.h" #include "hal/uart_hal.h" #if SOC_TOUCH_SENSOR_SUPPORTED -#include "hal/touch_sensor_hal.h" #include "hal/touch_sens_hal.h" #endif #include "hal/mspi_ll.h" @@ -304,7 +303,7 @@ static void ext0_wakeup_prepare(void); static void ext1_wakeup_prepare(void); #endif static esp_err_t timer_wakeup_prepare(int64_t sleep_duration); -#if SOC_TOUCH_SENSOR_VERSION >= 2 +#if SOC_TOUCH_SENSOR_SUPPORTED static void touch_wakeup_prepare(void); #endif #if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && SOC_DEEP_SLEEP_SUPPORTED @@ -877,7 +876,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m misc_modules_sleep_prepare(pd_flags, deep_sleep); -#if SOC_TOUCH_SENSOR_VERSION >= 2 +#if SOC_TOUCH_SENSOR_SUPPORTED bool keep_rtc_power_on = false; if (deep_sleep) { if (s_config.wakeup_triggers & RTC_TOUCH_TRIG_EN) { @@ -1733,14 +1732,11 @@ static esp_err_t timer_wakeup_prepare(int64_t sleep_duration) return ESP_OK; } -#if SOC_TOUCH_SENSOR_VERSION >= 2 +#if SOC_TOUCH_SENSOR_SUPPORTED static void touch_wakeup_prepare(void) { touch_hal_prepare_deep_sleep(); } -#endif - -#if SOC_TOUCH_SENSOR_SUPPORTED esp_err_t esp_sleep_enable_touchpad_wakeup(void) { @@ -1759,18 +1755,18 @@ esp_err_t esp_sleep_enable_touchpad_wakeup(void) return ESP_OK; } -touch_pad_t esp_sleep_get_touchpad_wakeup_status(void) +int esp_sleep_get_touchpad_wakeup_status(void) { if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_TOUCHPAD) { - return TOUCH_PAD_MAX; + return -1; } - touch_pad_t pad_num; -#if SOC_TOUCH_SENSOR_VERSION == 3 - touch_ll_sleep_get_channel_num((uint32_t *)(&pad_num)); + uint32_t chan_num; +#if SOC_TOUCH_SENSOR_VERSION == 1 + touch_ll_get_active_channel_mask(&chan_num); #else - touch_hal_get_wakeup_status(&pad_num); + touch_ll_sleep_get_channel_num(&chan_num); #endif - return pad_num; + return (int)chan_num; } #endif // SOC_TOUCH_SENSOR_SUPPORTED diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 87f51db8e2..47c1d8a404 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -283,15 +283,13 @@ if(NOT BOOTLOADER_BUILD AND NOT esp_tee_build) endif() if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED) - # Source files for legacy touch driver + # Source files for the legacy touch hal driver if(CONFIG_SOC_TOUCH_SENSOR_VERSION LESS 3) list(APPEND srcs "${target}/touch_sensor_hal.c") list(APPEND srcs "touch_sensor_hal.c") endif() - # Source files for touch driver-ng (currently only support ver2 & ver3) - if(CONFIG_SOC_TOUCH_SENSOR_VERSION GREATER 1) - list(APPEND srcs "touch_sens_hal.c") - endif() + # Source files for the new touch hal driver + list(APPEND srcs "touch_sens_hal.c") endif() if(${target} STREQUAL "esp32") diff --git a/components/hal/esp32/include/hal/touch_sensor_ll.h b/components/hal/esp32/include/hal/touch_sensor_ll.h index f154f16b0e..268a35e1be 100644 --- a/components/hal/esp32/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32/include/hal/touch_sensor_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,12 +17,13 @@ #include #include #include "hal/misc.h" +#include "hal/assert.h" #include "soc/touch_sensor_periph.h" #include "soc/sens_struct.h" #include "soc/rtc_io_struct.h" #include "soc/rtc_cntl_struct.h" -#include "hal/touch_sensor_legacy_types.h" - +#include "soc/soc_caps.h" +#include "hal/touch_sens_types.h" #ifdef __cplusplus extern "C" { @@ -30,9 +31,413 @@ extern "C" { //Some register bits of touch sensor 8 and 9 are mismatched, we need to swap the bits. #define TOUCH_LL_BIT_SWAP(data, n, m) (((data >> n) & 0x1) == ((data >> m) & 0x1) ? (data) : ((data) ^ ((0x1 <> 1], l_thresh, thresh); + } else { + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.touch_thresh[touch_num >> 1], h_thresh, thresh); + } +} + +/** + * Get touch sensor threshold of charge cycles that triggers pad active state. + * The threshold determines the sensitivity of the touch sensor. + * The threshold is the original value of the trigger state minus the benchmark value. + * + * @note If set "TOUCH_PAD_THRESHOLD_MAX", the touch is never be triggered. + * @param touch_num The touch pad id + * @return + * - The threshold of charge cycles + */ +static inline uint32_t touch_ll_get_chan_active_threshold(uint32_t touch_num) +{ + // Workaround: swap chan 8 and chan 9 + touch_num = TOUCH_LL_CHAN_SWAP(touch_num); + if (touch_num & 0x1) { + return HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_thresh[touch_num >> 1], l_thresh); + } else { + return HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_thresh[touch_num >> 1], h_thresh); + } +} + +/** + * Set the power on wait cycle + * + * @param wait_cycles + */ +static inline void touch_ll_set_power_on_wait_cycle(uint32_t wait_cycles) +{ + //the waiting cycles (in 8MHz) between TOUCH_START and TOUCH_XPD + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl1, touch_xpd_wait, wait_cycles); //wait volt stable +} + +/** + * Set the duration of the charge window + * + * @param duration The duration of the touch channel charge / discharge window. + * duration = meas_ticks / (8MHz), the maximum duration is 0xffff / 8M = 8.19 ms. + */ +static inline void touch_ll_set_charge_window_duration(uint32_t duration) +{ + //touch sensor charge/discharge window duration= meas_cycle / 8Mhz + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl1, touch_meas_delay, duration); +} + +/** + * Set touch sensor sleep time. + * + * @param interval_ticks The touch sensor will sleep for some cycles after each measurement. + * interval_ticks decide the interval between each measurement. + * t_sleep = interval_ticks / (RTC_SLOW_CLK frequency). + * The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function. + */ +static inline void touch_ll_set_measure_interval_ticks(uint16_t interval_ticks) +{ + //touch sensor sleep cycle Time = sleep_cycle / RTC_SLOW_CLK + HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.sar_touch_ctrl2, touch_sleep_cycles, interval_ticks); +} + +/** + * Set the Touch pad charge speed. + * + * @param touch_num Touch channel number + * @param charge_speed Charge speed of this touch channel + */ +static inline void touch_ll_set_charge_speed(uint32_t touch_num, touch_charge_speed_t charge_speed) +{ + RTCIO.touch_pad[touch_num].dac = charge_speed; +} + +/** + * Set the upper limitation of the touch channel voltage while charging + * + * @param high_lim The high(upper) limitation of charge + */ +static inline void touch_ll_set_charge_voltage_high_limit(touch_volt_lim_h_t high_lim) +{ + RTCIO.touch_cfg.drefh = (uint32_t)high_lim & 0x3; + RTCIO.touch_cfg.drange = (uint32_t)high_lim >> 2; +} + +/** + * Set the lower limitation of the touch channel voltage while discharging + * + * @param low_lim The lower limitation of discharge + */ +static inline void touch_ll_set_charge_voltage_low_limit(touch_volt_lim_l_t low_lim) +{ + RTCIO.touch_cfg.drefl = low_lim; +} + +/** + * Set the initial charge voltage of touch channel + * i.e., the touch pad measurement start from a low voltage or a high voltage + * + * @param touch_num Touch channel number + * @param init_charge_volt The initial charge voltage + */ +static inline void touch_ll_set_init_charge_voltage(uint32_t touch_num, touch_init_charge_volt_t init_charge_volt) +{ + // Workaround: swap chan 8 and chan 9 + touch_num = TOUCH_LL_CHAN_SWAP(touch_num); + RTCIO.touch_pad[touch_num].tie_opt = init_charge_volt; +} + +/** + * Enable touch sensor channel. Register touch channel into touch sensor measurement group. + * The working mode of the touch sensor is simultaneous measurement. + * This function will set the measure bits according to the given bitmask. + * + * @note If set this mask, the FSM timer should be stop firstly. + * @note The touch sensor that in scan map, should be deinit GPIO function firstly. + * @param enable_mask bitmask of touch sensor scan group. + * e.g. TOUCH_PAD_NUM1 -> BIT(1) + * @return + * - ESP_OK on success + */ +static inline void touch_ll_enable_channel_mask(uint16_t enable_mask) +{ + SENS.sar_touch_enable.touch_pad_worken = enable_mask; +} + +/** + * Clear all touch sensor channels active status. + * + * @note Generally no manual removal is required. + */ +static inline void touch_ll_clear_active_channel_status(void) +{ + SENS.sar_touch_ctrl2.touch_meas_en_clr = 1; +} + +/********************************* FSM Operation ******************************/ +/** + * Enable touch sensor FSM timer trigger (continuous) mode or software trigger (oneshot) mode. + * + * @param enable Enable FSM timer mode. + * True: the FSM will trigger scanning repeatedly under the control of the hardware timer (continuous mode) + * False: the FSM will trigger scanning once under the control of the software (continuous mode) + */ +__attribute__((always_inline)) +static inline void touch_ll_enable_fsm_timer(bool enable) +{ + SENS.sar_touch_ctrl2.touch_start_force = !enable; +} + +/** + * Start touch sensor FSM timer to run FSM repeatedly + * The measurement action can be triggered by the hardware timer, as well as by the software instruction. + * @note + * The timer should be triggered + */ +__attribute__((always_inline)) +static inline void touch_ll_start_fsm_repeated_timer(void) +{ + RTCCNTL.state0.touch_slp_timer_en = 1; +} + +/** + * Stop touch sensor FSM timer. + * The measurement action can be triggered by the hardware timer, as well as by the software instruction. + */ +__attribute__((always_inline)) +static inline void touch_ll_stop_fsm_repeated_timer(void) +{ + RTCCNTL.state0.touch_slp_timer_en = 0; +} + +/** + * Is the FSM repeated timer enabled. + * @note when the timer is enabled, RTC clock should not be power down + * + * @return + * - true: enabled + * - false: disabled + */ +__attribute__((always_inline)) +static inline bool touch_ll_is_fsm_repeated_timer_enabled(void) +{ + return (bool)RTCCNTL.state0.touch_slp_timer_en; +} + + +/** + * Enable the touch sensor FSM start signal from software + */ +__attribute__((always_inline)) +static inline void touch_ll_trigger_oneshot_measurement(void) +{ + SENS.sar_touch_ctrl2.touch_start_en = 1; + SENS.sar_touch_ctrl2.touch_start_en = 0; +} + +/** + * @brief Power on the channel by mask + * + * @param chan_mask The channel mask that needs to power on + */ +__attribute__((always_inline)) +static inline void touch_ll_channel_sw_measure_mask(uint16_t chan_mask) +{ + (void) chan_mask; + // Only for compatibility +} + +/************************************** Data **********************************/ +/** + * Get the data of the touch channel according to the types + * + * @param touch_num touch pad index + * @param type data type + * 0/1: TOUCH_LL_READ_RAW, raw data of touch channel + * 2: TOUCH_LL_READ_BENCHMARK, benchmark value of touch channel, + * the benchmark value is the maximum during the first measurement period + * 3: TOUCH_LL_READ_SMOOTH, the smoothed data that obtained by filtering the raw data. + * @param data pointer to the data + */ +__attribute__((always_inline)) +static inline void touch_ll_read_chan_data(uint32_t touch_num, uint8_t type, uint32_t *data) +{ + HAL_ASSERT(type == TOUCH_LL_READ_RAW); + HAL_ASSERT(touch_num < SOC_TOUCH_SENSOR_NUM); + touch_num = TOUCH_LL_CHAN_SWAP(touch_num); + if (touch_num & 0x1) { + *data = HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_meas[touch_num >> 1], l_val); + } else { + *data = HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_meas[touch_num >> 1], h_val); + } +} + +/******************************************************************************/ +/* Legacy APIs (to be removed in esp-idf v6.0) */ +/******************************************************************************/ + +#include "hal/touch_sensor_legacy_types.h" /** * Swap the number of touch8 and touch9. @@ -493,18 +898,6 @@ static inline uint32_t touch_ll_read_raw_data(touch_pad_t touch_num) HAL_FORCE_READ_U32_REG_FIELD(SENS.touch_meas[tp_wrap / 2], h_val)); } -/** - * Get touch sensor measure status. No block. - * - * @return - * - If touch sensors measure done. - */ -__attribute__((always_inline)) -static inline bool touch_ll_is_measure_done(void) -{ - return (bool)SENS.sar_touch_ctrl2.touch_meas_done; -} - #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/touch_sensor_ll.h b/components/hal/esp32p4/include/hal/touch_sensor_ll.h index b26c79092e..f7d34bb56a 100644 --- a/components/hal/esp32p4/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32p4/include/hal/touch_sensor_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -283,6 +283,24 @@ static inline void touch_ll_set_chan_active_threshold(uint32_t touch_num, uint8_ HAL_FORCE_MODIFY_U32_REG_FIELD(LP_ANA_PERI.touch_padx_thn[touch_num + 1].thresh[sample_cfg_id], threshold, thresh); // codespell:ignore } +/** + * Get touch sensor threshold of charge cycles that triggers pad active state. + * The threshold determines the sensitivity of the touch sensor. + * The threshold is the original value of the trigger state minus the benchmark value. + * + * @note If set "TOUCH_PAD_THRESHOLD_MAX", the touch is never be triggered. + * @param touch_num The touch pad id + * @param sample_cfg_id The sample configuration index + * @return + * - The threshold of charge cycles + */ +static inline uint32_t touch_ll_get_chan_active_threshold(uint32_t touch_num, uint8_t sample_cfg_id) +{ + HAL_ASSERT(sample_cfg_id < SOC_TOUCH_SAMPLE_CFG_NUM); + // Channel shift workaround + return HAL_FORCE_READ_U32_REG_FIELD(LP_ANA_PERI.touch_padx_thn[touch_num + 1].thresh[sample_cfg_id], threshold); // codespell:ignore +} + /** * @brief Enable or disable the channel that will be scanned. * @note The shield channel should not be enabled to scan here diff --git a/components/hal/esp32s2/include/hal/touch_sensor_ll.h b/components/hal/esp32s2/include/hal/touch_sensor_ll.h index 1b2bda597e..78de4e8bff 100644 --- a/components/hal/esp32s2/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32s2/include/hal/touch_sensor_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -200,6 +200,22 @@ static inline void touch_ll_set_chan_active_threshold(uint32_t touch_num, uint32 SENS.touch_thresh[touch_num - 1].thresh = thresh; } +/** + * Get touch sensor threshold of charge cycles that triggers pad active state. + * The threshold determines the sensitivity of the touch sensor. + * The threshold is the original value of the trigger state minus the benchmark value. + * + * @note If set "TOUCH_PAD_THRESHOLD_MAX", the touch is never be triggered. + * @param touch_num The touch pad id + * @return + * - The threshold of charge cycles + */ +static inline uint32_t touch_ll_get_chan_active_threshold(uint32_t touch_num) +{ + HAL_ASSERT(touch_num > 0); + return SENS.touch_thresh[touch_num - 1].thresh; +} + /** * Set the power on wait cycle * @@ -599,6 +615,17 @@ static inline void touch_ll_sleep_set_channel_num(uint32_t touch_num) RTCCNTL.touch_slp_thres.touch_slp_pad = touch_num; } +/** + * Get touch channel number for sleep pad. + * + * @note Only one touch sensor channel is supported in deep sleep mode. + * @param touch_num Touch sensor channel number. + */ +static inline void touch_ll_sleep_get_channel_num(uint32_t *touch_num) +{ + *touch_num = RTCCNTL.touch_slp_thres.touch_slp_pad; +} + /** * Enable proximity sensing function for sleep channel. */ @@ -1609,16 +1636,6 @@ static inline bool touch_ll_proximity_pad_check(touch_pad_t touch_num) } /************** sleep pad setting ***********************/ -/** - * Get touch channel number for sleep pad. - * - * @note Only one touch sensor channel is supported in deep sleep mode. - * @param touch_num Touch sensor channel number. - */ -static inline void touch_ll_sleep_get_channel_num(touch_pad_t *touch_num) -{ - *touch_num = (touch_pad_t)(RTCCNTL.touch_slp_thres.touch_slp_pad); -} /** * Get the trigger threshold of touch sensor in deep sleep. diff --git a/components/hal/esp32s2/touch_sensor_hal.c b/components/hal/esp32s2/touch_sensor_hal.c index c8f3789c8a..fe0ad605a6 100644 --- a/components/hal/esp32s2/touch_sensor_hal.c +++ b/components/hal/esp32s2/touch_sensor_hal.c @@ -151,7 +151,7 @@ void touch_hal_sleep_channel_enable(touch_pad_t pad_num, bool enable) void touch_hal_sleep_channel_get_config(touch_pad_sleep_channel_t *slp_config) { - touch_ll_sleep_get_channel_num(&slp_config->touch_num); + touch_ll_sleep_get_channel_num((uint32_t *)&slp_config->touch_num); slp_config->en_proximity = touch_ll_sleep_is_proximity_enabled(); } diff --git a/components/hal/esp32s3/include/hal/touch_sensor_ll.h b/components/hal/esp32s3/include/hal/touch_sensor_ll.h index b42083a1f2..193950ee70 100644 --- a/components/hal/esp32s3/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32s3/include/hal/touch_sensor_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -195,6 +195,22 @@ static inline void touch_ll_set_chan_active_threshold(uint32_t touch_num, uint32 SENS.touch_thresh[touch_num - 1].thresh = thresh; } +/** + * Get touch sensor threshold of charge cycles that triggers pad active state. + * The threshold determines the sensitivity of the touch sensor. + * The threshold is the original value of the trigger state minus the benchmark value. + * + * @note If set "TOUCH_PAD_THRESHOLD_MAX", the touch is never be triggered. + * @param touch_num The touch pad id + * @return + * - The threshold of charge cycles + */ +static inline uint32_t touch_ll_get_chan_active_threshold(uint32_t touch_num) +{ + HAL_ASSERT(touch_num > 0); + return SENS.touch_thresh[touch_num - 1].thresh; +} + /** * Set the power on wait cycle * @@ -609,6 +625,17 @@ static inline void touch_ll_sleep_set_channel_num(uint32_t touch_num) RTCCNTL.touch_slp_thres.touch_slp_pad = touch_num; } +/** + * Get touch channel number for sleep pad. + * + * @note Only one touch sensor channel is supported in deep sleep mode. + * @param touch_num Touch sensor channel number. + */ +static inline void touch_ll_sleep_get_channel_num(uint32_t *touch_num) +{ + *touch_num = RTCCNTL.touch_slp_thres.touch_slp_pad; +} + /** * Enable proximity sensing function for sleep channel. */ @@ -1646,17 +1673,6 @@ static inline bool touch_ll_proximity_pad_check(touch_pad_t touch_num) } /************** sleep pad setting ***********************/ -/** - * Get touch channel number for sleep pad. - * - * @note Only one touch sensor channel is supported in deep sleep mode. - * @param touch_num Touch sensor channel number. - */ -static inline void touch_ll_sleep_get_channel_num(touch_pad_t *touch_num) -{ - *touch_num = (touch_pad_t)(RTCCNTL.touch_slp_thres.touch_slp_pad); -} - /** * Get the trigger threshold of touch sensor in deep sleep. * The threshold determines the sensitivity of the touch sensor. diff --git a/components/hal/esp32s3/touch_sensor_hal.c b/components/hal/esp32s3/touch_sensor_hal.c index 4ae025a5b0..f4a662af59 100644 --- a/components/hal/esp32s3/touch_sensor_hal.c +++ b/components/hal/esp32s3/touch_sensor_hal.c @@ -152,7 +152,7 @@ void touch_hal_sleep_channel_enable(touch_pad_t pad_num, bool enable) void touch_hal_sleep_channel_get_config(touch_pad_sleep_channel_t *slp_config) { - touch_ll_sleep_get_channel_num(&slp_config->touch_num); + touch_ll_sleep_get_channel_num((uint32_t *)&slp_config->touch_num); slp_config->en_proximity = touch_ll_sleep_is_proximity_enabled(); } diff --git a/components/hal/include/hal/touch_sens_hal.h b/components/hal/include/hal/touch_sens_hal.h index 6e4e48ba11..61990cbb42 100644 --- a/components/hal/include/hal/touch_sens_hal.h +++ b/components/hal/include/hal/touch_sens_hal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,7 +14,7 @@ #pragma once #include "soc/soc_caps.h" -#if SOC_TOUCH_SENSOR_VERSION > 1 +#if SOC_TOUCH_SENSOR_SUPPORTED #include "hal/touch_sensor_ll.h" #include "hal/touch_sens_types.h" #endif // SOC_TOUCH_SENSOR_SUPPORTED @@ -22,10 +22,23 @@ #ifdef __cplusplus extern "C" { #endif +#if SOC_TOUCH_SENSOR_SUPPORTED +#if SOC_TOUCH_SENSOR_VERSION == 1 +/** + * @brief Sample configurations of the touch sensor V1 + */ +typedef struct { + uint32_t charge_duration_ticks; + touch_volt_lim_h_t charge_volt_lim_h; /*!< The upper voltage limit while charging a touch pad. i.e., the touch controller won't charge the touch pad higher than this high voltage limitation. */ + touch_volt_lim_l_t charge_volt_lim_l; /*!< The lower voltage limit while discharging a touch pad. i.e., the touch controller won't discharge the touch pad lower than this low voltage limitation. */ +} touch_hal_sample_config_v1_t; -#if SOC_TOUCH_SENSOR_VERSION > 1 +/** + * @brief Alias of touch_hal_sample_config_v1_t for compatibility + */ +typedef touch_hal_sample_config_v1_t touch_hal_sample_config_t; -#if SOC_TOUCH_SENSOR_VERSION == 2 +#elif SOC_TOUCH_SENSOR_VERSION == 2 /** * @brief Sample configurations of the touch sensor V2 @@ -68,6 +81,7 @@ typedef touch_hal_sample_config_v3_t touch_hal_sample_config_t; #else #error "Unsupported touch sensor version" +typedef int touch_hal_sample_config_t; #endif /** @@ -77,11 +91,19 @@ typedef touch_hal_sample_config_v3_t touch_hal_sample_config_t; typedef struct { uint32_t power_on_wait_ticks; /*!< The waiting time between the channels power on and able to measure, to ensure the data stability */ uint32_t meas_interval_ticks; /*!< Measurement interval of each channels */ // TODO: Test the supported range +#if SOC_TOUCH_SENSOR_VERSION == 1 + touch_intr_trig_mode_t intr_trig_mode; + touch_intr_trig_group_t intr_trig_group; +#elif SOC_TOUCH_SENSOR_VERSION == 2 + uint32_t timeout_ticks; /*!< The maximum time of measuring one channel, if the time exceeds this value, the timeout interrupt will be triggered. + * Set to '0' to ignore the measurement time limitation, otherwise please set a proper time considering the configurations + * of the sample configurations below. + */ +#elif SOC_TOUCH_SENSOR_VERSION == 3 uint32_t timeout_ticks; /*!< The maximum time of measuring one channel, if the time exceeds this value, the timeout interrupt will be triggered. * Set to '0' to ignore the measurement time limitation, otherwise please set a proper time considering the configurations * of the sample configurations below. */ -#if SOC_TOUCH_SENSOR_VERSION == 3 touch_out_mode_t output_mode; /*!< Touch channel counting mode of the binarized touch output */ #endif // SOC_TOUCH_SENSOR_VERSION == 3 uint32_t sample_cfg_num; /*!< The sample configuration number that used for sampling */ @@ -99,7 +121,7 @@ void touch_hal_config_controller(const touch_hal_config_t *cfg); * @brief Save the touch sensor hardware configuration * @note The saved configurations will be applied before entering deep sleep * - * @param[in] deep_slp_chan The touch sensor channel that can wake-up the chip from deep sleep + * @param[in] deep_slp_chan The touch sensor channel that can wake-up the chip from deep sleep, -1 means all enabled channel can wakeup * @param[in] deep_slp_cfg The hardware configuration that takes effect during the deep sleep * @param[in] dslp_allow_pd Whether allow RTC_PERIPH domain power down during the deep sleep */ diff --git a/components/hal/include/hal/touch_sens_types.h b/components/hal/include/hal/touch_sens_types.h index 65c3b92d6d..143d92d65d 100644 --- a/components/hal/include/hal/touch_sens_types.h +++ b/components/hal/include/hal/touch_sens_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -59,79 +59,79 @@ typedef enum { * @brief Touch sensor upper charging voltage limit */ typedef enum { - TOUCH_VOLT_LIM_H_0V9, /*!< Touch sensor upper voltage limit is 0.9V while charging a touch pad */ - TOUCH_VOLT_LIM_H_1V0, /*!< Touch sensor upper voltage limit is 1.0V while charging a touch pad */ - TOUCH_VOLT_LIM_H_1V1, /*!< Touch sensor upper voltage limit is 1.1V while charging a touch pad */ - TOUCH_VOLT_LIM_H_1V2, /*!< Touch sensor upper voltage limit is 1.2V while charging a touch pad */ + TOUCH_VOLT_LIM_H_0V9, /*!< Touch sensor upper voltage limit is 0.9V while charging a touch pad */ + TOUCH_VOLT_LIM_H_1V0, /*!< Touch sensor upper voltage limit is 1.0V while charging a touch pad */ + TOUCH_VOLT_LIM_H_1V1, /*!< Touch sensor upper voltage limit is 1.1V while charging a touch pad */ + TOUCH_VOLT_LIM_H_1V2, /*!< Touch sensor upper voltage limit is 1.2V while charging a touch pad */ // No 1V3 - TOUCH_VOLT_LIM_H_1V4, /*!< Touch sensor upper voltage limit is 1.4V while charging a touch pad */ - TOUCH_VOLT_LIM_H_1V5, /*!< Touch sensor upper voltage limit is 1.5V while charging a touch pad */ - TOUCH_VOLT_LIM_H_1V6, /*!< Touch sensor upper voltage limit is 1.6V while charging a touch pad */ - TOUCH_VOLT_LIM_H_1V7, /*!< Touch sensor upper voltage limit is 1.7V while charging a touch pad */ + TOUCH_VOLT_LIM_H_1V4, /*!< Touch sensor upper voltage limit is 1.4V while charging a touch pad */ + TOUCH_VOLT_LIM_H_1V5, /*!< Touch sensor upper voltage limit is 1.5V while charging a touch pad */ + TOUCH_VOLT_LIM_H_1V6, /*!< Touch sensor upper voltage limit is 1.6V while charging a touch pad */ + TOUCH_VOLT_LIM_H_1V7, /*!< Touch sensor upper voltage limit is 1.7V while charging a touch pad */ // No 1V8 - TOUCH_VOLT_LIM_H_1V9, /*!< Touch sensor upper voltage limit is 1.9V while charging a touch pad */ - TOUCH_VOLT_LIM_H_2V0, /*!< Touch sensor upper voltage limit is 2.0V while charging a touch pad */ - TOUCH_VOLT_LIM_H_2V1, /*!< Touch sensor upper voltage limit is 2.1V while charging a touch pad */ - TOUCH_VOLT_LIM_H_2V2, /*!< Touch sensor upper voltage limit is 2.2V while charging a touch pad */ + TOUCH_VOLT_LIM_H_1V9, /*!< Touch sensor upper voltage limit is 1.9V while charging a touch pad */ + TOUCH_VOLT_LIM_H_2V0, /*!< Touch sensor upper voltage limit is 2.0V while charging a touch pad */ + TOUCH_VOLT_LIM_H_2V1, /*!< Touch sensor upper voltage limit is 2.1V while charging a touch pad */ + TOUCH_VOLT_LIM_H_2V2, /*!< Touch sensor upper voltage limit is 2.2V while charging a touch pad */ // No 2V3 - TOUCH_VOLT_LIM_H_2V4, /*!< Touch sensor upper voltage limit is 2.4V while charging a touch pad */ - TOUCH_VOLT_LIM_H_2V5, /*!< Touch sensor upper voltage limit is 2.5V while charging a touch pad */ - TOUCH_VOLT_LIM_H_2V6, /*!< Touch sensor upper voltage limit is 2.6V while charging a touch pad */ - TOUCH_VOLT_LIM_H_2V7, /*!< Touch sensor upper voltage limit is 2.7V while charging a touch pad */ + TOUCH_VOLT_LIM_H_2V4, /*!< Touch sensor upper voltage limit is 2.4V while charging a touch pad */ + TOUCH_VOLT_LIM_H_2V5, /*!< Touch sensor upper voltage limit is 2.5V while charging a touch pad */ + TOUCH_VOLT_LIM_H_2V6, /*!< Touch sensor upper voltage limit is 2.6V while charging a touch pad */ + TOUCH_VOLT_LIM_H_2V7, /*!< Touch sensor upper voltage limit is 2.7V while charging a touch pad */ } touch_volt_lim_h_t; /** * @brief Touch sensor lower discharging voltage limit */ typedef enum { - TOUCH_VOLT_LIM_L_0V5, /*!< Touch sensor lower voltage limit is 0.5V while discharging a touch pad */ - TOUCH_VOLT_LIM_L_0V6, /*!< Touch sensor lower voltage limit is 0.6V while discharging a touch pad */ - TOUCH_VOLT_LIM_L_0V7, /*!< Touch sensor lower voltage limit is 0.7V while discharging a touch pad */ - TOUCH_VOLT_LIM_L_0V8, /*!< Touch sensor lower voltage limit is 0.8V while discharging a touch pad */ + TOUCH_VOLT_LIM_L_0V5, /*!< Touch sensor lower voltage limit is 0.5V while discharging a touch pad */ + TOUCH_VOLT_LIM_L_0V6, /*!< Touch sensor lower voltage limit is 0.6V while discharging a touch pad */ + TOUCH_VOLT_LIM_L_0V7, /*!< Touch sensor lower voltage limit is 0.7V while discharging a touch pad */ + TOUCH_VOLT_LIM_L_0V8, /*!< Touch sensor lower voltage limit is 0.8V while discharging a touch pad */ } touch_volt_lim_l_t; /** * @brief Touch sensor charge and discharge speed */ typedef enum { - TOUCH_CHARGE_SPEED_0 = 0, /*!< Touch sensor charge and discharge speed, no charge, always zero */ - TOUCH_CHARGE_SPEED_1 = 1, /*!< Touch sensor charge and discharge speed, slowest */ - TOUCH_CHARGE_SPEED_2 = 2, /*!< Touch sensor charge and discharge speed */ - TOUCH_CHARGE_SPEED_3 = 3, /*!< Touch sensor charge and discharge speed */ - TOUCH_CHARGE_SPEED_4 = 4, /*!< Touch sensor charge and discharge speed */ - TOUCH_CHARGE_SPEED_5 = 5, /*!< Touch sensor charge and discharge speed */ - TOUCH_CHARGE_SPEED_6 = 6, /*!< Touch sensor charge and discharge speed */ - TOUCH_CHARGE_SPEED_7 = 7, /*!< Touch sensor charge and discharge speed, fastest */ + TOUCH_CHARGE_SPEED_0 = 0, /*!< Touch sensor charge and discharge speed, no charge, always zero */ + TOUCH_CHARGE_SPEED_1 = 1, /*!< Touch sensor charge and discharge speed, slowest */ + TOUCH_CHARGE_SPEED_2 = 2, /*!< Touch sensor charge and discharge speed */ + TOUCH_CHARGE_SPEED_3 = 3, /*!< Touch sensor charge and discharge speed */ + TOUCH_CHARGE_SPEED_4 = 4, /*!< Touch sensor charge and discharge speed */ + TOUCH_CHARGE_SPEED_5 = 5, /*!< Touch sensor charge and discharge speed */ + TOUCH_CHARGE_SPEED_6 = 6, /*!< Touch sensor charge and discharge speed */ + TOUCH_CHARGE_SPEED_7 = 7, /*!< Touch sensor charge and discharge speed, fastest */ } touch_charge_speed_t; /** * @brief Touch sensor initial voltage before charging */ typedef enum { - TOUCH_INIT_CHARGE_VOLT_LOW = 0, /*!< Tie the initial charge voltage to low */ - TOUCH_INIT_CHARGE_VOLT_HIGH = 1,/*!< Tie the initial charge voltage to high */ + TOUCH_INIT_CHARGE_VOLT_LOW = 0, /*!< Tie the initial charge voltage to low */ + TOUCH_INIT_CHARGE_VOLT_HIGH = 1, /*!< Tie the initial charge voltage to high */ } touch_init_charge_volt_t; /** * @brief Touch channel idle state configuration */ typedef enum { - TOUCH_IDLE_CONN_HIGHZ = 0, /*!< The idle (enabled but not measuring) touch channel is at high resistance state */ - TOUCH_IDLE_CONN_GND = 1, /*!< The idle (enabled but not measuring) touch channel is connected to the ground */ + TOUCH_IDLE_CONN_HIGHZ = 0, /*!< The idle (enabled but not measuring) touch channel is at high resistance state */ + TOUCH_IDLE_CONN_GND = 1, /*!< The idle (enabled but not measuring) touch channel is connected to the ground */ } touch_idle_conn_t; /** * @brief Touch sensor denoise channel internal reference capacitance */ typedef enum { - TOUCH_DENOISE_CHAN_CAP_5PF = 0, /*!< Denoise channel internal reference capacitance is 5.0pf */ - TOUCH_DENOISE_CHAN_CAP_6PF = 1, /*!< Denoise channel internal reference capacitance is 6.4pf */ - TOUCH_DENOISE_CHAN_CAP_7PF = 2, /*!< Denoise channel internal reference capacitance is 7.8pf */ - TOUCH_DENOISE_CHAN_CAP_9PF = 3, /*!< Denoise channel internal reference capacitance is 9.2pf */ - TOUCH_DENOISE_CHAN_CAP_10PF = 4, /*!< Denoise channel internal reference capacitance is 10.6pf */ - TOUCH_DENOISE_CHAN_CAP_12PF = 5, /*!< Denoise channel internal reference capacitance is 12.0pf */ - TOUCH_DENOISE_CHAN_CAP_13PF = 6, /*!< Denoise channel internal reference capacitance is 13.4pf */ - TOUCH_DENOISE_CHAN_CAP_14PF = 7, /*!< Denoise channel internal reference capacitance is 14.8pf */ + TOUCH_DENOISE_CHAN_CAP_5PF = 0, /*!< Denoise channel internal reference capacitance is 5.0pf */ + TOUCH_DENOISE_CHAN_CAP_6PF = 1, /*!< Denoise channel internal reference capacitance is 6.4pf */ + TOUCH_DENOISE_CHAN_CAP_7PF = 2, /*!< Denoise channel internal reference capacitance is 7.8pf */ + TOUCH_DENOISE_CHAN_CAP_9PF = 3, /*!< Denoise channel internal reference capacitance is 9.2pf */ + TOUCH_DENOISE_CHAN_CAP_10PF = 4, /*!< Denoise channel internal reference capacitance is 10.6pf */ + TOUCH_DENOISE_CHAN_CAP_12PF = 5, /*!< Denoise channel internal reference capacitance is 12.0pf */ + TOUCH_DENOISE_CHAN_CAP_13PF = 6, /*!< Denoise channel internal reference capacitance is 13.4pf */ + TOUCH_DENOISE_CHAN_CAP_14PF = 7, /*!< Denoise channel internal reference capacitance is 14.8pf */ } touch_denoise_chan_cap_t; /** @@ -148,24 +148,42 @@ typedef enum { * @brief Touch sensor bias type */ typedef enum { - TOUCH_BIAS_TYPE_BANDGAP, /*!< Use bandgap-bias to charge/discharge the touch channel, which is more stable but power-consuming */ - TOUCH_BIAS_TYPE_SELF, /*!< Use self-bias to charge/discharge the touch channel, which is less stable but power-saving */ + TOUCH_BIAS_TYPE_BANDGAP, /*!< Use bandgap-bias to charge/discharge the touch channel, which is more stable but power-consuming */ + TOUCH_BIAS_TYPE_SELF, /*!< Use self-bias to charge/discharge the touch channel, which is less stable but power-saving */ } touch_bias_type_t; /** * @brief Touch channel binarized output counting mode */ typedef enum { - TOUCH_PAD_OUT_AS_DATA, /*!< Counting the output of touch channel as data. - * The value will be smaller than actual value but more sensitive when the frequency of touch_out is close to the source clock - * Normally we treat the output as data when it is lower than the sample clock - */ - TOUCH_PAD_OUT_AS_CLOCK, /*!< Counting the output of touch channel as clock. - * The value is accurate but less sensitive when the frequency of touch_out is close to the source clock - * Normally we treat the output as clock when it is higher than the sample clock - */ + TOUCH_PAD_OUT_AS_DATA, /*!< Counting the output of touch channel as data. + * The value will be smaller than actual value but more sensitive when the frequency of touch_out is close to the source clock + * Normally we treat the output as data when it is lower than the sample clock + */ + TOUCH_PAD_OUT_AS_CLOCK, /*!< Counting the output of touch channel as clock. + * The value is accurate but less sensitive when the frequency of touch_out is close to the source clock + * Normally we treat the output as clock when it is higher than the sample clock + */ } touch_out_mode_t; +/** + * @brief Touch interrupt trigger mode + * + */ +typedef enum { + TOUCH_INTR_TRIG_ON_BELOW_THRESH, /*!< The touch active interrupt will trigger when the measured data below the absolute threshold */ + TOUCH_INTR_TRIG_ON_ABOVE_THRESH, /*!< The touch active interrupt will trigger when the measured data above the absolute threshold */ +} touch_intr_trig_mode_t; + +/** + * @brief Touch interrupt trigger group + * + */ +typedef enum { + TOUCH_INTR_TRIG_GROUP_BOTH, /*!< Both channel groups can trigger the interrupt */ + TOUCH_INTR_TRIG_GROUP_1, /*!< Only the channels in group 1 can trigger the interrupt */ +} touch_intr_trig_group_t; + #ifdef __cplusplus } #endif diff --git a/components/hal/touch_sens_hal.c b/components/hal/touch_sens_hal.c index 58c9c03227..8f3a082efe 100644 --- a/components/hal/touch_sens_hal.c +++ b/components/hal/touch_sens_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -26,18 +26,26 @@ static touch_hal_deep_sleep_obj_t s_touch_slp_obj = { void touch_hal_config_controller(const touch_hal_config_t *cfg) { HAL_ASSERT(cfg); - touch_ll_sleep_set_channel_num(TOUCH_LL_NULL_CHANNEL); touch_ll_set_power_on_wait_cycle(cfg->power_on_wait_ticks); touch_ll_set_measure_interval_ticks(cfg->meas_interval_ticks); - touch_ll_set_timeout(cfg->timeout_ticks); -#if SOC_TOUCH_SENSOR_VERSION == 2 +#if SOC_TOUCH_SENSOR_VERSION == 1 + touch_ll_set_intr_trigger_mode(cfg->intr_trig_mode); + touch_ll_set_intr_trigger_group(cfg->intr_trig_group); + touch_ll_set_charge_window_duration(cfg->sample_cfg->charge_duration_ticks); + touch_ll_set_charge_voltage_high_limit(cfg->sample_cfg->charge_volt_lim_h); + touch_ll_set_charge_voltage_low_limit(cfg->sample_cfg->charge_volt_lim_l); +#elif SOC_TOUCH_SENSOR_VERSION == 2 + touch_ll_sleep_set_channel_num(TOUCH_LL_NULL_CHANNEL); + touch_ll_set_timeout(cfg->timeout_ticks); touch_ll_set_charge_times(cfg->sample_cfg->charge_times); touch_ll_set_charge_voltage_high_limit(cfg->sample_cfg->charge_volt_lim_h); touch_ll_set_charge_voltage_low_limit(cfg->sample_cfg->charge_volt_lim_l); touch_ll_set_idle_channel_connection(cfg->sample_cfg->idle_conn); touch_ll_set_bias_type(cfg->sample_cfg->bias_type); #elif SOC_TOUCH_SENSOR_VERSION == 3 + touch_ll_sleep_set_channel_num(TOUCH_LL_NULL_CHANNEL); + touch_ll_set_timeout(cfg->timeout_ticks); touch_ll_sample_cfg_set_engaged_num(cfg->sample_cfg_num); touch_ll_set_out_mode(cfg->output_mode); for (int i = 0; i < cfg->sample_cfg_num; i++) { @@ -66,6 +74,26 @@ void touch_hal_save_sleep_config(int deep_slp_chan, const touch_hal_config_t *de } } +#if SOC_TOUCH_SENSOR_VERSION == 1 +//This function will only be called when the chip is going to deep sleep. +static void s_touch_hal_apply_sleep_config(void) +{ + /* Apply the particular configuration for deep sleep */ + if (s_touch_slp_obj.apply_slp_cfg) { + /* Save the current channel threshold first, because they will be reset by hardware after the recofniguration */ + uint32_t chan_thresh[SOC_TOUCH_SENSOR_NUM] = {}; + for (int i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) { + chan_thresh[i] = touch_ll_get_chan_active_threshold(i); + } + /* Reconfigure the touch sensor to use the sleep configuration */ + touch_hal_config_controller(&s_touch_slp_obj.slp_cfg); + /* Restore the channel threshold */ + for (int i = 0; i < SOC_TOUCH_SENSOR_NUM; i++) { + touch_ll_set_chan_active_threshold(i, chan_thresh[i]); + } + } +} +#else //This function will only be called when the chip is going to deep sleep. static void s_touch_hal_apply_sleep_config(void) { @@ -86,10 +114,13 @@ static void s_touch_hal_apply_sleep_config(void) touch_ll_sleep_set_channel_num(TOUCH_LL_NULL_CHANNEL); } } +#endif void touch_hal_prepare_deep_sleep(void) { s_touch_hal_apply_sleep_config(); +#if SOC_TOUCH_SUPPORT_BENCHMARK touch_ll_sleep_reset_benchmark(); +#endif touch_ll_interrupt_clear(TOUCH_LL_INTR_MASK_ALL); } diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index fddab15bd5..ab709e39b5 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -727,6 +727,10 @@ config SOC_TOUCH_SENSOR_NUM int default 10 +config SOC_TOUCH_SUPPORT_SLEEP_WAKEUP + bool + default y + config SOC_TOUCH_SAMPLE_CFG_NUM int default 1 diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 8d3f86a29d..3c82507ac2 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -332,8 +332,8 @@ /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ #define SOC_TOUCH_SENSOR_VERSION (1U) /*!