From b9d3b161e490f7046094fa37d1e9c1f0c682fe79 Mon Sep 17 00:00:00 2001 From: Hu Rui Date: Tue, 7 Apr 2026 17:36:08 +0800 Subject: [PATCH] feat(touch_sens): support touch sensor on esp32s31 --- .../hw_ver1/touch_version_specific.c | 2 + .../hw_ver2/touch_version_specific.c | 2 + .../hw_ver3/touch_version_specific.c | 2 + .../test_apps/touch_sens/README.md | 4 +- .../main/test_touch_sens_common.cpp | 17 +- .../include/hal/touch_sensor_channel.h | 51 + .../esp32s31/include/hal/touch_sensor_ll.h | 1054 +++++++++++++++++ .../esp32s31/touch_sensor_periph.c | 25 + .../esp32s31/include/soc/Kconfig.soc_caps.in | 40 + .../soc/esp32s31/include/soc/soc_caps.h | 16 +- .../esp32s31/register/soc/touch_aon_struct.h | 776 +----------- .../soc/esp32s31/register/soc/touch_struct.h | 381 +----- docs/doxygen/Doxyfile_esp32s31 | 3 + .../peripherals/cap_touch_sens.rst | 3 +- .../peripherals/cap_touch_sens/esp32s31.inc | 61 + .../peripherals/cap_touch_sens.rst | 3 +- .../peripherals/cap_touch_sens/esp32s31.inc | 61 + examples/peripherals/.build-test-rules.yml | 2 +- examples/peripherals/touch_sensor/README.md | 2 +- .../touch_sensor/touch_sens_basic/README.md | 4 +- .../pytest_touch_sens_basic.py | 2 +- .../pytest_touch_sens_sleep.py | 8 +- 22 files changed, 1401 insertions(+), 1118 deletions(-) create mode 100644 components/esp_hal_touch_sens/esp32s31/include/hal/touch_sensor_channel.h create mode 100644 components/esp_hal_touch_sens/esp32s31/include/hal/touch_sensor_ll.h create mode 100644 components/esp_hal_touch_sens/esp32s31/touch_sensor_periph.c create mode 100644 docs/en/api-reference/peripherals/cap_touch_sens/esp32s31.inc create mode 100644 docs/zh_CN/api-reference/peripherals/cap_touch_sens/esp32s31.inc 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 index 98660e8aa2..45f56e60aa 100644 --- a/components/esp_driver_touch_sens/hw_ver1/touch_version_specific.c +++ b/components/esp_driver_touch_sens/hw_ver1/touch_version_specific.c @@ -237,9 +237,11 @@ esp_err_t touch_priv_deinit_controller(touch_sensor_handle_t sens_handle) { touch_ll_reset_trigger_groups(); /* Disable the additional functions */ +#if SOC_TOUCH_SUPPORT_SLEEP_WAKEUP if (sens_handle->sleep_en) { touch_sensor_config_sleep_wakeup(sens_handle, NULL); } +#endif return ESP_OK; } 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 8b9e2a8168..d7ee375600 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 @@ -223,9 +223,11 @@ esp_err_t touch_priv_deinit_controller(touch_sensor_handle_t sens_handle) if (sens_handle->proximity_en) { touch_sensor_config_proximity_sensing(sens_handle, NULL); } +#if SOC_TOUCH_SUPPORT_SLEEP_WAKEUP if (sens_handle->sleep_en) { touch_sensor_config_sleep_wakeup(sens_handle, NULL); } +#endif if (sens_handle->waterproof_en) { touch_sensor_config_waterproof(sens_handle, NULL); } 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 b7b7bcea0d..cb1b465a09 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 @@ -238,9 +238,11 @@ esp_err_t touch_priv_deinit_controller(touch_sensor_handle_t sens_handle) if (sens_handle->proximity_en) { touch_sensor_config_proximity_sensing(sens_handle, NULL); } +#if SOC_TOUCH_SUPPORT_SLEEP_WAKEUP if (sens_handle->sleep_en) { touch_sensor_config_sleep_wakeup(sens_handle, NULL); } +#endif if (sens_handle->waterproof_en) { touch_sensor_config_waterproof(sens_handle, NULL); } diff --git a/components/esp_driver_touch_sens/test_apps/touch_sens/README.md b/components/esp_driver_touch_sens/test_apps/touch_sens/README.md index 7824d26684..0b55d00c39 100644 --- a/components/esp_driver_touch_sens/test_apps/touch_sens/README.md +++ b/components/esp_driver_touch_sens/test_apps/touch_sens/README.md @@ -1,3 +1,3 @@ -| Supported Targets | ESP32 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | diff --git a/components/esp_driver_touch_sens/test_apps/touch_sens/main/test_touch_sens_common.cpp b/components/esp_driver_touch_sens/test_apps/touch_sens/main/test_touch_sens_common.cpp index b71964769b..3c8216181d 100644 --- a/components/esp_driver_touch_sens/test_apps/touch_sens/main/test_touch_sens_common.cpp +++ b/components/esp_driver_touch_sens/test_apps/touch_sens/main/test_touch_sens_common.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -151,7 +151,16 @@ static bool TEST_TCH_IRAM_ATTR s_test_touch_on_inactive_callback(touch_sensor_ha static void s_test_touch_simulate_touch(touch_sensor_handle_t touch, touch_channel_handle_t touch_chan, bool active) { -#if SOC_TOUCH_SENSOR_VERSION <= 2 +#if CONFIG_IDF_TARGET_ESP32S31 + /* ESP32-S31 has no internal capacitor, emulate touch by changing charging cycles. */ + for (int i = 0; i < TOUCH_SAMPLE_CFG_NUM; i++) { + uint32_t charge_times = s_sample_cfg[i].charge_times; + if (active) { + charge_times += charge_times >> 1; // 1.5x + } + touch_ll_set_charge_times(i, charge_times); + } +#elif SOC_TOUCH_SENSOR_VERSION <= 2 touch_chan_info_t chan_info = {}; touch_sensor_get_channel_info(touch_chan, &chan_info); touch_ll_set_charge_speed(chan_info.chan_id, active ? TOUCH_CHARGE_SPEED_4 : TOUCH_CHARGE_SPEED_7); @@ -186,10 +195,10 @@ TEST_CASE("touch_sens_active_inactive_test", "[touch]") touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG(); TEST_ESP_OK(touch_sensor_config_filter(touch, &filter_cfg)); TEST_ESP_OK(touch_sensor_new_channel(touch, TOUCH_MIN_CHAN_ID, &s_chan_cfg, &touch_chan)); -#if SOC_TOUCH_SENSOR_VERSION == 3 +#if SOC_TOUCH_SENSOR_VERSION == 3 && !CONFIG_IDF_TARGET_ESP32S31 /* Connect the touch channels to the internal capacitor */ touch_ll_enable_internal_capacitor(true); -#endif // SOC_TOUCH_SENSOR_VERSION == 3 +#endif s_test_touch_do_initial_scanning(touch, 3); diff --git a/components/esp_hal_touch_sens/esp32s31/include/hal/touch_sensor_channel.h b/components/esp_hal_touch_sens/esp32s31/include/hal/touch_sensor_channel.h new file mode 100644 index 0000000000..5a3bbc6742 --- /dev/null +++ b/components/esp_hal_touch_sens/esp32s31/include/hal/touch_sensor_channel.h @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +// Touch channels + +#define TOUCH_PAD_GPIO6_CHANNEL 0 +#define TOUCH_PAD_NUM0_GPIO_NUM 6 + +#define TOUCH_PAD_GPIO7_CHANNEL 1 +#define TOUCH_PAD_NUM1_GPIO_NUM 7 + +#define TOUCH_PAD_GPIO8_CHANNEL 2 +#define TOUCH_PAD_NUM2_GPIO_NUM 8 + +#define TOUCH_PAD_GPIO9_CHANNEL 3 +#define TOUCH_PAD_NUM3_GPIO_NUM 9 + +#define TOUCH_PAD_GPIO10_CHANNEL 4 +#define TOUCH_PAD_NUM4_GPIO_NUM 10 + +#define TOUCH_PAD_GPIO11_CHANNEL 5 +#define TOUCH_PAD_NUM5_GPIO_NUM 11 + +#define TOUCH_PAD_GPIO12_CHANNEL 6 +#define TOUCH_PAD_NUM6_GPIO_NUM 12 + +#define TOUCH_PAD_GPIO13_CHANNEL 7 +#define TOUCH_PAD_NUM7_GPIO_NUM 13 + +#define TOUCH_PAD_GPIO14_CHANNEL 8 +#define TOUCH_PAD_NUM8_GPIO_NUM 14 + +#define TOUCH_PAD_GPIO15_CHANNEL 9 +#define TOUCH_PAD_NUM9_GPIO_NUM 15 + +#define TOUCH_PAD_GPIO16_CHANNEL 10 +#define TOUCH_PAD_NUM10_GPIO_NUM 16 + +#define TOUCH_PAD_GPIO17_CHANNEL 11 +#define TOUCH_PAD_NUM11_GPIO_NUM 17 + +#define TOUCH_PAD_GPIO18_CHANNEL 12 +#define TOUCH_PAD_NUM12_GPIO_NUM 18 + +#define TOUCH_PAD_GPIO19_CHANNEL 13 +#define TOUCH_PAD_NUM13_GPIO_NUM 19 diff --git a/components/esp_hal_touch_sens/esp32s31/include/hal/touch_sensor_ll.h b/components/esp_hal_touch_sens/esp32s31/include/hal/touch_sensor_ll.h new file mode 100644 index 0000000000..dcdd0062c4 --- /dev/null +++ b/components/esp_hal_touch_sens/esp32s31/include/hal/touch_sensor_ll.h @@ -0,0 +1,1054 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The ll is not public api, don't use in application code. + * See readme.md in hal/include/hal/readme.md + ******************************************************************************/ + +#pragma once + +#include +#include +#include "hal/misc.h" +#include "hal/assert.h" +#include "hal/touch_sensor_periph.h" +#include "hal/touch_sens_types.h" +#include "hal/config.h" +#include "soc/lp_analog_peri_struct.h" +#include "soc/lp_peri_clkrst_struct.h" +#include "soc/touch_aon_struct.h" +#include "soc/touch_struct.h" +#include "soc/pmu_struct.h" +#include "soc/soc_caps.h" +#include "esp_rom_sys.h" + +#define TOUCH_LL_GET(_attr) TOUCH_LL_ ## _attr +#define TOUCH_LL_CHAN_NUM 14 + +#ifdef __cplusplus +extern "C" { +#endif + +#define TOUCH_LL_READ_BENCHMARK 0x2 +#define TOUCH_LL_READ_SMOOTH 0x3 + +#define TOUCH_LL_TIMER_FORCE_DONE_BY_SW 0x1 +#define TOUCH_LL_TIMER_DONE_BY_FSM 0x0 + +// Interrupt mask +#define TOUCH_LL_INTR_MASK_SCAN_DONE BIT(0) +#define TOUCH_LL_INTR_MASK_DONE BIT(1) +#define TOUCH_LL_INTR_MASK_ACTIVE BIT(2) +#define TOUCH_LL_INTR_MASK_INACTIVE BIT(3) +#define TOUCH_LL_INTR_MASK_TIMEOUT BIT(4) +#define TOUCH_LL_INTR_MASK_PROX_DONE BIT(5) +// #define TOUCH_LL_INTR_MASK_BENCHMARK_UPDATE BIT(6) +#define TOUCH_LL_INTR_MASK_ALL (0x3F) + +#define TOUCH_LL_FULL_CHANNEL_MASK ((uint16_t)((1U << (TOUCH_LL_GET(CHAN_NUM))) - 1) << SOC_TOUCH_MIN_CHAN_ID) +#define TOUCH_LL_NULL_CHANNEL (15) // Null Channel id. Used for disabling some functions like sleep/proximity/waterproof + +#define TOUCH_LL_PAD_MEASURE_WAIT_MAX (0x7FFF) // The timer frequency is 8Mhz, the max value is 0xff +#define TOUCH_LL_ACTIVE_THRESH_MAX (0xFFFF) // Max channel active threshold +#define TOUCH_LL_CLK_DIV_MAX (0x08) // Max clock divider value +#define TOUCH_LL_TIMEOUT_MAX (0xFFFF) // Max timeout value +#define TOUCH_LL_SLP_MEASURE_WAIT_MAX (0x1FF) // Max wait ticks to wait PMU entering HP SLEEP status during the sleep. + +#define TOUCH_LL_SUPPORT_PROX_DONE (1) + +#define TOUCH_LL_INTR_SOURCE ETS_LP_TOUCH_INTR_SOURCE // Touch sensor interrupt source, defined in ll for the driver compatibility + +/** + * Enable/disable clock gate of touch sensor. + * + * @param enable true/false. + */ +static inline void touch_ll_enable_module_clock(bool enable) +{ + LP_PERI_CLKRST.touch_ctrl.lp_touch_clk_en = enable; +} + +/** + * Enable/disable clock gate of touch sensor. + * + * @param enable true/false. + */ +static inline void touch_ll_reset_module(void) +{ + LP_PERI_CLKRST.touch_ctrl.lp_touch_rst_en = 1; + LP_PERI_CLKRST.touch_ctrl.lp_touch_rst_en = 0; +} + +/** + * Set the power on wait cycle + * + * @param wait_cycles + */ +static inline void touch_ll_set_power_on_wait_cycle(uint32_t wait_cycles) +{ + TOUCH_AON.scan_ctrl1.touch_xpd_wait = wait_cycles; +} + +/** + * Set touch sensor touch sensor charge and discharge times of every measurement on a pad. + * + * @param sample_cfg_id The sample configuration index + * @param charge_times The times of charge and discharge in each measure process of touch channels. + * The timer frequency is RTC_FAST (about 16M). Range: 0 ~ 0xffff. + */ +static inline void touch_ll_set_charge_times(uint8_t sample_cfg_id, uint16_t charge_times) +{ + //The times of charge and discharge in each measure process of touch channels. + switch (sample_cfg_id) { + case 0: + TOUCH_AON.work_meas_num.touch_meas_num0 = charge_times; + break; + case 1: + TOUCH_AON.work_meas_num.touch_meas_num1 = charge_times; + break; + case 2: + TOUCH_AON.work_meas_num.touch_meas_num2 = charge_times; + break; + default: + abort(); + } +} + +/** + * Get touch sensor times of charge and discharge. + * + * @param meas_times Pointer to accept times count of charge and discharge. + */ +static inline void touch_ll_get_charge_times(uint8_t sample_cfg_id, uint16_t *charge_times) +{ + switch (sample_cfg_id) { + case 0: + *charge_times = TOUCH_AON.work_meas_num.touch_meas_num0; + break; + case 1: + *charge_times = TOUCH_AON.work_meas_num.touch_meas_num1; + break; + case 2: + *charge_times = TOUCH_AON.work_meas_num.touch_meas_num2; + break; + default: + abort(); + } +} + +/** + * 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 = interval_ticks / RTC_SLOW_CLK + HAL_FORCE_MODIFY_U32_REG_FIELD(PMU.touch_pwr_ctrl, touch_sleep_cycles, interval_ticks); +} + +/** + * Get touch sensor sleep time. + * + * @param interval_ticks Pointer to accept measurement interval (sleep) cycle number. + */ +static inline void touch_ll_get_measure_interval_ticks(uint16_t *interval_ticks) +{ + *interval_ticks = HAL_FORCE_READ_U32_REG_FIELD(PMU.touch_pwr_ctrl, touch_sleep_cycles); +} + +/** + * 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) +{ + // FSM controlled by timer or software + TOUCH_AON.mux0.touch_fsm_en = enable; + // Set 0 to stop by timer, otherwise by software + TOUCH_AON.mux0.touch_done_force = !enable; + // Set 0 to start by timer, otherwise by software + TOUCH_AON.mux0.touch_start_force = !enable; +} + +/** + * Is touch sensor FSM using hardware timer to trigger scanning. + * The measurement action can be triggered by the hardware timer, as well as by the software instruction. + * + * @return Whether FSM timer enabled. + */ +static inline bool touch_ll_is_fsm_using_timer(void) +{ + return !TOUCH_AON.mux0.touch_start_force; +} + +/** + * Touch timer trigger measurement and always wait measurement done. + * Force done for touch timer ensures that the timer always can get the measurement done signal. + * @note The `force done` signal should last as least one slow clock tick + */ +__attribute__((always_inline)) +static inline void touch_ll_force_done_curr_measurement(void) +{ + // Set `force done` signal + PMU.touch_pwr_ctrl.touch_force_done = 1; + // Force done signal should last at least one slow clock tick + esp_rom_delay_us(3); + // Clear `force done` signal + PMU.touch_pwr_ctrl.touch_force_done = 0; +} + +/** + * 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) +{ + /** + * Touch timer trigger measurement and always wait measurement done. + * Force done for touch timer ensures that the timer always can get the measurement done signal. + */ + touch_ll_force_done_curr_measurement(); + PMU.touch_pwr_ctrl.touch_sleep_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) +{ + PMU.touch_pwr_ctrl.touch_sleep_timer_en = 0; + touch_ll_force_done_curr_measurement(); +} + +/** + * Is the FSM repeated timer enabled. + * @note when the timer is enabled, RTC clock should not be power down + * + * @return + * - true: enabled + * - true: disabled + */ +__attribute__((always_inline)) +static inline bool touch_ll_is_fsm_repeated_timer_enabled(void) +{ + return (bool)(PMU.touch_pwr_ctrl.touch_sleep_timer_en); +} + +/** + * Enable the touch sensor FSM start signal from software + */ +__attribute__((always_inline)) +static inline void touch_ll_trigger_oneshot_measurement(void) +{ + /* Trigger once measurement */ + TOUCH_AON.mux0.touch_start_en = 1; + TOUCH_AON.mux0.touch_start_en = 0; +} + +static inline void touch_ll_measure_channel_once(uint16_t chan_mask) +{ + TOUCH_AON.mux1.touch_start = chan_mask; +} + +/** + * Set 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 + * @param thresh The threshold of charge cycles + */ +static inline void touch_ll_set_chan_active_threshold(uint32_t touch_num, uint8_t sample_cfg_id, uint32_t thresh) +{ + HAL_ASSERT(sample_cfg_id < SOC_TOUCH_SAMPLE_CFG_NUM); + HAL_FORCE_MODIFY_U32_REG_FIELD(TOUCH_AON.padx_thn[touch_num].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); + return HAL_FORCE_READ_U32_REG_FIELD(TOUCH_AON.padx_thn[touch_num].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 + * + * @param chan_mask The channel mask to be enabled or disabled + * @param enable Enable or disable the channel mask + */ +__attribute__((always_inline)) +static inline void touch_ll_enable_scan_mask(uint16_t chan_mask, bool enable) +{ + uint16_t mask = chan_mask & TOUCH_LL_FULL_CHANNEL_MASK; + uint16_t prev_mask = TOUCH_AON.scan_ctrl1.touch_scan_pad_map; + if (enable) { + TOUCH_AON.scan_ctrl1.touch_scan_pad_map = prev_mask | mask; + } else { + TOUCH_AON.scan_ctrl1.touch_scan_pad_map = prev_mask & (~mask); + } +} + +/** + * 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) + */ +static inline void touch_ll_enable_channel_mask(uint16_t enable_mask) +{ + uint16_t mask = enable_mask & TOUCH_LL_FULL_CHANNEL_MASK; + TOUCH_AON.scan_ctrl1.touch_scan_pad_map = mask; + TOUCH_AON.filter2.touch_outen = mask; +} + +/** + * @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) +{ + TOUCH_AON.mux1.touch_xpd = chan_mask; + TOUCH_AON.mux1.touch_start = chan_mask; +} + +/** + * @brief Power off the channel by mask + * + * @param chan_mask The channel mask that needs to power off + */ +static inline void touch_ll_channel_power_off(uint16_t chan_mask) +{ + uint32_t curr_mask = TOUCH_AON.mux1.touch_xpd; + TOUCH_AON.mux1.touch_xpd = (~chan_mask) & curr_mask; +} + +/** + * Get the touch sensor active channel mask, usually used in ISR to decide which channels are 'touched'. + * + * @param active_mask The touch channel status. e.g. Touch1 trigger status is `status_mask & (BIT1)`. + */ +__attribute__((always_inline)) +static inline void touch_ll_get_active_channel_mask(uint32_t *active_mask) +{ + *active_mask = TOUCH_SENS.chn_status.pad_active; +} + +/** + * Clear all touch sensor channels active status. + * + * @note Generally no manual removal is required. + */ +static inline void touch_ll_clear_active_channel_status(void) +{ + TOUCH_AON.clr.touch_status_clr = 1; +} + +/** + * Get the data of the touch channel according to the types + * + * @param touch_num touch pad index + * @param sample_cfg_id The sample configuration index + * @param type data type + * 0/1: not work + * 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 sample_cfg_id, uint8_t type, uint32_t *data) +{ + HAL_ASSERT(sample_cfg_id < SOC_TOUCH_SAMPLE_CFG_NUM); + HAL_ASSERT(type == TOUCH_LL_READ_BENCHMARK || type == TOUCH_LL_READ_SMOOTH); + TOUCH_AON.mux0.touch_freq_sel = sample_cfg_id; + TOUCH_AON.mux0.touch_data_sel = type; + *data = HAL_FORCE_READ_U32_REG_FIELD(TOUCH_SENS.chn_data[touch_num], pad_data); +} + +/** + * 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)TOUCH_SENS.chn_status.meas_done; +} + +/** + * Select the counting mode of the binarized touch out wave + * + * @param mode 0: 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 + * 1: as clock, the value is accurate but less sensitive when the frequency of touch_out is close to the source clock + * No big difference when the frequency of touch_out is far more lower than the source clock + */ +static inline void touch_ll_set_out_mode(touch_out_mode_t mode) +{ + TOUCH_AON.work.touch_out_sel = mode; +} + +/** + * @brief Enable/disable the touch sensor output gate + * + * @param enable set true to enable the output gate, false to disable it + */ +static inline void touch_ll_enable_out_gate(bool enable) +{ + TOUCH_AON.work.touch_out_gate = enable; +} + +/** + * @brief Set the clock division of the sampling frequency + * + * @param sample_cfg_id The sample configuration index + * @param div_num Division number + */ +static inline void touch_ll_set_clock_div(uint8_t sample_cfg_id, uint32_t div_num) +{ + switch (sample_cfg_id) { + case 0: + TOUCH_AON.work.div_num0 = div_num - 1; + break; + case 1: + TOUCH_AON.work.div_num1 = div_num - 1; + break; + case 2: + TOUCH_AON.work.div_num2 = div_num - 1; + break; + default: + // invalid sample_cfg_id + abort(); + } +} + +/** + * Set connection type of touch channel in idle status. + * When a channel is in measurement mode, other initialized channels are in idle mode. + * The touch channel is generally adjacent to the trace, so the connection state of the idle channel + * affects the stability and sensitivity of the test channel. + * The `CONN_HIGHZ`(high resistance) setting increases the sensitivity of touch channels. + * The `CONN_GND`(grounding) setting increases the stability of touch channels. + * @note This option does not take effect, it is default to HIGH Z + * Only remained here to be compatible to other version + * + * @param type Select idle channel connect to high resistance state or ground. (No effect) + */ +static inline void touch_ll_set_idle_channel_connect(touch_idle_conn_t type) +{ + (void)type; +} + +/** + * Get the current channel that under measuring. + * + * @return + * - touch channel number + */ +__attribute__((always_inline)) +static inline uint32_t touch_ll_get_current_meas_channel(void) +{ + return TOUCH_SENS.chn_status.scan_curr; +} + +/** + * Enable touch sensor interrupt by bitmask. + * + * @param int_mask interrupt mask + */ +static inline void touch_ll_interrupt_enable(uint32_t int_mask) +{ + uint32_t mask = TOUCH_SENS.int_ena.val; + mask |= (int_mask & TOUCH_LL_INTR_MASK_ALL); + TOUCH_SENS.int_ena.val = mask; +} + +/** + * Disable touch sensor interrupt by bitmask. + * + * @param int_mask interrupt mask + */ +static inline void touch_ll_interrupt_disable(uint32_t int_mask) +{ + uint32_t mask = TOUCH_SENS.int_ena.val; + mask &= ~(int_mask & TOUCH_LL_INTR_MASK_ALL); + TOUCH_SENS.int_ena.val = mask; +} + +/** + * Clear touch sensor interrupt by bitmask. + * + * @param int_mask Pad mask to clear interrupts + */ +__attribute__((always_inline)) +static inline void touch_ll_interrupt_clear(uint32_t int_mask) +{ + TOUCH_SENS.int_clr.val = int_mask; +} + +/** + * Get the bitmask of touch sensor interrupt status. + * + * @return type interrupt type + */ +__attribute__((always_inline)) +static inline uint32_t touch_ll_get_intr_status_mask(void) +{ + uint32_t intr_st = TOUCH_SENS.int_st.val; + return (intr_st & TOUCH_LL_INTR_MASK_ALL); +} + +/** + * Set the timeout to enable or disable the check for all touch sensor channels measurements. + * When the touch reading of a touch channel exceeds the measurement threshold, + * If enable: a timeout interrupt will be generated and it will go to the next channel measurement. + * If disable: the FSM is always on the channel, until the measurement of this channel is over. + * + * @param timeout_cycles The maximum time cycles of the measurement on one channel. + * Set to 0 to disable the timeout. + * Set to non-zero to enable the timeout and set the timeout cycles. + */ +static inline void touch_ll_set_timeout(uint32_t timeout_cycles) +{ + if (timeout_cycles) { + HAL_FORCE_MODIFY_U32_REG_FIELD(TOUCH_AON.scan_ctrl2, touch_timeout_num, timeout_cycles); + TOUCH_AON.scan_ctrl2.touch_timeout_en = 1; + } else { + TOUCH_AON.scan_ctrl2.touch_timeout_en = 0; + } +} + +/** + * Set the engaged sample configuration number + * + * @param sample_cfg_num The enabled sample configuration number, range 0~3. + * 0/1 means only one sample configuration enabled, which can not support frequency hopping + */ +static inline void touch_ll_sample_cfg_set_engaged_num(uint8_t sample_cfg_num) +{ + HAL_ASSERT(sample_cfg_num <= SOC_TOUCH_SAMPLE_CFG_NUM); + TOUCH_AON.scan_ctrl2.freq_scan_en = !!sample_cfg_num; + TOUCH_AON.scan_ctrl2.freq_scan_cnt_limit = sample_cfg_num ? sample_cfg_num : 1; +} + +/** + * Get the engaged sample configuration number + * + * @return The engaged sample configuration number, range 0~3. + */ +static inline uint32_t touch_ll_sample_cfg_get_engaged_num(void) +{ + uint32_t sample_cfg_num = TOUCH_AON.scan_ctrl2.freq_scan_cnt_limit; + return sample_cfg_num ? sample_cfg_num : 1; +} + +/** + * Set the number of trigger rise count + * + * @param rise_cnt Configure the number of hit frequency points that need to be determined for touch + * in frequency hopping mode. + */ +static inline void touch_ll_sample_cfg_set_trigger_rise_cnt(uint8_t rise_cnt) +{ + TOUCH_AON.scan_ctrl2.freq_scan_cnt_rise = rise_cnt; +} + +/** + * Set capacitance and resistance of the RC filter of the sampling frequency. + * + * @param sample_cfg_id The sample configuration index + * @param cap Capacitance of the RC filter. + * @param res Resistance of the RC filter. + */ +static inline void touch_ll_sample_cfg_set_rc_filter(uint8_t sample_cfg_id, uint32_t cap, uint32_t res) +{ + HAL_ASSERT(sample_cfg_id < SOC_TOUCH_SAMPLE_CFG_NUM); + TOUCH_AON.freq_scan_para[sample_cfg_id].touch_freq_dcap_lpf = cap; + TOUCH_AON.freq_scan_para[sample_cfg_id].touch_freq_dres_lpf = res; +} + +/** + * @brief Set the driver of the sampling frequency + * + * @param sample_cfg_id The sample configuration index + * @param ls_drv Low speed touch driver + * @param hs_drv High speed touch driver + */ +static inline void touch_ll_sample_cfg_set_driver(uint8_t sample_cfg_id, uint32_t ls_drv, uint32_t hs_drv) +{ + HAL_ASSERT(sample_cfg_id < SOC_TOUCH_SAMPLE_CFG_NUM); + TOUCH_AON.freq_scan_para[sample_cfg_id].touch_freq_drv_ls = ls_drv; + TOUCH_AON.freq_scan_para[sample_cfg_id].touch_freq_drv_hs = hs_drv; +} + +/** + * Set the touch internal LDO bias voltage of the sampling frequency + * + * @param sample_cfg_id The sample configuration index + * @param bias_volt LDO bias voltage + */ +static inline void touch_ll_sample_cfg_set_bias_voltage(uint8_t sample_cfg_id, uint32_t bias_volt) +{ + HAL_ASSERT(sample_cfg_id < SOC_TOUCH_SAMPLE_CFG_NUM); + TOUCH_AON.freq_scan_para[sample_cfg_id].touch_freq_dbias = bias_volt; +} + +/** + * @brief Set the internal loop capacitance + * Can simulate the touch signal via the internal capacitance + * Need to turn off touch pad + * @param cap The internal capacitance + */ +static inline void touch_ll_set_internal_loop_capacitance(int cap) +{ + bool enable = cap > 0; + TOUCH_AON.ana_para.touch_touch_en_cal = enable; + TOUCH_AON.ana_para.touch_touch_dcap_cal = enable ? cap : 0; +} + +/************************ Filter register setting ************************/ + +/** + * Force reset benchmark to raw data of touch sensor. + * + * @note If call this API, make sure enable clock gate(`touch_ll_clkgate`) first. + * @param chan_mask touch channel mask + */ +__attribute__((always_inline)) +static inline void touch_ll_reset_chan_benchmark(uint32_t chan_mask) +{ + TOUCH_AON.clr.touch_channel_clr = chan_mask; +} + +/** + * Set filter mode. The input of the filter is the raw value of touch reading, + * and the output of the filter is involved in the judgment of the touch state. + * + * @param mode Filter mode type. Refer to ``touch_benchmark_filter_mode_t``. + */ +static inline void touch_ll_filter_set_filter_mode(touch_benchmark_filter_mode_t mode) +{ + TOUCH_AON.filter1.touch_filter_mode = mode; +} + +/** + * Set filter mode. The input to the filter is raw data and the output is the smooth data. + * The smooth data is used to determine the touch status. + * + * @param mode Filter mode type. Refer to ``touch_smooth_filter_mode_t``. + */ +static inline void touch_ll_filter_set_smooth_mode(touch_smooth_filter_mode_t mode) +{ + TOUCH_AON.filter1.touch_smooth_lvl = mode; +} + +/** + * Set debounce count, such as `n`. If the measured values continue to exceed + * the threshold for `n+1` times, it is determined that the touch sensor state changes. + * + * @param dbc_cnt Debounce count value. + */ +static inline void touch_ll_filter_set_debounce(uint32_t dbc_cnt) +{ + TOUCH_AON.filter1.touch_debounce_limit = dbc_cnt; +} + +/** + * Set the denoise coefficient regarding the denoise level. + * + * @param denoise_lvl Range [0 ~ 4]. 0 = no noise resistance, otherwise higher denoise_lvl means more noise resistance. + */ +static inline void touch_ll_filter_set_denoise_level(int denoise_lvl) +{ + HAL_ASSERT(denoise_lvl >= 0 && denoise_lvl <= 4); + bool always_update = denoise_lvl == 0; + // Map denoise level to actual noise threshold coefficients + uint32_t noise_thresh = denoise_lvl == 4 ? 3 : 3 - denoise_lvl; + + TOUCH_AON.filter2.touch_bypass_noise_thres = always_update; + TOUCH_AON.filter1.touch_noise_thres = always_update ? 0 : noise_thresh; + + TOUCH_AON.filter2.touch_bypass_nn_thres = always_update; + TOUCH_AON.filter1.touch_nn_thres = always_update ? 0 : noise_thresh; + TOUCH_AON.filter1.touch_nn_limit = 5; // 5 is the default value +} + +/** + * Set the hysteresis value of the active threshold + * While the touch data is greater than active_threshold + hysteresis and last for several ticks, the channel is activated, + * and while the touch data is smaller than active_threshold - hysteresis and last for several ticks, the channel is inactivated + * + * @param hysteresis The hysteresis value of active threshold + */ +static inline void touch_ll_filter_set_active_hysteresis(uint32_t hysteresis) +{ + TOUCH_AON.filter1.touch_hysteresis = hysteresis; +} + +/** + * Set jitter filter step size. + * If filter mode is jitter, should set filter step for jitter. + * Range: 0 ~ 15 + * + * @param step The step size of the data change. + */ +static inline void touch_ll_filter_set_jitter_step(uint32_t step) +{ + TOUCH_AON.filter1.touch_jitter_step = step; +} + +/** + * Enable or disable touch sensor filter and detection algorithm. + * For more details on the detection algorithm, please refer to the application documentation. + */ +static inline void touch_ll_filter_enable(bool enable) +{ + TOUCH_AON.filter1.touch_filter_en = enable; +} + +/** + * Force the update the benchmark by software + * @note This benchmark will be applied to all enabled channel and all sampling frequency + * + * @param pad_num The pad number, range [0-13] + * @param sample_cfg_id The sample configuration index, range [0-2] + * @param benchmark The benchmark specified by software + */ +static inline void touch_ll_force_update_benchmark(uint32_t pad_num, uint8_t sample_cfg_id, uint32_t benchmark) +{ + TOUCH_AON.filter3.touch_update_benchmark_pad_sel = pad_num; + TOUCH_AON.filter3.touch_update_benchmark_freq_sel = sample_cfg_id; + HAL_FORCE_MODIFY_U32_REG_FIELD(TOUCH_AON.filter3, touch_benchmark_sw, benchmark); + TOUCH_AON.filter3.touch_update_benchmark_sw = 1; + // waiting for update + while (TOUCH_AON.filter3.touch_update_benchmark_sw); +} + +/************************ Waterproof register setting ************************/ + +/** + * Set touch channel use for guard pad. + * + * @param pad_num Touch sensor channel number. + */ +static inline void touch_ll_waterproof_set_guard_chan(uint32_t pad_num) +{ + TOUCH_AON.scan_ctrl2.touch_out_ring = pad_num; +} + +/** + * Enable or disable parameter of waterproof function. + * + * The waterproof function includes a shielded channel and a guard channel. + * Guard pad is used to detect the large area of water covering the touch panel. + * Shield pad is used to shield the influence of water droplets covering the touch panel. + * It is generally designed as a grid and is placed around the touch buttons. + */ +static inline void touch_ll_waterproof_enable(bool enable) +{ + TOUCH_AON.scan_ctrl1.touch_shield_pad_en = enable; +} + +/** + * Set the shield channel mask + * + * @param mask The channels that set in the mask will be used as shield channel + */ +static inline void touch_ll_waterproof_set_shield_chan_mask(uint32_t mask) +{ + TOUCH_AON.mux0.touch_bufsel = mask; +} + +/** + * Set the touch buff driver for the shield channel. + * + * @param driver_level The driver level of the touch buff + */ +static inline void touch_ll_waterproof_set_shield_driver(touch_chan_shield_cap_t driver_level) +{ + TOUCH_AON.ana_para.touch_touch_buf_drv = driver_level; +} + +/************************ Approach register setting ************************/ + +/** + * Set the proximity sensing channel to the specific touch channel + * To disable the proximity channel, point this pad to `TOUCH_LL_NULL_CHANNEL` + * + * @param prox_chan proximity sensing channel. + * @param touch_num The touch channel that supposed to be used as proximity sensing channel + */ +static inline void touch_ll_set_proximity_sensing_channel(uint8_t prox_chan, uint32_t touch_num) +{ + switch (prox_chan) { + case 0: + TOUCH_AON.approach.touch_approach_pad0 = touch_num; + break; + case 1: + TOUCH_AON.approach.touch_approach_pad1 = touch_num; + break; + case 2: + TOUCH_AON.approach.touch_approach_pad2 = touch_num; + break; + default: + // invalid proximity channel + abort(); + } +} + +/** + * Set the total scan times of the proximity sensing channel. + * + * @param scan_times The total scan times of the proximity sensing channel + */ +static inline void touch_ll_proximity_set_total_scan_times(uint32_t scan_times) +{ + HAL_FORCE_MODIFY_U32_REG_FIELD(TOUCH_AON.filter1, touch_approach_limit, scan_times); +} + +/** + * Set charge times for each sample configuration in proximity sensing mode. + * + * @param sample_cfg_id The sample configuration index + * @param charge_times The charge and discharge times. + */ +static inline void touch_ll_proximity_set_charge_times(uint8_t sample_cfg_id, uint32_t charge_times) +{ + switch (sample_cfg_id) { + case 0: + TOUCH_AON.approach_work_meas_num.touch_approach_meas_num0 = charge_times; + break; + case 1: + TOUCH_AON.approach_work_meas_num.touch_approach_meas_num1 = charge_times; + break; + case 2: + TOUCH_AON.approach_work_meas_num.touch_approach_meas_num2 = charge_times; + break; + default: + // invalid sample_cfg_id + abort(); + } +} + +/** + * Read current cumulative measurement times for proximity sensing channel. + * + * @param prox_chan proximity sensing channel. + * @param cnt The cumulative number of measurement cycles. + */ +static inline void touch_ll_proximity_read_measure_cnt(uint8_t prox_chan, uint32_t *cnt) +{ + switch (prox_chan) { + case 0: + *cnt = HAL_FORCE_READ_U32_REG_FIELD(TOUCH_SENS.aprch_ch_data, approach_pad0_cnt); + break; + case 1: + *cnt = HAL_FORCE_READ_U32_REG_FIELD(TOUCH_SENS.aprch_ch_data, approach_pad1_cnt); + break; + case 2: + *cnt = HAL_FORCE_READ_U32_REG_FIELD(TOUCH_SENS.aprch_ch_data, approach_pad2_cnt); + break; + default: // sleep channel + *cnt = HAL_FORCE_READ_U32_REG_FIELD(TOUCH_SENS.aprch_ch_data, slp_approach_cnt); + break; + } +} + +/** + * Check if the touch sensor channel is the proximity sensing channel. + * + * @param touch_num The touch sensor channel number. + */ +static inline bool touch_ll_is_proximity_sensing_channel(uint32_t touch_num) +{ + if ((TOUCH_AON.approach.touch_approach_pad0 != touch_num) + && (TOUCH_AON.approach.touch_approach_pad1 != touch_num) + && (TOUCH_AON.approach.touch_approach_pad2 != touch_num)) { + return false; + } + return true; +} + +/************** sleep channel setting ***********************/ + +/** + * Set touch channel number for sleep channel. + * + * @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_set_channel_num(uint32_t touch_num) +{ + TOUCH_AON.slp0.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 = (uint32_t)(TOUCH_AON.slp0.touch_slp_pad); +} + +/** + * Set the trigger threshold of touch sensor in deep sleep. + * The threshold determines the sensitivity of the touch sensor. + * The threshold is the original value of the trigger state minus the benchmark value. + * + * @note In general, the touch threshold during sleep can use the threshold parameter parameters before sleep. + */ +static inline void touch_ll_sleep_set_threshold(uint8_t sample_cfg_id, uint32_t touch_thresh) +{ + switch (sample_cfg_id) { + case 0: + HAL_FORCE_MODIFY_U32_REG_FIELD(TOUCH_AON.slp0, touch_slp_th0, touch_thresh); + break; + case 1: + HAL_FORCE_MODIFY_U32_REG_FIELD(TOUCH_AON.slp1, touch_slp_th1, touch_thresh); + break; + case 2: + HAL_FORCE_MODIFY_U32_REG_FIELD(TOUCH_AON.slp1, touch_slp_th2, touch_thresh); + break; + default: + // invalid sample_cfg_id + abort(); + } +} + +/** + * Set the touch sensor wait ticks after PMU is woken up by touch timer during the sleep. + * @note The PMU will be woken up after the measure interval timer time-up, + * PMU needs some time to prepare the clock and power for the touch sensor, + * If the wait ticks is too short, the touch sensor can't work properly and fail to wakeup the chip from sleep. + * + * @param wait_ticks The wait ticks after PMU is woken up by touch FSM during the sleep. + * Typically recommended to set it to the max value, + * the PMU will start the touch sensor FSM immediately after the PMU enters HP SLEEP state. + */ +static inline void touch_ll_sleep_set_measure_wait_ticks(uint32_t wait_ticks) +{ + PMU.touch_pwr_ctrl.touch_wait_cycles = wait_ticks; +} + +/** + * Enable proximity sensing function for sleep channel. + */ +static inline void touch_ll_sleep_enable_proximity_sensing(bool enable) +{ + TOUCH_AON.approach.touch_slp_approach_en = enable; +} + +/** + * Get the data of the touch channel according to the types + * + * @param sample_cfg_id The sample configuration index + * @param type data type + * 0/1: TOUCH_LL_READ_RAW, the raw data of the 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 smooth_data pointer to smoothed data + */ +__attribute__((always_inline)) +static inline void touch_ll_sleep_read_chan_data(uint8_t type, uint8_t sample_cfg_id, uint32_t *data) +{ + HAL_ASSERT(type <= TOUCH_LL_READ_SMOOTH); + TOUCH_AON.mux0.touch_freq_sel = sample_cfg_id + 1; + TOUCH_AON.mux0.touch_data_sel = type; + *data = HAL_FORCE_READ_U32_REG_FIELD(TOUCH_SENS.slp_ch_data, slp_data); +} + +/** + * @brief Reset the benchmark of the sleep channel + * + */ +static inline void touch_ll_sleep_reset_benchmark(void) +{ + TOUCH_AON.slp0.touch_slp_channel_clr = 1; +} + +/** + * Read debounce of touch sensor for sleep channel. + * + * @param debounce Pointer to accept touch sensor debounce value. + */ +static inline void touch_ll_sleep_read_debounce(uint32_t *debounce) +{ + *debounce = TOUCH_SENS.slp_ch_data.slp_debounce_cnt; +} + +/** + * Read proximity count of touch sensor for sleep channel. + * @param prox_cnt Pointer to accept touch sensor proximity count value. + */ +static inline void touch_ll_sleep_read_proximity_cnt(uint32_t *prox_cnt) +{ + *prox_cnt = HAL_FORCE_READ_U32_REG_FIELD(TOUCH_SENS.aprch_ch_data, slp_approach_cnt); +} + +/** + * @brief Enable or disable the internal capacitor, mainly for debug + * + * @param enable enable or disable the internal capacitor + */ +static inline void touch_ll_enable_internal_capacitor(bool enable) +{ + TOUCH_AON.ana_para.touch_touch_en_cal = enable; +} + +/** + * @brief Set the internal capacitor, mainly for debug + * @note Only take effect when the internal capacitor is enabled + * + * @param cap the capacitor value + */ +static inline void touch_ll_set_internal_capacitor(uint32_t cap) +{ + TOUCH_AON.ana_para.touch_touch_dcap_cal = cap; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hal_touch_sens/esp32s31/touch_sensor_periph.c b/components/esp_hal_touch_sens/esp32s31/touch_sensor_periph.c new file mode 100644 index 0000000000..06177746d2 --- /dev/null +++ b/components/esp_hal_touch_sens/esp32s31/touch_sensor_periph.c @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/touch_sensor_channel.h" + +/* Store IO number corresponding to the Touch Sensor channel number. */ +const int touch_sensor_channel_io_map[] = { + TOUCH_PAD_NUM0_GPIO_NUM, + TOUCH_PAD_NUM1_GPIO_NUM, + TOUCH_PAD_NUM2_GPIO_NUM, + TOUCH_PAD_NUM3_GPIO_NUM, + TOUCH_PAD_NUM4_GPIO_NUM, + TOUCH_PAD_NUM5_GPIO_NUM, + TOUCH_PAD_NUM6_GPIO_NUM, + TOUCH_PAD_NUM7_GPIO_NUM, + TOUCH_PAD_NUM8_GPIO_NUM, + TOUCH_PAD_NUM9_GPIO_NUM, + TOUCH_PAD_NUM10_GPIO_NUM, + TOUCH_PAD_NUM11_GPIO_NUM, + TOUCH_PAD_NUM12_GPIO_NUM, + TOUCH_PAD_NUM13_GPIO_NUM, +}; diff --git a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in index f70e6339be..a9cb9b28cc 100644 --- a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in @@ -163,6 +163,10 @@ config SOC_SPI_FLASH_SUPPORTED bool default y +config SOC_TOUCH_SENSOR_SUPPORTED + bool + default y + config SOC_MODEM_CLOCK_SUPPORTED bool default y @@ -791,6 +795,42 @@ config SOC_ASYNCHRONOUS_BUS_ERROR_MODE bool default y +config SOC_TOUCH_SENSOR_VERSION + int + default 3 + +config SOC_TOUCH_MIN_CHAN_ID + int + default 0 + +config SOC_TOUCH_MAX_CHAN_ID + int + default 13 + +config SOC_TOUCH_SUPPORT_SLEEP_WAKEUP + bool + default n + +config SOC_TOUCH_SUPPORT_BENCHMARK + bool + default y + +config SOC_TOUCH_SUPPORT_WATERPROOF + bool + default y + +config SOC_TOUCH_SUPPORT_PROX_SENSING + bool + default y + +config SOC_TOUCH_PROXIMITY_CHANNEL_NUM + int + default 3 + +config SOC_TOUCH_SAMPLE_CFG_NUM + int + default 3 + config SOC_PM_SUPPORT_EXT1_WAKEUP bool default y diff --git a/components/soc/esp32s31/include/soc/soc_caps.h b/components/soc/esp32s31/include/soc/soc_caps.h index d4bef506c7..4b44e9e937 100644 --- a/components/soc/esp32s31/include/soc/soc_caps.h +++ b/components/soc/esp32s31/include/soc/soc_caps.h @@ -90,7 +90,7 @@ #define SOC_WDT_SUPPORTED 1 #define SOC_RTC_WDT_SUPPORTED 1 #define SOC_SPI_FLASH_SUPPORTED 1 // TODO: [ESP32S31] IDF-14777 -// #define SOC_TOUCH_SENSOR_SUPPORTED 1 // TODO: [ESP32S31] IDF-14796 +#define SOC_TOUCH_SENSOR_SUPPORTED 1 // #define SOC_RNG_SUPPORTED 1 // TODO: [ESP32S31] IDF-14632 // #define SOC_PPA_SUPPORTED 1 // TODO: [ESP32S31] IDF-14769 // #define SOC_LIGHT_SLEEP_SUPPORTED 1 // TODO: [ESP32S31] IDF-14645 @@ -373,6 +373,20 @@ #define SOC_RCC_IS_INDEPENDENT 1 /*!< Reset and Clock Control has own registers for each module */ /*-------------------------- Memory CAPS --------------------------*/ #define SOC_ASYNCHRONOUS_BUS_ERROR_MODE (1) + +/*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ +#define SOC_TOUCH_SENSOR_VERSION (3) /*!< Hardware version of touch sensor */ +#define SOC_TOUCH_MIN_CHAN_ID (0U) /*!< Touch minimum channel number */ +#define SOC_TOUCH_MAX_CHAN_ID (13) /*!< Touch maximum channel number */ + +/* Touch Sensor Features */ +#define SOC_TOUCH_SUPPORT_SLEEP_WAKEUP (0) /*!< Touch sensor supports sleep awake */ +#define SOC_TOUCH_SUPPORT_BENCHMARK (1) /*!< Touch sensor supports benchmark configuration */ +#define SOC_TOUCH_SUPPORT_WATERPROOF (1) /*!< Touch sensor supports waterproof */ +#define SOC_TOUCH_SUPPORT_PROX_SENSING (1) /*!< Touch sensor supports proximity sensing */ +#define SOC_TOUCH_PROXIMITY_CHANNEL_NUM (3) /*!< Support touch proximity channel number. */ +#define SOC_TOUCH_SAMPLE_CFG_NUM (3) /*!< The sample configurations number in total, each sampler can be used to sample on one frequency */ + /*-------------------------- Power Management CAPS ----------------------------*/ #define SOC_PM_SUPPORT_EXT1_WAKEUP (1) #define SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN (1) /*! None: dut.expect(r'Touch \[CH [0-9]+\] enabled on GPIO[0-9]+') dut.expect_exact('Initial benchmark and new threshold are:') diff --git a/examples/peripherals/touch_sensor/touch_sens_sleep/pytest_touch_sens_sleep.py b/examples/peripherals/touch_sensor/touch_sens_sleep/pytest_touch_sens_sleep.py index 21c40d7ef6..66d3e8638d 100644 --- a/examples/peripherals/touch_sensor/touch_sens_sleep/pytest_touch_sens_sleep.py +++ b/examples/peripherals/touch_sensor/touch_sens_sleep/pytest_touch_sens_sleep.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut @@ -17,7 +17,11 @@ from pytest_embedded_idf.utils import soc_filtered_targets ) @idf_parametrize( 'target', - soc_filtered_targets('SOC_TOUCH_SENSOR_SUPPORTED == 1 and SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP == 1'), + soc_filtered_targets( + 'SOC_TOUCH_SENSOR_SUPPORTED == 1 and ' + 'SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP == 1 and ' + 'SOC_TOUCH_SUPPORT_SLEEP_WAKEUP == 1' + ), indirect=['target'], ) def test_touch_sens_sleep(dut: Dut) -> None: