diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index 093e321823..c9026b268c 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -60,7 +60,9 @@ if(${target} STREQUAL "esp32s3") "mcpwm.c" "usb_serial_jtag.c" "spi_slave_hd.c" - "touch_sensor_common.c") + "touch_sensor_common.c" + "esp32s2/touch_sensor.c" # The touch sensor function is the same as the esp32s2 platform. + ) endif() if(IDF_TARGET STREQUAL "esp32c3") diff --git a/components/driver/esp32s3/include/driver/touch_sensor.h b/components/driver/esp32s3/include/driver/touch_sensor.h index 7240590e27..178e3b1a9d 100644 --- a/components/driver/esp32s3/include/driver/touch_sensor.h +++ b/components/driver/esp32s3/include/driver/touch_sensor.h @@ -6,12 +6,12 @@ #pragma once +#include "driver/touch_sensor_common.h" + #ifdef __cplusplus extern "C" { #endif -#include "driver/touch_sensor_common.h" - /** * @brief Set touch sensor FSM start * @note Start FSM after the touch sensor FSM mode is set. @@ -180,6 +180,7 @@ uint32_t touch_pad_read_intr_status_mask(void); /** * @brief Enable touch sensor interrupt by bitmask. + * @note This API can be called in ISR handler. * @param int_mask Pad mask to enable interrupts * @return * - ESP_OK on success @@ -188,6 +189,7 @@ esp_err_t touch_pad_intr_enable(touch_pad_intr_mask_t int_mask); /** * @brief Disable touch sensor interrupt by bitmask. + * @note This API can be called in ISR handler. * @param int_mask Pad mask to disable interrupts * @return * - ESP_OK on success diff --git a/components/driver/esp32s3/touch_sensor.c b/components/driver/esp32s3/touch_sensor.c new file mode 100644 index 0000000000..ba6323ce30 --- /dev/null +++ b/components/driver/esp32s3/touch_sensor.c @@ -0,0 +1,4 @@ +/** + * The touch sensor function is the same as the esp32s2 platform. + * Please refer to the source files of the ESP32S2 platform. +*/ diff --git a/components/driver/test/touch_sensor_test/test_esp32s2.c b/components/driver/test/touch_sensor_test/test_esp32s2.c index a5ddf94ee7..9d9d9fbb14 100644 --- a/components/driver/test/touch_sensor_test/test_esp32s2.c +++ b/components/driver/test/touch_sensor_test/test_esp32s2.c @@ -8,7 +8,7 @@ Tests for the touch sensor device driver for ESP32-S2 only */ #include "sdkconfig.h" -#if CONFIG_IDF_TARGET_ESP32S2 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #include #include "esp_system.h" @@ -64,9 +64,9 @@ void test_pxp_deinit_io(void) #define TOUCH_EXCEED_TIME_MS (1000) #define TOUCH_REG_BASE_TEST() ({ \ - TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_CNTL_DATE), RTCCNTL.date.date); \ - TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(SENS_SARDATE_REG, SENS_SAR_DATE), SENS.sardate.sar_date); \ - TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(RTC_IO_DATE_REG, RTC_IO_IO_DATE), RTCIO.date.date); \ + TEST_ASSERT_EQUAL_UINT32(REG_READ(RTC_CNTL_DATE_REG), RTCCNTL.date.date); \ + TEST_ASSERT_EQUAL_UINT32(REG_READ(SENS_SARDATE_REG), SENS.sardate.sar_date); \ + TEST_ASSERT_EQUAL_UINT32(REG_READ(RTC_IO_DATE_REG), RTCIO.date.date); \ }) #define TEST_TOUCH_COUNT_NUM (5) @@ -1157,16 +1157,28 @@ esp_err_t test_touch_filter_parameter_reset(int reset_cnt) } printf_touch_hw_read("[raw ] cnt:"); printf_touch_benchmark_read("[base] cnt:"); - - test_touch_measure_step(1); - /* ESP32S2 reset benchmark to raw data */ +#if CONFIG_IDF_TARGET_ESP32S3 + uint32_t smooth_data[TEST_TOUCH_CHANNEL] = {0}; for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { - TEST_ESP_OK( touch_pad_read_raw_data(touch_list[i], &touch_value) ); - TEST_ESP_OK( touch_pad_read_benchmark(touch_list[i], &base_value) ); - TEST_ASSERT_EQUAL_UINT32(base_value, touch_value); + TEST_ESP_OK( touch_pad_filter_read_smooth(touch_list[i], &(smooth_data[i])) ); } +#endif + test_touch_measure_step(1); printf_touch_hw_read("[raw ] cnt+1:"); + printf_touch_smooth_read("[smooth]cnt+1:"); printf_touch_benchmark_read("[base] cnt+1:"); + /* ESP32S2 reset benchmark to smooth data */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_read_benchmark(touch_list[i], &base_value) ); +#if CONFIG_IDF_TARGET_ESP32S2 + /* In ESP32S3, reset to raw data. */ + TEST_ESP_OK( touch_pad_read_raw_data(touch_list[i], &touch_value) ); + TEST_ASSERT_EQUAL_UINT32(base_value, touch_value); +#elif CONFIG_IDF_TARGET_ESP32S3 + /* In ESP32S3, reset to smooth data, smooth data filtered from raw data by IIR. */ + TEST_ASSERT_EQUAL_UINT32(base_value, smooth_data[i]); +#endif + } int test_cnt = 2; while (test_cnt--) { @@ -2115,4 +2127,4 @@ void test_touch_slope_debug(int pad_num) TEST_ESP_OK( touch_pad_deinit() ); } -#endif // CONFIG_IDF_TARGET_ESP32S2 +#endif // CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 0b88d4c8ec..c9278b91ec 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -364,10 +364,12 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) if (deep_sleep) { if (s_config.wakeup_triggers & RTC_TOUCH_TRIG_EN) { touch_wakeup_prepare(); +#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. */ pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH; +#endif } } else { /* In light sleep, the RTC_PERIPH power domain should be in the power-on state (Power on the touch circuit in light sleep), @@ -702,7 +704,7 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source) s_config.ext1_trigger_mode = 0; s_config.wakeup_triggers &= ~RTC_EXT1_TRIG_EN; #endif -#if SOC_TOUCH_PAD_WAKE_SUPPORTED +#if SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TOUCHPAD, RTC_TOUCH_TRIG_EN)) { s_config.wakeup_triggers &= ~RTC_TOUCH_TRIG_EN; #endif @@ -1065,7 +1067,7 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) } else if (wakeup_cause & RTC_EXT1_TRIG_EN) { return ESP_SLEEP_WAKEUP_EXT1; #endif -#if SOC_TOUCH_PAD_WAKE_SUPPORTED +#if SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP } else if (wakeup_cause & RTC_TOUCH_TRIG_EN) { return ESP_SLEEP_WAKEUP_TOUCHPAD; #endif @@ -1137,7 +1139,7 @@ static uint32_t get_power_down_flags(void) // RTC_PERIPH is needed for EXT0 wakeup and GPIO wakeup. // If RTC_PERIPH is auto, and EXT0/GPIO aren't enabled, power down RTC_PERIPH. if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] == ESP_PD_OPTION_AUTO) { -#if SOC_TOUCH_PAD_WAKE_SUPPORTED +#if SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP uint32_t wakeup_source = RTC_TOUCH_TRIG_EN; #if SOC_ULP_SUPPORTED wakeup_source |= RTC_ULP_TRIG_EN; @@ -1155,7 +1157,7 @@ static uint32_t get_power_down_flags(void) } else { s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_OFF; } -#endif // SOC_TOUCH_PAD_WAKE_SUPPORTED +#endif // SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP } #if SOC_PM_SUPPORT_CPU_PD diff --git a/components/hal/esp32s3/include/hal/rtc_io_ll.h b/components/hal/esp32s3/include/hal/rtc_io_ll.h index bde6bf3c66..bdf3a77156 100644 --- a/components/hal/esp32s3/include/hal/rtc_io_ll.h +++ b/components/hal/esp32s3/include/hal/rtc_io_ll.h @@ -56,14 +56,14 @@ typedef enum { static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func) { if (func == RTCIO_FUNC_RTC) { - // SENS.sar_io_mux_conf.iomux_clk_gate_en = 1; + SENS.sar_peri_clk_gate_conf.iomux_clk_en = 1; // 0: GPIO connected to digital GPIO module. 1: GPIO connected to analog RTC module. SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux)); //0:RTC FUNCTION 1,2,3:Reserved SET_PERI_REG_BITS(rtc_io_desc[rtcio_num].reg, RTC_IO_TOUCH_PAD1_FUN_SEL_V, RTCIO_LL_PIN_FUNC, rtc_io_desc[rtcio_num].func); } else if (func == RTCIO_FUNC_DIGITAL) { CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux)); - // SENS.sar_io_mux_conf.iomux_clk_gate_en = 0; + SENS.sar_peri_clk_gate_conf.iomux_clk_en = 0; } } @@ -276,6 +276,7 @@ static inline void rtcio_ll_force_unhold_all(void) */ static inline void rtcio_ll_wakeup_enable(int rtcio_num, rtcio_ll_wake_type_t type) { + SENS.sar_peri_clk_gate_conf.iomux_clk_en = 1; RTCIO.pin[rtcio_num].wakeup_enable = 0x1; RTCIO.pin[rtcio_num].int_type = type; } diff --git a/components/hal/esp32s3/include/hal/touch_sensor_hal.h b/components/hal/esp32s3/include/hal/touch_sensor_hal.h index 565bde40c6..8dc0263d94 100644 --- a/components/hal/esp32s3/include/hal/touch_sensor_hal.h +++ b/components/hal/esp32s3/include/hal/touch_sensor_hal.h @@ -18,7 +18,7 @@ * See readme.md in hal/include/hal/readme.md ******************************************************************************/ -// The HAL layer for touch sensor (esp32s2 specific part) +// The HAL layer for touch sensor (ESP32-S3 specific part) #pragma once diff --git a/components/hal/esp32s3/include/hal/touch_sensor_ll.h b/components/hal/esp32s3/include/hal/touch_sensor_ll.h index 1d62690be0..7af44b463a 100644 --- a/components/hal/esp32s3/include/hal/touch_sensor_ll.h +++ b/components/hal/esp32s3/include/hal/touch_sensor_ll.h @@ -1,4 +1,4 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -174,7 +174,11 @@ static inline void touch_ll_get_voltage_attenuation(touch_volt_atten_t *atten) */ static inline void touch_ll_set_slope(touch_pad_t touch_num, touch_cnt_slope_t slope) { - abort();//IDF-3417 + if (touch_num < TOUCH_PAD_NUM10) { + SET_PERI_REG_BITS(RTC_CNTL_TOUCH_DAC_REG, RTC_CNTL_TOUCH_PAD0_DAC_V, slope, (RTC_CNTL_TOUCH_PAD0_DAC_S - touch_num * 3)); + } else { + SET_PERI_REG_BITS(RTC_CNTL_TOUCH_DAC1_REG, RTC_CNTL_TOUCH_PAD10_DAC_V, slope, (RTC_CNTL_TOUCH_PAD10_DAC_S - (touch_num - TOUCH_PAD_NUM10) * 3)); + } } /** @@ -189,7 +193,11 @@ static inline void touch_ll_set_slope(touch_pad_t touch_num, touch_cnt_slope_t s */ static inline void touch_ll_get_slope(touch_pad_t touch_num, touch_cnt_slope_t *slope) { - abort();//IDF-3417 + if (touch_num < TOUCH_PAD_NUM10) { + *slope = GET_PERI_REG_BITS2(RTC_CNTL_TOUCH_DAC_REG, RTC_CNTL_TOUCH_PAD0_DAC_V, (RTC_CNTL_TOUCH_PAD0_DAC_S - touch_num * 3)); + } else { + *slope = GET_PERI_REG_BITS2(RTC_CNTL_TOUCH_DAC1_REG, RTC_CNTL_TOUCH_PAD10_DAC_V, (RTC_CNTL_TOUCH_PAD10_DAC_S - (touch_num - TOUCH_PAD_NUM10) * 3)); + } } /** @@ -413,7 +421,7 @@ static inline void touch_ll_clear_trigger_status_mask(void) static inline uint32_t IRAM_ATTR touch_ll_read_raw_data(touch_pad_t touch_num) { SENS.sar_touch_conf.touch_data_sel = TOUCH_LL_READ_RAW; - return SENS.sar_touch_status[touch_num - 1].touch_pad1_data; + return SENS.sar_touch_status[touch_num - 1].touch_pad_data; } /** @@ -490,19 +498,22 @@ static inline touch_pad_t IRAM_ATTR touch_ll_get_current_meas_channel(void) static inline void touch_ll_intr_enable(touch_pad_intr_mask_t int_mask) { if (int_mask & TOUCH_PAD_INTR_MASK_DONE) { - RTCCNTL.int_ena.rtc_touch_done = 1; + RTCCNTL.int_ena_w1ts.rtc_touch_done_w1ts = 1; } if (int_mask & TOUCH_PAD_INTR_MASK_ACTIVE) { - RTCCNTL.int_ena.rtc_touch_active = 1; + RTCCNTL.int_ena_w1ts.rtc_touch_active_w1ts = 1; } if (int_mask & TOUCH_PAD_INTR_MASK_INACTIVE) { - RTCCNTL.int_ena.rtc_touch_inactive = 1; + RTCCNTL.int_ena_w1ts.rtc_touch_inactive_w1ts = 1; } if (int_mask & TOUCH_PAD_INTR_MASK_SCAN_DONE) { - RTCCNTL.int_ena.rtc_touch_scan_done = 1; + RTCCNTL.int_ena_w1ts.rtc_touch_scan_done_w1ts = 1; } if (int_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) { - RTCCNTL.int_ena.rtc_touch_timeout = 1; + RTCCNTL.int_ena_w1ts.rtc_touch_timeout_w1ts = 1; + } + if (int_mask & TOUCH_PAD_INTR_MASK_PROXI_MEAS_DONE) { + RTCCNTL.int_ena_w1ts.rtc_touch_approach_loop_done_w1ts = 1; } } @@ -514,19 +525,22 @@ static inline void touch_ll_intr_enable(touch_pad_intr_mask_t int_mask) static inline void touch_ll_intr_disable(touch_pad_intr_mask_t int_mask) { if (int_mask & TOUCH_PAD_INTR_MASK_DONE) { - RTCCNTL.int_ena.rtc_touch_done = 0; + RTCCNTL.int_ena_w1tc.rtc_touch_done_w1tc = 1; } if (int_mask & TOUCH_PAD_INTR_MASK_ACTIVE) { - RTCCNTL.int_ena.rtc_touch_active = 0; + RTCCNTL.int_ena_w1tc.rtc_touch_active_w1tc = 1; } if (int_mask & TOUCH_PAD_INTR_MASK_INACTIVE) { - RTCCNTL.int_ena.rtc_touch_inactive = 0; + RTCCNTL.int_ena_w1tc.rtc_touch_inactive_w1tc = 1; } if (int_mask & TOUCH_PAD_INTR_MASK_SCAN_DONE) { - RTCCNTL.int_ena.rtc_touch_scan_done = 0; + RTCCNTL.int_ena_w1tc.rtc_touch_scan_done_w1tc = 1; } if (int_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) { - RTCCNTL.int_ena.rtc_touch_timeout = 0; + RTCCNTL.int_ena_w1tc.rtc_touch_timeout_w1tc = 1; + } + if (int_mask & TOUCH_PAD_INTR_MASK_PROXI_MEAS_DONE) { + RTCCNTL.int_ena_w1tc.rtc_touch_approach_loop_done_w1tc = 1; } } @@ -552,6 +566,9 @@ static inline void touch_ll_intr_clear(touch_pad_intr_mask_t int_mask) if (int_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) { RTCCNTL.int_clr.rtc_touch_timeout = 1; } + if (int_mask & TOUCH_PAD_INTR_MASK_PROXI_MEAS_DONE) { + RTCCNTL.int_clr.rtc_touch_approach_loop_done = 1; + } } /** @@ -579,6 +596,9 @@ static inline uint32_t touch_ll_read_intr_status_mask(void) if (intr_st & RTC_CNTL_TOUCH_TIMEOUT_INT_ST_M) { intr_msk |= TOUCH_PAD_INTR_MASK_TIMEOUT; } + if (intr_st & RTC_CNTL_TOUCH_APPROACH_LOOP_DONE_INT_ST_M) { + intr_msk |= TOUCH_PAD_INTR_MASK_PROXI_MEAS_DONE; + } return (intr_msk & TOUCH_PAD_INTR_MASK_ALL); } @@ -641,7 +661,7 @@ static inline void touch_ll_timeout_get_threshold(uint32_t *threshold) static inline void IRAM_ATTR touch_ll_filter_read_smooth(touch_pad_t touch_num, uint32_t *smooth_data) { SENS.sar_touch_conf.touch_data_sel = TOUCH_LL_READ_SMOOTH; - *smooth_data = SENS.sar_touch_status[touch_num - 1].touch_pad1_data; + *smooth_data = SENS.sar_touch_status[touch_num - 1].touch_pad_data; } /** @@ -654,7 +674,7 @@ static inline void IRAM_ATTR touch_ll_filter_read_smooth(touch_pad_t touch_num, static inline void IRAM_ATTR touch_ll_read_benchmark(touch_pad_t touch_num, uint32_t *benchmark) { SENS.sar_touch_conf.touch_data_sel = TOUCH_LL_READ_BENCHMARK; - *benchmark = SENS.sar_touch_status[touch_num - 1].touch_pad1_data; + *benchmark = SENS.sar_touch_status[touch_num - 1].touch_pad_data; } /** @@ -749,9 +769,9 @@ static inline void touch_ll_filter_get_debounce(uint32_t *dbc_cnt) static inline void touch_ll_filter_set_noise_thres(uint32_t noise_thr) { RTCCNTL.touch_filter_ctrl.touch_noise_thres = noise_thr; - RTCCNTL.touch_filter_ctrl.touch_neg_noise_thres = noise_thr; - RTCCNTL.touch_filter_ctrl.touch_neg_noise_limit = 0xF; - RTCCNTL.touch_filter_ctrl.touch_hysteresis = 2; + RTCCNTL.touch_filter_ctrl.config2 = noise_thr; + RTCCNTL.touch_filter_ctrl.config1 = 0xF; + RTCCNTL.touch_filter_ctrl.config3 = 2; } /** @@ -889,7 +909,7 @@ static inline void touch_ll_denoise_get_grade(touch_pad_denoise_grade_t *grade) */ static inline void touch_ll_denoise_read_data(uint32_t *data) { - *data = SENS.sar_touch_status0.touch_denoise_data; + *data = SENS.sar_touch_denoise.touch_denoise_data; } /************************ Waterproof register setting ************************/ @@ -1014,6 +1034,13 @@ static inline void touch_ll_proximity_get_meas_times(uint32_t *times) */ static inline void touch_ll_proximity_read_meas_cnt(touch_pad_t touch_num, uint32_t *cnt) { + if (SENS.sar_touch_conf.touch_approach_pad0 == touch_num) { + *cnt = SENS.sar_touch_appr_status.touch_approach_pad0_cnt; + } else if (SENS.sar_touch_conf.touch_approach_pad1 == touch_num) { + *cnt = SENS.sar_touch_appr_status.touch_approach_pad1_cnt; + } else if (SENS.sar_touch_conf.touch_approach_pad2 == touch_num) { + *cnt = SENS.sar_touch_appr_status.touch_approach_pad2_cnt; + } } /** @@ -1111,17 +1138,22 @@ static inline bool touch_ll_sleep_get_approach_status(void) */ static inline void touch_ll_sleep_read_benchmark(uint32_t *benchmark) { + SENS.sar_touch_conf.touch_data_sel = TOUCH_LL_READ_BENCHMARK; + *benchmark = SENS.sar_touch_slp_status.touch_slp_data; } static inline void touch_ll_sleep_read_smooth(uint32_t *smooth_data) { + SENS.sar_touch_conf.touch_data_sel = TOUCH_LL_READ_SMOOTH; + *smooth_data = SENS.sar_touch_slp_status.touch_slp_data; } +/* Workaround: Note: sleep pad raw data is not in `sar_touch_slp_status` */ static inline void touch_ll_sleep_read_data(uint32_t *raw_data) { uint32_t touch_num = RTCCNTL.touch_slp_thres.touch_slp_pad; SENS.sar_touch_conf.touch_data_sel = TOUCH_LL_READ_RAW; - *raw_data = SENS.sar_touch_status[touch_num - 1].touch_pad1_data; + *raw_data = SENS.sar_touch_status[touch_num - 1].touch_pad_data; } static inline void touch_ll_sleep_reset_benchmark(void) @@ -1146,6 +1178,7 @@ static inline void touch_ll_sleep_low_power(bool is_low_power) */ static inline void touch_ll_sleep_read_debounce(uint32_t *debounce) { + *debounce = SENS.sar_touch_slp_status.touch_slp_debounce; } /** @@ -1154,6 +1187,7 @@ static inline void touch_ll_sleep_read_debounce(uint32_t *debounce) */ static inline void touch_ll_sleep_read_proximity_cnt(uint32_t *approach_cnt) { + *approach_cnt = SENS.sar_touch_appr_status.touch_slp_approach_cnt; } /** diff --git a/components/hal/esp32s3/touch_sensor_hal.c b/components/hal/esp32s3/touch_sensor_hal.c index f9a43465d8..99d5a3699d 100644 --- a/components/hal/esp32s3/touch_sensor_hal.c +++ b/components/hal/esp32s3/touch_sensor_hal.c @@ -1,4 +1,4 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,6 +14,7 @@ // The HAL layer for Touch Sensor (common part) +#include "soc/soc_pins.h" #include "hal/touch_sensor_hal.h" #include "hal/touch_sensor_types.h" #include "soc/soc_caps.h" diff --git a/components/hal/include/hal/touch_sensor_types.h b/components/hal/include/hal/touch_sensor_types.h index ec027bf870..373d978260 100644 --- a/components/hal/include/hal/touch_sensor_types.h +++ b/components/hal/include/hal/touch_sensor_types.h @@ -155,12 +155,23 @@ typedef enum { TOUCH_PAD_INTR_MASK_INACTIVE = BIT(2), /*! +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "esp_log.h" +#include "driver/touch_pad.h" +#include "soc/rtc_periph.h" +#include "soc/sens_periph.h" +#include "esp_sleep.h" + +static const char *TAG = "Touch pad"; + +static QueueHandle_t que_touch = NULL; +typedef struct touch_msg { + touch_pad_intr_mask_t intr_mask; + uint32_t pad_status_msk; + uint32_t curr_pad; +} touch_event_t; + +#define TOUCH_BUTTON_NUM 4 +#define TOUCH_BUTTON_WATERPROOF_ENABLE 1 +#define TOUCH_BUTTON_DENOISE_ENABLE 1 +#define TOUCH_CHANGE_CONFIG 0 + +static const touch_pad_t button[TOUCH_BUTTON_NUM] = { + TOUCH_PAD_NUM7, // 'SELECT' button. + TOUCH_PAD_NUM9, // 'MENU' button. + TOUCH_PAD_NUM11, // 'BACK' button. + TOUCH_PAD_NUM13, // Guard ring for waterproof design. + // If this pad be touched, other pads no response. +}; + +/* + * Touch threshold. The threshold determines the sensitivity of the touch. + * This threshold is derived by testing changes in readings from different touch channels. + * If (raw_data - benchmark) > benchmark * threshold, the pad be activated. + * If (raw_data - benchmark) < benchmark * threshold, the pad be inactivated. + */ +static const float button_threshold[TOUCH_BUTTON_NUM] = { + 0.2, // 20%. + 0.2, // 20%. + 0.2, // 20%. + 0.1, // 10%. +}; + +/* + Handle an interrupt triggered when a pad is touched. + Recognize what pad has been touched and save it in a table. + */ +static void touchsensor_interrupt_cb(void *arg) +{ + int task_awoken = pdFALSE; + touch_event_t evt; + + evt.intr_mask = touch_pad_read_intr_status_mask(); + evt.pad_status_msk = touch_pad_get_status(); + /* Note: Obtaining channel information in the interrupt callback function as the channel that triggers the interrupt is risky. + If the execution of the interrupt callback function is delayed by a channel measurement time, + the channel information obtained is wrong. Both light sleep and SPI FLASH reading and + writing may delay the response of the interrupt function. */ + evt.curr_pad = touch_pad_get_current_meas_channel(); + + xQueueSendFromISR(que_touch, &evt, &task_awoken); + if (task_awoken == pdTRUE) { + portYIELD_FROM_ISR(); + } +} + +static void tp_example_set_thresholds(void) +{ + uint32_t touch_value; + for (int i = 0; i < TOUCH_BUTTON_NUM; i++) { + //read benchmark value + touch_pad_read_benchmark(button[i], &touch_value); + //set interrupt threshold. + touch_pad_set_thresh(button[i], touch_value * button_threshold[i]); + ESP_LOGI(TAG, "touch pad [%d] base %d, thresh %d", \ + button[i], touch_value, (uint32_t)(touch_value * button_threshold[i])); + } +} + +static void touchsensor_filter_set(touch_filter_mode_t mode) +{ + /* Filter function */ + touch_filter_config_t filter_info = { + .mode = mode, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .noise_thr = 0, // 50% + .jitter_step = 4, // use for jitter mode. + .smh_lvl = TOUCH_PAD_SMOOTH_IIR_2, + }; + touch_pad_filter_set_config(&filter_info); + touch_pad_filter_enable(); + ESP_LOGI(TAG, "touch pad filter init"); +} + +static void tp_example_read_task(void *pvParameter) +{ + uint8_t pad_num = 0; + uint32_t touch_trig_diff = 0; + touch_event_t evt = {0}; + static uint8_t guard_mode_flag = 0; + /* Wait touch sensor init done */ + vTaskDelay(50 / portTICK_RATE_MS); + uint32_t last_pad_status_msk = touch_pad_get_status(); + tp_example_set_thresholds(); + + while (1) { + int ret = xQueueReceive(que_touch, &evt, (portTickType)portMAX_DELAY); + if (ret != pdTRUE) { + continue; + } + if (evt.intr_mask & (TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE)) { + if (last_pad_status_msk == evt.pad_status_msk) { + ESP_LOGW(TAG, "TouchSensor status no changes, pad mask 0x%x", evt.pad_status_msk); + continue; + } + pad_num = 0; + touch_trig_diff = evt.pad_status_msk ^ last_pad_status_msk; // Record changes in channel status. Each bit represents a channel + last_pad_status_msk = evt.pad_status_msk; // Update the pad active status + + /* Traverse all channels and find out the channel where the state changes, and determine the state type */ + while (touch_trig_diff) { + if (touch_trig_diff & BIT(pad_num)) { + if (evt.pad_status_msk & BIT(pad_num)) { // Touch channel active + /* if guard pad be touched, other pads no response. */ + if (pad_num == button[3]) { + guard_mode_flag = 1; + ESP_LOGW(TAG, "TouchSensor [%d] be activated, enter guard mode", pad_num); + } else { + if (guard_mode_flag == 0) { + ESP_LOGI(TAG, "TouchSensor [%d] be activated, status mask 0x%x", pad_num, evt.pad_status_msk); + } else { + ESP_LOGW(TAG, "In guard mode. No response"); + } + } + } else { // Touch channel inactive + /* if guard pad be touched, other pads no response. */ + if (pad_num == button[3]) { + guard_mode_flag = 0; + ESP_LOGW(TAG, "TouchSensor [%d] be inactivated, exit guard mode", pad_num); + } else { + if (guard_mode_flag == 0) { + ESP_LOGI(TAG, "TouchSensor [%d] be inactivated, status mask 0x%x", pad_num, evt.pad_status_msk); + } + } + } + touch_trig_diff &= (~(BIT(pad_num))); // Clear the channels that have been checked + } + pad_num ++; + } + } + + if (evt.intr_mask & TOUCH_PAD_INTR_MASK_SCAN_DONE) { + ESP_LOGI(TAG, "The touch sensor group measurement is done [%d].", evt.curr_pad); + } + if (evt.intr_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) { + /* Add your exception handling in here. */ + ESP_LOGI(TAG, "Touch sensor channel %d measure timeout. Skip this exception channel!!", evt.curr_pad); + touch_pad_timeout_resume(); // Point on the next channel to measure. + } + } +} + +void app_main(void) +{ + if (que_touch == NULL) { + que_touch = xQueueCreate(TOUCH_BUTTON_NUM, sizeof(touch_event_t)); + } + // Initialize touch pad peripheral, it will start a timer to run a filter + ESP_LOGI(TAG, "Initializing touch pad"); + /* Initialize touch pad peripheral. */ + touch_pad_init(); + for (int i = 0; i < TOUCH_BUTTON_NUM; i++) { + touch_pad_config(button[i]); + } + +#if TOUCH_CHANGE_CONFIG + /* If you want change the touch sensor default setting, please write here(after initialize). There are examples: */ + touch_pad_set_meas_time(TOUCH_PAD_SLEEP_CYCLE_DEFAULT, TOUCH_PAD_MEASURE_CYCLE_DEFAULT); + touch_pad_set_voltage(TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD); + touch_pad_set_idle_channel_connect(TOUCH_PAD_IDLE_CH_CONNECT_DEFAULT); + for (int i = 0; i < TOUCH_BUTTON_NUM; i++) { + touch_pad_set_cnt_mode(i, TOUCH_PAD_SLOPE_DEFAULT, TOUCH_PAD_TIE_OPT_DEFAULT); + } +#endif + +#if TOUCH_BUTTON_DENOISE_ENABLE + /* Denoise setting at TouchSensor 0. */ + touch_pad_denoise_t denoise = { + /* The bits to be cancelled are determined according to the noise level. */ + .grade = TOUCH_PAD_DENOISE_BIT4, + /* By adjusting the parameters, the reading of T0 should be approximated to the reading of the measured channel. */ + .cap_level = TOUCH_PAD_DENOISE_CAP_L4, + }; + touch_pad_denoise_set_config(&denoise); + touch_pad_denoise_enable(); + ESP_LOGI(TAG, "Denoise function init"); +#endif + +#if TOUCH_BUTTON_WATERPROOF_ENABLE + /* Waterproof function */ + touch_pad_waterproof_t waterproof = { + .guard_ring_pad = button[3], // If no ring pad, set 0; + /* It depends on the number of the parasitic capacitance of the shield pad. + Based on the touch readings of T14 and T0, estimate the size of the parasitic capacitance on T14 + and set the parameters of the appropriate hardware. */ + .shield_driver = TOUCH_PAD_SHIELD_DRV_L2, + }; + touch_pad_waterproof_set_config(&waterproof); + touch_pad_waterproof_enable(); + ESP_LOGI(TAG, "touch pad waterproof init"); +#endif + + /* Filter setting */ + touchsensor_filter_set(TOUCH_PAD_FILTER_IIR_16); + touch_pad_timeout_set(true, SOC_TOUCH_PAD_THRESHOLD_MAX); + /* Register touch interrupt ISR, enable intr type. */ + touch_pad_isr_register(touchsensor_interrupt_cb, NULL, TOUCH_PAD_INTR_MASK_ALL); + /* If you have other touch algorithm, you can get the measured value after the `TOUCH_PAD_INTR_MASK_SCAN_DONE` interrupt is generated. */ + touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE | TOUCH_PAD_INTR_MASK_TIMEOUT); + + /* In ESP32-S3 If the touch wakeup not enable, the touch action of the touch sensor during light sleep may be lost. */ + esp_sleep_enable_touchpad_wakeup(); + + /* Enable touch sensor clock. Work mode is "timer trigger". */ + touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); + touch_pad_fsm_start(); + + // Start a task to show what pads have been touched + xTaskCreate(&tp_example_read_task, "touch_pad_read_task", 2048, NULL, 5, NULL); +} diff --git a/examples/peripherals/touch_pad_read/main/esp32s3/tp_read_main.c b/examples/peripherals/touch_pad_read/main/esp32s3/tp_read_main.c new file mode 100644 index 0000000000..b6c0472ce5 --- /dev/null +++ b/examples/peripherals/touch_pad_read/main/esp32s3/tp_read_main.c @@ -0,0 +1,90 @@ +/* Touch Pad Read Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/touch_pad.h" +#include "esp_log.h" + +#define TOUCH_BUTTON_NUM 14 +#define TOUCH_CHANGE_CONFIG 0 + +static const char *TAG = "touch read"; +static const touch_pad_t button[TOUCH_BUTTON_NUM] = { + TOUCH_PAD_NUM1, + TOUCH_PAD_NUM2, + TOUCH_PAD_NUM3, + TOUCH_PAD_NUM4, + TOUCH_PAD_NUM5, + TOUCH_PAD_NUM6, + TOUCH_PAD_NUM7, + TOUCH_PAD_NUM8, + TOUCH_PAD_NUM9, + TOUCH_PAD_NUM10, + TOUCH_PAD_NUM11, + TOUCH_PAD_NUM12, + TOUCH_PAD_NUM13, + TOUCH_PAD_NUM14 +}; + +/* + Read values sensed at all available touch pads. + Print out values in a loop on a serial monitor. + */ +static void tp_example_read_task(void *pvParameter) +{ + uint32_t touch_value; + + /* Wait touch sensor init done */ + vTaskDelay(100 / portTICK_RATE_MS); + printf("Touch Sensor read, the output format is: \nTouchpad num:[raw data]\n\n"); + + while (1) { + for (int i = 0; i < TOUCH_BUTTON_NUM; i++) { + touch_pad_read_raw_data(button[i], &touch_value); // read raw data. + printf("T%d: [%4d] ", button[i], touch_value); + } + printf("\n"); + vTaskDelay(200 / portTICK_PERIOD_MS); + } +} + +void app_main(void) +{ + /* Initialize touch pad peripheral. */ + touch_pad_init(); + for (int i = 0; i < TOUCH_BUTTON_NUM; i++) { + touch_pad_config(button[i]); + } +#if TOUCH_CHANGE_CONFIG + /* If you want change the touch sensor default setting, please write here(after initialize). There are examples: */ + touch_pad_set_meas_time(TOUCH_PAD_SLEEP_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT); + touch_pad_set_voltage(TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD); + touch_pad_set_idle_channel_connect(TOUCH_PAD_IDLE_CH_CONNECT_DEFAULT); + for (int i = 0; i < TOUCH_BUTTON_NUM; i++) { + touch_pad_set_cnt_mode(i, TOUCH_PAD_SLOPE_DEFAULT, TOUCH_PAD_TIE_OPT_DEFAULT); + } +#endif + /* Denoise setting at TouchSensor 0. */ + touch_pad_denoise_t denoise = { + /* The bits to be cancelled are determined according to the noise level. */ + .grade = TOUCH_PAD_DENOISE_BIT4, + .cap_level = TOUCH_PAD_DENOISE_CAP_L4, + }; + touch_pad_denoise_set_config(&denoise); + touch_pad_denoise_enable(); + ESP_LOGI(TAG, "Denoise function init"); + + /* Enable touch sensor clock. Work mode is "timer trigger". */ + touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); + touch_pad_fsm_start(); + + /* Start task to read values by pads. */ + xTaskCreate(&tp_example_read_task, "touch_pad_read_task", 2048, NULL, 5, NULL); +} diff --git a/examples/system/deep_sleep/main/deep_sleep_example_main.c b/examples/system/deep_sleep/main/deep_sleep_example_main.c index a53a8f939e..1b09748ae6 100644 --- a/examples/system/deep_sleep/main/deep_sleep_example_main.c +++ b/examples/system/deep_sleep/main/deep_sleep_example_main.c @@ -211,7 +211,7 @@ void app_main(void) touch_pad_config(TOUCH_PAD_NUM9, TOUCH_THRESH_NO_USE); calibrate_touch_pad(TOUCH_PAD_NUM8); calibrate_touch_pad(TOUCH_PAD_NUM9); -#elif CONFIG_IDF_TARGET_ESP32S2 +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 /* Initialize touch pad peripheral. */ touch_pad_init(); /* Only support one touch channel in sleep mode. */