forked from espressif/esp-idf
Merge branch 'feature/touch_driver_ng_on_32' into 'master'
feat(touch): support touch v1 in new touch driver Closes IDF-10183 and IDF-11423 See merge request espressif/esp-idf!34781
This commit is contained in:
@@ -1,2 +1,3 @@
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_ESP_TASK_WDT_EN=n
|
||||
CONFIG_TOUCH_SUPPRESS_DEPRECATE_WARN=y
|
||||
|
@@ -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
|
||||
|
@@ -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
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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()
|
||||
|
||||
# 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}
|
||||
)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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 absolute 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 customized filter context pointer.
|
||||
* This pointer will be passed to the second parameter of `touch_sw_filter_t` .
|
||||
* So that users can access their customized 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
|
||||
|
@@ -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 <inttypes.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
@@ -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
|
||||
*/
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#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
|
@@ -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)
|
||||
if SOC_TOUCH_SUPPORT_BENCHMARK = y:
|
||||
touch_sens_common: touch_channel_config_benchmark (noflash)
|
||||
touch_sens_version_specific: touch_priv_config_benchmark (noflash)
|
||||
|
@@ -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
|
||||
*/
|
||||
@@ -10,12 +10,13 @@
|
||||
#include "unity.h"
|
||||
#include "driver/touch_sens.h"
|
||||
#include "hal/touch_sensor_ll.h"
|
||||
#include "esp_private/touch_sens_helper.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
static touch_sensor_sample_config_t s_sample_cfg[TOUCH_SAMPLE_CFG_NUM] = {
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 2
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1
|
||||
TOUCH_SENSOR_V1_DEFAULT_SAMPLE_CONFIG(5.0, TOUCH_VOLT_LIM_L_0V5, TOUCH_VOLT_LIM_H_1V7),
|
||||
#elif SOC_TOUCH_SENSOR_VERSION == 2
|
||||
TOUCH_SENSOR_V2_DEFAULT_SAMPLE_CONFIG(500, TOUCH_VOLT_LIM_L_0V5, TOUCH_VOLT_LIM_H_2V2),
|
||||
#elif SOC_TOUCH_SENSOR_VERSION == 3
|
||||
TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG(1, 1, 1),
|
||||
@@ -27,7 +28,12 @@ static touch_sensor_sample_config_t s_sample_cfg[TOUCH_SAMPLE_CFG_NUM] = {
|
||||
};
|
||||
|
||||
static touch_channel_config_t s_chan_cfg = {
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 2
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1
|
||||
.abs_active_thresh = {1000},
|
||||
.charge_speed = TOUCH_CHARGE_SPEED_7,
|
||||
.init_charge_volt = TOUCH_INIT_CHARGE_VOLT_LOW,
|
||||
.group = TOUCH_CHAN_TRIG_GROUP_BOTH,
|
||||
#elif SOC_TOUCH_SENSOR_VERSION == 2
|
||||
.active_thresh = {
|
||||
2000,
|
||||
},
|
||||
@@ -77,15 +83,24 @@ TEST_CASE("touch_sens_install_uninstall_test", "[touch]")
|
||||
typedef struct {
|
||||
int active_count;
|
||||
int inactive_count;
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1
|
||||
int hw_active_count;
|
||||
#endif
|
||||
} test_touch_cb_data_t;
|
||||
|
||||
static touch_channel_config_t s_test_get_chan_cfg_by_benchmark(uint32_t benchmark[], uint32_t num, float coeff)
|
||||
{
|
||||
touch_channel_config_t chan_cfg = {};
|
||||
touch_channel_config_t chan_cfg = s_chan_cfg;
|
||||
for (int i = 0; i < num; i++) {
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1
|
||||
chan_cfg.abs_active_thresh[i] = benchmark[i] * (1 - coeff);
|
||||
printf("[Sampler %d] benchmark %5"PRIu32" abs thresh %4"PRIu32"\n",
|
||||
i, benchmark[i], chan_cfg.abs_active_thresh[i]);
|
||||
#else
|
||||
chan_cfg.active_thresh[i] = benchmark[i] * coeff;
|
||||
printf("[Sampler %d] benchmark %5"PRIu32" thresh %4"PRIu32"\n",
|
||||
i, benchmark[i], chan_cfg.active_thresh[i]);
|
||||
#endif
|
||||
}
|
||||
return chan_cfg;
|
||||
}
|
||||
@@ -108,6 +123,15 @@ static void s_test_touch_do_initial_scanning(touch_sensor_handle_t touch, int sc
|
||||
#define TEST_TCH_IRAM_ATTR
|
||||
#endif
|
||||
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1
|
||||
static bool TEST_TCH_IRAM_ATTR s_test_touch_on_hw_active_callback(touch_sensor_handle_t sens_handle, const touch_hw_active_event_data_t *event, void *user_ctx)
|
||||
{
|
||||
test_touch_cb_data_t *cb_data = (test_touch_cb_data_t *)user_ctx;
|
||||
cb_data->hw_active_count++;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool TEST_TCH_IRAM_ATTR s_test_touch_on_active_callback(touch_sensor_handle_t sens_handle, const touch_active_event_data_t *event, void *user_ctx)
|
||||
{
|
||||
ESP_EARLY_LOGI("touch_callback", "[CH %d] active", (int)event->chan_id);
|
||||
@@ -126,7 +150,7 @@ 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 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);
|
||||
@@ -169,7 +193,12 @@ TEST_CASE("touch_sens_active_inactive_test", "[touch]")
|
||||
|
||||
/* Read benchmark */
|
||||
uint32_t benchmark[TOUCH_SAMPLE_CFG_NUM] = {0};
|
||||
TEST_ESP_OK(touch_channel_read_data(touch_chan, TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark));
|
||||
#if SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
touch_chan_data_type_t data_type = TOUCH_CHAN_DATA_TYPE_BENCHMARK;
|
||||
#else
|
||||
touch_chan_data_type_t data_type = TOUCH_CHAN_DATA_TYPE_SMOOTH;
|
||||
#endif // SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
TEST_ESP_OK(touch_channel_read_data(touch_chan, data_type, benchmark));
|
||||
/* Test whether success to finish the initial scanning */
|
||||
for (int i = 0; i < TOUCH_SAMPLE_CFG_NUM; i++) {
|
||||
TEST_ASSERT_GREATER_THAN(0, benchmark[i]);
|
||||
@@ -177,10 +206,12 @@ TEST_CASE("touch_sens_active_inactive_test", "[touch]")
|
||||
/* Re-configure the threshold according to the benchmark */
|
||||
touch_channel_config_t chan_cfg = s_test_get_chan_cfg_by_benchmark(benchmark, TOUCH_SAMPLE_CFG_NUM, TEST_ACTIVE_THRESH_RATIO);
|
||||
TEST_ESP_OK(touch_sensor_reconfig_channel(touch_chan, &chan_cfg));
|
||||
|
||||
touch_event_callbacks_t callbacks = {
|
||||
.on_active = s_test_touch_on_active_callback,
|
||||
.on_inactive = s_test_touch_on_inactive_callback,
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1
|
||||
.on_hw_active = s_test_touch_on_hw_active_callback,
|
||||
#endif
|
||||
};
|
||||
test_touch_cb_data_t cb_data = {};
|
||||
TEST_ESP_OK(touch_sensor_register_callbacks(touch, &callbacks, &cb_data));
|
||||
@@ -196,13 +227,13 @@ TEST_CASE("touch_sens_active_inactive_test", "[touch]")
|
||||
s_test_touch_log_data(touch_chan, TOUCH_SAMPLE_CFG_NUM, "Data Before");
|
||||
// Simulate touch
|
||||
s_test_touch_simulate_touch(touch, touch_chan, true);
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
|
||||
// Read data after touched
|
||||
s_test_touch_log_data(touch_chan, TOUCH_SAMPLE_CFG_NUM, "Data After ");
|
||||
// Simulate release
|
||||
s_test_touch_simulate_touch(touch, touch_chan, false);
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
@@ -212,6 +243,12 @@ TEST_CASE("touch_sens_active_inactive_test", "[touch]")
|
||||
TEST_ESP_OK(touch_sensor_del_controller(touch));
|
||||
|
||||
/* Check the callback count */
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1
|
||||
// The Touch V1 interrupt will keep triggering as long as the channel data is below the threshold
|
||||
// So it might be greater than the touch count
|
||||
printf("hardware active interrupt count: %d\n", cb_data.hw_active_count);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL_UINT32(touch_cnt, cb_data.hw_active_count);
|
||||
#endif // SOC_TOUCH_SENSOR_VERSION == 1
|
||||
TEST_ASSERT_EQUAL_INT32(touch_cnt, cb_data.active_count);
|
||||
TEST_ASSERT_EQUAL_INT32(touch_cnt, cb_data.inactive_count);
|
||||
}
|
||||
|
@@ -1,2 +1,2 @@
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_ESP_TASK_WDT=n
|
||||
CONFIG_ESP_TASK_WDT_INIT=n
|
||||
|
@@ -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
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
|
@@ -283,16 +283,14 @@ 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)
|
||||
# Source files for the new touch hal driver
|
||||
list(APPEND srcs "touch_sens_hal.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${target} STREQUAL "esp32")
|
||||
list(APPEND srcs
|
||||
|
@@ -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 <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#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 <<n) | (0x1 << m))))
|
||||
#define TOUCH_LL_BITS_SWAP(v) TOUCH_LL_BIT_SWAP(v, TOUCH_PAD_NUM8, TOUCH_PAD_NUM9)
|
||||
#define TOUCH_LL_BITS_SWAP(v) TOUCH_LL_BIT_SWAP(v, 8, 9)
|
||||
#define TOUCH_LL_CHAN_SWAP(chan) ((chan) == 8 ? 9 : ((chan) == 9 ? 8 : (chan)))
|
||||
#define TOUCH_LL_FULL_CHANNEL_MASK ((uint16_t)((1U << SOC_TOUCH_SENSOR_NUM) - 1))
|
||||
#define TOUCH_LL_READ_RAW 0x0
|
||||
|
||||
#define TOUCH_LL_PAD_MEASURE_WAIT_MAX (0xFF) /*!<The timer frequency is 8Mhz, the max value is 0xff */
|
||||
#define TOUCH_LL_CHARGE_DURATION_MAX (0xFFFF)
|
||||
#define TOUCH_LL_PAD_MEASURE_WAIT_MAX (0xFF) // The timer frequency is 8Mhz, the max value is 0xff
|
||||
#define TOUCH_LL_ACTIVE_THRESH_MAX (0xFFFF) // Max channel active threshold
|
||||
|
||||
#define TOUCH_LL_INTR_MASK_TRIGGER (1UL << 6) // Interrupt when the touch interrupt is triggered (depends on intr trigger mode)
|
||||
#define TOUCH_LL_INTR_MASK_ALL (TOUCH_LL_INTR_MASK_TRIGGER)
|
||||
|
||||
/*********************************** Interrupts *******************************/
|
||||
/**
|
||||
* Enable touch sensor interrupt by bitmask.
|
||||
*
|
||||
* @param int_mask interrupt mask
|
||||
*/
|
||||
static inline void touch_ll_interrupt_enable(uint32_t int_mask)
|
||||
{
|
||||
(void) int_mask;
|
||||
// Only one interrupt, set directly
|
||||
RTCCNTL.int_ena.rtc_touch = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable touch sensor interrupt by bitmask.
|
||||
*
|
||||
* @param int_mask interrupt mask
|
||||
*/
|
||||
static inline void touch_ll_interrupt_disable(uint32_t int_mask)
|
||||
{
|
||||
(void) int_mask;
|
||||
// Only one interrupt, clear directly
|
||||
RTCCNTL.int_ena.rtc_touch = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
(void) int_mask;
|
||||
RTCCNTL.int_clr.rtc_touch = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
// intr status bit of touch (bit7) is not same as the enable bit (bit6)
|
||||
return RTCCNTL.int_st.rtc_touch ? TOUCH_LL_INTR_MASK_TRIGGER : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set touch sensor interrupt trigger mode.
|
||||
* Interrupt can be triggered either when touch value is below the threshold (touched) or
|
||||
* or when touch value exceed the threshold (release).
|
||||
*
|
||||
* @param mode Touch sensor interrupt trigger mode.
|
||||
* - TOUCH_INTR_TRIG_ON_BELOW_THRESH: interrupt triggers when touched (touch value is below the threshold)
|
||||
* - TOUCH_INTR_TRIG_ON_ABOVE_THRESH: interrupt triggers when released (touch value is exceed the threshold)
|
||||
*/
|
||||
static inline void touch_ll_set_intr_trigger_mode(touch_intr_trig_mode_t mode)
|
||||
{
|
||||
SENS.sar_touch_ctrl1.touch_out_sel = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 group Touch sensor interrupt trigger group.
|
||||
*/
|
||||
static inline void touch_ll_set_intr_trigger_group(touch_intr_trig_group_t group)
|
||||
{
|
||||
SENS.sar_touch_ctrl1.touch_out_1en = group;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 group1_mask bitmask of touch sensor signal group1, it's a 10-bit value
|
||||
* @param group2_mask bitmask of touch sensor signal group2, it's a 10-bit value
|
||||
*/
|
||||
static inline void touch_ll_config_trigger_group1(uint32_t touch_num, bool enable)
|
||||
{
|
||||
touch_num = TOUCH_LL_CHAN_SWAP(touch_num);
|
||||
uint32_t mask = SENS.sar_touch_enable.touch_pad_outen1;
|
||||
if (enable) {
|
||||
mask |= (1 << touch_num);
|
||||
} else {
|
||||
mask &= ~(1 << touch_num);
|
||||
}
|
||||
SENS.sar_touch_enable.touch_pad_outen1 = mask;
|
||||
}
|
||||
|
||||
static inline void touch_ll_config_trigger_group2(uint32_t touch_num, bool enable)
|
||||
{
|
||||
touch_num = TOUCH_LL_CHAN_SWAP(touch_num);
|
||||
uint32_t mask = SENS.sar_touch_enable.touch_pad_outen2;
|
||||
if (enable) {
|
||||
mask |= (1 << touch_num);
|
||||
} else {
|
||||
mask &= ~(1 << touch_num);
|
||||
}
|
||||
SENS.sar_touch_enable.touch_pad_outen2 = mask;
|
||||
}
|
||||
|
||||
static inline void touch_ll_reset_trigger_groups(void)
|
||||
{
|
||||
SENS.sar_touch_enable.touch_pad_outen1 = 0;
|
||||
SENS.sar_touch_enable.touch_pad_outen2 = 0;
|
||||
}
|
||||
|
||||
/********************************* Status Info ********************************/
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_LL_BITS_SWAP(SENS.sar_touch_ctrl2.touch_meas_en);
|
||||
}
|
||||
|
||||
/**************************** Measurement Configuration ***********************/
|
||||
|
||||
/**
|
||||
* 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 thresh The threshold of charge cycles
|
||||
*/
|
||||
static inline void touch_ll_set_chan_active_threshold(uint32_t touch_num, uint32_t thresh)
|
||||
{
|
||||
// Workaround: swap chan 8 and chan 9
|
||||
touch_num = TOUCH_LL_CHAN_SWAP(touch_num);
|
||||
if (touch_num & 0x1) {
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(SENS.touch_thresh[touch_num >> 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
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -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
|
||||
*/
|
||||
@@ -166,6 +166,24 @@ typedef enum {
|
||||
*/
|
||||
} 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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -332,7 +332,7 @@
|
||||
/*-------------------------- TOUCH SENSOR CAPS -------------------------------*/
|
||||
#define SOC_TOUCH_SENSOR_VERSION (1U) /*!<Hardware version of touch sensor */
|
||||
#define SOC_TOUCH_SENSOR_NUM (10)
|
||||
|
||||
#define SOC_TOUCH_SUPPORT_SLEEP_WAKEUP (1)
|
||||
#define SOC_TOUCH_SAMPLE_CFG_NUM (1U) /*!< The sample configuration number in total, each sampler can be used to sample on one frequency */
|
||||
|
||||
/*-------------------------- TWAI CAPS ---------------------------------------*/
|
||||
|
@@ -1711,6 +1711,10 @@ config SOC_TOUCH_SUPPORT_SLEEP_WAKEUP
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_TOUCH_SUPPORT_WATERPROOF
|
||||
bool
|
||||
default y
|
||||
|
@@ -633,6 +633,7 @@
|
||||
|
||||
/* Touch Sensor Features */
|
||||
#define SOC_TOUCH_SUPPORT_SLEEP_WAKEUP (1) /*!< 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. */
|
||||
|
@@ -819,6 +819,10 @@ config SOC_TOUCH_SENSOR_NUM
|
||||
int
|
||||
default 15
|
||||
|
||||
config SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_TOUCH_SUPPORT_SLEEP_WAKEUP
|
||||
bool
|
||||
default y
|
||||
|
@@ -343,6 +343,7 @@
|
||||
/*-------------------------- TOUCH SENSOR CAPS -------------------------------*/
|
||||
#define SOC_TOUCH_SENSOR_VERSION (2) /*!< Hardware version of touch sensor */
|
||||
#define SOC_TOUCH_SENSOR_NUM (15) /*!< 15 Touch channels */
|
||||
#define SOC_TOUCH_SUPPORT_BENCHMARK (1) /*!< Touch sensor supports benchmark configuration */
|
||||
#define SOC_TOUCH_SUPPORT_SLEEP_WAKEUP (1) /*!< Touch sensor supports sleep awake */
|
||||
#define SOC_TOUCH_SUPPORT_WATERPROOF (1) /*!< Touch sensor supports waterproof */
|
||||
#define SOC_TOUCH_SUPPORT_PROX_SENSING (1) /*!< Touch sensor supports proximity sensing */
|
||||
|
@@ -1007,6 +1007,10 @@ config SOC_TOUCH_SENSOR_NUM
|
||||
int
|
||||
default 15
|
||||
|
||||
config SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_TOUCH_SUPPORT_SLEEP_WAKEUP
|
||||
bool
|
||||
default y
|
||||
|
@@ -390,6 +390,7 @@
|
||||
/*-------------------------- TOUCH SENSOR CAPS -------------------------------*/
|
||||
#define SOC_TOUCH_SENSOR_VERSION (2) /*!< Hardware version of touch sensor */
|
||||
#define SOC_TOUCH_SENSOR_NUM (15) /*!< 15 Touch channels */
|
||||
#define SOC_TOUCH_SUPPORT_BENCHMARK (1) /*!< Touch sensor supports benchmark configuration */
|
||||
#define SOC_TOUCH_SUPPORT_SLEEP_WAKEUP (1) /*!< Touch sensor supports sleep awake */
|
||||
#define SOC_TOUCH_SUPPORT_WATERPROOF (1) /*!< Touch sensor supports waterproof */
|
||||
#define SOC_TOUCH_SUPPORT_PROX_SENSING (1) /*!< Touch sensor supports proximity sensing */
|
||||
|
@@ -122,6 +122,8 @@ LDO_DOCS = ['api-reference/peripherals/ldo_regulator.rst']
|
||||
|
||||
TEMP_SENSOR_DOCS = ['api-reference/peripherals/temp_sensor.rst']
|
||||
|
||||
TOUCH_SENSOR_DOCS = ['api-reference/peripherals/cap_touch_sens.rst']
|
||||
|
||||
SPIRAM_DOCS = ['api-guides/external-ram.rst']
|
||||
|
||||
USB_DOCS = ['api-reference/peripherals/usb_device.rst',
|
||||
@@ -212,7 +214,6 @@ ESP32_DOCS = ['api-reference/system/himem.rst',
|
||||
'security/secure-boot-v1.rst',
|
||||
'api-reference/peripherals/dac.rst',
|
||||
'api-reference/peripherals/sd_pullup_requirements.rst',
|
||||
'api-reference/peripherals/touch_pad.rst',
|
||||
'hw-reference/esp32/**',
|
||||
'api-guides/RF_calibration.rst',
|
||||
'api-guides/phy.rst'] + FTDI_JTAG_DOCS + QEMU_DOCS
|
||||
@@ -222,7 +223,6 @@ ESP32S2_DOCS = ['hw-reference/esp32s2/**',
|
||||
'api-reference/peripherals/ds.rst',
|
||||
'api-reference/peripherals/temp_sensor.rst',
|
||||
'api-reference/system/async_memcpy.rst',
|
||||
'api-reference/peripherals/cap_touch_sens.rst',
|
||||
'api-reference/peripherals/touch_element.rst',
|
||||
'api-guides/RF_calibration.rst',
|
||||
'api-guides/phy.rst'] + FTDI_JTAG_DOCS + USB_OTG_DFU_DOCS + USB_OTG_CONSOLE_DOCS
|
||||
@@ -230,7 +230,6 @@ ESP32S2_DOCS = ['hw-reference/esp32s2/**',
|
||||
ESP32S3_DOCS = ['hw-reference/esp32s3/**',
|
||||
'api-reference/system/ipc.rst',
|
||||
'api-guides/flash_psram_config.rst',
|
||||
'api-reference/peripherals/cap_touch_sens.rst',
|
||||
'api-reference/peripherals/sd_pullup_requirements.rst',
|
||||
'api-guides/RF_calibration.rst',
|
||||
'api-guides/phy.rst'] + USB_OTG_DFU_DOCS + USB_OTG_CONSOLE_DOCS + QEMU_DOCS
|
||||
@@ -297,6 +296,7 @@ conditional_include_dict = {'SOC_BT_SUPPORTED':BT_DOCS,
|
||||
'CONFIG_IDF_TARGET_ARCH_XTENSA':XTENSA_DOCS,
|
||||
'CONFIG_IDF_TARGET_ARCH_RISCV':RISCV_DOCS,
|
||||
'SOC_TEMP_SENSOR_SUPPORTED':TEMP_SENSOR_DOCS,
|
||||
'SOC_TOUCH_SENSOR_SUPPORTED':TOUCH_SENSOR_DOCS,
|
||||
'SOC_TWAI_SUPPORTED':TWAI_DOCS,
|
||||
'SOC_I2C_SUPPORTED':I2C_DOCS,
|
||||
'SOC_GPSPI_SUPPORTED':SPI_DOCS,
|
||||
|
@@ -74,7 +74,6 @@ INPUT = \
|
||||
$(PROJECT_PATH)/components/bt/host/bluedroid/api/include/api/esp_spp_api.h \
|
||||
$(PROJECT_PATH)/components/bt/host/nimble/esp-hci/include/esp_nimble_hci.h \
|
||||
$(PROJECT_PATH)/components/console/esp_console.h \
|
||||
$(PROJECT_PATH)/components/driver/touch_sensor/include/driver/touch_sensor_common.h \
|
||||
$(PROJECT_PATH)/components/driver/twai/include/driver/twai.h \
|
||||
$(PROJECT_PATH)/components/driver/test_apps/components/esp_serial_slave_link/include/esp_serial_slave_link/essl_sdio.h \
|
||||
$(PROJECT_PATH)/components/driver/test_apps/components/esp_serial_slave_link/include/esp_serial_slave_link/essl_spi.h \
|
||||
|
@@ -1,10 +1,10 @@
|
||||
INPUT += \
|
||||
$(PROJECT_PATH)/components/driver/touch_sensor/$(IDF_TARGET)/include/driver/touch_sensor.h \
|
||||
$(PROJECT_PATH)/components/hal/include/hal/touch_sensor_legacy_types.h \
|
||||
$(PROJECT_PATH)/components/esp_driver_touch_sens/include/driver/touch_sens.h \
|
||||
$(PROJECT_PATH)/components/esp_driver_touch_sens/include/driver/touch_sens_types.h \
|
||||
$(PROJECT_PATH)/components/esp_driver_touch_sens/hw_ver1/include/driver/touch_version_types.h \
|
||||
$(PROJECT_PATH)/components/esp_psram/include/esp32/himem.h \
|
||||
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/dac_channel.h \
|
||||
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/rtc_io_channel.h \
|
||||
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \
|
||||
$(PROJECT_PATH)/components/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.h \
|
||||
$(PROJECT_PATH)/components/bt/include/$(IDF_TARGET)/include/esp_bt.h \
|
||||
$(PROJECT_PATH)/components/perfmon/include/xtensa_perfmon_access.h \
|
||||
|
@@ -3,7 +3,7 @@ Capacitive Touch Sensor
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
{IDF_TARGET_TOUCH_SENSOR_VERSION:default="NOT_UPDATED", esp32s2="v2", esp32s3="v2", esp32p4="v3"}
|
||||
{IDF_TARGET_TOUCH_SENSOR_VERSION:default="NOT_UPDATED", esp32="v1", esp32s2="v2", esp32s3="v2", esp32p4="v3"}
|
||||
|
||||
Introduction
|
||||
---------------
|
||||
@@ -19,18 +19,45 @@ In-depth design details of touch sensors and firmware development guidelines for
|
||||
Overview of Capacitive Touch Sensor Versions
|
||||
-----------------------------------------------
|
||||
|
||||
+------------------+--------------+------------------------------------------------------------------------+
|
||||
+------------------+-----------+---------------------------------------------------------------------------------------+
|
||||
| Hardware Version | Chip | Main Features |
|
||||
+==================+==============+========================================================================+
|
||||
+==================+===========+=======================================================================================+
|
||||
| V1 | ESP32 | Version 1, the channel value decreases when it is touched |
|
||||
+------------------+--------------+------------------------------------------------------------------------+
|
||||
+------------------+-----------+---------------------------------------------------------------------------------------+
|
||||
| V2 | ESP32-S2 | Version 2, the channel value increases when it is touched |
|
||||
| | | Supports waterproof, proximity sensing and sleep wake-up |
|
||||
| +--------------+------------------------------------------------------------------------+
|
||||
| | | Supports hardware filter, benchmark, waterproof, proximity sensing and sleep wake-up |
|
||||
| +-----------+---------------------------------------------------------------------------------------+
|
||||
| | ESP32-S3 | Version 2, support proximity measurement done interrupt |
|
||||
+------------------+--------------+------------------------------------------------------------------------+
|
||||
+------------------+-----------+---------------------------------------------------------------------------------------+
|
||||
| V3 | ESP32-P4 | Version 3, support frequency hopping |
|
||||
+------------------+--------------+------------------------------------------------------------------------+
|
||||
+------------------+-----------+---------------------------------------------------------------------------------------+
|
||||
|
||||
Measurement Principle
|
||||
---------------------
|
||||
|
||||
The touch sensor will charge and discharge the touch channel by the internal current or voltage bias. Due to the internal capacitance and the stray capacitance in the circuit, the signals on the touch pins will present as a sawtooth wave. When the finger is approaching or touched on the touch pad, the capacitance of the touch channel increases, which leads to a slower charge and discharge, and a longer sawtooth period.
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
The touch sensor charges and discharges the touch channel within a fixed time and counts the number of charge-discharge cycles, and the count result serves as the raw data. The duration of a single charge-discharge measurement can be specified by :cpp:member:`touch_sensor_sample_config_t::charge_times`, and the interval between two measurements can be specified by :cpp:member:`touch_sensor_config_t::meas_interval_us`.
|
||||
|
||||
.. figure:: ../../../_static/touch_pad-measurement-parameters.jpg
|
||||
:align: center
|
||||
:alt: Touch Pad - relationship between measurement parameters
|
||||
:figclass: align-center
|
||||
|
||||
Touch Sensor Working Principle
|
||||
|
||||
.. only:: not esp32
|
||||
|
||||
The touch sensor counts the number of clock cycles spent for a fixed number of charge-discharge cycles, and the count result serves as the raw data. The number of charge-discharge cycles for a single measurement can be specified by :cpp:member:`touch_sensor_sample_config_t::charge_duration_ms`, and the interval between two measurements can be specified by :cpp:member:`touch_sensor_config_t::meas_interval_us`.
|
||||
|
||||
.. figure:: ../../../_static/touch_pad-measurement-parameters-version2.png
|
||||
:align: center
|
||||
:alt: Touch Pad - relationship between measurement parameters
|
||||
:figclass: align-center
|
||||
|
||||
Touch Sensor Working Principle
|
||||
|
||||
Overview of Touch Sensor Channels
|
||||
------------------------------------
|
||||
@@ -93,8 +120,8 @@ Categorized by functionality, the APIs of Capacitive Touch Sensor mainly include
|
||||
- `Enable and Disable <#touch-enable>`__
|
||||
- `Continuous Scan <#touch-conti-scan>`__
|
||||
- `Oneshot Scan <#touch-oneshot-scan>`__
|
||||
- `Benchmark Configuration <#touch-benchmark>`__
|
||||
- `Read Measurement Data <#touch-read>`__
|
||||
:SOC_TOUCH_SUPPORT_BENCHMARK: - `Benchmark Configuration <#touch-benchmark>`__
|
||||
:SOC_TOUCH_SUPPORT_WATERPROOF: - `Waterproof Configuration <#touch-waterproof>`__
|
||||
:SOC_TOUCH_SUPPORT_PROX_SENSING: - `Proximity Sensing Configuration <#touch-prox-sensing>`__
|
||||
:SOC_TOUCH_SUPPORT_SLEEP_WAKEUP: - `Sleep Wake-up Configuration <#touch-sleep-wakeup>`__
|
||||
@@ -182,6 +209,14 @@ The filter can help to increase the stability in different use cases. The filter
|
||||
|
||||
To deregister the filter, you can call :cpp:func:`touch_sensor_config_filter` again, and set the second parameter (i.e. :cpp:type:`touch_sensor_filter_config_t` pointer) to ``NULL``.
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
The touch sensor version {IDF_TARGET_TOUCH_SENSOR_VERSION} does not natively support the hardware filter, but the driver can set up a periodically triggered software filter based on ``esp_timer``. The interval for the software filter can be specified by :cpp:member:`touch_sensor_filter_config_t::interval_ms`. Additionally, the :cpp:member:`touch_sensor_filter_config_t::data_filter_fn` supports to specify a custom filtering function. If there are no special filter requirements, this interface can be set to ``NULL`` to use the default filter in the driver.
|
||||
|
||||
.. only:: not esp32
|
||||
|
||||
The touch sensor version {IDF_TARGET_TOUCH_SENSOR_VERSION} supports the hardware filter. The filtering and updating strategy for the benchmark can be configured by :cpp:member:`touch_sensor_filter_config_t::benchmark`, while the filtering of read values can be configured by :cpp:member:`touch_sensor_filter_config_t::data`.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
// ...
|
||||
@@ -268,21 +303,6 @@ With the touch controller enabled, :cpp:func:`touch_sensor_trigger_oneshot_scann
|
||||
// Trigger an oneshot scan with timeout 1000 ms
|
||||
ESP_ERROR_CHECK(touch_sensor_trigger_oneshot_scanning(sens_handle, 1000));
|
||||
|
||||
.. _touch-benchmark:
|
||||
|
||||
Benchmark Configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Normally, you don't have to set the benchmark manually, but you can force reset the benchmark to the current smooth value by calling :cpp:func:`touch_channel_config_benchmark` when necessary.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
touch_chan_benchmark_config_t benchmark_cfg = {
|
||||
// Benchmark operations
|
||||
// ...
|
||||
};
|
||||
ESP_ERROR_CHECK(touch_channel_config_benchmark(chan_handle, &benchmark_cfg));
|
||||
|
||||
.. _touch-read:
|
||||
|
||||
Read Measurement Data
|
||||
@@ -301,6 +321,23 @@ Call :cpp:func:`touch_channel_read_data` to read the data with different types.
|
||||
// Read the smooth data
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle, TOUCH_CHAN_DATA_TYPE_SMOOTH, smooth_data));
|
||||
|
||||
.. _touch-benchmark:
|
||||
|
||||
.. only:: SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
|
||||
Benchmark Configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Normally, you don't have to set the benchmark manually, but you can force reset the benchmark to the current smooth value by calling :cpp:func:`touch_channel_config_benchmark` when necessary.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
touch_chan_benchmark_config_t benchmark_cfg = {
|
||||
// Benchmark operations
|
||||
// ...
|
||||
};
|
||||
ESP_ERROR_CHECK(touch_channel_config_benchmark(chan_handle, &benchmark_cfg));
|
||||
|
||||
.. _touch-waterproof:
|
||||
|
||||
.. only:: SOC_TOUCH_SUPPORT_WATERPROOF
|
||||
@@ -377,8 +414,11 @@ Call :cpp:func:`touch_channel_read_data` to read the data with different types.
|
||||
|
||||
If you want to read or configure the touch sensor during the sleep, you can turn to the driver ``components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_touch_ulp_core.h`` which based on the :doc:`Ultra Low Power (ULP) Coprocessor <../system/ulp>`.
|
||||
|
||||
.. list::
|
||||
|
||||
- Light sleep wake-up: you need to set :cpp:member:`slp_wakeup_lvl` to :cpp:enumerator:`TOUCH_LIGHT_SLEEP_WAKEUP` to enable the light sleep wake-up by touch sensor. Note that any registered touch channel can wake-up the chip from light sleep.
|
||||
- Deep sleep wake-up: beside setting :cpp:member:`slp_wakeup_lvl` to :cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP`, you need to specify :cpp:member:`deep_slp_chan` additionally. In order to reduce the power consumption, only the specified channel can wake-up the chip from the deep sleep when RTC_PREI power domain off. And also, the driver supports to store another set of configurations for the deep sleep via :cpp:member:`deep_slp_sens_cfg`, this set of configurations only takes effect during the deep sleep, you can customize the configurations to save more power. The configurations will be reset to the previous set after waking-up from the deep sleep. Please be aware that, not only deep sleep wake-up, but also light sleep wake-up will be enabled when the :cpp:member:`slp_wakeup_lvl` is :cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP`.
|
||||
:esp32: - Deep sleep wake-up: you need to set :cpp:member:`slp_wakeup_lvl` to :cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP` to enable the deep sleep wake-up by touch sensor. Note that in version {IDF_TARGET_TOUCH_SENSOR_VERSION}, enabling Deep-sleep wake-up will keep the RTC domain power on during the deep-sleep to maintain the operation of the touch sensor. At this time, any registered touch sensor channels can continue sampling and support waking up from Deep-sleep.
|
||||
:not esp32: - Deep sleep wake-up: beside setting :cpp:member:`slp_wakeup_lvl` to :cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP`, you need to specify :cpp:member:`deep_slp_chan` additionally. In order to reduce the power consumption, only the specified channel can wake-up the chip from the deep sleep when RTC_PREI power domain off. And also, the driver supports to store another set of configurations for the deep sleep via :cpp:member:`deep_slp_sens_cfg`, this set of configurations only takes effect during the deep sleep, you can customize the configurations to save more power. The configurations will be reset to the previous set after waking-up from the deep sleep. Please be aware that, not only deep sleep wake-up, but also light sleep wake-up will be enabled when the :cpp:member:`slp_wakeup_lvl` is :cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP`.
|
||||
|
||||
.. only:: not esp32
|
||||
|
||||
@@ -437,11 +477,28 @@ Application Examples
|
||||
|
||||
- :example:`peripherals/touch_sensor/touch_sens_basic` demonstrates how to register touch channels and read the data, including hardware requirements and project configuration instructions.
|
||||
|
||||
Application Notes
|
||||
-----------------
|
||||
|
||||
Touch Sensor Power Consumption Issues
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Due to the capacitive charging and discharging operation in the touch sensor measurements, it is a relatively high power-consuming peripheral. In applications with high power consumption requirements, the following methods can be helpful to reduce the power consumption.
|
||||
|
||||
.. list::
|
||||
|
||||
- Reduce the number of touch channels: Multiple functions (such as single-press, double-press, long press, etc.) can be multiplexed on the same channel, thereby reducing the number of touch sensors.
|
||||
- Increase the measurement interval: By increasing the measurement interval :cpp:member:`touch_sensor_config_t::meas_interval_us`, the measurement frequency will be reduced, thereby lowering down the power consumption.
|
||||
:esp32: - Reduce single measurement duration: By decreasing the single measurement duration :cpp:member:`touch_sensor_sample_config_t::charge_duration_ms`, the number of charging and discharging cycles is reduced, resulting in lower power consumption.
|
||||
:not esp32: - Reduce single measurement charging and discharging cycles: By lowering down the single measurement charging and discharging cycles :cpp:member:`touch_sensor_sample_config_t::charge_times`, power consumption will be decreased.
|
||||
:esp32s2 or esp32s3: - Set the current bias type to self-bias: By configuring :cpp:member:`touch_sensor_sample_config_t::bias_type` to :cpp:enumerator:`touch_bias_type_t::TOUCH_BIAS_TYPE_SELF` to use self-bias, which is more power-saving but less stable.
|
||||
:esp32 or esp32s2 or esp32s3: - Lower down the charging and discharging amplitudes: :cpp:member:`touch_sensor_sample_config_t::charge_volt_lim_l` and :cpp:member:`touch_sensor_sample_config_t::charge_volt_lim_h` can specify the lower voltage limit during the discharging and the upper voltage limit during the charging. Reducing both voltage limitations and the voltage error between them can also decrease the power consumption.
|
||||
:esp32 or esp32s2 or esp32s3: - Reduce the current bias intensity: Lowering down :cpp:member:`touch_channel_config_t::charge_speed` (i.e., the current magnitude of the current bias) can help to reduce the power consumption.
|
||||
:esp32p4: - Lower down the LDO voltage biasing intensity: Decreasing :cpp:member:`touch_channel_config_t::bias_volt` can reduce the power consumption.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. only:: esp32p4 or esp32s2 or esp32s3
|
||||
|
||||
.. include-build-file:: inc/touch_sens.inc
|
||||
.. include-build-file:: inc/touch_sens_types.inc
|
||||
.. include-build-file:: inc/touch_version_types.inc
|
||||
|
49
docs/en/api-reference/peripherals/cap_touch_sens/esp32.inc
Normal file
49
docs/en/api-reference/peripherals/cap_touch_sens/esp32.inc
Normal file
@@ -0,0 +1,49 @@
|
||||
.. This file gets included from other .rst files in this folder.
|
||||
.. It contains target-specific snippets.
|
||||
.. Comments and '---' lines act as delimiters.
|
||||
..
|
||||
.. This is necessary mainly because RST doesn't support substitutions
|
||||
.. (defined in RST, not in Python) inside code blocks. If that is ever implemented,
|
||||
.. These code blocks can be moved back to the main .rst files, with target-specific
|
||||
.. file names being replaced by substitutions.
|
||||
|
||||
.. touch-chan-mapping
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:widths: 20 20
|
||||
|
||||
* - Channel
|
||||
- GPIO
|
||||
|
||||
* - CH0
|
||||
- IO4
|
||||
|
||||
* - CH1
|
||||
- IO0
|
||||
|
||||
* - CH2
|
||||
- IO2
|
||||
|
||||
* - CH3
|
||||
- IO15
|
||||
|
||||
* - CH4
|
||||
- IO13
|
||||
|
||||
* - CH5
|
||||
- IO12
|
||||
|
||||
* - CH6
|
||||
- IO14
|
||||
|
||||
* - CH7
|
||||
- IO27
|
||||
|
||||
* - CH8
|
||||
- IO33
|
||||
|
||||
* - CH9
|
||||
- IO32
|
||||
|
||||
---
|
@@ -45,8 +45,7 @@ Peripherals API
|
||||
:SOC_LP_I2S_SUPPORTED: lp_i2s
|
||||
:SOC_LP_VAD_SUPPORTED: vad
|
||||
:SOC_TEMP_SENSOR_SUPPORTED: temp_sensor
|
||||
:esp32: touch_pad
|
||||
:SOC_TOUCH_SENSOR_SUPPORTED and not esp32: cap_touch_sens
|
||||
:SOC_TOUCH_SENSOR_SUPPORTED: cap_touch_sens
|
||||
:esp32s2: touch_element
|
||||
:SOC_TWAI_SUPPORTED: twai
|
||||
uart
|
||||
|
@@ -1,328 +0,0 @@
|
||||
Touch Sensor
|
||||
============
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
{IDF_TARGET_TOUCH_SENSOR_VERSION:default="v2", esp32="v1"}
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
.. warning::
|
||||
|
||||
The touch driver in this document has been deprecated, please move to the new document for the latest touch driver: :doc:`Capacitive Touch Sensor </api-reference/peripherals/cap_touch_sens>`.
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
A touch sensor system is built on a substrate which carries electrodes and relevant connections under a protective flat surface. When the surface is touched, the capacitance variation is used to evaluate if the touch was valid.
|
||||
|
||||
The sensing pads can be arranged in different combinations (e.g., matrix, slider), so that a larger area or more points can be detected. The touch pad sensing process is under the control of a hardware-implemented finite-state machine (FSM) which is initiated by software or a dedicated hardware timer.
|
||||
|
||||
For design, operation, and control registers of a touch sensor, see **{IDF_TARGET_NAME} Technical Reference Manual** > **On-Chip Sensors and Analog Signal Processing** [`PDF <{IDF_TARGET_TRM_EN_URL}#sensor>`__].
|
||||
|
||||
In-depth design details of touch sensors and firmware development guidelines for {IDF_TARGET_NAME} are available in `Touch Sensor Application Note <https://github.com/espressif/esp-iot-solution/blob/release/v1.0/documents/touch_pad_solution/touch_sensor_design_en.md>`_.
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
For more information about testing touch sensors in various configurations, please check the `Guide for ESP32-Sense-Kit <https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32/esp32-sense-kit/user_guide.html>`_.
|
||||
|
||||
Functionality Overview
|
||||
----------------------
|
||||
|
||||
Description of API is broken down into groups of functions to provide a quick overview of the following features:
|
||||
|
||||
- Initialization of touch pad driver
|
||||
- Configuration of touch pad GPIO pins
|
||||
- Taking measurements
|
||||
- Adjusting parameters of measurements
|
||||
- Filtering measurements
|
||||
- Touch detection methods
|
||||
- Setting up interrupts to report touch detection
|
||||
- Waking up from Sleep mode on interrupt
|
||||
|
||||
For detailed description of a particular function, please go to Section :ref:`touch_pad-api-reference`. Practical implementation of this API is covered in Section :ref:`Application Examples <touch_pad-api-examples>`.
|
||||
|
||||
Initialization
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Before using a touch pad, you need to initialize the touch pad driver by calling the function :cpp:func:`touch_pad_init`. This function sets several ``.._DEFAULT`` driver parameters listed in :ref:`touch_pad-api-reference` under **Macros**. It also removes the information about which pads have been touched before, if any, and disables interrupts.
|
||||
|
||||
If the driver is not required anymore, deinitialize it by calling :cpp:func:`touch_pad_deinit`.
|
||||
|
||||
Configuration
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
Enabling the touch sensor functionality for a particular GPIO is done with :cpp:func:`touch_pad_config()`. The following 10 capacitive touch pads are supported for {IDF_TARGET_NAME}.
|
||||
|
||||
.. list-table::
|
||||
:align: center
|
||||
:widths: 50 50
|
||||
:header-rows: 1
|
||||
|
||||
* - Touch Pad
|
||||
- GPIO Pin
|
||||
* - T0
|
||||
- GPIO4
|
||||
* - T1
|
||||
- GPIO0
|
||||
* - T2
|
||||
- GPIO2
|
||||
* - T3
|
||||
- MTDO
|
||||
* - T4
|
||||
- MTCK
|
||||
* - T5
|
||||
- MTDI
|
||||
* - T6
|
||||
- MTMS
|
||||
* - T7
|
||||
- GPIO27
|
||||
* - T8
|
||||
- 32K_XN
|
||||
* - T9
|
||||
- 32K_XP
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
Enabling the touch sensor functionality for a particular GPIO is done with :cpp:func:`touch_pad_config()`. The following 14 capacitive touch pads are supported for {IDF_TARGET_NAME}.
|
||||
|
||||
.. list-table::
|
||||
:align: center
|
||||
:widths: 50 50
|
||||
:header-rows: 1
|
||||
|
||||
* - Touch Pad
|
||||
- GPIO Pin
|
||||
* - T0
|
||||
- Internal channel, not connect to a GPIO
|
||||
* - T1
|
||||
- GPIO1
|
||||
* - T2
|
||||
- GPIO2
|
||||
* - T3
|
||||
- GPIO3
|
||||
* - T4
|
||||
- GPIO4
|
||||
* - T5
|
||||
- GPIO5
|
||||
* - T6
|
||||
- GPIO6
|
||||
* - T7
|
||||
- GPIO7
|
||||
* - T8
|
||||
- GPIO8
|
||||
* - T9
|
||||
- GPIO9
|
||||
* - T10
|
||||
- GPIO10
|
||||
* - T11
|
||||
- GPIO11
|
||||
* - T12
|
||||
- GPIO12
|
||||
* - T13
|
||||
- GPIO13
|
||||
* - T14
|
||||
- GPIO14
|
||||
|
||||
Use the function :cpp:func:`touch_pad_set_fsm_mode` to select if touch pad measurement (operated by FSM) should be started automatically by a hardware timer, or by software. If software mode is selected, use :cpp:func:`touch_pad_sw_start` to start the FSM.
|
||||
|
||||
Touch State Measurements
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
The following two functions come in handy to read raw or filtered measurements from the sensor:
|
||||
|
||||
* :cpp:func:`touch_pad_read_raw_data`
|
||||
* :cpp:func:`touch_pad_read_filtered`
|
||||
|
||||
They can also be used, for example, to evaluate a particular touch pad design by checking the range of sensor readings when a pad is touched or released. This information can be then used to establish a touch threshold.
|
||||
|
||||
.. note::
|
||||
|
||||
Before using :cpp:func:`touch_pad_read_filtered`, you need to initialize and configure the filter by calling specific filter functions described in Section `Filtering of Measurements`_.
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
The following function come in handy to read raw measurements from the sensor:
|
||||
|
||||
* :cpp:func:`touch_pad_read_raw_data`
|
||||
|
||||
It can also be used, for example, to evaluate a particular touch pad design by checking the range of sensor readings when a pad is touched or released. This information can be then used to establish a touch threshold.
|
||||
|
||||
Method of Measurements
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
The touch sensor counts the number of charge/discharge cycles over a fixed period of time (specified by :cpp:func:`touch_pad_set_measurement_clock_cycles`). The count result is the raw data that read from :cpp:func:`touch_pad_read_raw_data`. After finishing one measurement, the touch sensor sleeps until the next measurement start, this interval between two measurements can be set by :cpp:func:`touch_pad_set_measurement_interval`.
|
||||
|
||||
.. note::
|
||||
|
||||
If the specified clock cycles for measurement is too small, the result may be inaccurate, but increasing clock cycles will increase the power consumption as well. Additionally, the response of the touch sensor will slow down if the total time of the interval and measurement is too long.
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
The touch sensor records the period of time (i.e., the number of clock cycles) over a fixed charge/discharge cycles (specified by :cpp:func:`touch_pad_set_charge_discharge_times`). The count result is the raw data that read from :cpp:func:`touch_pad_read_raw_data`. After finishing one measurement, the touch sensor sleeps until the next measurement start, this interval between two measurements can be set by :cpp:func:`touch_pad_set_measurement_interval`.
|
||||
|
||||
.. note::
|
||||
|
||||
If the specified charge and discharge cycles for measurement is too small, the result may be inaccurate, but increasing charge and discharge cycles will increase the power consumption as well. Additionally, the response of the touch sensor will slow down if the total time of the interval and measurement is too long.
|
||||
|
||||
Optimization of Measurements
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A touch sensor has several configurable parameters to match the characteristics of a particular touch pad design. For instance, to sense smaller capacity changes, it is possible to narrow down the reference voltage range within which the touch pads are charged/discharged. The high and low reference voltages are set using the function :cpp:func:`touch_pad_set_voltage`.
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
Besides the ability to discern smaller capacity changes, a positive side effect is reduction of power consumption for low power applications. A likely negative effect is an increase in measurement noise. If the dynamic range of obtained readings is still satisfactory, then further reduction of power consumption might be done by reducing the measurement time with :cpp:func:`touch_pad_set_measurement_clock_cycles`.
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
Besides the ability to discern smaller capacity changes, a positive side effect is reduction of power consumption for low power applications. A likely negative effect is an increase in measurement noise. If the dynamic range of obtained readings is still satisfactory, then further reduction of power consumption might be done by reducing the measurement time with :cpp:func:`touch_pad_set_charge_discharge_times`.
|
||||
|
||||
The following list summarizes available measurement parameters and corresponding 'set' functions:
|
||||
|
||||
* Touch pad charge / discharge parameters:
|
||||
|
||||
* voltage range: :cpp:func:`touch_pad_set_voltage`
|
||||
* speed (slope): :cpp:func:`touch_pad_set_cnt_mode`
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
* Clock cycles of one measurement: :cpp:func:`touch_pad_set_measurement_clock_cycles`
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
* Charge and discharge times of one measurement: :cpp:func:`touch_pad_set_charge_discharge_times`
|
||||
|
||||
Relationship between the voltage range (high/low reference voltages), speed (slope), and measurement time is shown in the figure below.
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
.. figure:: ../../../_static/touch_pad-measurement-parameters.jpg
|
||||
:align: center
|
||||
:alt: Touch Pad - relationship between measurement parameters
|
||||
:figclass: align-center
|
||||
|
||||
Touch pad - relationship between measurement parameters
|
||||
|
||||
The last chart **Output** represents the touch sensor reading, i.e., the count of pulses collected within the measurement time.
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
.. figure:: ../../../_static/touch_pad-measurement-parameters-version2.png
|
||||
:align: center
|
||||
:alt: Touch Pad - relationship between measurement parameters
|
||||
:figclass: align-center
|
||||
|
||||
Touch pad - relationship between measurement parameters
|
||||
|
||||
The last chart **Output** represents the touch sensor reading, i.e., the time taken to accumulate the fixed number of cycles.
|
||||
|
||||
All functions are provided in pairs to **set** a specific parameter and to **get** the current parameter's value, e.g., :cpp:func:`touch_pad_set_voltage` and :cpp:func:`touch_pad_get_voltage`.
|
||||
|
||||
.. _touch_pad-api-filtering-of-measurements:
|
||||
|
||||
Filtering of Measurements
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
.. only:: esp32
|
||||
|
||||
If measurements are noisy, you can filter them with provided API functions. Before using the filter, please start it by calling :cpp:func:`touch_pad_filter_start`.
|
||||
|
||||
The filter type is IIR (infinite impulse response), and it has a configurable period that can be set with the function :cpp:func:`touch_pad_set_filter_period`.
|
||||
|
||||
You can stop the filter with :cpp:func:`touch_pad_filter_stop`. If not required anymore, the filter can be deleted by invoking :cpp:func:`touch_pad_filter_delete`.
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
If measurements are noisy, you can filter them with provided API functions. The {IDF_TARGET_NAME}'s touch functionality provide two sets of APIs for doing this.
|
||||
|
||||
There is an internal touch channel that is not connected to any external GPIO. The measurements from this denoise pad can be used to filters out interference introduced on all channels, such as noise introduced by the power supply and external EMI.
|
||||
|
||||
The denoise parameters are set with the function :cpp:func:`touch_pad_denoise_set_config` and started by with :cpp:func:`touch_pad_denoise_enable`
|
||||
|
||||
There is also a configurable hardware implemented IIR-filter (infinite impulse response). This IIR-filter is configured with the function :cpp:func:`touch_pad_filter_set_config` and enabled by calling :cpp:func:`touch_pad_filter_enable`
|
||||
|
||||
Touch Detection
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Touch detection is implemented in ESP32's hardware based on the user-configured threshold and raw measurements executed by FSM. Use the functions :cpp:func:`touch_pad_get_status` to check which pads have been touched and :cpp:func:`touch_pad_clear_status` to clear the touch status information.
|
||||
|
||||
Hardware touch detection can also be wired to interrupts. This is described in the next section.
|
||||
|
||||
If measurements are noisy and capacity changes are small, hardware touch detection might be unreliable. To resolve this issue, instead of using hardware detection/provided interrupts, implement measurement filtering and perform touch detection in your own application.
|
||||
|
||||
Touch Triggered Interrupts
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Before enabling an interrupt on a touch detection, you should establish a touch detection threshold. Use the functions described in `Touch State Measurements`_ to read and display sensor measurements when a pad is touched and released. Apply a filter if measurements are noisy and relative capacity changes are small. Depending on your application and environment conditions, test the influence of temperature and power supply voltage changes on measured values.
|
||||
|
||||
Once a detection threshold is established, it can be set during initialization with :cpp:func:`touch_pad_config` or at the runtime with :cpp:func:`touch_pad_set_thresh`.
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
In the next step, configure how interrupts are triggered. They can be triggered below or above the threshold, which is set with the function :cpp:func:`touch_pad_set_trigger_mode`.
|
||||
|
||||
Finally, configure and manage interrupt calls using the following functions:
|
||||
|
||||
* :cpp:func:`touch_pad_isr_register` / :cpp:func:`touch_pad_isr_deregister`
|
||||
* :cpp:func:`touch_pad_intr_enable` / :cpp:func:`touch_pad_intr_disable`
|
||||
|
||||
When interrupts are operational, you can obtain the information from which particular pad an interrupt came by invoking :cpp:func:`touch_pad_get_status` and clear the pad status with :cpp:func:`touch_pad_clear_status`.
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
.. note::
|
||||
|
||||
Interrupts on touch detection operate on raw/unfiltered measurements checked against user established threshold and are implemented in hardware. Enabling the software filtering API (see :ref:`touch_pad-api-filtering-of-measurements`) does not affect this process.
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
Wakeup from Sleep Mode
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If touch pad interrupts are used to wake up the chip from a sleep mode, you can select a certain configuration of pads (SET1 or both SET1 and SET2) that should be touched to trigger the interrupt and cause the subsequent wakeup. To do so, use the function :cpp:func:`touch_pad_set_trigger_source`.
|
||||
|
||||
Configuration of required bit patterns of pads may be managed for each 'SET' with:
|
||||
|
||||
* :cpp:func:`touch_pad_set_group_mask` / :cpp:func:`touch_pad_get_group_mask`
|
||||
* :cpp:func:`touch_pad_clear_group_mask`
|
||||
|
||||
.. _touch_pad-api-examples:
|
||||
|
||||
Application Examples
|
||||
--------------------
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
- :example:`peripherals/touch_sensor/touch_sensor_v1/touch_pad_read` demonstrates how to read and print raw or IIR filtered values from capacitive touch sensors on {IDF_TARGET_NAME}, and how to calibrate the sensors.
|
||||
- :example:`peripherals/touch_sensor/touch_sensor_v1/touch_pad_interrupt` demonstrates how to set up the {IDF_TARGET_NAME}'s capacitive touch pad to trigger an interrupt when touched, and how to use software detection for greater sensitivity, comparing the performance of hardware interrupt mode and software polling mode.
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
.. warning::
|
||||
|
||||
The example that uses legacy driver is removed, please see :example:`peripherals/touch_sensor/touch_sens_basic` for the usage of the new driver.
|
||||
|
||||
.. _touch_pad-api-reference:
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. include-build-file:: inc/touch_sensor.inc
|
||||
.. include-build-file:: inc/touch_sensor_common.inc
|
||||
|
||||
GPIO Lookup Macros
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Some useful macros can be used to specified the GPIO number of a touch pad channel, or vice versa. e.g.,
|
||||
|
||||
1. ``TOUCH_PAD_NUM5_GPIO_NUM`` is the GPIO number of channel 5 (12);
|
||||
2. ``TOUCH_PAD_GPIO4_CHANNEL`` is the channel number of GPIO 4 (channel 0).
|
||||
|
||||
.. include-build-file:: inc/touch_sensor_channel.inc
|
||||
.. include-build-file:: inc/touch_sensor_legacy_types.inc
|
@@ -7,3 +7,4 @@ Migration from 5.4 to 5.5
|
||||
:maxdepth: 1
|
||||
|
||||
system
|
||||
peripherals
|
||||
|
27
docs/en/migration-guides/release-5.x/5.5/peripherals.rst
Normal file
27
docs/en/migration-guides/release-5.x/5.5/peripherals.rst
Normal file
@@ -0,0 +1,27 @@
|
||||
Peripherals
|
||||
===========
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
.. only:: SOC_TOUCH_SENSOR_SUPPORTED
|
||||
|
||||
Touch Sensor
|
||||
------------
|
||||
|
||||
The touch sensor driver has been redesigned into :doc:`Capacitive Touch Sensor <../../../api-reference/peripherals/cap_touch_sens>`.
|
||||
|
||||
- The new driver is in ``esp_driver_touch_sens`` component and the include path is ``driver/touch_sens.h``.
|
||||
- The legacy driver is still available in the previous include path ``driver/touch_sensor.h``.
|
||||
|
||||
Although it is recommended to use the new driver APIs, the legacy driver is still available in the previous include path ``driver/touch_sensor.h``. However, by default, including ``driver/touch_sensor.h`` triggers the build warning below. The warning can be suppressed by the Kconfig option :ref:`CONFIG_TOUCH_SUPPRESS_DEPRECATE_WARN`.
|
||||
|
||||
The major changes are listed as follows:
|
||||
|
||||
Major Changes
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
- Now the touch sensor APIs based on different hardware version are integrated into one API set. And each sub-feature is configurable via its own individual API.
|
||||
- Almost all hardware configurations are public to provide enough flexibility, meanwhile the driver also offers some default configurations to save your time on figuring out a basic workable configuration.
|
||||
- The new touch driver implemented Finite-State Machine (FSM) to ensure a correct touch sensor operation. Please refer to the programming guide :doc:`Capacitive Touch Sensor <../../../api-reference/peripherals/cap_touch_sens>` for more details.
|
||||
- All new APIs are guaranteed to be thread-safe.
|
||||
- Implemented a software filter for the touch sensor V1 (ESP32), and open for customization.
|
@@ -3,7 +3,7 @@
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
{IDF_TARGET_TOUCH_SENSOR_VERSION:default="NOT_UPDATED", esp32s2="v2", esp32s3="v2", esp32p4="v3"}
|
||||
{IDF_TARGET_TOUCH_SENSOR_VERSION:default="NOT_UPDATED", esp32="v1", esp32s2="v2", esp32s3="v2", esp32p4="v3"}
|
||||
|
||||
概述
|
||||
------
|
||||
@@ -25,13 +25,40 @@
|
||||
| V1 | ESP32 | 第一代触摸传感器,触摸时读数变小 |
|
||||
+-----------+--------------+------------------------------------------------------------------------+
|
||||
| V2 | ESP32-S2 | 第二代触摸传感器,触摸时读数变大 |
|
||||
| | | 新增防水防潮、接近感应、睡眠唤醒功能 |
|
||||
| | | 新增硬件滤波器、基线、防水防潮、接近感应、睡眠唤醒功能 |
|
||||
| +--------------+------------------------------------------------------------------------+
|
||||
| | ESP32-S3 | 第二代触摸传感器,新增接近感应测量完成中断 |
|
||||
+-----------+--------------+------------------------------------------------------------------------+
|
||||
| V3 | ESP32-P4 | 第三代触摸传感器,新增跳频扫描 |
|
||||
+-----------+--------------+------------------------------------------------------------------------+
|
||||
|
||||
测量原理
|
||||
-----------
|
||||
|
||||
触摸传感器通过硬件内部的电流或电压偏置对触摸通道进行充电和放电操作,由于触摸通道存在内部电容和电路中的寄生电容,充放电时在通道引脚上表现为锯齿波。当手指贴近或者触摸该通道时,通道、人体和大地之间形成充放电回路,使得触摸通道耦合的电容增大,充放电速度变慢,即锯齿波周期增大。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
触摸传感器会在固定时间内对触摸通道进行充放电,并统计充放电次数,其计数结果即为原始数据。其中单次测量的充放电持续时间可由 :cpp:member:`touch_sensor_sample_config_t::charge_times` 指定,两次测量中间的间隔时间可由 :cpp:member:`touch_sensor_config_t::meas_interval_us` 指定。
|
||||
|
||||
.. figure:: ../../../_static/touch_pad-measurement-parameters.jpg
|
||||
:align: center
|
||||
:alt: Touch Pad - relationship between measurement parameters
|
||||
:figclass: align-center
|
||||
|
||||
触摸传感器工作原理示意图
|
||||
|
||||
.. only:: not esp32
|
||||
|
||||
触摸传感器会统计固定充放电次数所需的时钟周期数,其计数结果即为原始数据。其中单次测量的充放电次数可由 :cpp:member:`touch_sensor_sample_config_t::charge_duration_ms` 指定,两次测量中间的间隔时间可由 :cpp:member:`touch_sensor_config_t::meas_interval_us` 指定。
|
||||
|
||||
.. figure:: ../../../_static/touch_pad-measurement-parameters-version2.png
|
||||
:align: center
|
||||
:alt: Touch Pad - relationship between measurement parameters
|
||||
:figclass: align-center
|
||||
|
||||
触摸传感器工作原理示意图
|
||||
|
||||
触摸通道概览
|
||||
----------------------
|
||||
|
||||
@@ -93,8 +120,8 @@
|
||||
- `启用和禁用 <#touch-enable>`__
|
||||
- `连续扫描 <#touch-conti-scan>`__
|
||||
- `单次扫描 <#touch-oneshot-scan>`__
|
||||
- `基线值配置 <#touch-benchmark>`__
|
||||
- `测量值读数 <#touch-read>`__
|
||||
:SOC_TOUCH_SUPPORT_BENCHMARK: - `基线值配置 <#touch-benchmark>`__
|
||||
:SOC_TOUCH_SUPPORT_WATERPROOF: - `防水防潮配置 <#touch-waterproof>`__
|
||||
:SOC_TOUCH_SUPPORT_PROX_SENSING: - `接近感应配置 <#touch-prox-sensing>`__
|
||||
:SOC_TOUCH_SUPPORT_SLEEP_WAKEUP: - `睡眠唤醒配置 <#touch-sleep-wakeup>`__
|
||||
@@ -182,6 +209,14 @@
|
||||
|
||||
若需要注销滤波器,可再次调用 :cpp:func:`touch_sensor_config_filter` 并将第二个参数(即 :cpp:type:`touch_sensor_filter_config_t` 的配置结构体指针)设为 ``NULL`` 来注销滤波器功能。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
触摸传感器版本 {IDF_TARGET_TOUCH_SENSOR_VERSION} 本身不支持硬件滤波器,但是驱动中可以基于 ``esp_timer`` 设置周期性触发的软件滤波器。可以通过 :cpp:member:`touch_sensor_filter_config_t::interval_ms` 来制定软件滤波触发的间隔时间,另外 :cpp:member:`touch_sensor_filter_config_t::data_filter_fn` 接口支持指定自定义滤波函数,若无特殊滤波器要求,也可将该接口设为 ``NULL`` 来使用驱动中的默认滤波器。
|
||||
|
||||
.. only:: not esp32
|
||||
|
||||
触摸传感器版本 {IDF_TARGET_TOUCH_SENSOR_VERSION} 支持硬件滤波器。基线的滤波与更新策略可通过 :cpp:member:`touch_sensor_filter_config_t::benchmark` 进行配置,而读数值的滤波可通过 :cpp:member:`touch_sensor_filter_config_t::data` 进行配置。
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
// ...
|
||||
@@ -268,21 +303,6 @@
|
||||
// 触发单次扫描,并设置超时时间为 1000 ms
|
||||
ESP_ERROR_CHECK(touch_sensor_trigger_oneshot_scanning(sens_handle, 1000));
|
||||
|
||||
.. _touch-benchmark:
|
||||
|
||||
基线值配置
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
一般情况下,不需要额外设置触摸传感器的基线值,若有必要强制复位基线值到当前平滑值,可调用 :cpp:func:`touch_channel_config_benchmark`。
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
touch_chan_benchmark_config_t benchmark_cfg = {
|
||||
// 基线操作
|
||||
// ...
|
||||
};
|
||||
ESP_ERROR_CHECK(touch_channel_config_benchmark(chan_handle, &benchmark_cfg));
|
||||
|
||||
.. _touch-read:
|
||||
|
||||
测量值读数
|
||||
@@ -301,6 +321,23 @@
|
||||
// 读取滤波后的平滑数据
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle, TOUCH_CHAN_DATA_TYPE_SMOOTH, smooth_data));
|
||||
|
||||
.. _touch-benchmark:
|
||||
|
||||
.. only:: SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
|
||||
基线值配置
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
一般情况下,不需要额外设置触摸传感器的基线值,若有必要强制复位基线值到当前平滑值,可调用 :cpp:func:`touch_channel_config_benchmark`。
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
touch_chan_benchmark_config_t benchmark_cfg = {
|
||||
// 基线操作
|
||||
// ...
|
||||
};
|
||||
ESP_ERROR_CHECK(touch_channel_config_benchmark(chan_handle, &benchmark_cfg));
|
||||
|
||||
.. _touch-waterproof:
|
||||
|
||||
.. only:: SOC_TOUCH_SUPPORT_WATERPROOF
|
||||
@@ -377,8 +414,11 @@
|
||||
|
||||
若需要在睡眠过程中进行读数、配置等操作,可通过运行在 :doc:`超低功耗协处理器 ULP <../system/ulp>` 上的触摸传感器驱动 ``components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_touch_ulp_core.h`` 实现。
|
||||
|
||||
.. list::
|
||||
|
||||
- Light-sleep 状态唤醒:通过指定 :cpp:member:`slp_wakeup_lvl` 为 :cpp:enumerator:`TOUCH_LIGHT_SLEEP_WAKEUP` 即可启用触摸传感器 Light-sleep 唤醒功能。注意任何已注册的触摸传感器通道都会在 Light-sleep 状态下保持采样并支持唤醒 Light-sleep。
|
||||
- Deep-sleep 状态唤醒:启用触摸传感器 Deep-sleep 唤醒功能除了指定 :cpp:member:`slp_wakeup_lvl` 为 :cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP` 外,还需要指定 Deep-sleep 唤醒通道 :cpp:member:`deep_slp_chan`,注意只有该指定的通道才会在 Deep-sleep 状态下保持采样以及唤醒,以此降低在 Deep-sleep 状态下的功耗。此外,若需要在深度睡眠下使用另一套低功耗的配置来进一步降低功耗,可以通过 :cpp:member:`deep_slp_sens_cfg` 额外指定一套低功耗配置,在进入 Deep-sleep 前,驱动会应用这套配置,从 Deep-sleep 状态唤醒后,则会重新配置到之前的配置。请注意当 :cpp:member:`slp_wakeup_lvl` 配置为 :cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP` 后,触摸传感器不仅能唤醒 Deep-sleep 状态,还能唤醒 Light-sleep 状态。
|
||||
:esp32: - Deep-sleep 状态唤醒:通过指定 :cpp:member:`slp_wakeup_lvl` 为 :cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP` 即可启用触摸传感器 Deep-sleep 唤醒功能。注意版本 {IDF_TARGET_TOUCH_SENSOR_VERSION} 启用 Deep-sleep 唤醒后,会在 Deep-sleep 中保持 RTC 电源域开启,以维持触摸传感器工作,此时任何已注册的触摸传感器通道都可以在 Deep-sleep 状态下保持采样并支持唤醒 Deep-sleep。
|
||||
:not esp32: - Deep-sleep 状态唤醒:启用触摸传感器 Deep-sleep 唤醒功能除了指定 :cpp:member:`slp_wakeup_lvl` 为 :cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP` 外,还需要指定 Deep-sleep 唤醒通道 :cpp:member:`deep_slp_chan`,注意只有该指定的通道才会在 Deep-sleep 状态下保持采样以及唤醒,以此降低在 Deep-sleep 状态下的功耗。此外,若需要在深度睡眠下使用另一套低功耗的配置来进一步降低功耗,可以通过 :cpp:member:`deep_slp_sens_cfg` 额外指定一套低功耗配置,在进入 Deep-sleep 前,驱动会应用这套配置,从 Deep-sleep 状态唤醒后,则会重新配置到之前的配置。请注意当 :cpp:member:`slp_wakeup_lvl` 配置为 :cpp:enumerator:`TOUCH_DEEP_SLEEP_WAKEUP` 后,触摸传感器不仅能唤醒 Deep-sleep 状态,还能唤醒 Light-sleep 状态。
|
||||
|
||||
.. only:: not esp32
|
||||
|
||||
@@ -437,11 +477,28 @@
|
||||
|
||||
- :example:`peripherals/touch_sensor/touch_sens_basic` 演示了如何注册触摸通道并读取数据,并说明了硬件要求及项目配置。
|
||||
|
||||
应用注意事项
|
||||
------------
|
||||
|
||||
触摸传感器功耗问题
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
由于触摸传感器的测量需要对电容进行充放电,所以它是一个比较耗能的外设。在一些对功耗要求比较高的应用中,可采用以下几个方法来降低触摸传感器功耗。
|
||||
|
||||
.. list::
|
||||
|
||||
- 减少触摸通道数量:可在同一通道上复用多种功能(如单双击、长按等),从而减少触摸传感器的数量。
|
||||
- 增加测量间隔:通过增大 :cpp:member:`touch_sensor_config_t::meas_interval_us` 测量间隔,来降低测量频率,从而降低功耗。
|
||||
:esp32: - 降低单次测量时间:通过降低 :cpp:member:`touch_sensor_sample_config_t::charge_duration_ms` 单次测量时间,来减少充放电次数,从而降低功耗。
|
||||
:not esp32: - 减少单次测量充放电次数:通过减少 :cpp:member:`touch_sensor_sample_config_t::charge_times` 单次测量充放电次数,以降低功耗。
|
||||
:esp32s2 or esp32s3: - 电流偏置类型设为自偏置:通过设置 :cpp:member:`touch_sensor_sample_config_t::bias_type` 为 :cpp:enumerator:`touch_bias_type_t::TOUCH_BIAS_TYPE_SELF` 来使用功耗更低的自偏置。
|
||||
:esp32 or esp32s2 or esp32s3: - 降低充放电幅度::cpp:member:`touch_sensor_sample_config_t::charge_volt_lim_l` 和 :cpp:member:`touch_sensor_sample_config_t::charge_volt_lim_h` 用于指定放电时的电压下限和充电时的电压上限,同时降低这两个电压值以及上下限之间的压差可降低功耗。
|
||||
:esp32 or esp32s2 or esp32s3: - 降低电流偏置强度:降低 :cpp:member:`touch_channel_config_t::charge_speed` 充放电速度(即电流偏置的电流大小)从而降低功耗。
|
||||
:esp32p4: - 降低 LDO 电压偏置强度:降低 :cpp:member:`touch_channel_config_t::bias_volt` 从而降低功耗。
|
||||
|
||||
API 参考
|
||||
----------
|
||||
|
||||
.. only:: esp32p4 or esp32s2 or esp32s3
|
||||
|
||||
.. include-build-file:: inc/touch_sens.inc
|
||||
.. include-build-file:: inc/touch_sens_types.inc
|
||||
.. include-build-file:: inc/touch_version_types.inc
|
||||
|
@@ -0,0 +1,49 @@
|
||||
.. This file gets included from other .rst files in this folder.
|
||||
.. It contains target-specific snippets.
|
||||
.. Comments and '---' lines act as delimiters.
|
||||
..
|
||||
.. This is necessary mainly because RST doesn't support substitutions
|
||||
.. (defined in RST, not in Python) inside code blocks. If that is ever implemented,
|
||||
.. These code blocks can be moved back to the main .rst files, with target-specific
|
||||
.. file names being replaced by substitutions.
|
||||
|
||||
.. touch-chan-mapping
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:widths: 20 20
|
||||
|
||||
* - 通道
|
||||
- GPIO
|
||||
|
||||
* - CH0
|
||||
- IO4
|
||||
|
||||
* - CH1
|
||||
- IO0
|
||||
|
||||
* - CH2
|
||||
- IO2
|
||||
|
||||
* - CH3
|
||||
- IO15
|
||||
|
||||
* - CH4
|
||||
- IO13
|
||||
|
||||
* - CH5
|
||||
- IO12
|
||||
|
||||
* - CH6
|
||||
- IO14
|
||||
|
||||
* - CH7
|
||||
- IO27
|
||||
|
||||
* - CH8
|
||||
- IO33
|
||||
|
||||
* - CH9
|
||||
- IO32
|
||||
|
||||
---
|
@@ -45,8 +45,7 @@
|
||||
:SOC_LP_VAD_SUPPORTED: vad
|
||||
:SOC_JPEG_CODEC_SUPPORTED: jpeg
|
||||
:SOC_TEMP_SENSOR_SUPPORTED: temp_sensor
|
||||
:esp32: touch_pad
|
||||
:SOC_TOUCH_SENSOR_SUPPORTED and not esp32: cap_touch_sens
|
||||
:SOC_TOUCH_SENSOR_SUPPORTED: cap_touch_sens
|
||||
:esp32s2: touch_element
|
||||
:SOC_TWAI_SUPPORTED: twai
|
||||
uart
|
||||
|
@@ -1,328 +0,0 @@
|
||||
触摸传感器
|
||||
============
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
{IDF_TARGET_TOUCH_SENSOR_VERSION:default="v2", esp32="v1"}
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
.. warning::
|
||||
|
||||
该文档所演示的 Touch 驱动已弃用, 请移步新文档查看最新的 Touch 驱动: :doc:`Capacitive Touch Sensor </api-reference/peripherals/cap_touch_sens>`.
|
||||
|
||||
概述
|
||||
------------
|
||||
|
||||
触摸传感器系统由保护覆盖层、触摸电极、绝缘基板和走线组成,保护覆盖层位于最上层,绝缘基板上设有电极及走线。触摸覆盖层将引起电容变化,根据电容变化,可以判断此次触摸是否为有效触摸行为。
|
||||
|
||||
触摸传感器可以以矩阵或滑条等方式组合使用,从而覆盖更大触感区域及更多触感点。触摸传感由软件或专用硬件计时器发起,由有限状态机 (FSM) 硬件控制。
|
||||
|
||||
如需了解触摸传感器设计、操作及其控制寄存器等相关信息,请参考《`{IDF_TARGET_NAME} 技术参考手册 <{IDF_TARGET_TRM_CN_URL}>`_》(PDF) 中“片上传感器与模拟信号处理”章节。
|
||||
|
||||
请参考 `触摸传感器应用方案简介 <https://github.com/espressif/esp-iot-solution/blob/release/v1.0/documents/touch_pad_solution/touch_sensor_design_en.md>`_,查看触摸传感器设计详情和固件开发指南。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
如果想评估触摸传感器的多种应用场景,请查看 `ESP32 触摸功能开发套件 <https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32/esp32-sense-kit/user_guide.html>`_。
|
||||
|
||||
功能介绍
|
||||
----------------------
|
||||
|
||||
下面将 API 分解成几个函数组进行介绍:
|
||||
|
||||
- 初始化触摸传感器驱动程序
|
||||
- 配置触摸传感器 GPIO 管脚
|
||||
- 触摸状态测量
|
||||
- 调整测量参数(优化测量)
|
||||
- 滤波采样
|
||||
- 触摸监测方式
|
||||
- 设置中断信号监测触碰动作
|
||||
- 中断触发,唤醒睡眠模式
|
||||
|
||||
请前往 :ref:`touch_pad-api-reference` 章节,查看某一函数的具体描述。:ref:`应用示例 <touch_pad-api-examples>` 章节则介绍了此 API 的具体实现。
|
||||
|
||||
初始化触摸传感器驱动程序
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
使用触摸传感器之前,需要先调用 :cpp:func:`touch_pad_init` 函数初始化触摸传感器驱动程序。此函数设置了 :ref:`touch_pad-api-reference` 项下的 *Macros* 中列出的几项 ``.._DEFAULT`` 驱动程序参数,同时删除之前设置过的触摸传感器信息(如有),并禁用中断。
|
||||
|
||||
如果不再需要该驱动程序,可以调用 :cpp:func:`touch_pad_deinit` 释放已初始化的驱动程序。
|
||||
|
||||
配置触摸传感器 GPIO 管脚
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
可调用 :cpp:func:`touch_pad_config()` 使能某一 GPIO 的触感功能。{IDF_TARGET_NAME} 最多可支持 10 个电容式触摸传感器通道。
|
||||
|
||||
.. list-table::
|
||||
:align: center
|
||||
:widths: 50 50
|
||||
:header-rows: 1
|
||||
|
||||
* - 触摸传感器通道
|
||||
- GPIO 管脚
|
||||
* - T0
|
||||
- GPIO4
|
||||
* - T1
|
||||
- GPIO0
|
||||
* - T2
|
||||
- GPIO2
|
||||
* - T3
|
||||
- MTDO
|
||||
* - T4
|
||||
- MTCK
|
||||
* - T5
|
||||
- MTDI
|
||||
* - T6
|
||||
- MTMS
|
||||
* - T7
|
||||
- GPIO27
|
||||
* - T8
|
||||
- 32K_XN
|
||||
* - T9
|
||||
- 32K_XP
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
可调用 :cpp:func:`touch_pad_config()` 使能某一 GPIO 的触感功能。{IDF_TARGET_NAME} 最多可支持 14 个电容式触摸传感器通道。
|
||||
|
||||
.. list-table::
|
||||
:align: center
|
||||
:widths: 50 50
|
||||
:header-rows: 1
|
||||
|
||||
* - 触摸传感器通道
|
||||
- 管脚
|
||||
* - T0
|
||||
- 内部通道,无对应管脚
|
||||
* - T1
|
||||
- GPIO1
|
||||
* - T2
|
||||
- GPIO2
|
||||
* - T3
|
||||
- GPIO3
|
||||
* - T4
|
||||
- GPIO4
|
||||
* - T5
|
||||
- GPIO5
|
||||
* - T6
|
||||
- GPIO6
|
||||
* - T7
|
||||
- GPIO7
|
||||
* - T8
|
||||
- GPIO8
|
||||
* - T9
|
||||
- GPIO9
|
||||
* - T10
|
||||
- GPIO10
|
||||
* - T11
|
||||
- GPIO11
|
||||
* - T12
|
||||
- GPIO12
|
||||
* - T13
|
||||
- GPIO13
|
||||
* - T14
|
||||
- GPIO14
|
||||
|
||||
使用 :cpp:func:`touch_pad_set_fsm_mode` 选择触摸传感器测量(由 FSM 操作)是由硬件定时器自动启动,还是由软件自动启动。如果选择软件模式,请使用 :cpp:func:`touch_pad_sw_start` 启动 FSM。
|
||||
|
||||
触摸状态测量
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
借助以下两个函数从传感器读取原始数据和滤波后的数据:
|
||||
|
||||
* :cpp:func:`touch_pad_read_raw_data`
|
||||
* :cpp:func:`touch_pad_read_filtered`
|
||||
|
||||
这两个函数也可以用于检查触碰和释放触摸传感器时传感器读数变化范围,然后根据这些信息设定触摸传感器的触摸阈值。
|
||||
|
||||
.. note::
|
||||
|
||||
使用 :cpp:func:`touch_pad_read_filtered` 之前,需要先调用 `滤波采样`_ 中特定的滤波器函数来初始化并配置该滤波器。
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
借助以下函数从传感器读取原始数据:
|
||||
|
||||
* :cpp:func:`touch_pad_read_raw_data`
|
||||
|
||||
该函数也可以用于检查触碰和释放触摸传感器时传感器读数变化范围,然后根据这些信息设定触摸传感器的触摸阈值。
|
||||
|
||||
测量方式
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
触摸传感器会统计固定时间内的充放电次数,其计数结果即为原始数据,可由 :cpp:func:`touch_pad_read_raw_data` 读出。上述固定时间可通过 :cpp:func:`touch_pad_set_measurement_clock_cycles` 设置。完成一次测量后,触摸传感器会在下次测量开始前保持睡眠状态。两次测量之前的间隔时间可由 :cpp:func:`touch_pad_set_measurement_interval` 进行设置。
|
||||
|
||||
.. note::
|
||||
|
||||
若设置的计数时间太短(即测量持续的时钟周期数太小),则可能导致结果不准确,但是过大的计数时间也会造成功耗上升。另外,若睡眠时间加测量时间的总时间过长,则会造成触摸传感器响应变慢。
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
触摸传感器会统计固定充放电次数所需的时间(即所需时钟周期数),其结果即为原始数据,可由 :cpp:func:`touch_pad_read_raw_data` 读出。上述固定的充放电次数可通过 :cpp:func:`touch_pad_set_charge_discharge_times` 设置。完成一次测量后,触摸传感器会在下次测量开始前保持睡眠状态。两次测量之前的间隔时间可由 :cpp:func:`touch_pad_set_measurement_interval` 进行设置。
|
||||
|
||||
.. note::
|
||||
|
||||
若设置的充放电次数太少,则可能导致结果不准确,但是充放电次数过多也会造成功耗上升。另外,若睡眠时间加测量时间的总时间过长,则会造成触摸传感器响应变慢。
|
||||
|
||||
优化测量
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
触摸传感器设有数个可配置参数,以适应触摸传感器设计特点。例如,如果需要感知较细微的电容变化,则可以缩小触摸传感器充放电的参考电压范围。使用 :cpp:func:`touch_pad_set_voltage` 函数,可以设置电压参考低值和参考高值。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
优化测量除了可以识别细微的电容变化之外,还可以降低应用程序功耗,但可能会增加测量噪声干扰。如果得到的动态读数范围结果比较理想,则可以调用 :cpp:func:`touch_pad_set_measurement_clock_cycles` 函数来减少测量时间,从而进一步降低功耗。
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
优化测量除了可以识别细微的电容变化之外,还可以降低应用程序功耗,但可能会增加测量噪声干扰。如果得到的动态读数范围结果比较理想,则可以调用 :cpp:func:`touch_pad_set_charge_discharge_times` 函数来减少测量时间,从而进一步降低功耗。
|
||||
|
||||
可用的测量参数及相应的 'set' 函数总结如下:
|
||||
|
||||
* 触摸传感器充放电参数:
|
||||
|
||||
* 电压门限::cpp:func:`touch_pad_set_voltage`
|
||||
* 速率(斜率)::cpp:func:`touch_pad_set_cnt_mode`
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
* 单次测量所用的时钟周期::cpp:func:`touch_pad_set_measurement_clock_cycles`
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
* 单次测量所需充放电次数::cpp:func:`touch_pad_set_charge_discharge_times`
|
||||
|
||||
电压门限(参考低值/参考高值)、速率(斜率)与测量时间的关系如下图所示:
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
.. figure:: ../../../_static/touch_pad-measurement-parameters.jpg
|
||||
:align: center
|
||||
:alt: Touch Pad - relationship between measurement parameters
|
||||
:figclass: align-center
|
||||
|
||||
触摸传感器 - 测量参数之间的关系
|
||||
|
||||
上图中的 **Output** 代表触摸传感器读值,即一个测量周期内测得的脉冲计数值。
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
.. figure:: ../../../_static/touch_pad-measurement-parameters-version2.png
|
||||
:align: center
|
||||
:alt: Touch Pad - relationship between measurement parameters
|
||||
:figclass: align-center
|
||||
|
||||
触摸传感器 - 测量参数之间的关系
|
||||
|
||||
上图中的 **Output** 代表触摸传感器读值,即固定充放电次数所需的时间。
|
||||
|
||||
所有函数均成对出现,用于设定某一特定参数,并获取当前参数值。例如::cpp:func:`touch_pad_set_voltage` 和 :cpp:func:`touch_pad_get_voltage`。
|
||||
|
||||
.. _touch_pad-api-filtering-of-measurements:
|
||||
|
||||
滤波采样
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
.. only:: esp32
|
||||
|
||||
如果测量中存在噪声,可以使用提供的 API 函数对采样进行滤波。使用滤波器之前,请先调用 :cpp:func:`touch_pad_filter_start` 启动该滤波器。
|
||||
|
||||
滤波器类型为 IIR(无限脉冲响应滤波器),可以调用 :cpp:func:`touch_pad_set_filter_period` 配置此类滤波器的采样周期。
|
||||
|
||||
如需停止滤波器,请调用 :cpp:func:`touch_pad_filter_stop` 函数。如果不再使用该滤波器,请调用 :cpp:func:`touch_pad_filter_delete` 删除此滤波器。
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
如果测量中存在噪声,可以使用提供的 API 函数对采样进行滤波。{IDF_TARGET_NAME} 的触摸功能提供了两套 API 可实现此功能。
|
||||
|
||||
一个是内部触摸通道,它没有连接到任何外部 GPIO。该降噪板的测量值可用于过滤所有通道上的干扰,如来自电源和外部 EMI 的噪声。
|
||||
|
||||
降噪参数由 :cpp:func:`touch_pad_denoise_set_config` 设置并由 :cpp:func:`touch_pad_denoise_enable` 启动。
|
||||
|
||||
另一是可配置的硬件实现 IIR-滤波器(无限脉冲响应滤波器),该滤波器可通过调用 :cpp:func:`touch_pad_filter_set_config` 函数进行配置,调用 :cpp:func:`touch_pad_filter_enable` 函数启用。
|
||||
|
||||
触摸监测
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
触摸监测基于配置的阈值和 FSM 执行的原始测量,并由 ESP32 硬件实现。可以调用 :cpp:func:`touch_pad_get_status` 查看被触碰的触摸传感器,或调用 :cpp:func:`touch_pad_clear_status` 清除触摸状态信息。
|
||||
|
||||
也可以将硬件触摸监测连接至中断,详细介绍见下一章节。
|
||||
|
||||
如果测量中存在噪声,且电容变化幅度较小,硬件触摸监测结果可能就不太理想。如需解决这一问题,不建议使用硬件监测或中断信号,建议在自己的应用程序中进行采样滤波,并执行触摸监测。
|
||||
|
||||
中断触发
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
在对触摸监测启用中断之前,请先设置一个触摸监测阈值。然后使用 `触摸状态测量`_ 中所述的函数读取并显示触摸和释放触摸传感器时测得的结果。如果测量中存在噪声且相对电容变化较小,请使用滤波器。也可以根据应用程序和环境条件,测试温度和电源电压变化对测量值的影响。
|
||||
|
||||
确定监测阈值后就可以在初始化时调用 :cpp:func:`touch_pad_config` 设置此阈值,或在运行时调用 :cpp:func:`touch_pad_set_thresh` 设置此阈值。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
下一步就是设置如何触发中断。可以设置在阈值以下或以上触发中断,具体触发模式由函数 :cpp:func:`touch_pad_set_trigger_mode` 设置。
|
||||
|
||||
最后可以使用以下函数配置和管理中断调用:
|
||||
|
||||
* :cpp:func:`touch_pad_isr_register` / :cpp:func:`touch_pad_isr_deregister`
|
||||
* :cpp:func:`touch_pad_intr_enable` / :cpp:func:`touch_pad_intr_disable`
|
||||
|
||||
中断配置完成后,可以调用 :cpp:func:`touch_pad_get_status` 查看中断信号来自哪个触摸传感器,也可以调用 :cpp:func:`touch_pad_clear_status` 清除触摸传感器状态信息。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
.. note::
|
||||
|
||||
触摸监测中的中断信号基于原始/未经滤波的采样(对比设置的阈值),并在硬件中实现。启用软件滤波 API(请参考 :ref:`touch_pad-api-filtering-of-measurements`)并不会影响这一过程。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
从睡眠模式唤醒
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
如果使用触摸传感器中断将芯片从睡眠模式唤醒,可以选择配置一些触摸传感器,例如 SET1 或 SET1 和 SET2,触摸这些触摸传感器将触发中断并唤醒芯片。请调用 :cpp:func:`touch_pad_set_trigger_source` 实现上述操作。
|
||||
|
||||
可以使用以下函数管理 'SET' 中触摸传感器所需的位模式配置:
|
||||
|
||||
* :cpp:func:`touch_pad_set_group_mask` / :cpp:func:`touch_pad_get_group_mask`
|
||||
* :cpp:func:`touch_pad_clear_group_mask`
|
||||
|
||||
.. _touch_pad-api-examples:
|
||||
|
||||
应用示例
|
||||
--------
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
- :example:`peripherals/touch_sensor/touch_sensor_v1/touch_pad_read` 演示了如何在 {IDF_TARGET_NAME} 上读取并打印电容触摸传感器的原始值或 IIR 滤波后的值,以及如何校准传感器。
|
||||
- :example:`peripherals/touch_sensor/touch_sensor_v1/touch_pad_interrupt` 演示了如何设置 {IDF_TARGET_NAME} 的电容触摸板,使其在被触摸时触发中断,以及如何使用软件监测来提高灵敏度,并比较硬件中断模式和软件轮询模式的性能。
|
||||
|
||||
.. only:: esp32s2 or esp32s3
|
||||
|
||||
.. warning::
|
||||
|
||||
使用老驱动的例程已移除,新驱动用法请参考 :example:`peripherals/touch_sensor/touch_sens_basic`。
|
||||
|
||||
.. _touch_pad-api-reference:
|
||||
|
||||
API 参考
|
||||
-------------
|
||||
|
||||
.. include-build-file:: inc/touch_sensor.inc
|
||||
.. include-build-file:: inc/touch_sensor_common.inc
|
||||
|
||||
GPIO 宏查找表
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
可以使用宏定义某一触摸传感器通道的 GPIO,或定义某一 GPIO 的通道。例如:
|
||||
|
||||
1. ``TOUCH_PAD_NUM5_GPIO_NUM`` 定义了通道 5 的 GPIO(即 GPIO 12);
|
||||
2. ``TOUCH_PAD_GPIO4_CHANNEL`` 定义了 GPIO 4 的通道(即通道 0)。
|
||||
|
||||
.. include-build-file:: inc/touch_sensor_channel.inc
|
||||
.. include-build-file:: inc/touch_sensor_legacy_types.inc
|
@@ -7,3 +7,4 @@
|
||||
:maxdepth: 1
|
||||
|
||||
system
|
||||
peripherals
|
||||
|
27
docs/zh_CN/migration-guides/release-5.x/5.5/peripherals.rst
Normal file
27
docs/zh_CN/migration-guides/release-5.x/5.5/peripherals.rst
Normal file
@@ -0,0 +1,27 @@
|
||||
Peripherals
|
||||
===========
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
.. only:: SOC_TOUCH_SENSOR_SUPPORTED
|
||||
|
||||
Touch Sensor
|
||||
------------
|
||||
|
||||
电容式触摸传感器的驱动已更新为 :doc:`Capacitive Touch Sensor <../../../api-reference/peripherals/cap_touch_sens>`.
|
||||
|
||||
- The new driver is in ``esp_driver_touch_sens`` component and the include path is ``driver/touch_sens.h``.
|
||||
- The legacy driver is still available in the previous include path ``driver/touch_sensor.h``.
|
||||
|
||||
尽管我们推荐使用新的驱动 API, 旧版驱动仍然可用,其头文件引用路径为 ``driver/touch_sensor.h``。但是,引用 ``driver/touch_sensor.h`` 会默认触发如下编译警告,可通过配置 Kconfig 选项 :ref:`CONFIG_TOUCH_SUPPRESS_DEPRECATE_WARN` 关闭该警告。
|
||||
|
||||
使用方法上的主要更新如下所示:
|
||||
|
||||
主要使用方法更新
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- 基于不同硬件版本的触摸传感器 API 现已经整合为一套 API,每个子功能都有独立的 API 可配置。
|
||||
- 所有的硬件配置都可配置,以提供足够的灵活性,同时驱动程序还提供了一些默认配置,以便您不必花费时间去确定可用的基本配置。
|
||||
- 新的触摸驱动实现了有限状态机(FSM)以确保正确的触摸传感器操作。请参阅编程指南 :doc:`电容式触摸传感器 <../../../api-reference/peripherals/cap_touch_sens>` 了解更多详情。
|
||||
- 所有新的API都保证是线程安全的。
|
||||
- 为触摸传感器 V1(ESP32)实现了软件滤波器,并开放自定义滤波器接口。
|
@@ -461,16 +461,9 @@ examples/peripherals/touch_sensor/touch_element:
|
||||
examples/peripherals/touch_sensor/touch_sens_basic:
|
||||
disable:
|
||||
- if: SOC_TOUCH_SENSOR_SUPPORTED != 1
|
||||
- if: SOC_TOUCH_SENSOR_VERSION == 1
|
||||
temporary: true
|
||||
reason: not supported yet
|
||||
depends_components:
|
||||
- esp_driver_touch_sens
|
||||
|
||||
examples/peripherals/touch_sensor/touch_sensor_v1:
|
||||
disable:
|
||||
- if: SOC_TOUCH_SENSOR_VERSION != 1
|
||||
|
||||
examples/peripherals/twai/twai_alert_and_recovery:
|
||||
disable:
|
||||
- if: SOC_TWAI_SUPPORTED != 1
|
||||
|
@@ -1,7 +1,7 @@
|
||||
| Supported Targets | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- |
|
||||
|
||||
# Capacity Touch Sensor Example (for hardware version 3)
|
||||
# Capacity Touch Sensor Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
@@ -34,42 +34,44 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
|
||||
|
||||
## Example Output
|
||||
|
||||
You can see the following output in the monitor if the example runs successfully:
|
||||
You can see the following output in the monitor if the example runs successfully (take ESP32-P4 for example):
|
||||
|
||||
```
|
||||
W (461) touch: [sample_cfg_id 0] clock precision loss, expect 4000000 hz, got 4006725 hz
|
||||
W (461) touch: [sample_cfg_id 1] clock precision loss, expect 8000000 hz, got 8013450 hz
|
||||
W (461) touch: [sample_cfg_id 2] clock precision loss, expect 16000000 hz, got 16026900 hz
|
||||
Touch [CH 0] enabled on GPIO2
|
||||
Touch [CH 1] enabled on GPIO3
|
||||
Touch [CH 2] enabled on GPIO4
|
||||
Touch [CH 3] enabled on GPIO5
|
||||
=================================
|
||||
Initial benchmark and new threshold are:
|
||||
[CH 0] 0: 4114, 411 1: 2057, 205 2: 1028, 102
|
||||
[CH 1] 0: 4643, 464 1: 2322, 232 2: 1160, 116
|
||||
[CH 2] 0: 4848, 484 1: 2424, 242 2: 1211, 121
|
||||
[CH 3] 0: 4340, 434 1: 2170, 217 2: 1085, 108
|
||||
Touch [CH 0] 0: 5161, 77 1: 5121, 76 2: 2533, 37
|
||||
Touch [CH 1] 0: 5007, 75 1: 5036, 75 2: 2464, 36
|
||||
Touch [CH 2] 0: 5086, 76 1: 5056, 75 2: 2487, 37
|
||||
Touch [CH 3] 0: 4965, 74 1: 4989, 74 2: 2433, 36
|
||||
=================================
|
||||
benchmark [CH 0]: 4115 2056 1028
|
||||
chan_data [CH 0]: 4115 2056 1028
|
||||
benchmark [CH 0]: 5160 5121 2533
|
||||
smooth [CH 0]: 5160 5122 2533
|
||||
|
||||
benchmark [CH 1]: 4644 2322 1160
|
||||
chan_data [CH 1]: 4644 2322 1160
|
||||
benchmark [CH 1]: 5007 5036 2464
|
||||
smooth [CH 1]: 5007 5036 2464
|
||||
|
||||
benchmark [CH 2]: 4848 2423 1211
|
||||
chan_data [CH 2]: 4848 2423 1211
|
||||
benchmark [CH 2]: 5086 5056 2487
|
||||
smooth [CH 2]: 5086 5056 2487
|
||||
|
||||
benchmark [CH 3]: 4337 2168 1084
|
||||
chan_data [CH 3]: 4337 2168 1084
|
||||
benchmark [CH 3]: 4964 4989 2433
|
||||
smooth [CH 3]: 4964 4990 2433
|
||||
|
||||
=================================
|
||||
benchmark [CH 0]: 4109 2054 1027
|
||||
chan_data [CH 0]: 4109 2054 1027
|
||||
benchmark [CH 0]: 5159 5121 2533
|
||||
smooth [CH 0]: 5160 5121 2533
|
||||
|
||||
benchmark [CH 1]: 4638 2318 1158
|
||||
chan_data [CH 1]: 4638 2318 1158
|
||||
benchmark [CH 1]: 5005 5036 2464
|
||||
smooth [CH 1]: 5006 5035 2464
|
||||
|
||||
benchmark [CH 2]: 4843 2421 1210
|
||||
chan_data [CH 2]: 4845 2421 1210
|
||||
benchmark [CH 2]: 5085 5056 2487
|
||||
smooth [CH 2]: 5086 5056 2488
|
||||
|
||||
benchmark [CH 3]: 4334 2167 1084
|
||||
chan_data [CH 3]: 4334 2167 1083
|
||||
benchmark [CH 3]: 4964 4990 2433
|
||||
smooth [CH 3]: 4964 4990 2433
|
||||
...
|
||||
```
|
||||
|
||||
@@ -77,46 +79,33 @@ And if you touch and release a button, you will see the following output:
|
||||
|
||||
```
|
||||
...
|
||||
I (1321) touch_callback: [CH 1] active
|
||||
I (2861) touch_callback: [CH 0] active
|
||||
=================================
|
||||
benchmark [CH 0]: 4111 2055 1027
|
||||
chan_data [CH 0]: 4111 2055 1027
|
||||
benchmark [CH 0]: 5755 5425 2762
|
||||
smooth [CH 0]: 5997 5666 2841
|
||||
|
||||
benchmark [CH 1]: 4676 2339 1168
|
||||
chan_data [CH 1]: 17701 8798 4399
|
||||
benchmark [CH 1]: 5025 5049 2473
|
||||
smooth [CH 1]: 5025 5050 2473
|
||||
|
||||
benchmark [CH 2]: 4870 2434 1217
|
||||
chan_data [CH 2]: 4867 2433 1217
|
||||
benchmark [CH 2]: 5104 5066 2495
|
||||
smooth [CH 2]: 5105 5066 2495
|
||||
|
||||
benchmark [CH 3]: 4333 2165 1082
|
||||
chan_data [CH 3]: 4333 2165 1082
|
||||
benchmark [CH 3]: 4982 5002 2441
|
||||
smooth [CH 3]: 4982 5001 2441
|
||||
|
||||
I (3021) touch_callback: [CH 0] inactive
|
||||
=================================
|
||||
benchmark [CH 0]: 4109 2053 1027
|
||||
chan_data [CH 0]: 4108 2053 1027
|
||||
benchmark [CH 0]: 5756 5428 2763
|
||||
smooth [CH 0]: 5756 5428 2764
|
||||
|
||||
benchmark [CH 1]: 4676 2339 1168
|
||||
chan_data [CH 1]: 11256 8817 4363
|
||||
benchmark [CH 1]: 5025 5048 2473
|
||||
smooth [CH 1]: 5026 5048 2474
|
||||
|
||||
benchmark [CH 2]: 4868 2434 1217
|
||||
chan_data [CH 2]: 4862 2429 1214
|
||||
benchmark [CH 2]: 5104 5066 2495
|
||||
smooth [CH 2]: 5104 5066 2495
|
||||
|
||||
benchmark [CH 3]: 4332 2165 1082
|
||||
chan_data [CH 3]: 4330 2164 1081
|
||||
|
||||
I (1931) touch_callback: [CH 1] inactive
|
||||
=================================
|
||||
benchmark [CH 0]: 4106 2052 1026
|
||||
chan_data [CH 0]: 4106 2052 1026
|
||||
|
||||
benchmark [CH 1]: 4649 2323 1161
|
||||
chan_data [CH 1]: 4650 2323 1161
|
||||
|
||||
benchmark [CH 2]: 4847 2422 1211
|
||||
chan_data [CH 2]: 4846 2422 1211
|
||||
|
||||
benchmark [CH 3]: 4329 2163 1082
|
||||
chan_data [CH 3]: 4329 2164 1082
|
||||
benchmark [CH 3]: 4981 5002 2441
|
||||
smooth [CH 3]: 4981 5002 2441
|
||||
...
|
||||
```
|
||||
|
||||
|
@@ -1,3 +1,2 @@
|
||||
idf_component_register(SRCS "touch_sens_basic_example_main.c"
|
||||
REQUIRES esp_driver_touch_sens
|
||||
INCLUDE_DIRS ".")
|
||||
REQUIRES esp_driver_touch_sens)
|
||||
|
@@ -0,0 +1,3 @@
|
||||
dependencies:
|
||||
touch_sens_examples_common:
|
||||
path: ${IDF_PATH}/examples/peripherals/touch_sensor/touch_sens_examples_common
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
@@ -12,13 +12,21 @@
|
||||
#include "esp_check.h"
|
||||
#include "touch_sens_example_config.h"
|
||||
|
||||
static touch_sensor_handle_t s_sens_handle = NULL;
|
||||
static touch_channel_handle_t s_chan_handle[EXAMPLE_TOUCH_CHANNEL_NUM] = {};
|
||||
// Touch version 3 supports multiple sample configurations (i.e. supports frequency hopping),
|
||||
// others only have one set of sample configurations.
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_NUM TOUCH_SAMPLE_CFG_NUM // Up to 'TOUCH_SAMPLE_CFG_NUM'
|
||||
#define EXAMPLE_TOUCH_CHANNEL_NUM 4
|
||||
#define EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES 3
|
||||
|
||||
ESP_STATIC_ASSERT(EXAMPLE_TOUCH_SAMPLE_CFG_NUM <= TOUCH_SAMPLE_CFG_NUM, "sample configuration number exceed the supported number");
|
||||
ESP_STATIC_ASSERT(EXAMPLE_TOUCH_CHANNEL_NUM <= (TOUCH_MAX_CHAN_ID - TOUCH_MIN_CHAN_ID + 1), "touch channel number exceed the max supported number ");
|
||||
|
||||
// Active threshold to benchmark ratio. (i.e., touch will be activated when data >= benchmark * (1 + ratio))
|
||||
static float s_thresh2bm_ratio[EXAMPLE_TOUCH_CHANNEL_NUM] = {
|
||||
[0 ... EXAMPLE_TOUCH_CHANNEL_NUM - 1] = 0.015f, // 1.5%
|
||||
};
|
||||
// The touch channel IDs that used in this example
|
||||
// For the corresponding GPIOs of these channel, please refer to 'touch_sensor_channel.h'
|
||||
static int s_channel_id[EXAMPLE_TOUCH_CHANNEL_NUM] = {
|
||||
TOUCH_MIN_CHAN_ID,
|
||||
TOUCH_MIN_CHAN_ID + 1,
|
||||
@@ -38,50 +46,62 @@ bool example_touch_on_inactive_callback(touch_sensor_handle_t sens_handle, const
|
||||
return false;
|
||||
}
|
||||
|
||||
static void example_touch_do_initial_scanning(void)
|
||||
static void example_touch_do_initial_scanning(touch_sensor_handle_t sens_handle, touch_channel_handle_t chan_handle[])
|
||||
{
|
||||
/* Enable the touch sensor to do the initial scanning, so that to initialize the channel data */
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(s_sens_handle));
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(sens_handle));
|
||||
|
||||
/* Scan the enabled touch channels for several times, to make sure the initial channel data is stable */
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES; i++) {
|
||||
ESP_ERROR_CHECK(touch_sensor_trigger_oneshot_scanning(s_sens_handle, 2000));
|
||||
ESP_ERROR_CHECK(touch_sensor_trigger_oneshot_scanning(sens_handle, 2000));
|
||||
}
|
||||
|
||||
/* Disable the touch channel to rollback the state */
|
||||
ESP_ERROR_CHECK(touch_sensor_disable(s_sens_handle));
|
||||
ESP_ERROR_CHECK(touch_sensor_disable(sens_handle));
|
||||
|
||||
/* (Optional) Read the initial channel benchmark and reconfig the channel active threshold accordingly */
|
||||
printf("Initial benchmark and new threshold are:\n");
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
/* Read the initial benchmark of the touch channel */
|
||||
uint32_t benchmark[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {};
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(s_chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark));
|
||||
#if SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark));
|
||||
#else
|
||||
/* Read smooth data instead if the touch V1 hardware does not support benchmark */
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_SMOOTH, benchmark));
|
||||
#endif // SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
/* Calculate the proper active thresholds regarding the initial benchmark */
|
||||
printf("[CH %d]", i);
|
||||
printf("Touch [CH %d]", s_channel_id[i]);
|
||||
/* Generate the default channel configuration and then update the active threshold based on the real benchmark */
|
||||
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
|
||||
for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) {
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1
|
||||
// Touch V1 (ESP32) uses absolute threshold.
|
||||
chan_cfg.abs_active_thresh[j] = (uint32_t)(benchmark[j] * (1 - s_thresh2bm_ratio[i]));
|
||||
printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.abs_active_thresh[j]);
|
||||
#else
|
||||
chan_cfg.active_thresh[j] = (uint32_t)(benchmark[j] * s_thresh2bm_ratio[i]);
|
||||
printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.active_thresh[j]);
|
||||
#endif // SOC_TOUCH_SENSOR_VERSION == 1
|
||||
}
|
||||
printf("\n");
|
||||
/* Update the channel configuration */
|
||||
ESP_ERROR_CHECK(touch_sensor_reconfig_channel(s_chan_handle[i], &chan_cfg));
|
||||
ESP_ERROR_CHECK(touch_sensor_reconfig_channel(chan_handle[i], &chan_cfg));
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
/* Use the default sample configurations */
|
||||
touch_sensor_sample_config_t sample_cfg[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT();
|
||||
/* Allocate new touch controller handle */
|
||||
/* Handles of touch sensor */
|
||||
touch_sensor_handle_t sens_handle = NULL;
|
||||
touch_channel_handle_t chan_handle[EXAMPLE_TOUCH_CHANNEL_NUM];
|
||||
|
||||
/* Step 1: Create a new touch sensor controller handle with default sample configuration */
|
||||
touch_sensor_sample_config_t sample_cfg[TOUCH_SAMPLE_CFG_NUM] = EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT();
|
||||
touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(EXAMPLE_TOUCH_SAMPLE_CFG_NUM, sample_cfg);
|
||||
ESP_ERROR_CHECK(touch_sensor_new_controller(&sens_cfg, &s_sens_handle));
|
||||
|
||||
/* Configure the touch sensor filter */
|
||||
touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_sensor_config_filter(s_sens_handle, &filter_cfg));
|
||||
ESP_ERROR_CHECK(touch_sensor_new_controller(&sens_cfg, &sens_handle));
|
||||
|
||||
/* Step 2: Create and enable the new touch channel handles with default configurations */
|
||||
/** Following is about setting the touch channel active threshold of each sample configuration.
|
||||
*
|
||||
* @How to Determine:
|
||||
@@ -89,7 +109,10 @@ void app_main(void)
|
||||
* we need to run the touch app first to get the `benchmark` and the `smooth_data` that being touched.
|
||||
*
|
||||
* @Formula:
|
||||
* threshold = benchmark * coeff, (coeff for example, 0.1%~20%)
|
||||
* Touch V1 uses absolute threshold, and it has no benchmark, so you can use untouched smooth data instead:
|
||||
* abs_active_thresh = benchmark * (1 - coeff), (coeff for example, 0.1%~20%)
|
||||
* Touch V2/V3 uses relative threshold:
|
||||
* active_thresh = benchmark * coeff, (coeff for example, 0.1%~20%)
|
||||
* Please adjust the coeff to guarantee the threshold < smooth_data - benchmark
|
||||
*
|
||||
* @Typical Practice:
|
||||
@@ -102,48 +125,55 @@ void app_main(void)
|
||||
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
|
||||
/* Allocate new touch channel on the touch controller */
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
ESP_ERROR_CHECK(touch_sensor_new_channel(s_sens_handle, s_channel_id[i], &chan_cfg, &s_chan_handle[i]));
|
||||
ESP_ERROR_CHECK(touch_sensor_new_channel(sens_handle, s_channel_id[i], &chan_cfg, &chan_handle[i]));
|
||||
/* Display the touch channel corresponding GPIO number, you can also know from `touch_sensor_channel.h` */
|
||||
touch_chan_info_t chan_info = {};
|
||||
ESP_ERROR_CHECK(touch_sensor_get_channel_info(chan_handle[i], &chan_info));
|
||||
printf("Touch [CH %d] enabled on GPIO%d\n", s_channel_id[i], chan_info.chan_gpio);
|
||||
}
|
||||
printf("=================================\n");
|
||||
|
||||
/* Do the initial scanning to initialize the touch channel data
|
||||
/* Step 3: Confiture the default filter for the touch sensor (Note: Touch V1 uses software filter) */
|
||||
touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_sensor_config_filter(sens_handle, &filter_cfg));
|
||||
|
||||
/* Step 4: Do the initial scanning to initialize the touch channel data
|
||||
* Without this step, the channel data in the first read will be invalid
|
||||
*/
|
||||
example_touch_do_initial_scanning();
|
||||
example_touch_do_initial_scanning(sens_handle, chan_handle);
|
||||
|
||||
/* Register the touch sensor callbacks, here only take `active` and `deactivate` event for example */
|
||||
/* Step 5: Register the touch sensor callbacks, here only take `active` and `inactive` event for example */
|
||||
touch_event_callbacks_t callbacks = {
|
||||
.on_active = example_touch_on_active_callback,
|
||||
.on_inactive = example_touch_on_inactive_callback,
|
||||
.on_measure_done = NULL,
|
||||
.on_scan_done = NULL,
|
||||
.on_timeout = NULL,
|
||||
.on_proximity_meas_done = NULL,
|
||||
};
|
||||
ESP_ERROR_CHECK(touch_sensor_register_callbacks(s_sens_handle, &callbacks, NULL));
|
||||
ESP_ERROR_CHECK(touch_sensor_register_callbacks(sens_handle, &callbacks, NULL));
|
||||
|
||||
/* Enable the touch sensor */
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(s_sens_handle));
|
||||
/* Step 6: Enable the touch sensor */
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(sens_handle));
|
||||
|
||||
/* Start continuous scanning, you can also trigger oneshot scanning manually */
|
||||
ESP_ERROR_CHECK(touch_sensor_start_continuous_scanning(s_sens_handle));
|
||||
/* Step 7: Start continuous scanning, you can also trigger oneshot scanning manually */
|
||||
ESP_ERROR_CHECK(touch_sensor_start_continuous_scanning(sens_handle));
|
||||
|
||||
uint32_t benchmark[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {};
|
||||
uint32_t chan_data[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {};
|
||||
/* Step8: Print the sampled data of each enabled touch channel */
|
||||
uint32_t data[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {};
|
||||
while (1) {
|
||||
printf("=================================\n");
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
#if SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
/* Read and print the benchmark of each sample configuration */
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(s_chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark));
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, data));
|
||||
printf("benchmark [CH %d]:", s_channel_id[i]);
|
||||
for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) {
|
||||
printf(" %"PRIu32, benchmark[j]);
|
||||
printf(" %"PRIu32, data[j]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
/* Read and print the channel data of each sample configuration */
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(s_chan_handle[i], TOUCH_CHAN_DATA_TYPE_SMOOTH, chan_data));
|
||||
printf("chan_data [CH %d]:", s_channel_id[i]);
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_SMOOTH, data));
|
||||
printf("smooth [CH %d]:", s_channel_id[i]);
|
||||
for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) {
|
||||
printf(" %"PRIu32, chan_data[j]);
|
||||
printf(" %"PRIu32, data[j]);
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
|
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/touch_sens.h"
|
||||
#include "esp_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Touch version 3 supports multiple sample configurations
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_NUM TOUCH_SAMPLE_CFG_NUM // Up to 'TOUCH_SAMPLE_CFG_NUM'
|
||||
#define EXAMPLE_TOUCH_CHANNEL_NUM 4
|
||||
#define EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES 3
|
||||
|
||||
ESP_STATIC_ASSERT(EXAMPLE_TOUCH_SAMPLE_CFG_NUM <= TOUCH_SAMPLE_CFG_NUM, "sample configuration number exceed the supported number");
|
||||
ESP_STATIC_ASSERT(EXAMPLE_TOUCH_CHANNEL_NUM <= (TOUCH_MAX_CHAN_ID - TOUCH_MIN_CHAN_ID + 1), "touch channel number exceed the max supported number ");
|
||||
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 2
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT() {TOUCH_SENSOR_V2_DEFAULT_SAMPLE_CONFIG(500, TOUCH_VOLT_LIM_L_0V5, TOUCH_VOLT_LIM_H_2V2)}
|
||||
#define EXAMPLE_TOUCH_CHAN_CFG_DEFAULT() { \
|
||||
.active_thresh = {2000}, \
|
||||
.charge_speed = TOUCH_CHARGE_SPEED_7, \
|
||||
.init_charge_volt = TOUCH_INIT_CHARGE_VOLT_LOW, \
|
||||
}
|
||||
#elif SOC_TOUCH_SENSOR_VERSION == 3
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG(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, \
|
||||
}
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT() {EXAMPLE_TOUCH_SAMPLE_CFG(3, 29, 8, 3),\
|
||||
EXAMPLE_TOUCH_SAMPLE_CFG(2, 88, 31, 7), \
|
||||
EXAMPLE_TOUCH_SAMPLE_CFG(3, 10, 31, 7)}
|
||||
#define EXAMPLE_TOUCH_CHAN_CFG_DEFAULT() { \
|
||||
.active_thresh = {1000, 2500, 5000}, \
|
||||
}
|
||||
#else
|
||||
#error "Target not supported"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -1,15 +1,16 @@
|
||||
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.esp32p4
|
||||
@pytest.mark.generic
|
||||
def test_touch_sens_v3(dut: Dut) -> None:
|
||||
def test_touch_sens(dut: Dut) -> None:
|
||||
dut.expect(r'Touch \[CH [0-9]+\] enabled on GPIO[0-9]+')
|
||||
dut.expect_exact('Initial benchmark and new threshold are:')
|
||||
dut.expect(r'\[CH [0-9]+\] 0: [0-9]+, [0-9]+')
|
||||
dut.expect(r'benchmark \[CH [0-9]+\]: [0-9]+')
|
||||
dut.expect(r'chan_data \[CH [0-9]+\]: [0-9]+')
|
||||
dut.expect(r'Touch \[CH [0-9]+\] 0: [0-9]+, [0-9]+')
|
||||
dut.expect(r'smooth \[CH [0-9]+\]: [0-9]+')
|
||||
|
@@ -0,0 +1,2 @@
|
||||
# register I2S common dependencies as a component
|
||||
idf_component_register(INCLUDE_DIRS ".")
|
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/touch_sens.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1 // ESP32
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT() {TOUCH_SENSOR_V1_DEFAULT_SAMPLE_CONFIG(5.0, TOUCH_VOLT_LIM_L_0V5, TOUCH_VOLT_LIM_H_1V7)}
|
||||
#define EXAMPLE_TOUCH_CHAN_CFG_DEFAULT() { \
|
||||
.abs_active_thresh = {1000}, \
|
||||
.charge_speed = TOUCH_CHARGE_SPEED_7, \
|
||||
.init_charge_volt = TOUCH_INIT_CHARGE_VOLT_LOW, \
|
||||
.group = TOUCH_CHAN_TRIG_GROUP_BOTH, \
|
||||
}
|
||||
#elif SOC_TOUCH_SENSOR_VERSION == 2 // ESP32-S2 & ESP32-S3
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT() {TOUCH_SENSOR_V2_DEFAULT_SAMPLE_CONFIG(500, TOUCH_VOLT_LIM_L_0V5, TOUCH_VOLT_LIM_H_2V2)}
|
||||
#define EXAMPLE_TOUCH_CHAN_CFG_DEFAULT() { \
|
||||
.active_thresh = {2000}, \
|
||||
.charge_speed = TOUCH_CHARGE_SPEED_7, \
|
||||
.init_charge_volt = TOUCH_INIT_CHARGE_VOLT_LOW, \
|
||||
}
|
||||
#elif SOC_TOUCH_SENSOR_VERSION == 3 // ESP32-P4
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT() {TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG2(3, 29, 8, 3),\
|
||||
TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG2(2, 88, 31, 7), \
|
||||
TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG2(3, 10, 31, 7)}
|
||||
#define EXAMPLE_TOUCH_CHAN_CFG_DEFAULT() { \
|
||||
.active_thresh = {1000, 2500, 5000}, \
|
||||
}
|
||||
#else
|
||||
#error "Target not supported"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -1,8 +0,0 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
idf_build_set_property(MINIMAL_BUILD ON)
|
||||
project(touch_pad_interrupt)
|
@@ -1,65 +0,0 @@
|
||||
| Supported Targets | ESP32 |
|
||||
| ----------------- | ----- |
|
||||
|
||||
# Touch Pad Interrupt Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example demonstrates how to set up ESP32's capacitive touch pad peripheral to trigger interrupt when a pad is touched. It also shows how to detect the touch event by software for sensor designs where greater touch detection sensitivity is required.
|
||||
|
||||
- The hardware interrupt mode occupies less CPU resources, but we can only apply fixed threshold and software algorithms are also impossibile.
|
||||
- The polling mode is flexible and supports various software algorithms. However, it comsumes more CPU.
|
||||
|
||||
ESP32 supports touch detection by configuring hardware registers. The hardware periodically detects the pulse counts. If the number of pulse counts exceeds the set threshold, a hardware interrupt will be generated to notify the application layer that a certain touch sensor channel may be triggered.
|
||||
|
||||
For the sensors covered with glass or plastic, the capacitance difference caused by a touch action could be very small. In such cases, software polling is used so software algorithms can be applied to reduce noise and catch small changes of the pulse counts. In certain cases, we may need to add additional routines to adjust the threshold level dynamically as it may change depending on environment conditions.
|
||||
|
||||
For a simpler example how to configure and read capacitive touch pads, please refer to [touch_pad_read](../touch_pad_read).
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* A development board with ESP32 chip
|
||||
* Proper touch sensor system
|
||||
|
||||
For hardware and firmware design guidelines on ESP32 touch sensor system, please refer to [Touch Sensor Application Note](https://github.com/espressif/esp-iot-solution/blob/release/v1.1/documents/touch_pad_solution/touch_sensor_design_en.md), where you may find comprehensive information on how to design and implement touch sensing applications, such as linear slider, wheel slider, matrix buttons and spring buttons.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(Replace PORT with the name of the serial port to use.)
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
The application cycles between the interrupt mode and the pooling mode with a filter, to compare performance of the touch sensor system between both scenarios:
|
||||
|
||||
```
|
||||
I (6303) Touch pad: Waiting for any pad being touched...
|
||||
I (6733) Touch pad: T6 activated!
|
||||
I (7333) Touch pad: T5 activated!
|
||||
I (7723) Touch pad: T3 activated!
|
||||
I (8043) Touch pad: T2 activated!
|
||||
I (8883) Touch pad: T4 activated!
|
||||
I (9523) Touch pad: T7 activated!
|
||||
I (12503) Touch pad: Waiting for any pad being touched...
|
||||
I (15483) Touch pad: T6 activated!
|
||||
I (16253) Touch pad: T5 activated!
|
||||
I (17903) Touch pad: Waiting for any pad being touched...
|
||||
I (22903) Touch pad: Waiting for any pad being touched...
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Sensing threshold is set up automatically at start up by performing simple calibration. Application is reading current value for each pad and assuming two thirds of this value as the sensing threshold. Do not touch pads on application start up, otherwise sensing may not work correctly.
|
||||
|
||||
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
@@ -1,3 +0,0 @@
|
||||
idf_component_register(SRCS "tp_interrupt_main.c"
|
||||
PRIV_REQUIRES driver
|
||||
INCLUDE_DIRS ".")
|
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#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"
|
||||
|
||||
static const char *TAG = "Touch pad";
|
||||
|
||||
#define TOUCH_THRESH_NO_USE (0)
|
||||
#define TOUCH_THRESH_PERCENT (80)
|
||||
#define TOUCHPAD_FILTER_TOUCH_PERIOD (10)
|
||||
|
||||
static bool s_pad_activated[TOUCH_PAD_MAX];
|
||||
static uint32_t s_pad_init_val[TOUCH_PAD_MAX];
|
||||
|
||||
/*
|
||||
Read values sensed at all available touch pads.
|
||||
Use 2 / 3 of read value as the threshold
|
||||
to trigger interrupt when the pad is touched.
|
||||
Note: this routine demonstrates a simple way
|
||||
to configure activation threshold for the touch pads.
|
||||
Do not touch any pads when this routine
|
||||
is running (on application start).
|
||||
*/
|
||||
static void tp_example_set_thresholds(void)
|
||||
{
|
||||
uint16_t touch_value;
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
//read filtered value
|
||||
touch_pad_read_filtered(i, &touch_value);
|
||||
s_pad_init_val[i] = touch_value;
|
||||
ESP_LOGI(TAG, "test init: touch pad [%d] val is %d", i, touch_value);
|
||||
//set interrupt threshold.
|
||||
ESP_ERROR_CHECK(touch_pad_set_thresh(i, touch_value * 2 / 3));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Check if any of touch pads has been activated
|
||||
by reading a table updated by rtc_intr()
|
||||
If so, then print it out on a serial monitor.
|
||||
Clear related entry in the table afterwards
|
||||
|
||||
In interrupt mode, the table is updated in touch ISR.
|
||||
|
||||
In filter mode, we will compare the current filtered value with the initial one.
|
||||
If the current filtered value is less than 80% of the initial value, we can
|
||||
regard it as a 'touched' event.
|
||||
When calling touch_pad_init, a timer will be started to run the filter.
|
||||
This mode is designed for the situation that the pad is covered
|
||||
by a 2-or-3-mm-thick medium, usually glass or plastic.
|
||||
The difference caused by a 'touch' action could be very small, but we can still use
|
||||
filter mode to detect a 'touch' event.
|
||||
*/
|
||||
static void tp_example_read_task(void *pvParameter)
|
||||
{
|
||||
static int show_message;
|
||||
int change_mode = 0;
|
||||
int filter_mode = 0;
|
||||
while (1) {
|
||||
if (filter_mode == 0) {
|
||||
//interrupt mode, enable touch interrupt
|
||||
touch_pad_intr_enable();
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
if (s_pad_activated[i] == true) {
|
||||
ESP_LOGI(TAG, "T%d activated!", i);
|
||||
// Wait a while for the pad being released
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
// Clear information on pad activation
|
||||
s_pad_activated[i] = false;
|
||||
// Reset the counter triggering a message
|
||||
// that application is running
|
||||
show_message = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//filter mode, disable touch interrupt
|
||||
touch_pad_intr_disable();
|
||||
touch_pad_clear_status();
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
uint16_t value = 0;
|
||||
touch_pad_read_filtered(i, &value);
|
||||
if (value < s_pad_init_val[i] * TOUCH_THRESH_PERCENT / 100) {
|
||||
ESP_LOGI(TAG, "T%d activated!", i);
|
||||
ESP_LOGI(TAG, "value: %"PRIu16"; init val: %"PRIu32, value, s_pad_init_val[i]);
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
// Reset the counter to stop changing mode.
|
||||
change_mode = 1;
|
||||
show_message = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
|
||||
// If no pad is touched, every couple of seconds, show a message
|
||||
// that application is running
|
||||
if (show_message++ % 500 == 0) {
|
||||
ESP_LOGI(TAG, "Waiting for any pad being touched...");
|
||||
}
|
||||
// Change mode if no pad is touched for a long time.
|
||||
// We can compare the two different mode.
|
||||
if (change_mode++ % 2000 == 0) {
|
||||
filter_mode = !filter_mode;
|
||||
ESP_LOGW(TAG, "Change mode...%s", filter_mode == 0 ? "interrupt mode" : "filter mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Handle an interrupt triggered when a pad is touched.
|
||||
Recognize what pad has been touched and save it in a table.
|
||||
*/
|
||||
static void tp_example_rtc_intr(void *arg)
|
||||
{
|
||||
uint32_t pad_intr = touch_pad_get_status();
|
||||
//clear interrupt
|
||||
touch_pad_clear_status();
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
if ((pad_intr >> i) & 0x01) {
|
||||
s_pad_activated[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Before reading touch pad, we need to initialize the RTC IO.
|
||||
*/
|
||||
static void tp_example_touch_pad_init(void)
|
||||
{
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
//init RTC IO and mode for touch pad.
|
||||
touch_pad_config(i, TOUCH_THRESH_NO_USE);
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// Initialize touch pad peripheral, it will start a timer to run a filter
|
||||
ESP_LOGI(TAG, "Initializing touch pad");
|
||||
ESP_ERROR_CHECK(touch_pad_init());
|
||||
// If use interrupt trigger mode, should set touch sensor FSM mode at 'TOUCH_FSM_MODE_TIMER'.
|
||||
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
|
||||
// Set reference voltage for charging/discharging
|
||||
// For most usage scenarios, we recommend using the following combination:
|
||||
// the high reference valtage will be 2.7V - 1V = 1.7V, The low reference voltage will be 0.5V.
|
||||
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
|
||||
// Init touch pad IO
|
||||
tp_example_touch_pad_init();
|
||||
// Initialize and start a software filter to detect slight change of capacitance.
|
||||
touch_pad_filter_start(TOUCHPAD_FILTER_TOUCH_PERIOD);
|
||||
// Set thresh hold
|
||||
tp_example_set_thresholds();
|
||||
// Register touch interrupt ISR
|
||||
touch_pad_isr_register(tp_example_rtc_intr, NULL);
|
||||
// Start a task to show what pads have been touched
|
||||
xTaskCreate(&tp_example_read_task, "touch_pad_read_task", 4096, NULL, 5, NULL);
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.generic
|
||||
def test_touch_pad_interrupt_v1(dut: Dut) -> None:
|
||||
dut.expect_exact('Touch pad: Initializing touch pad')
|
||||
dut.expect(r'test init: touch pad \[\d+\] val is \d+')
|
||||
dut.expect_exact('Touch pad: Waiting for any pad being touched...')
|
||||
dut.expect_exact('Touch pad: Change mode...filter mode')
|
||||
dut.expect_exact('Touch pad: Waiting for any pad being touched...')
|
@@ -1,8 +0,0 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
|
||||
idf_build_set_property(MINIMAL_BUILD ON)
|
||||
project(touch_pad_read)
|
@@ -1,55 +0,0 @@
|
||||
| Supported Targets | ESP32 |
|
||||
| ----------------- | ----- |
|
||||
|
||||
# Touch Pad Read Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
Read and print raw values or IIR filtered values from capacitive touch sensors.
|
||||
|
||||
Once configured, ESP32 will continuously measure capacitance of touch pad sensors. Measurement is reflected as numeric value inversely related to sensor's capacitance. With a finger touched on a pad, its capacitance will get larger meanwhile the measured value gets smaller, and vice versa.
|
||||
|
||||
To detect if a sensor is touched or not, each particular design should be calibrated by obtaining both measurements for each individual sensor. Then a threshold between both values can be established. With specific threshold, API is then able to distinguish whether specific sensor is touched or released.
|
||||
|
||||
|
||||
There is another similar example that demonstrates how to perform simple calibration and trigger an interrupt when a pad is touched - see [touch_pad_interrupt](../touch_pad_interrupt).
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* A development board with ESP32 chip
|
||||
* Proper touch sensor system
|
||||
|
||||
For hardware and firmware design guidelines on ESP32 touch sensor system, please refer to [Touch Sensor Application Note](https://github.com/espressif/esp-iot-solution/blob/release/v1.1/documents/touch_pad_solution/touch_sensor_design_en.md), where you may find comprehensive information on how to design and implement touch sensing applications, such as linear slider, wheel slider, matrix buttons and spring buttons.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(Replace PORT with the name of the serial port to use.)
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
ESP32 supports up to ten capacitive touch pad sensors, T0 - T9, which are connected to specific GPIO pins. For the information about touch sensor capable pins, please refer to [Technical Reference Manual](https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf). This example will initialize all the 10 touch pads, and print the measured values to serial terminal:
|
||||
|
||||
```
|
||||
Touch Sensor filter mode read, the output format is:
|
||||
Touchpad num:[raw data, filtered data]
|
||||
|
||||
T0:[1072,1071] T1:[ 475, 475] T2:[1004,1003] T3:[1232,1231] T4:[1675,1676] T5:[1146,1146] T6:[1607,1607] T7:[1118,1118] T8:[1695,1695] T9:[1223,1222]
|
||||
T0:[1072,1071] T1:[ 475, 475] T2:[1003,1003] T3:[1231,1231] T4:[1676,1676] T5:[1146,1146] T6:[1607,1607] T7:[1118,1118] T8:[1694,1694] T9:[1222,1221]
|
||||
T0:[1071,1071] T1:[ 475, 475] T2:[1004,1004] T3:[1231,1231] T4:[1678,1677] T5:[1147,1146] T6:[1607,1607] T7:[1118,1118] T8:[1694,1694] T9:[1222,1221]
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
@@ -1,3 +0,0 @@
|
||||
idf_component_register(SRCS "tp_read_main.c"
|
||||
PRIV_REQUIRES driver
|
||||
INCLUDE_DIRS ".")
|
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/touch_pad.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#define TOUCH_PAD_NO_CHANGE (-1)
|
||||
#define TOUCH_THRESH_NO_USE (0)
|
||||
#define TOUCH_FILTER_MODE_EN (1)
|
||||
#define TOUCHPAD_FILTER_TOUCH_PERIOD (10)
|
||||
/*
|
||||
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)
|
||||
{
|
||||
uint16_t touch_value;
|
||||
uint16_t touch_filter_value;
|
||||
#if TOUCH_FILTER_MODE_EN
|
||||
printf("Touch Sensor filter mode read, the output format is: \nTouchpad num:[raw data, filtered data]\n\n");
|
||||
#else
|
||||
printf("Touch Sensor normal mode read, the output format is: \nTouchpad num:[raw data]\n\n");
|
||||
#endif
|
||||
while (1) {
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
#if TOUCH_FILTER_MODE_EN
|
||||
// If open the filter mode, please use this API to get the touch pad count.
|
||||
touch_pad_read_raw_data(i, &touch_value);
|
||||
touch_pad_read_filtered(i, &touch_filter_value);
|
||||
printf("T%d:[%4"PRIu16",%4"PRIu16"] ", i, touch_value, touch_filter_value);
|
||||
#else
|
||||
touch_pad_read(i, &touch_value);
|
||||
printf("T%d:[%4"PRIu16"] ", i, touch_value);
|
||||
#endif
|
||||
}
|
||||
printf("\n");
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
static void tp_example_touch_pad_init(void)
|
||||
{
|
||||
for (int i = 0; i < TOUCH_PAD_MAX; i++) {
|
||||
touch_pad_config(i, TOUCH_THRESH_NO_USE);
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// Initialize touch pad peripheral.
|
||||
// The default fsm mode is software trigger mode.
|
||||
ESP_ERROR_CHECK(touch_pad_init());
|
||||
// Set reference voltage for charging/discharging
|
||||
// In this case, the high reference valtage will be 2.7V - 1V = 1.7V
|
||||
// The low reference voltage will be 0.5
|
||||
// The larger the range, the larger the pulse count value.
|
||||
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
|
||||
tp_example_touch_pad_init();
|
||||
#if TOUCH_FILTER_MODE_EN
|
||||
touch_pad_filter_start(TOUCHPAD_FILTER_TOUCH_PERIOD);
|
||||
#endif
|
||||
// Start task to read values sensed by pads
|
||||
xTaskCreate(&tp_example_read_task, "touch_pad_read_task", 4096, NULL, 5, NULL);
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.generic
|
||||
def test_touch_pad_read_v1(dut: Dut) -> None:
|
||||
dut.expect_exact('Touch Sensor filter mode read, the output format is:')
|
||||
dut.expect(r'T0:\[\s*\d+,\s*\d+\] T1:\[\s*\d+,\s*\d+\] T2:\[\s*\d+,\s*\d+\] T3:\[\s*\d+,\s*\d+\] T4:\[\s*\d+,\s*\d+\]'
|
||||
r' T5:\[\s*\d+,\s*\d+\] T6:\[\s*\d+,\s*\d+\] T7:\[\s*\d+,\s*\d+\] T8:\[\s*\d+,\s*\d+\] T9:\[\s*\d+,\s*\d+\]')
|
@@ -1,6 +1,12 @@
|
||||
idf_component_register(SRCS "deep_sleep_example_main.c"
|
||||
set(srcs "deep_sleep_example_main.c"
|
||||
"gpio_wakeup.c"
|
||||
"ext_wakeup.c"
|
||||
"touch_wakeup.c"
|
||||
PRIV_REQUIRES driver nvs_flash ulp
|
||||
INCLUDE_DIRS ".")
|
||||
"ext_wakeup.c")
|
||||
set(includes ".")
|
||||
|
||||
if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED AND CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP)
|
||||
list(APPEND srcs "touch_sens_wakeup.c")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
PRIV_REQUIRES nvs_flash ulp esp_driver_gpio esp_driver_touch_sens
|
||||
INCLUDE_DIRS ${includes})
|
||||
|
@@ -3,11 +3,12 @@ menu "Example Configuration"
|
||||
config EXAMPLE_TOUCH_WAKEUP
|
||||
bool "Enable touch wake up"
|
||||
default y
|
||||
depends on SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP && !IDF_TARGET_ESP32P4
|
||||
depends on SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP && SOC_TOUCH_SENSOR_SUPPORTED
|
||||
help
|
||||
This option enables wake up from deep sleep using touch pads.
|
||||
ESP32 - TOUCH8 and TOUCH9, which correspond to GPIO33 and GPIO32.
|
||||
ESP32S2/S3 - TOUCH9, which corresponds to GPIO9.
|
||||
ESP32P4 - TOUCH2, which corresponds to GPIO4.
|
||||
|
||||
Note: On ESP32, touch wakeup source can not be used together with ext0 wakeup source.
|
||||
|
||||
@@ -284,4 +285,18 @@ menu "Example Configuration"
|
||||
supported. If this option is enabled, it is a high level wake up, otherwise it is a low level wake up.
|
||||
endmenu
|
||||
|
||||
menu "Touch wakeup configuration"
|
||||
visible if EXAMPLE_TOUCH_WAKEUP
|
||||
|
||||
config EXAMPLE_TOUCH_ALLOW_DSLP_PD
|
||||
bool "Allow RTC_PERIPH power domain to be powered down during deep sleep"
|
||||
depends on !IDF_TARGET_ESP32
|
||||
default y
|
||||
help
|
||||
Enable this option if allow the RTC_PERIPH power domain (contain touch sensor) to be powered down
|
||||
during deep sleep. It can help to save more power, but only one specified touch channel can wakeup
|
||||
from the deep sleep. If this option is disabled, the RTC_PERIPH power domain will be powered up
|
||||
during deep sleep, and all enabled touch channels can wakeup from the deep sleep.
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
@@ -100,7 +100,7 @@ static void deep_sleep_task(void *args)
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_TOUCH_WAKEUP
|
||||
case ESP_SLEEP_WAKEUP_TOUCHPAD: {
|
||||
printf("Wake up from touch on pad %d\n", esp_sleep_get_touchpad_wakeup_status());
|
||||
printf("Wake up from touch\n");
|
||||
break;
|
||||
}
|
||||
#endif // CONFIG_EXAMPLE_TOUCH_WAKEUP
|
||||
|
3
examples/system/deep_sleep/main/idf_component.yml
Normal file
3
examples/system/deep_sleep/main/idf_component.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
dependencies:
|
||||
touch_sens_examples_common:
|
||||
path: ${IDF_PATH}/examples/peripherals/touch_sensor/touch_sens_examples_common
|
148
examples/system/deep_sleep/main/touch_sens_wakeup.c
Normal file
148
examples/system/deep_sleep/main/touch_sens_wakeup.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/touch_sens.h"
|
||||
#include "touch_sens_example_config.h"
|
||||
|
||||
static const char *TAG = "touch_wakeup";
|
||||
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_NUM 1
|
||||
#define EXAMPLE_TOUCH_CHANNEL_NUM 3
|
||||
#define EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES 3
|
||||
|
||||
// The touch channel IDs that used in this example
|
||||
// If you want to change the wake-up channels, please make sure the channel GPIOs won't conflict to the EXT wakeup GPIOs
|
||||
static int s_channel_id[EXAMPLE_TOUCH_CHANNEL_NUM] = {7, 8, 9};
|
||||
|
||||
// Active threshold to benchmark ratio. (i.e., touch will be activated when data >= benchmark * (1 + ratio))
|
||||
static float s_thresh2bm_ratio[EXAMPLE_TOUCH_CHANNEL_NUM] = {
|
||||
[0 ... EXAMPLE_TOUCH_CHANNEL_NUM - 1] = 0.02f, // 2%
|
||||
};
|
||||
|
||||
static bool example_touch_on_active_cb(touch_sensor_handle_t sens_handle, const touch_active_event_data_t *event, void *user_ctx)
|
||||
{
|
||||
ESP_EARLY_LOGW("touch callback", "ch %d active", (int)event->chan_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool example_touch_on_inactive_cb(touch_sensor_handle_t sens_handle, const touch_inactive_event_data_t *event, void *user_ctx)
|
||||
{
|
||||
ESP_EARLY_LOGW("touch callback", "ch %d inactive", (int)event->chan_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void example_touch_do_initial_scanning(touch_sensor_handle_t sens_handle, touch_channel_handle_t chan_handle[])
|
||||
{
|
||||
/* Enable the touch sensor to do the initial scanning, so that to initialize the channel data */
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(sens_handle));
|
||||
|
||||
/* Scan the enabled touch channels for several times, to make sure the initial channel data is stable */
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES; i++) {
|
||||
ESP_ERROR_CHECK(touch_sensor_trigger_oneshot_scanning(sens_handle, 2000));
|
||||
}
|
||||
|
||||
/* Disable the touch channel to rollback the state */
|
||||
ESP_ERROR_CHECK(touch_sensor_disable(sens_handle));
|
||||
|
||||
/* (Optional) Read the initial channel benchmark and reconfig the channel active threshold accordingly */
|
||||
printf("Initial benchmark and new threshold are:\n");
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
/* Read the initial benchmark of the touch channel */
|
||||
uint32_t benchmark[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {};
|
||||
#if SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark));
|
||||
#else
|
||||
/* Read smooth data instead if the hardware does not support benchmark */
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_SMOOTH, benchmark));
|
||||
#endif // SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
/* Calculate the proper active thresholds regarding the initial benchmark */
|
||||
printf("Touch [CH %d]", s_channel_id[i]);
|
||||
/* Generate the default channel configuration and then update the active threshold based on the real benchmark */
|
||||
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
|
||||
for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) {
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1
|
||||
// Touch V1 (ESP32) uses absolute threshold.
|
||||
chan_cfg.abs_active_thresh[j] = (uint32_t)(benchmark[j] * (1 - s_thresh2bm_ratio[i]));
|
||||
printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.abs_active_thresh[j]);
|
||||
#else
|
||||
chan_cfg.active_thresh[j] = (uint32_t)(benchmark[j] * s_thresh2bm_ratio[i]);
|
||||
printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.active_thresh[j]);
|
||||
#endif // SOC_TOUCH_SENSOR_VERSION == 1
|
||||
}
|
||||
printf("\n");
|
||||
/* Update the channel configuration */
|
||||
ESP_ERROR_CHECK(touch_sensor_reconfig_channel(chan_handle[i], &chan_cfg));
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t example_deep_sleep_register_touch_wakeup(void)
|
||||
{
|
||||
printf("Enabling touch wakeup\n");
|
||||
|
||||
/* Handles of touch sensor */
|
||||
touch_sensor_handle_t sens_handle = NULL;
|
||||
touch_channel_handle_t chan_handle[EXAMPLE_TOUCH_CHANNEL_NUM];
|
||||
|
||||
/* Step 1: Create a new touch sensor controller handle with default sample configuration */
|
||||
touch_sensor_sample_config_t sample_cfg[TOUCH_SAMPLE_CFG_NUM] = EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT();
|
||||
touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(EXAMPLE_TOUCH_SAMPLE_CFG_NUM, sample_cfg);
|
||||
ESP_ERROR_CHECK(touch_sensor_new_controller(&sens_cfg, &sens_handle));
|
||||
|
||||
/* Step 2: Create and enable the new touch channel handles with default configurations */
|
||||
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
ESP_ERROR_CHECK(touch_sensor_new_channel(sens_handle, s_channel_id[i], &chan_cfg, &chan_handle[i]));
|
||||
/* Display the touch channel corresponding GPIO number, you can also know from `touch_sensor_channel.h` */
|
||||
touch_chan_info_t chan_info = {};
|
||||
ESP_ERROR_CHECK(touch_sensor_get_channel_info(chan_handle[i], &chan_info));
|
||||
printf("Touch [CH %d] enabled on GPIO%d\n", s_channel_id[i], chan_info.chan_gpio);
|
||||
}
|
||||
|
||||
/* Step 3: Confiture the default filter for the touch sensor (Note: Touch V1 uses software filter) */
|
||||
touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_sensor_config_filter(sens_handle, &filter_cfg));
|
||||
|
||||
/* (Optional) Do the initial scanning to initialize the touch channel data
|
||||
* Without this step, the channel data in the first read will be invalid
|
||||
*/
|
||||
example_touch_do_initial_scanning(sens_handle, chan_handle);
|
||||
|
||||
/* (Optional) Register the callbacks, optional for deep sleep wakeup */
|
||||
touch_event_callbacks_t callbacks = {
|
||||
.on_active = example_touch_on_active_cb,
|
||||
.on_inactive = example_touch_on_inactive_cb,
|
||||
};
|
||||
ESP_ERROR_CHECK(touch_sensor_register_callbacks(sens_handle, &callbacks, NULL));
|
||||
|
||||
/* Step 4: Enable the deep sleep wake-up with the basic configuration */
|
||||
#if CONFIG_EXAMPLE_TOUCH_ALLOW_DSLP_PD
|
||||
/* Get the channel information to use same active threshold for the sleep channel */
|
||||
touch_chan_info_t chan_info = {};
|
||||
ESP_ERROR_CHECK(touch_sensor_get_channel_info(chan_handle[0], &chan_info));
|
||||
|
||||
touch_sleep_config_t deep_slp_cfg = TOUCH_SENSOR_DEFAULT_DSLP_PD_CONFIG(chan_handle[0],
|
||||
chan_info.active_thresh[0],
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 3
|
||||
chan_info.active_thresh[1],
|
||||
chan_info.active_thresh[2],
|
||||
#endif
|
||||
);
|
||||
printf("Touch channel %d (GPIO%d) is selected as deep sleep wakeup channel\n", chan_info.chan_id, chan_info.chan_gpio);
|
||||
#else
|
||||
touch_sleep_config_t deep_slp_cfg = TOUCH_SENSOR_DEFAULT_DSLP_CONFIG();
|
||||
#endif
|
||||
/* Enable deep sleep wake up for touch sensor */
|
||||
ESP_ERROR_CHECK(touch_sensor_config_sleep_wakeup(sens_handle, &deep_slp_cfg));
|
||||
|
||||
/* Step 5: Enable touch sensor controller and start continuous scanning before entering deep sleep */
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(sens_handle));
|
||||
ESP_ERROR_CHECK(touch_sensor_start_continuous_scanning(sens_handle));
|
||||
|
||||
ESP_LOGI(TAG, "touch wakeup source is ready");
|
||||
return ESP_OK;
|
||||
}
|
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include "esp_sleep.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_TOUCH_WAKEUP
|
||||
#include "driver/touch_pad.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define TOUCH_THRESH_NO_USE 0
|
||||
|
||||
static void calibrate_touch_pad(touch_pad_t pad)
|
||||
{
|
||||
int avg = 0;
|
||||
const size_t calibration_count = 128;
|
||||
for (int i = 0; i < calibration_count; ++i) {
|
||||
uint16_t val;
|
||||
touch_pad_read(pad, &val);
|
||||
avg += val;
|
||||
}
|
||||
avg /= calibration_count;
|
||||
const int min_reading = 300;
|
||||
if (avg < min_reading) {
|
||||
printf("Touch pad #%d average reading is too low: %d (expecting at least %d). "
|
||||
"Not using for deep sleep wakeup.\n", pad, avg, min_reading);
|
||||
touch_pad_config(pad, 0);
|
||||
} else {
|
||||
int threshold = avg - 100;
|
||||
printf("Touch pad #%d average: %d, wakeup threshold set to %d.\n", pad, avg, threshold);
|
||||
touch_pad_config(pad, threshold);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void example_deep_sleep_register_touch_wakeup(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
// Initialize touch pad peripheral.
|
||||
// The default fsm mode is software trigger mode.
|
||||
ESP_ERROR_CHECK(touch_pad_init());
|
||||
// If use touch pad wake up, should set touch sensor FSM mode at 'TOUCH_FSM_MODE_TIMER'.
|
||||
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
|
||||
// Set reference voltage for charging/discharging
|
||||
// In this case, the high reference voltage will be 2.4V - 1V = 1.4V
|
||||
// The low reference voltage will be 0.5
|
||||
// The larger the range, the larger the pulse count value.
|
||||
touch_pad_set_voltage(TOUCH_HVOLT_2V4, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
|
||||
//init RTC IO and mode for touch pad.
|
||||
touch_pad_config(TOUCH_PAD_NUM8, TOUCH_THRESH_NO_USE);
|
||||
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 || CONFIG_IDF_TARGET_ESP32S3
|
||||
/* Initialize touch pad peripheral. */
|
||||
touch_pad_init();
|
||||
/* Only support one touch channel in sleep mode. */
|
||||
touch_pad_config(TOUCH_PAD_NUM9);
|
||||
/* 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();
|
||||
printf("Denoise function init\n");
|
||||
/* Filter setting */
|
||||
touch_filter_config_t filter_info = {
|
||||
.mode = TOUCH_PAD_FILTER_IIR_16,
|
||||
.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();
|
||||
printf("touch pad filter init %d\n", TOUCH_PAD_FILTER_IIR_8);
|
||||
/* Set sleep touch pad. */
|
||||
touch_pad_sleep_channel_enable(TOUCH_PAD_NUM9, true);
|
||||
touch_pad_sleep_channel_enable_proximity(TOUCH_PAD_NUM9, false);
|
||||
/* Reducing the operating frequency can effectively reduce power consumption. */
|
||||
touch_pad_sleep_channel_set_work_time(1000, TOUCH_PAD_MEASURE_CYCLE_DEFAULT);
|
||||
/* Enable touch sensor clock. Work mode is "timer trigger". */
|
||||
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
|
||||
touch_pad_fsm_start();
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
|
||||
/* set touchpad wakeup threshold */
|
||||
uint32_t touch_value, wake_threshold;
|
||||
touch_pad_sleep_channel_read_smooth(TOUCH_PAD_NUM9, &touch_value);
|
||||
wake_threshold = touch_value * 0.1; // wakeup when touch sensor crosses 10% of background level
|
||||
touch_pad_sleep_set_threshold(TOUCH_PAD_NUM9, wake_threshold);
|
||||
printf("Touch pad #%d average: %"PRIu32", wakeup threshold set to %"PRIu32"\n",
|
||||
TOUCH_PAD_NUM9, touch_value, (uint32_t)(touch_value * 0.1));
|
||||
#endif
|
||||
printf("Enabling touch pad wakeup\n");
|
||||
ESP_ERROR_CHECK(esp_sleep_enable_touchpad_wakeup());
|
||||
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
||||
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON));
|
||||
#endif
|
||||
}
|
||||
#endif // CONFIG_EXAMPLE_TOUCH_WAKEUP
|
@@ -1,4 +1,4 @@
|
||||
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
import logging
|
||||
import time
|
||||
@@ -6,9 +6,6 @@ import time
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
touch_wake_up_support = ['esp32', 'esp32s2']
|
||||
|
||||
|
||||
CONFIGS = [
|
||||
pytest.param('esp32_singlecore', marks=[pytest.mark.esp32]),
|
||||
pytest.param(
|
||||
@@ -33,18 +30,12 @@ CONFIGS = [
|
||||
@pytest.mark.generic
|
||||
def test_deep_sleep(dut: Dut) -> None:
|
||||
def expect_enable_deep_sleep_touch() -> None:
|
||||
# different targets configure different wake pin(s)
|
||||
wake_pads = {
|
||||
'esp32': [8, 9],
|
||||
'esp32s2': [9],
|
||||
}[dut.target]
|
||||
|
||||
logging.info('Expecting to see wakeup configured on pad(s): {}'.format(wake_pads))
|
||||
|
||||
expect_items = ['Enabling timer wakeup, 20s']
|
||||
for pad in wake_pads:
|
||||
expect_items += [r'Touch pad #{} average: \d+, wakeup threshold set to \d+.'.format(pad)]
|
||||
expect_items += ['Enabling touch pad wakeup']
|
||||
expect_items += ['Enabling touch wakeup']
|
||||
expect_items += [r'Touch \[CH [0-9]+\] enabled on GPIO[0-9]+']
|
||||
if dut.target != 'esp32':
|
||||
expect_items += [r'Touch channel [0-9]+ \(GPIO[0-9]+\) is selected as deep sleep wakeup channel']
|
||||
expect_items += ['touch wakeup source is ready']
|
||||
|
||||
for exp in expect_items:
|
||||
dut.expect(exp, timeout=10)
|
||||
@@ -52,7 +43,7 @@ def test_deep_sleep(dut: Dut) -> None:
|
||||
def expect_enable_deep_sleep_no_touch() -> None:
|
||||
dut.expect_exact('Enabling timer wakeup, 20s', timeout=10)
|
||||
|
||||
if dut.target in touch_wake_up_support:
|
||||
if dut.app.sdkconfig.get('SOC_TOUCH_SUPPORT_SLEEP_WAKEUP'):
|
||||
expect_enable_deep_sleep = expect_enable_deep_sleep_touch
|
||||
else:
|
||||
expect_enable_deep_sleep = expect_enable_deep_sleep_no_touch
|
||||
|
@@ -4,21 +4,12 @@ set(srcs "light_sleep_example_main.c"
|
||||
"gpio_wakeup.c"
|
||||
"timer_wakeup.c"
|
||||
"uart_wakeup.c")
|
||||
set(includes ".")
|
||||
|
||||
set(priv_reqs esp_driver_uart esp_driver_gpio esp_timer)
|
||||
|
||||
set(TOUCH_ELEMENT_COMPATIBLE_TARGETS "esp32s2" "esp32s3")
|
||||
|
||||
if(${target} IN_LIST TOUCH_ELEMENT_COMPATIBLE_TARGETS)
|
||||
list(APPEND srcs "touch_wakeup.c")
|
||||
list(APPEND priv_reqs touch_element)
|
||||
endif()
|
||||
|
||||
if("${target}" STREQUAL "esp32p4")
|
||||
if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED AND CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP)
|
||||
list(APPEND srcs "touch_sens_wakeup.c")
|
||||
list(APPEND priv_reqs esp_driver_touch_sens)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
PRIV_REQUIRES ${priv_reqs}
|
||||
INCLUDE_DIRS ".")
|
||||
PRIV_REQUIRES esp_driver_uart esp_driver_gpio esp_timer esp_driver_touch_sens
|
||||
INCLUDE_DIRS ${includes})
|
||||
|
3
examples/system/light_sleep/main/idf_component.yml
Normal file
3
examples/system/light_sleep/main/idf_component.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
dependencies:
|
||||
touch_sens_examples_common:
|
||||
path: ${IDF_PATH}/examples/peripherals/touch_sensor/touch_sens_examples_common
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@@ -12,8 +12,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// TODO: [ESP32P4] add P4 when runner is ready
|
||||
#define EXAMPLE_TOUCH_LSLEEP_WAKEUP_SUPPORT (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
#define TOUCH_LSLEEP_SUPPORTED (SOC_TOUCH_SENSOR_SUPPORTED && SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP)
|
||||
|
||||
void example_wait_gpio_inactive(void);
|
||||
|
||||
@@ -23,7 +22,7 @@ esp_err_t example_register_timer_wakeup(void);
|
||||
|
||||
esp_err_t example_register_uart_wakeup(void);
|
||||
|
||||
#if EXAMPLE_TOUCH_LSLEEP_WAKEUP_SUPPORT
|
||||
#if TOUCH_LSLEEP_SUPPORTED
|
||||
void example_register_touch_wakeup(void);
|
||||
#endif
|
||||
|
||||
|
@@ -50,7 +50,7 @@ static void light_sleep_task(void *args)
|
||||
* Otherwise the chip may fall sleep again before running uart task */
|
||||
vTaskDelay(1);
|
||||
break;
|
||||
#if EXAMPLE_TOUCH_LSLEEP_WAKEUP_SUPPORT
|
||||
#if TOUCH_LSLEEP_SUPPORTED
|
||||
case ESP_SLEEP_WAKEUP_TOUCHPAD:
|
||||
wakeup_reason = "touch";
|
||||
break;
|
||||
@@ -83,7 +83,7 @@ void app_main(void)
|
||||
example_register_timer_wakeup();
|
||||
/* Enable wakeup from light sleep by uart */
|
||||
example_register_uart_wakeup();
|
||||
#if EXAMPLE_TOUCH_LSLEEP_WAKEUP_SUPPORT
|
||||
#if TOUCH_LSLEEP_SUPPORTED
|
||||
/* Enable wakeup from light sleep by touch element */
|
||||
example_register_touch_wakeup();
|
||||
#endif
|
||||
|
@@ -1,18 +1,22 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/touch_sens.h"
|
||||
#include "touch_sens_example_config.h"
|
||||
|
||||
static const char *TAG = "touch_wakeup";
|
||||
|
||||
#define EXAMPLE_TOUCH_SAMPLE_CFG_NUM 1
|
||||
#define EXAMPLE_TOUCH_CHANNEL_NUM 5
|
||||
#define EXAMPLE_TOUCH_CHANNEL_NUM 3
|
||||
#define EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES 3
|
||||
|
||||
// If you want to change the wake-up channels, please make sure the channel GPIOs won't conflict to the EXT wakeup GPIOs
|
||||
static int s_channel_id[EXAMPLE_TOUCH_CHANNEL_NUM] = {7, 8, 9};
|
||||
|
||||
// Active threshold to benchmark ratio. (i.e., touch will be activated when data >= benchmark * (1 + ratio))
|
||||
static float s_thresh2bm_ratio[EXAMPLE_TOUCH_CHANNEL_NUM] = {
|
||||
[0 ... EXAMPLE_TOUCH_CHANNEL_NUM - 1] = 0.02f, // 2%
|
||||
@@ -20,13 +24,13 @@ static float s_thresh2bm_ratio[EXAMPLE_TOUCH_CHANNEL_NUM] = {
|
||||
|
||||
static bool example_touch_on_active_cb(touch_sensor_handle_t sens_handle, const touch_active_event_data_t *event, void *user_ctx)
|
||||
{
|
||||
ESP_EARLY_LOGW("isr", "ch %d active", (int)event->chan_id);
|
||||
ESP_EARLY_LOGW("touch callback", "ch %d active", (int)event->chan_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool example_touch_on_inactive_cb(touch_sensor_handle_t sens_handle, const touch_inactive_event_data_t *event, void *user_ctx)
|
||||
{
|
||||
ESP_EARLY_LOGW("isr", "ch %d inactive", (int)event->chan_id);
|
||||
ESP_EARLY_LOGW("touch callback", "ch %d inactive", (int)event->chan_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -48,13 +52,25 @@ static void example_touch_do_initial_scanning(touch_sensor_handle_t sens_handle,
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
/* Read the initial benchmark of the touch channel */
|
||||
uint32_t benchmark[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {};
|
||||
#if SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark));
|
||||
#else
|
||||
/* Read smooth data instead if the hardware does not support benchmark */
|
||||
ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_SMOOTH, benchmark));
|
||||
#endif // SOC_TOUCH_SUPPORT_BENCHMARK
|
||||
/* Calculate the proper active thresholds regarding the initial benchmark */
|
||||
printf("[CH %d]", i);
|
||||
touch_channel_config_t chan_cfg = {};
|
||||
printf("Touch [CH %d]", s_channel_id[i]);
|
||||
/* Generate the default channel configuration and then update the active threshold based on the real benchmark */
|
||||
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
|
||||
for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) {
|
||||
chan_cfg.active_thresh[j] = (uint32_t)(benchmark[j] * s_thresh2bm_ratio[j]);
|
||||
#if SOC_TOUCH_SENSOR_VERSION == 1
|
||||
// Touch V1 (ESP32) uses absolute threshold.
|
||||
chan_cfg.abs_active_thresh[j] = (uint32_t)(benchmark[j] * (1 - s_thresh2bm_ratio[i]));
|
||||
printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.abs_active_thresh[j]);
|
||||
#else
|
||||
chan_cfg.active_thresh[j] = (uint32_t)(benchmark[j] * s_thresh2bm_ratio[i]);
|
||||
printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.active_thresh[j]);
|
||||
#endif // SOC_TOUCH_SENSOR_VERSION == 1
|
||||
}
|
||||
printf("\n");
|
||||
/* Update the channel configuration */
|
||||
@@ -64,39 +80,46 @@ static void example_touch_do_initial_scanning(touch_sensor_handle_t sens_handle,
|
||||
|
||||
esp_err_t example_register_touch_wakeup(void)
|
||||
{
|
||||
/* Handles of touch sensor */
|
||||
touch_sensor_handle_t sens_handle = NULL;
|
||||
touch_sensor_sample_config_t sample_cfg[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {
|
||||
TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG(1, 1, 1),
|
||||
};
|
||||
touch_channel_handle_t chan_handle[EXAMPLE_TOUCH_CHANNEL_NUM];
|
||||
|
||||
/* Step 1: Create a new touch sensor controller handle with default sample configuration */
|
||||
touch_sensor_sample_config_t sample_cfg[TOUCH_SAMPLE_CFG_NUM] = EXAMPLE_TOUCH_SAMPLE_CFG_DEFAULT();
|
||||
touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(EXAMPLE_TOUCH_SAMPLE_CFG_NUM, sample_cfg);
|
||||
ESP_ERROR_CHECK(touch_sensor_new_controller(&sens_cfg, &sens_handle));
|
||||
|
||||
/* Step 2: Create and enable the new touch channel handles with default configurations */
|
||||
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
ESP_ERROR_CHECK(touch_sensor_new_channel(sens_handle, s_channel_id[i], &chan_cfg, &chan_handle[i]));
|
||||
/* Display the touch channel corresponding GPIO number, you can also know from `touch_sensor_channel.h` */
|
||||
touch_chan_info_t chan_info = {};
|
||||
ESP_ERROR_CHECK(touch_sensor_get_channel_info(chan_handle[i], &chan_info));
|
||||
printf("Touch [CH %d] enabled on GPIO%d\n", s_channel_id[i], chan_info.chan_gpio);
|
||||
}
|
||||
|
||||
/* Step 3: Confiture the default filter for the touch sensor (Note: Touch V1 uses software filter) */
|
||||
touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_sensor_config_filter(sens_handle, &filter_cfg));
|
||||
|
||||
touch_channel_handle_t chan_handle[EXAMPLE_TOUCH_CHANNEL_NUM];
|
||||
touch_channel_config_t chan_cfg = {
|
||||
.active_thresh = {5000}, // Initial threshold
|
||||
|
||||
};
|
||||
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
|
||||
ESP_ERROR_CHECK(touch_sensor_new_channel(sens_handle, i, &chan_cfg, &chan_handle[i]));
|
||||
}
|
||||
|
||||
/* (Optional) Do the initial scanning to initialize the touch channel data
|
||||
* Without this step, the channel data in the first read will be invalid
|
||||
*/
|
||||
example_touch_do_initial_scanning(sens_handle, chan_handle);
|
||||
|
||||
/* (Optional) Register the callbacks, optional for light sleep wakeup */
|
||||
touch_event_callbacks_t callbacks = {
|
||||
.on_active = example_touch_on_active_cb,
|
||||
.on_inactive = example_touch_on_inactive_cb,
|
||||
};
|
||||
ESP_ERROR_CHECK(touch_sensor_register_callbacks(sens_handle, &callbacks, NULL));
|
||||
|
||||
/* Step 4: Enable the light sleep wake-up with the basic configuration */
|
||||
touch_sleep_config_t light_slp_cfg = TOUCH_SENSOR_DEFAULT_LSLP_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_sensor_config_sleep_wakeup(sens_handle, &light_slp_cfg));
|
||||
|
||||
/* Step 5: Enable touch sensor controller and start continuous scanning before entering light sleep */
|
||||
ESP_ERROR_CHECK(touch_sensor_enable(sens_handle));
|
||||
ESP_ERROR_CHECK(touch_sensor_start_continuous_scanning(sens_handle));
|
||||
|
||||
|
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "touch_element/touch_button.h"
|
||||
|
||||
static const char *TAG = "touch_wakeup";
|
||||
|
||||
#define TOUCH_BUTTON_NUM 5
|
||||
|
||||
/* Touch buttons handle */
|
||||
static touch_button_handle_t button_handle[TOUCH_BUTTON_NUM];
|
||||
|
||||
|
||||
/* Touch buttons channel array */
|
||||
static const touch_pad_t channel_array[TOUCH_BUTTON_NUM] = {
|
||||
TOUCH_PAD_NUM1,
|
||||
TOUCH_PAD_NUM2,
|
||||
TOUCH_PAD_NUM3,
|
||||
TOUCH_PAD_NUM4,
|
||||
TOUCH_PAD_NUM5,
|
||||
};
|
||||
|
||||
/* Touch buttons channel sensitivity array */
|
||||
static const float channel_sens_array[TOUCH_BUTTON_NUM] = {
|
||||
0.03F,
|
||||
0.03F,
|
||||
0.03F,
|
||||
0.03F,
|
||||
0.03F,
|
||||
};
|
||||
|
||||
/* Button event handler task */
|
||||
static void button_handler_task(void *arg)
|
||||
{
|
||||
(void) arg; //Unused
|
||||
touch_elem_message_t element_message;
|
||||
while (1) {
|
||||
/* Waiting for touch element messages */
|
||||
touch_element_message_receive(&element_message, portMAX_DELAY);
|
||||
if (element_message.element_type != TOUCH_ELEM_TYPE_BUTTON) {
|
||||
continue;
|
||||
}
|
||||
/* Decode message */
|
||||
const touch_button_message_t *button_message = touch_button_get_message(&element_message);
|
||||
if (button_message->event == TOUCH_BUTTON_EVT_ON_PRESS) {
|
||||
ESP_LOGI(TAG, "Button[%"PRIu32"] Press", (uint32_t)element_message.arg);
|
||||
} else if (button_message->event == TOUCH_BUTTON_EVT_ON_RELEASE) {
|
||||
ESP_LOGI(TAG, "Button[%"PRIu32"] Release", (uint32_t)element_message.arg);
|
||||
} else if (button_message->event == TOUCH_BUTTON_EVT_ON_LONGPRESS) {
|
||||
ESP_LOGI(TAG, "Button[%"PRIu32"] LongPress", (uint32_t)element_message.arg);
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
esp_err_t example_register_touch_wakeup(void)
|
||||
{
|
||||
/* Initialize Touch Element library */
|
||||
touch_elem_global_config_t global_config = TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_element_install(&global_config));
|
||||
ESP_LOGI(TAG, "Touch element library installed");
|
||||
|
||||
touch_button_global_config_t button_global_config = TOUCH_BUTTON_GLOBAL_DEFAULT_CONFIG();
|
||||
ESP_ERROR_CHECK(touch_button_install(&button_global_config));
|
||||
ESP_LOGI(TAG, "Touch button installed");
|
||||
for (int i = 0; i < TOUCH_BUTTON_NUM; i++) {
|
||||
touch_button_config_t button_config = {
|
||||
.channel_num = channel_array[i],
|
||||
.channel_sens = channel_sens_array[i]
|
||||
};
|
||||
/* Create Touch buttons */
|
||||
ESP_ERROR_CHECK(touch_button_create(&button_config, &button_handle[i]));
|
||||
/* Set EVENT as the dispatch method */
|
||||
ESP_ERROR_CHECK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_EVENT));
|
||||
/* Subscribe touch button events (On Press, On Release, On LongPress) */
|
||||
ESP_ERROR_CHECK(touch_button_subscribe_event(button_handle[i],
|
||||
TOUCH_ELEM_EVENT_ON_PRESS |
|
||||
TOUCH_ELEM_EVENT_ON_RELEASE |
|
||||
TOUCH_ELEM_EVENT_ON_LONGPRESS,
|
||||
(void *)channel_array[i]));
|
||||
}
|
||||
ESP_LOGI(TAG, "Touch buttons created");
|
||||
|
||||
touch_elem_sleep_config_t sleep_config = {
|
||||
.sample_count = global_config.hardware.sample_count,
|
||||
.sleep_cycle = global_config.hardware.sleep_cycle,
|
||||
};
|
||||
/* Enable one of registered touch button as light/deep sleep wake-up source */
|
||||
ESP_ERROR_CHECK(touch_element_enable_light_sleep(&sleep_config));
|
||||
|
||||
touch_element_start();
|
||||
xTaskCreate(&button_handler_task, "button_handler_task", 4 * 1024, NULL, 6, NULL);
|
||||
ESP_LOGI(TAG, "touch wakeup source is ready");
|
||||
return ESP_OK;
|
||||
}
|
Reference in New Issue
Block a user