remove(touch_element): remove touch_element from idf

Touch Element Library is moved to managed component.
(https://components.espressif.com/components/espressif/touch_element/versions/1.0.0/readme)
This commit is contained in:
laokaiyao
2025-09-03 11:20:49 +08:00
parent 012318db96
commit f15a60f2f6
82 changed files with 98 additions and 8241 deletions

View File

@@ -156,7 +156,6 @@
/components/spi_flash/ @esp-idf-codeowners/peripherals
/components/spiffs/ @esp-idf-codeowners/storage
/components/tcp_transport/ @esp-idf-codeowners/network
/components/touch_element/ @esp-idf-codeowners/peripherals
/components/ulp/ @esp-idf-codeowners/system
/components/unity/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
/components/usb/ @esp-idf-codeowners/peripherals/usb

View File

@@ -23,6 +23,19 @@ components/driver/test_apps/legacy_twai:
depends_components:
- esp_driver_gpio
components/driver/test_apps/touch_element:
disable:
- if: IDF_TARGET not in ["esp32s2", "esp32s3"]
reason: only supports esp32s2 and esp32s3
depends_filepatterns:
- components/soc/**/touch_sensor_periph.h
- components/soc/esp32s2/**/rtc_cntl_*
- components/soc/esp32s3/**/rtc_cntl_*
- components/soc/esp32s2/**/rtc_io_struct.h
- components/soc/esp32s3/**/rtc_io_struct.h
- components/soc/esp32s2/**/sens_struct.h
- components/soc/esp32s3/**/sens_struct.h
components/driver/test_apps/touch_sensor_v1:
disable:
- if: SOC_TOUCH_SENSOR_VERSION != 1

View File

@@ -1,5 +1,5 @@
idf_component_register(SRCS "test_app_main.c" "test_touch_element.c" "test_touch_button.c"
"test_touch_slider.c" "test_touch_matrix.c"
PRIV_REQUIRES unity touch_element
PRIV_REQUIRES unity touch_element esp_pm
WHOLE_ARCHIVE
)

View File

@@ -0,0 +1,2 @@
dependencies:
espressif/touch_element: ^1.0.0

View File

@@ -10,7 +10,6 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
// Some resources are lazy allocated in gpio/dedicated_gpio/delta_sigma driver, the threshold is left for that case
#define TEST_MEMORY_LEAK_THRESHOLD (-400)
static size_t before_free_8bit;

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -14,7 +14,8 @@
#include "unity.h"
#include "esp_random.h"
#include "touch_element/touch_element_private.h"
#include "esp_private/touch_element_private.h"
#include "esp_private/touch_sensor_legacy_ll.h"
#include "touch_element/touch_button.h"
static portMUX_TYPE test_button_spinlock = portMUX_INITIALIZER_UNLOCKED;
@@ -103,11 +104,14 @@ void test_button_event_simulator(touch_button_handle_t button_handle, touch_butt
te_button_handle_t te_button = (te_button_handle_t) button_handle;
touch_pad_t channel = te_button->device->channel;
if (button_event == TOUCH_BUTTON_EVT_ON_PRESS) {
touch_pad_set_cnt_mode(channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(channel, TOUCH_PAD_SLOPE_3);
touch_ll_set_tie_option(channel, TOUCH_PAD_TIE_OPT_DEFAULT);
} else if (button_event == TOUCH_BUTTON_EVT_ON_RELEASE) {
touch_pad_set_cnt_mode(channel, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(channel, TOUCH_PAD_SLOPE_7);
touch_ll_set_tie_option(channel, TOUCH_PAD_TIE_OPT_DEFAULT);
} else {
touch_pad_set_cnt_mode(channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT); //LongPress
touch_ll_set_slope(channel, TOUCH_PAD_SLOPE_3);
touch_ll_set_tie_option(channel, TOUCH_PAD_TIE_OPT_DEFAULT);
}
}
@@ -129,7 +133,8 @@ static void test_button_callback_check(touch_button_handle_t current_handle, tou
}
void test_button_event_trigger_and_check(touch_button_handle_t handle, touch_button_event_t button_event)
{//TODO: refactor this with a constructor
{
//TODO: refactor this with a constructor
touch_elem_message_t valid_message = {
.handle = handle,
.element_type = TOUCH_ELEM_TYPE_BUTTON,
@@ -295,7 +300,7 @@ static void test_button_event_change_lp(void)
printf("Touch button event change longtime test start\n");
for (int i = 0; i < 10; i++) {
printf("Touch button event change longtime test... (%d/10)\n", i + 1);
esp_err_t ret;
esp_err_t ret = ESP_OK;
uint8_t channel_index = random() % BUTTON_CHANNEL_NUM;
touch_elem_message_t valid_message = {
.handle = button_handle[channel_index],
@@ -412,7 +417,7 @@ static void test_button_event_concurrent(void)
printf("Touch button event concurrent test start\n");
for (int i = 0; i < 10; i++) {
printf("Touch button event concurrent test... (%d/10)\n", i + 1);
esp_err_t ret;
esp_err_t ret = ESP_OK;
uint32_t message_count = 0;
touch_elem_message_t current_message;
@@ -488,7 +493,6 @@ static void test_button_random_trigger_concurrent(void)
TEST_ASSERT(os_ret == pdPASS);
}
uint32_t run_count = 0;
while (1) {
if (run_count++ % 1000 == 0) {

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -34,6 +34,7 @@
#include "touch_element/touch_button.h"
#include "touch_element/touch_slider.h"
#include "touch_element/touch_matrix.h"
#include "esp_private/touch_sensor_legacy_ll.h"
typedef struct {
QueueHandle_t valid_msg_handle;
@@ -110,7 +111,8 @@ static void test_system_waterproof_guard(void)
printf("Touch Element waterproof guard sensor test start\n");
srandom((unsigned int)time(NULL));
{//No use waterproof guard sensor
{
//No use waterproof guard sensor
touch_elem_waterproof_config_t waterproof_config = {
.guard_channel = TOUCH_WATERPROOF_GUARD_NOUSE,
.guard_sensitivity = 0.0F
@@ -128,7 +130,8 @@ static void test_system_waterproof_guard(void)
touch_element_waterproof_uninstall();
}
{//Use waterproof guard sensor(Add all handles)
{
//Use waterproof guard sensor(Add all handles)
touch_elem_waterproof_config_t waterproof_config = {
.guard_channel = TOUCH_PAD_NUM13,
.guard_sensitivity = 0.1F
@@ -158,7 +161,8 @@ static void test_system_waterproof_guard(void)
touch_element_waterproof_uninstall();
}
{//Put half button handles into guard ring
{
//Put half button handles into guard ring
const uint8_t protect_handle_threshold = BUTTON_CHANNEL_NUM / 2;
touch_elem_waterproof_config_t waterproof_config = {
.guard_channel = TOUCH_PAD_NUM13,
@@ -196,9 +200,11 @@ static void test_system_waterproof_guard(void)
static void test_waterproof_event_simulator(touch_pad_t guard_channel, touch_button_event_t guard_state)
{
if (guard_state == TOUCH_BUTTON_EVT_ON_PRESS) {
touch_pad_set_cnt_mode(guard_channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(guard_channel, TOUCH_PAD_SLOPE_3);
touch_ll_set_tie_option(guard_channel, TOUCH_PAD_TIE_OPT_DEFAULT);
} else if (guard_state == TOUCH_BUTTON_EVT_ON_RELEASE) {
touch_pad_set_cnt_mode(guard_channel, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(guard_channel, TOUCH_PAD_SLOPE_7);
touch_ll_set_tie_option(guard_channel, TOUCH_PAD_TIE_OPT_DEFAULT);
} else {
printf("guard sensor simulator doesn't support this operation\n");
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -13,7 +13,8 @@
#include "freertos/semphr.h"
#include "unity.h"
#include "touch_element/touch_element_private.h"
#include "esp_private/touch_element_private.h"
#include "esp_private/touch_sensor_legacy_ll.h"
#include "touch_element/touch_matrix.h"
static const touch_pad_t x_axis_channel[3] = {
@@ -95,23 +96,31 @@ void test_matrix_event_simulator(touch_matrix_handle_t matrix_handle, touch_matr
touch_pad_t x_channel = te_matrix->device[pos_index / te_matrix->y_channel_num]->channel;
touch_pad_t y_channel = te_matrix->device[te_matrix->x_channel_num + (pos_index % te_matrix->y_channel_num)]->channel;
if (matrix_event == TOUCH_MATRIX_EVT_ON_PRESS) {
touch_pad_set_cnt_mode(x_channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_pad_set_cnt_mode(y_channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(x_channel, TOUCH_PAD_SLOPE_3);
touch_ll_set_tie_option(x_channel, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(y_channel, TOUCH_PAD_SLOPE_3);
touch_ll_set_tie_option(y_channel, TOUCH_PAD_TIE_OPT_DEFAULT);
} else if (matrix_event == TOUCH_MATRIX_EVT_ON_RELEASE) {
touch_pad_set_cnt_mode(x_channel, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_pad_set_cnt_mode(y_channel, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(x_channel, TOUCH_PAD_SLOPE_7);
touch_ll_set_tie_option(x_channel, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(y_channel, TOUCH_PAD_SLOPE_7);
touch_ll_set_tie_option(y_channel, TOUCH_PAD_TIE_OPT_DEFAULT);
} else {
touch_pad_set_cnt_mode(x_channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT); // LongPress
touch_pad_set_cnt_mode(y_channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(x_channel, TOUCH_PAD_SLOPE_3);
touch_ll_set_tie_option(x_channel, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(y_channel, TOUCH_PAD_SLOPE_3);
touch_ll_set_tie_option(y_channel, TOUCH_PAD_TIE_OPT_DEFAULT);
}
}
static void test_matrix_channel_simulator(touch_pad_t channel, touch_matrix_event_t matrix_event)
{
if (matrix_event == TOUCH_MATRIX_EVT_ON_PRESS) {
touch_pad_set_cnt_mode(channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(channel, TOUCH_PAD_SLOPE_3);
touch_ll_set_tie_option(channel, TOUCH_PAD_TIE_OPT_DEFAULT);
} else if (matrix_event == TOUCH_MATRIX_EVT_ON_RELEASE) {
touch_pad_set_cnt_mode(channel, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(channel, TOUCH_PAD_SLOPE_7);
touch_ll_set_tie_option(channel, TOUCH_PAD_TIE_OPT_DEFAULT);
}
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -13,7 +13,8 @@
#include "freertos/semphr.h"
#include "unity.h"
#include "touch_element/touch_element_private.h"
#include "esp_private/touch_element_private.h"
#include "esp_private/touch_sensor_legacy_ll.h"
#include "touch_element/touch_slider.h"
static const touch_pad_t slider_channel_array[5] = {
@@ -63,9 +64,11 @@ void test_slider_event_simulator(touch_slider_handle_t slider_handle, touch_slid
te_slider_handle_t te_slider = (te_slider_handle_t) slider_handle;
touch_pad_t channel = te_slider->device[random % te_slider->channel_sum]->channel;
if (slider_event == TOUCH_SLIDER_EVT_ON_PRESS) {
touch_pad_set_cnt_mode(channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(channel, TOUCH_PAD_SLOPE_3);
touch_ll_set_tie_option(channel, TOUCH_PAD_TIE_OPT_DEFAULT);
} else if (slider_event == TOUCH_SLIDER_EVT_ON_RELEASE) {
touch_pad_set_cnt_mode(channel, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT);
touch_ll_set_slope(channel, TOUCH_PAD_SLOPE_7);
touch_ll_set_tie_option(channel, TOUCH_PAD_TIE_OPT_DEFAULT);
}
}
@@ -126,7 +129,6 @@ void test_slider_callback_trigger_and_check(touch_slider_handle_t handle, touch_
}
}
static void test_slider_disp_event(void)
{
touch_slider_handle_t slider_handle;
@@ -161,7 +163,6 @@ static void test_slider_disp_event(void)
touch_slider_uninstall();
}
static void test_slider_disp_callback(void)
{
test_monitor_t monitor;

View File

@@ -1,17 +0,0 @@
idf_build_get_property(target IDF_TARGET)
if(${target} STREQUAL "linux")
return() # This component is not supported by the POSIX/Linux simulator
endif()
set(TOUCH_ELEMENT_COMPATIBLE_TARGETS "esp32s2" "esp32s3")
if(${target} IN_LIST TOUCH_ELEMENT_COMPATIBLE_TARGETS)
idf_component_register(SRCS "touch_element.c"
"touch_button.c"
"touch_slider.c"
"touch_matrix.c"
INCLUDE_DIRS include
REQUIRES driver # touch_element uses legacy "driver/touch_sensor.h"
PRIV_REQUIRES esp_timer)
endif()

View File

@@ -1,196 +0,0 @@
/*
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "touch_element/touch_element.h"
#ifdef __cplusplus
extern "C" {
#endif
/* --------------------------------- General button instance default configuration --------------------------------- */
#define TOUCH_BUTTON_GLOBAL_DEFAULT_CONFIG() \
{ \
.threshold_divider = 0.8, \
.default_lp_time = 1000 \
}
/* ------------------------------------------------------------------------------------------------------------------ */
/**
* @brief Button initialization configuration passed to touch_button_install
*/
typedef struct {
float threshold_divider; //!< Button channel threshold divider
uint32_t default_lp_time; //!< Button default LongPress event time (ms)
} touch_button_global_config_t;
/**
* @brief Button configuration (for new instance) passed to touch_button_create()
*/
typedef struct {
touch_pad_t channel_num; //!< Button channel number (index)
float channel_sens; //!< Button channel sensitivity
} touch_button_config_t;
/**
* @brief Button event type
*/
typedef enum {
TOUCH_BUTTON_EVT_ON_PRESS, //!< Button Press event
TOUCH_BUTTON_EVT_ON_RELEASE, //!< Button Release event
TOUCH_BUTTON_EVT_ON_LONGPRESS, //!< Button LongPress event
TOUCH_BUTTON_EVT_MAX
} touch_button_event_t;
/**
* @brief Button message type
*/
typedef struct {
touch_button_event_t event; //!< Button event
} touch_button_message_t;
typedef touch_elem_handle_t touch_button_handle_t; //!< Button handle
typedef void(*touch_button_callback_t)(touch_button_handle_t, touch_button_message_t *, void *); //!< Button callback type
/**
* @brief Touch Button initialize
*
* This function initializes touch button global and acts on all
* touch button instances.
*
* @param[in] global_config Button object initialization configuration
*
* @return
* - ESP_OK: Successfully initialized touch button
* - ESP_ERR_INVALID_STATE: Touch element library was not initialized
* - ESP_ERR_INVALID_ARG: button_init is NULL
* - ESP_ERR_NO_MEM: Insufficient memory
*/
esp_err_t touch_button_install(const touch_button_global_config_t *global_config);
/**
* @brief Release resources allocated using touch_button_install()
*/
void touch_button_uninstall(void);
/**
* @brief Create a new touch button instance
*
* @param[in] button_config Button configuration
* @param[out] button_handle Button handle
*
* @note The sensitivity has to be explored in experiments,
* Sensitivity = (Raw(touch) - Raw(release)) / Raw(release) * 100%
*
* @return
* - ESP_OK: Successfully create touch button
* - ESP_ERR_INVALID_STATE: Touch button driver was not initialized
* - ESP_ERR_NO_MEM: Insufficient memory
* - ESP_ERR_INVALID_ARG: Invalid configuration struct or arguments is NULL
*/
esp_err_t touch_button_create(const touch_button_config_t *button_config, touch_button_handle_t *button_handle);
/**
* @brief Release resources allocated using touch_button_create()
*
* @param[in] button_handle Button handle
* @return
* - ESP_OK: Successfully released resources
* - ESP_ERR_INVALID_STATE: Touch button driver was not initialized
* - ESP_ERR_INVALID_ARG: button_handle is null
* - ESP_ERR_NOT_FOUND: Input handle is not a button handle
*/
esp_err_t touch_button_delete(touch_button_handle_t button_handle);
/**
* @brief Touch button subscribes event
*
* This function uses event mask to subscribe to touch button events, once one of
* the subscribed events occurs, the event message could be retrieved by calling
* touch_element_message_receive() or input callback routine.
*
* @param[in] button_handle Button handle
* @param[in] event_mask Button subscription event mask
* @param[in] arg User input argument
*
* @note Touch button only support three kind of event masks, they are
* TOUCH_ELEM_EVENT_ON_PRESS, TOUCH_ELEM_EVENT_ON_RELEASE, TOUCH_ELEM_EVENT_ON_LONGPRESS.
* You can use those event masks in any combination to achieve the desired effect.
*
* @return
* - ESP_OK: Successfully subscribed touch button event
* - ESP_ERR_INVALID_STATE: Touch button driver was not initialized
* - ESP_ERR_INVALID_ARG: button_handle is null or event is not supported
*/
esp_err_t touch_button_subscribe_event(touch_button_handle_t button_handle, uint32_t event_mask, void *arg);
/**
* @brief Touch button set dispatch method
*
* This function sets a dispatch method that the driver core will use
* this method as the event notification method.
*
* @param[in] button_handle Button handle
* @param[in] dispatch_method Dispatch method (By callback/event)
*
* @return
* - ESP_OK: Successfully set dispatch method
* - ESP_ERR_INVALID_STATE: Touch button driver was not initialized
* - ESP_ERR_INVALID_ARG: button_handle is null or dispatch_method is invalid
*/
esp_err_t touch_button_set_dispatch_method(touch_button_handle_t button_handle, touch_elem_dispatch_t dispatch_method);
/**
* @brief Touch button set callback
*
* This function sets a callback routine into touch element driver core,
* when the subscribed events occur, the callback routine will be called.
*
* @param[in] button_handle Button handle
* @param[in] button_callback User input callback
*
* @note Button message will be passed from the callback function and it will be destroyed when the callback function return.
*
* @warning Since this input callback routine runs on driver core (esp-timer callback routine),
* it should not do something that attempts to Block, such as calling vTaskDelay().
*
* @return
* - ESP_OK: Successfully set callback
* - ESP_ERR_INVALID_STATE: Touch button driver was not initialized
* - ESP_ERR_INVALID_ARG: button_handle or button_callback is null
*/
esp_err_t touch_button_set_callback(touch_button_handle_t button_handle, touch_button_callback_t button_callback);
/**
* @brief Touch button set long press trigger time
*
* This function sets the threshold time (ms) for a long press event. If a button is pressed
* and held for a period of time that exceeds the threshold time, a long press event is triggered.
*
* @param[in] button_handle Button handle
* @param[in] threshold_time Threshold time (ms) of long press event occur
*
* @return
* - ESP_OK: Successfully set the threshold time of long press event
* - ESP_ERR_INVALID_STATE: Touch button driver was not initialized
* - ESP_ERR_INVALID_ARG: button_handle is null or time (ms) is not lager than 0
*/
esp_err_t touch_button_set_longpress(touch_button_handle_t button_handle, uint32_t threshold_time);
/**
* @brief Touch button get message
*
* This function decodes the element message from touch_element_message_receive() and return
* a button message pointer.
*
* @param[in] element_message element message
*
* @return Touch button message pointer
*/
const touch_button_message_t* touch_button_get_message(const touch_elem_message_t* element_message);
#ifdef __cplusplus
}
#endif

View File

@@ -1,338 +0,0 @@
/*
* SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "driver/touch_sensor_legacy.h"
#ifdef __cplusplus
extern "C" {
#endif
/* -------------------------------- General hardware & system default configuration -------------------------------- */
/* Since those are important hardware and algorithm parameters, user should not change them before knowing all details*/
/* ------------------------------------------------------------------------------------------------------------------ */
#define TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG() \
{ \
.hardware = { \
.upper_voltage = TOUCH_HVOLT_2V7, \
.voltage_attenuation = TOUCH_HVOLT_ATTEN_0V5, \
.lower_voltage = TOUCH_LVOLT_0V5, \
.suspend_channel_polarity = TOUCH_PAD_CONN_HIGHZ, \
.denoise_level = TOUCH_PAD_DENOISE_BIT4, \
.denoise_equivalent_cap = TOUCH_PAD_DENOISE_CAP_L0, \
.smooth_filter_mode = TOUCH_PAD_SMOOTH_IIR_2, \
.benchmark_filter_mode = TOUCH_PAD_FILTER_IIR_16, \
.sample_count = 500, \
.sleep_cycle = 0xf, \
.benchmark_debounce_count = 2, \
.benchmark_calibration_threshold = 2, \
.benchmark_jitter_step = 5 \
}, \
.software = { \
.waterproof_threshold_divider = 0.8, \
.processing_period = 10, \
.intr_message_size = 14, \
.event_message_size = 20 \
} \
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------- Event subscription ----------------------------------------------- */
#define TOUCH_ELEM_EVENT_NONE BIT(0) //!< None event
#define TOUCH_ELEM_EVENT_ON_PRESS BIT(1) //!< On Press event
#define TOUCH_ELEM_EVENT_ON_RELEASE BIT(2) //!< On Release event
#define TOUCH_ELEM_EVENT_ON_LONGPRESS BIT(3) //!< On LongPress event
#define TOUCH_ELEM_EVENT_ON_CALCULATION BIT(4) //!< On Calculation event
/* ------------------------------------------------------------------------------------------------------------------ */
#define TOUCH_WATERPROOF_GUARD_NOUSE (0) //!< Waterproof no use guard sensor
/* -------------------------------- Global hardware & software configuration struct --------------------------------- */
/**
* @brief Touch element software configuration
*/
typedef struct {
float waterproof_threshold_divider; //!< Waterproof guard channel threshold divider
uint8_t processing_period; //!< Processing period(ms)
uint8_t intr_message_size; //!< Interrupt message queue size
uint8_t event_message_size; //!< Event message queue size
} touch_elem_sw_config_t;
/**
* @brief Touch element hardware configuration
*/
typedef struct {
touch_high_volt_t upper_voltage; //!< Touch sensor channel upper charge voltage
touch_volt_atten_t voltage_attenuation; //!< Touch sensor channel upper charge voltage attenuation (Diff voltage is upper - attenuation - lower)
touch_low_volt_t lower_voltage; //!< Touch sensor channel lower charge voltage
touch_pad_conn_type_t suspend_channel_polarity; //!< Suspend channel polarity (High Impedance State or GND)
touch_pad_denoise_grade_t denoise_level; //!< Internal de-noise level
touch_pad_denoise_cap_t denoise_equivalent_cap; //!< Internal de-noise channel (Touch channel 0) equivalent capacitance
touch_smooth_mode_t smooth_filter_mode; //!< Smooth value filter mode (This only apply to touch_pad_filter_read_smooth())
touch_filter_mode_t benchmark_filter_mode; //!< Benchmark filter mode
uint16_t sample_count; //!< The count of sample in each measurement of touch sensor
uint16_t sleep_cycle; //!< The cycle (RTC slow clock) of sleep
uint8_t benchmark_debounce_count; //!< Benchmark debounce count
uint8_t benchmark_calibration_threshold; //!< Benchmark calibration threshold
uint8_t benchmark_jitter_step; //!< Benchmark jitter filter step (This only works at while benchmark filter mode is jitter filter)
} touch_elem_hw_config_t;
/**
* @brief Touch element global configuration passed to touch_element_install
*/
typedef struct {
touch_elem_hw_config_t hardware; //!< Hardware configuration
touch_elem_sw_config_t software; //!< Software configuration
} touch_elem_global_config_t;
/**
* @brief Touch element waterproof configuration passed to touch_element_waterproof_install
*/
typedef struct {
touch_pad_t guard_channel; //!< Waterproof Guard-Sensor channel number (index)
float guard_sensitivity; //!< Waterproof Guard-Sensor sensitivity
} touch_elem_waterproof_config_t;
/**
* @brief Touch element sleep configuration passed to touch_element_enable_light_sleep or touch_element_enable_deep_sleep
*/
typedef struct {
uint16_t sample_count; //!< scan times in every measurement, normally equal to the 'sample_count' field in 'touch_elem_hw_config_t'.
uint16_t sleep_cycle; //!< sleep_cycle decide the interval between two measurements t_sleep = sleep_cycle / (RTC_SLOW_CLK frequency), normally equal to the 'sleep_cycle' field in 'touch_elem_hw_config_t'.
} touch_elem_sleep_config_t;
/* ------------------------------------------------------------------------------------------------------------------ */
typedef void *touch_elem_handle_t; //!< Touch element handle type
typedef uint32_t touch_elem_event_t; //!< Touch element event type
/**
* @brief Touch element handle type
*/
typedef enum {
TOUCH_ELEM_TYPE_BUTTON, //!< Touch element button
TOUCH_ELEM_TYPE_SLIDER, //!< Touch element slider
TOUCH_ELEM_TYPE_MATRIX, //!< Touch element matrix button
} touch_elem_type_t;
/**
* @brief Touch element event dispatch methods (event queue/callback)
*/
typedef enum {
TOUCH_ELEM_DISP_EVENT, //!< Event queue dispatch
TOUCH_ELEM_DISP_CALLBACK, //!< Callback dispatch
TOUCH_ELEM_DISP_MAX
} touch_elem_dispatch_t;
/**
* @brief Touch element event message type from touch_element_message_receive()
*/
typedef struct {
touch_elem_handle_t handle; //!< Touch element handle
touch_elem_type_t element_type; //!< Touch element type
void *arg; //!< User input argument
uint8_t child_msg[8]; //!< Encoded message
} touch_elem_message_t;
/* ------------------------------------------------------------------------------------------------------------------ */
/**
* @brief Touch element processing initialization
*
* @param[in] global_config Global initialization configuration structure
*
* @note To reinitialize the touch element object, call touch_element_uninstall() first
*
* @return
* - ESP_OK: Successfully initialized
* - ESP_ERR_INVALID_ARG: Invalid argument
* - ESP_ERR_NO_MEM: Insufficient memory
* - ESP_ERR_INVALID_STATE: Touch element is already initialized
* - Others: Unknown touch driver layer or lower layer error
*/
esp_err_t touch_element_install(const touch_elem_global_config_t *global_config);
/**
* @brief Touch element processing start
*
* This function starts the touch element processing system
*
* @note This function must only be called after all the touch element instances finished creating
*
* @return
* - ESP_OK: Successfully started to process
* - Others: Unknown touch driver layer or lower layer error
*/
esp_err_t touch_element_start(void);
/**
* @brief Touch element processing stop
*
* This function stops the touch element processing system
*
* @note This function must be called before changing the system (hardware, software) parameters
*
* @return
* - ESP_OK: Successfully stopped to process
* - Others: Unknown touch driver layer or lower layer error
*/
esp_err_t touch_element_stop(void);
/**
* @brief Release resources allocated using touch_element_install
*
*/
void touch_element_uninstall(void);
/**
* @brief Get current event message of touch element instance
*
* This function will receive the touch element message (handle, event type, etc...)
* from te_event_give(). It will block until a touch element event or a timeout occurs.
*
* @param[out] element_message Touch element event message structure
* @param[in] ticks_to_wait Number of FreeRTOS ticks to block for waiting event
* @return
* - ESP_OK: Successfully received touch element event
* - ESP_ERR_INVALID_STATE: Touch element library is not initialized
* - ESP_ERR_INVALID_ARG: element_message is null
* - ESP_ERR_TIMEOUT: Timed out waiting for event
*/
esp_err_t touch_element_message_receive(touch_elem_message_t *element_message, uint32_t ticks_to_wait);
/**
* @brief Touch element waterproof initialization
*
* This function enables the hardware waterproof, then touch element system uses Shield-Sensor
* and Guard-Sensor to mitigate the influence of water-drop and water-stream.
*
* @param[in] waterproof_config Waterproof configuration
*
* @note If the waterproof function is used, Shield-Sensor can not be disabled and it will use channel 14 as
* it's internal channel. Hence, the user can not use channel 14 for another propose. And the Guard-Sensor
* is not necessary since it is optional.
*
* @note Shield-Sensor: It always uses channel 14 as the shield channel, so user must connect
* the channel 14 and Shield-Layer in PCB since it will generate a synchronous signal automatically
*
* @note Guard-Sensor: This function is optional. If used, the user must connect the guard channel and Guard-Ring
* in PCB. Any channels user wants to protect should be added into Guard-Ring in PCB.
*
* @return
* - ESP_OK: Successfully initialized
* - ESP_ERR_INVALID_STATE: Touch element library is not initialized
* - ESP_ERR_INVALID_ARG: waterproof_config is null or invalid Guard-Sensor channel
* - ESP_ERR_NO_MEM: Insufficient memory
*/
esp_err_t touch_element_waterproof_install(const touch_elem_waterproof_config_t *waterproof_config);
/**
* @brief Release resources allocated using touch_element_waterproof_install()
*/
void touch_element_waterproof_uninstall(void);
/**
* @brief Add a masked handle to protect while Guard-Sensor has been triggered
*
* This function will add an application handle (button, slider, etc...) as a masked handle. While Guard-Sensor
* has been triggered, waterproof function will start working and lock the application internal state. While the
* influence of water is reduced, the application will be unlock and reset into IDLE state.
*
* @param[in] element_handle Touch element instance handle
*
* @note The waterproof protection logic must follow the real circuit in PCB, it means that all of the channels
* inside the input handle must be inside the Guard-Ring in real circuit.
*
* @return
* - ESP_OK: Successfully added a masked handle
* - ESP_ERR_INVALID_STATE: Waterproof is not initialized
* - ESP_ERR_INVALID_ARG: element_handle is null
*/
esp_err_t touch_element_waterproof_add(touch_elem_handle_t element_handle);
/**
* @brief Remove a masked handle to protect
*
* This function will remove an application handle from masked handle table.
*
* @param[in] element_handle Touch element instance handle
*
* @return
* - ESP_OK: Successfully removed a masked handle
* - ESP_ERR_INVALID_STATE: Waterproof is not initialized
* - ESP_ERR_INVALID_ARG: element_handle is null
* - ESP_ERR_NOT_FOUND: Failed to search element_handle from waterproof mask_handle list
*/
esp_err_t touch_element_waterproof_remove(touch_elem_handle_t element_handle);
/**
* @brief Touch element light sleep initialization
*
* @note It should be called after touch button element installed.
* Any of installed touch element can wake up from the light sleep
*
* @param[in] sleep_config Sleep configurations, set NULL to use default config
* @return
* - ESP_OK: Successfully initialized touch sleep
* - ESP_ERR_INVALID_STATE: Touch element is not installed or touch sleep has been installed
* - ESP_ERR_INVALID_ARG: inputted argument is NULL
* - ESP_ERR_NO_MEM: no memory for touch sleep struct
* - ESP_ERR_NOT_SUPPORTED: inputted wakeup_elem_handle is not touch_button_handle_t type, currently only touch_button_handle_t supported
*/
esp_err_t touch_element_enable_light_sleep(const touch_elem_sleep_config_t *sleep_config);
/**
* @brief Release the resources that allocated by touch_element_enable_deep_sleep()
*
* This function will also disable the touch sensor to wake up the device
*
* @return
* - ESP_OK: uninstall success
* - ESP_ERR_INVALID_STATE: touch sleep has not been installed
*/
esp_err_t touch_element_disable_light_sleep(void);
/**
* @brief Touch element deep sleep initialization
*
* This function will enable the device wake-up from deep sleep or light sleep by touch sensor
*
* @note It should be called after touch button element installed.
* Only one touch button can be registered as the deep sleep wake-up button
*
* @param[in] wakeup_elem_handle Touch element instance handle for waking up the device, only support button element
* @param[in] sleep_config Sleep configurations, set NULL to use default config
*
* @return
* - ESP_OK: Successfully initialized touch sleep
* - ESP_ERR_INVALID_STATE: Touch element is not installed or touch sleep has been installed
* - ESP_ERR_INVALID_ARG: inputted argument is NULL
* - ESP_ERR_NO_MEM: no memory for touch sleep struct
* - ESP_ERR_NOT_SUPPORTED: inputted wakeup_elem_handle is not touch_button_handle_t type, currently only touch_button_handle_t supported
*/
esp_err_t touch_element_enable_deep_sleep(touch_elem_handle_t wakeup_elem_handle, const touch_elem_sleep_config_t *sleep_config);
/**
* @brief Release the resources that allocated by touch_element_enable_deep_sleep()
*
* This function will also disable the touch sensor to wake up the device
*
* @return
* - ESP_OK: uninstall success
* - ESP_ERR_INVALID_STATE: touch sleep has not been installed
*/
esp_err_t touch_element_disable_deep_sleep(void);
/**
* @brief Touch element wake up calibrations
*
* This function will also disable the touch sensor to wake up the device
*
* @return
* - ESP_OK: uninstall success
* - ESP_ERR_INVALID_STATE: touch sleep has not been installed
*/
esp_err_t touch_element_sleep_enable_wakeup_calibration(touch_elem_handle_t element_handle, bool en);
#ifdef __cplusplus
}
#endif

View File

@@ -1,200 +0,0 @@
/*
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "touch_element/touch_element.h"
#include "touch_element/touch_button.h"
#include "touch_element/touch_slider.h"
#include "touch_element/touch_matrix.h"
#include "esp_pm.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TE_TAG "Touch Element"
#define TE_DEBUG_TAG "Touch Element Debug"
#define TE_UNUSED(arg) (void)arg
#define TE_CHECK(cond, ret_val) ({ \
if (!(cond)) { \
ESP_LOGE(TE_TAG, "%s(%d)", __FUNCTION__, __LINE__); \
return (ret_val); \
} \
})
#define TE_CHECK_GOTO(cond, label) ({ \
if (!(cond)) { \
goto label; \
} \
})
#define TE_FREE_AND_NULL(ptr) ({ \
free(ptr); \
(ptr) = NULL; \
})
#define TE_DEFAULT_THRESHOLD_DIVIDER(obj) ((obj)->global_config->threshold_divider)
#define TE_DEFAULT_LONGPRESS_TIME(obj) ((obj)->global_config->default_lp_time)
typedef enum {
TE_STATE_IDLE = 0,
TE_STATE_PRESS,
TE_STATE_RELEASE,
} te_state_t;
typedef te_state_t te_dev_state_t;
typedef touch_elem_type_t te_dev_type_t;
typedef struct {
float sens; //!< Touch channel sensitivity
touch_pad_t channel; //!< Touch channel number(index)
te_dev_type_t type; //!< Touch channel type TODO: need to refactor as te_class_type_t
te_dev_state_t state; //!< Touch channel current state
bool is_use_last_threshold;
} te_dev_t;
typedef enum {
TE_CLS_TYPE_BUTTON = 0,
TE_CLS_TYPE_SLIDER,
TE_CLS_TYPE_MATRIX,
TE_CLS_TYPE_MAX //TODO: add waterproof class
} te_class_type_t;
typedef struct {
touch_elem_handle_t handle;
bool (*check_channel) (touch_pad_t);
esp_err_t (*set_threshold) (void);
void (*process_state) (void);
void (*update_state) (touch_pad_t, te_state_t);
} te_object_methods_t;
/* -------------------------------------------- Waterproof basic type --------------------------------------------- */
struct te_waterproof_s {
te_dev_t *guard_device; //Waterproof guard channel device
touch_elem_handle_t *mask_handle; //Waterproof masked handle array
touch_pad_t shield_channel; //Waterproof shield channel
bool is_shield_level_set; //Waterproof shield level setting bit
};
typedef struct te_waterproof_s* te_waterproof_handle_t;
/* -------------------------------------------- Sleep basic type --------------------------------------------- */
struct te_sleep_s {
touch_elem_handle_t wakeup_handle;
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_handle_t pm_lock;
#endif
uint32_t *non_volatile_threshold;
};
typedef struct te_sleep_s* te_sleep_handle_t;
/* -------------------------------------------- Button basic type --------------------------------------------- */
typedef struct {
touch_elem_dispatch_t dispatch_method; //Button dispatch method
touch_button_callback_t callback; //Button callback routine
uint32_t event_mask; //Button subscribed event mask
void *arg; //User input argument
} te_button_handle_config_t;
typedef te_state_t te_button_state_t; //TODO: add Long Press state
struct te_button_s {
te_button_handle_config_t *config; //Button configuration
te_dev_t *device; //Base device information
te_button_state_t current_state; //Button current state
te_button_state_t last_state; //Button last state
touch_button_event_t event; //Button outside state(for application layer)
uint32_t trigger_cnt; //Button long time trigger counter
uint32_t trigger_thr; //Button long time trigger counter threshold
};
typedef struct te_button_s* te_button_handle_t;
/* -------------------------------------------- Slider basic type --------------------------------------------- */
typedef struct {
touch_elem_dispatch_t dispatch_method; //Slider dispatch method
touch_slider_callback_t callback; //Slider callback routine
uint32_t event_mask; //Slider subscribed event mask
void *arg; //User input argument
} te_slider_handle_config_t;
typedef te_state_t te_slider_state_t;
struct te_slider_s {
te_slider_handle_config_t *config; //Slider configuration
te_dev_t **device; //Base device information set
te_slider_state_t current_state; //Slider current state
te_slider_state_t last_state; //Slider last state
touch_slider_event_t event; //Slider outside state(for application layer)
float position_scale; //Slider position scale(step size)
float *quantify_signal_array; //Slider re-quantization array
uint32_t *channel_bcm; //Channel benchmark array
uint32_t channel_bcm_update_cnt; //Channel benchmark update counter
uint32_t filter_reset_cnt; //Slider reset counter
uint32_t last_position; //Slider last position
touch_slider_position_t position; //Slider position
uint8_t position_range; //Slider position range([0, position_range])
uint8_t channel_sum; //Slider channel sum
uint8_t *pos_filter_window; //Slider position moving average filter window
uint8_t pos_window_idx; //Slider position moving average filter window index
bool is_first_sample; //Slider first time sample record bit
};
typedef struct te_slider_s* te_slider_handle_t;
/* -------------------------------------------- Matrix basic type --------------------------------------------- */
typedef struct {
touch_elem_dispatch_t dispatch_method; //Matrix button dispatch method
touch_matrix_callback_t callback; //Matrix button callback routine
uint32_t event_mask; //Matrix button subscribed event mask
void *arg; //User input argument
} te_matrix_handle_config_t;
typedef te_state_t te_matrix_state_t; //TODO: add Long Press state
struct te_matrix_s {
te_matrix_handle_config_t *config; //Matrix button configuration
te_dev_t **device; //Base device information
te_matrix_state_t current_state; //Matrix button current state
te_matrix_state_t last_state; //Matrix button current state
touch_matrix_event_t event; //Matrix button outside state(for application layer)
uint32_t trigger_cnt; //Matrix button long time trigger counter
uint32_t trigger_thr; //Matrix button long time trigger counter threshold
touch_matrix_position_t position; //Matrix button position
uint8_t x_channel_num; //The number of touch sensor channel in x axis
uint8_t y_channel_num; //The number of touch sensor channel in y axis
};
typedef struct te_matrix_s* te_matrix_handle_t;
/* ------------------------------------------------------------------------------------------------------------------ */
/* --------------------------------------------- Global system methods ---------------------------------------------- */
uint32_t te_read_smooth_signal(touch_pad_t channel_num);
bool te_system_check_state(void);
//TODO: Refactor this function with function overload
esp_err_t te_dev_init(te_dev_t **device, uint8_t device_num, te_dev_type_t type, const touch_pad_t *channel, const float *sens, float divider);
void te_dev_deinit(te_dev_t **device, uint8_t device_num);
esp_err_t te_dev_set_threshold(te_dev_t *device);
esp_err_t te_event_give(touch_elem_message_t te_message);
uint8_t te_get_timer_period(void);
void te_object_method_register(te_object_methods_t *object_methods, te_class_type_t object_type);
void te_object_method_unregister(te_class_type_t object_type);
bool te_object_check_channel(const touch_pad_t *channel_array, uint8_t channel_sum);
bool waterproof_check_mask_handle(touch_elem_handle_t te_handle);
bool te_is_touch_dsleep_wakeup(void);
touch_pad_t te_get_sleep_channel(void);
bool is_button_object_handle(touch_elem_handle_t element_handle);
bool is_slider_object_handle(touch_elem_handle_t element_handle);
bool is_matrix_object_handle(touch_elem_handle_t element_handle);
void button_enable_wakeup_calibration(te_button_handle_t button_handle, bool en);
void slider_enable_wakeup_calibration(te_slider_handle_t slider_handle, bool en);
void matrix_enable_wakeup_calibration(te_matrix_handle_t matrix_handle, bool en);
/* ------------------------------------------------------------------------------------------------------------------ */
#ifdef __cplusplus
}
#endif

View File

@@ -1,213 +0,0 @@
/*
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "touch_element/touch_element.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ----------------------------- General matrix button instance default configuration ------------------------------ */
#define TOUCH_MATRIX_GLOBAL_DEFAULT_CONFIG() \
{ \
.threshold_divider = 0.8, \
.default_lp_time = 1000 \
}
/* ------------------------------------------------------------------------------------------------------------------ */
/**
* @brief Matrix button initialization configuration passed to touch_matrix_install
*/
typedef struct {
float threshold_divider; //!< Matrix button channel threshold divider
uint32_t default_lp_time; //!< Matrix button default LongPress event time (ms)
} touch_matrix_global_config_t;
/**
* @brief Matrix button configuration (for new instance) passed to touch_matrix_create()
*/
typedef struct {
const touch_pad_t *x_channel_array; //!< Matrix button x-axis channels array
const touch_pad_t *y_channel_array; //!< Matrix button y-axis channels array
const float *x_sensitivity_array; //!< Matrix button x-axis channels sensitivity array
const float *y_sensitivity_array; //!< Matrix button y-axis channels sensitivity array
uint8_t x_channel_num; //!< The number of channels in x-axis
uint8_t y_channel_num; //!< The number of channels in y-axis
} touch_matrix_config_t;
/**
* @brief Matrix button event type
*/
typedef enum {
TOUCH_MATRIX_EVT_ON_PRESS, //!< Matrix button Press event
TOUCH_MATRIX_EVT_ON_RELEASE, //!< Matrix button Press event
TOUCH_MATRIX_EVT_ON_LONGPRESS, //!< Matrix button LongPress event
TOUCH_MATRIX_EVT_MAX
} touch_matrix_event_t;
/**
* @brief Matrix button position data type
*/
typedef struct {
uint8_t x_axis; //!< Matrix button x axis position
uint8_t y_axis; //!< Matrix button y axis position
uint8_t index; //!< Matrix button position index
} touch_matrix_position_t;
/**
* @brief Matrix message type
*/
typedef struct {
touch_matrix_event_t event; //!< Matrix event
touch_matrix_position_t position; //!< Matrix position
} touch_matrix_message_t;
typedef touch_elem_handle_t touch_matrix_handle_t; //!< Matrix button instance handle
typedef void(*touch_matrix_callback_t)(touch_matrix_handle_t, touch_matrix_message_t *, void *); //!< Matrix button callback type
/**
* @brief Touch matrix button initialize
*
* This function initializes touch matrix button object and acts on all
* touch matrix button instances.
*
* @param[in] global_config Touch matrix global initialization configuration
*
* @return
* - ESP_OK: Successfully initialized touch matrix button
* - ESP_ERR_INVALID_STATE: Touch element library was not initialized
* - ESP_ERR_INVALID_ARG: matrix_init is NULL
* - ESP_ERR_NO_MEM: Insufficient memory
*/
esp_err_t touch_matrix_install(const touch_matrix_global_config_t *global_config);
/**
* @brief Release resources allocated using touch_matrix_install()
*
*/
void touch_matrix_uninstall(void);
/**
* @brief Create a new touch matrix button instance
*
* @param[in] matrix_config Matrix button configuration
* @param[out] matrix_handle Matrix button handle
*
* @note Channel array and sensitivity array must be one-one correspondence in those array
*
* @note Touch matrix button does not support Multi-Touch now
*
* @return
* - ESP_OK: Successfully create touch matrix button
* - ESP_ERR_INVALID_STATE: Touch matrix driver was not initialized
* - ESP_ERR_INVALID_ARG: Invalid configuration struct or arguments is NULL
* - ESP_ERR_NO_MEM: Insufficient memory
*/
esp_err_t touch_matrix_create(const touch_matrix_config_t *matrix_config, touch_matrix_handle_t *matrix_handle);
/**
* @brief Release resources allocated using touch_matrix_create()
*
* @param[in] matrix_handle Matrix handle
* @return
* - ESP_OK: Successfully released resources
* - ESP_ERR_INVALID_STATE: Touch matrix driver was not initialized
* - ESP_ERR_INVALID_ARG: matrix_handle is null
* - ESP_ERR_NOT_FOUND: Input handle is not a matrix handle
*/
esp_err_t touch_matrix_delete(touch_matrix_handle_t matrix_handle);
/**
* @brief Touch matrix button subscribes event
*
* This function uses event mask to subscribe to touch matrix events, once one of
* the subscribed events occurs, the event message could be retrieved by calling
* touch_element_message_receive() or input callback routine.
*
* @param[in] matrix_handle Matrix handle
* @param[in] event_mask Matrix subscription event mask
* @param[in] arg User input argument
*
* @note Touch matrix button only support three kind of event masks, they are
* TOUCH_ELEM_EVENT_ON_PRESS, TOUCH_ELEM_EVENT_ON_RELEASE, TOUCH_ELEM_EVENT_ON_LONGPRESS. You can use those event
* masks in any combination to achieve the desired effect.
*
* @return
* - ESP_OK: Successfully subscribed touch matrix event
* - ESP_ERR_INVALID_STATE: Touch matrix driver was not initialized
* - ESP_ERR_INVALID_ARG: matrix_handle is null or event is not supported
*/
esp_err_t touch_matrix_subscribe_event(touch_matrix_handle_t matrix_handle, uint32_t event_mask, void *arg);
/**
* @brief Touch matrix button set dispatch method
*
* This function sets a dispatch method that the driver core will use
* this method as the event notification method.
*
* @param[in] matrix_handle Matrix button handle
* @param[in] dispatch_method Dispatch method (By callback/event)
*
* @return
* - ESP_OK: Successfully set dispatch method
* - ESP_ERR_INVALID_STATE: Touch matrix driver was not initialized
* - ESP_ERR_INVALID_ARG: matrix_handle is null or dispatch_method is invalid
*/
esp_err_t touch_matrix_set_dispatch_method(touch_matrix_handle_t matrix_handle, touch_elem_dispatch_t dispatch_method);
/**
* @brief Touch matrix button set callback
*
* This function sets a callback routine into touch element driver core,
* when the subscribed events occur, the callback routine will be called.
*
* @param[in] matrix_handle Matrix button handle
* @param[in] matrix_callback User input callback
*
* @note Matrix message will be passed from the callback function and it will be destroyed when the callback function return.
*
* @warning Since this input callback routine runs on driver core (esp-timer callback routine),
* it should not do something that attempts to Block, such as calling vTaskDelay().
*
* @return
* - ESP_OK: Successfully set callback
* - ESP_ERR_INVALID_STATE: Touch matrix driver was not initialized
* - ESP_ERR_INVALID_ARG: matrix_handle or matrix_callback is null
*/
esp_err_t touch_matrix_set_callback(touch_matrix_handle_t matrix_handle, touch_matrix_callback_t matrix_callback);
/**
* @brief Touch matrix button set long press trigger time
*
* This function sets the threshold time (ms) for a long press event. If a matrix button is pressed
* and held for a period of time that exceeds the threshold time, a long press event is triggered.
*
* @param[in] matrix_handle Matrix button handle
* @param[in] threshold_time Threshold time (ms) of long press event occur
*
* @return
* - ESP_OK: Successfully set the time of long press event
* - ESP_ERR_INVALID_STATE: Touch matrix driver was not initialized
* - ESP_ERR_INVALID_ARG: matrix_handle is null or time (ms) is 0
*/
esp_err_t touch_matrix_set_longpress(touch_matrix_handle_t matrix_handle, uint32_t threshold_time);
/**
* @brief Touch matrix get message
*
* This function decodes the element message from touch_element_message_receive() and return
* a matrix message pointer.
*
* @param[in] element_message element message
*
* @return Touch matrix message pointer
*/
const touch_matrix_message_t* touch_matrix_get_message(const touch_elem_message_t* element_message);
#ifdef __cplusplus
}
#endif

View File

@@ -1,197 +0,0 @@
/*
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "touch_element/touch_element.h"
#ifdef __cplusplus
extern "C" {
#endif
/* --------------------------------- General slider instance default configuration --------------------------------- */
#define TOUCH_SLIDER_GLOBAL_DEFAULT_CONFIG() \
{ \
.quantify_lower_threshold = 0.3, \
.threshold_divider = 0.8, \
.filter_reset_time = 50, \
.benchmark_update_time = 500, \
.position_filter_size = 10, \
.position_filter_factor = 2, \
.calculate_channel_count = 3 \
}
/* ------------------------------------------------------------------------------------------------------------------ */
/**
* @brief Slider initialization configuration passed to touch_slider_install
*/
typedef struct {
float quantify_lower_threshold; //!< Slider signal quantification threshold
float threshold_divider; //!< Slider channel threshold divider
uint16_t filter_reset_time; //!< Slider position filter reset time (Unit is esp_timer callback tick)
uint16_t benchmark_update_time; //!< Slider benchmark update time (Unit is esp_timer callback tick)
uint8_t position_filter_size; //!< Moving window filter buffer size
uint8_t position_filter_factor; //!< One-order IIR filter factor
uint8_t calculate_channel_count; //!< The number of channels which will take part in calculation
} touch_slider_global_config_t;
/**
* @brief Slider configuration (for new instance) passed to touch_slider_create()
*/
typedef struct {
const touch_pad_t *channel_array; //!< Slider channel array
const float *sensitivity_array; //!< Slider channel sensitivity array
uint8_t channel_num; //!< The number of slider channels
uint8_t position_range; //!< The right region of touch slider position range, [0, position_range (less than or equal to 255)]
} touch_slider_config_t;
/**
* @brief Slider event type
*/
typedef enum {
TOUCH_SLIDER_EVT_ON_PRESS, //!< Slider on Press event
TOUCH_SLIDER_EVT_ON_RELEASE, //!< Slider on Release event
TOUCH_SLIDER_EVT_ON_CALCULATION, //!< Slider on Calculation event
TOUCH_SLIDER_EVT_MAX
} touch_slider_event_t;
typedef uint32_t touch_slider_position_t; //!< Slider position data type
/**
* @brief Slider message type
*/
typedef struct {
touch_slider_event_t event; //!< Slider event
touch_slider_position_t position; //!< Slider position
} touch_slider_message_t;
typedef touch_elem_handle_t touch_slider_handle_t; //!< Slider instance handle
typedef void(*touch_slider_callback_t)(touch_slider_handle_t, touch_slider_message_t *, void *); //!< Slider callback type
/**
* @brief Touch slider initialize
*
* This function initializes touch slider object and acts on all
* touch slider instances.
*
* @param[in] global_config Touch slider global initialization configuration
*
* @return
* - ESP_OK: Successfully initialized touch slider
* - ESP_ERR_INVALID_STATE: Touch element library was not initialized
* - ESP_ERR_INVALID_ARG: slider_init is NULL
* - ESP_ERR_NO_MEM: Insufficient memory
*/
esp_err_t touch_slider_install(const touch_slider_global_config_t *global_config);
/**
* @brief Release resources allocated using touch_slider_install()
*
*/
void touch_slider_uninstall(void);
/**
* @brief Create a new touch slider instance
*
* @param[in] slider_config Slider configuration
* @param[out] slider_handle Slider handle
*
* @note The index of Channel array and sensitivity array must be one-one correspondence
*
* @return
* - ESP_OK: Successfully create touch slider
* - ESP_ERR_INVALID_STATE: Touch slider driver was not initialized
* - ESP_ERR_INVALID_ARG: Invalid configuration struct or arguments is NULL
* - ESP_ERR_NO_MEM: Insufficient memory
*/
esp_err_t touch_slider_create(const touch_slider_config_t *slider_config, touch_slider_handle_t *slider_handle);
/**
* @brief Release resources allocated using touch_slider_create
*
* @param[in] slider_handle Slider handle
* @return
* - ESP_OK: Successfully released resources
* - ESP_ERR_INVALID_STATE: Touch slider driver was not initialized
* - ESP_ERR_INVALID_ARG: slider_handle is null
* - ESP_ERR_NOT_FOUND: Input handle is not a slider handle
*/
esp_err_t touch_slider_delete(touch_slider_handle_t slider_handle);
/**
* @brief Touch slider subscribes event
*
* This function uses event mask to subscribe to touch slider events, once one of
* the subscribed events occurs, the event message could be retrieved by calling
* touch_element_message_receive() or input callback routine.
*
* @param[in] slider_handle Slider handle
* @param[in] event_mask Slider subscription event mask
* @param[in] arg User input argument
*
* @note Touch slider only support three kind of event masks, they are
* TOUCH_ELEM_EVENT_ON_PRESS, TOUCH_ELEM_EVENT_ON_RELEASE. You can use those event masks in any
* combination to achieve the desired effect.
*
* @return
* - ESP_OK: Successfully subscribed touch slider event
* - ESP_ERR_INVALID_STATE: Touch slider driver was not initialized
* - ESP_ERR_INVALID_ARG: slider_handle is null or event is not supported
*/
esp_err_t touch_slider_subscribe_event(touch_slider_handle_t slider_handle, uint32_t event_mask, void *arg);
/**
* @brief Touch slider set dispatch method
*
* This function sets a dispatch method that the driver core will use
* this method as the event notification method.
*
* @param[in] slider_handle Slider handle
* @param[in] dispatch_method Dispatch method (By callback/event)
*
* @return
* - ESP_OK: Successfully set dispatch method
* - ESP_ERR_INVALID_STATE: Touch slider driver was not initialized
* - ESP_ERR_INVALID_ARG: slider_handle is null or dispatch_method is invalid
*/
esp_err_t touch_slider_set_dispatch_method(touch_slider_handle_t slider_handle, touch_elem_dispatch_t dispatch_method);
/**
* @brief Touch slider set callback
*
* This function sets a callback routine into touch element driver core,
* when the subscribed events occur, the callback routine will be called.
*
* @param[in] slider_handle Slider handle
* @param[in] slider_callback User input callback
*
* @note Slider message will be passed from the callback function and it will be destroyed when the callback function return.
*
* @warning Since this input callback routine runs on driver core (esp-timer callback routine),
* it should not do something that attempts to Block, such as calling vTaskDelay().
*
* @return
* - ESP_OK: Successfully set callback
* - ESP_ERR_INVALID_STATE: Touch slider driver was not initialized
* - ESP_ERR_INVALID_ARG: slider_handle or slider_callback is null
*/
esp_err_t touch_slider_set_callback(touch_slider_handle_t slider_handle, touch_slider_callback_t slider_callback);
/**
* @brief Touch slider get message
*
* This function decodes the element message from touch_element_message_receive() and return
* a slider message pointer.
*
* @param[in] element_message element message
*
* @return Touch slider message pointer
*/
const touch_slider_message_t* touch_slider_get_message(const touch_elem_message_t* element_message);
#ifdef __cplusplus
}
#endif

View File

@@ -1,6 +0,0 @@
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
components/touch_element/test_apps:
enable:
- if: IDF_TARGET in ["esp32s2", "esp32s3"]
reason: only supports esp32s2 and esp32s3

View File

@@ -1,440 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <sys/queue.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp_log.h"
#include "touch_element/touch_element_private.h"
typedef struct te_button_handle_list {
te_button_handle_t button_handle; //Button handle
SLIST_ENTRY(te_button_handle_list) next; //Button handle list entry
} te_button_handle_list_t;
typedef struct {
SLIST_HEAD(te_button_handle_list_head, te_button_handle_list) handle_list; //Button handle (instance) list
touch_button_global_config_t *global_config; //Button global configuration
SemaphoreHandle_t mutex; //Button object mutex
} te_button_obj_t;
static te_button_obj_t *s_te_btn_obj = NULL; //Button object
/* ---------------------------------------- Button handle(instance) methods ----------------------------------------- */
static bool button_channel_check(te_button_handle_t button_handle, touch_pad_t channel_num);
static esp_err_t button_set_threshold(te_button_handle_t button_handle);
static inline te_state_t button_get_state(te_dev_t *device);
static void button_reset_state(te_button_handle_t button_handle);
static void button_update_state(te_button_handle_t button_handle, touch_pad_t channel_num, te_state_t channel_state);
static void button_proc_state(te_button_handle_t button_handle);
static void button_event_give(te_button_handle_t button_handle);
static inline void button_dispatch(te_button_handle_t button_handle, touch_elem_dispatch_t dispatch_method);
/* ------------------------------------------ Button object(class) methods ------------------------------------------ */
static esp_err_t button_object_add_instance(te_button_handle_t button_handle);
static esp_err_t button_object_remove_instance(te_button_handle_t button_handle);
static bool button_object_check_channel(touch_pad_t channel_num);
static esp_err_t button_object_set_threshold(void);
static void button_object_process_state(void);
static void button_object_update_state(touch_pad_t channel_num, te_state_t channel_state);
/* ------------------------------------------------------------------------------------------------------------------ */
esp_err_t touch_button_install(const touch_button_global_config_t *global_config)
{
TE_CHECK(te_system_check_state() == true, ESP_ERR_INVALID_STATE);
TE_CHECK(global_config != NULL, ESP_ERR_INVALID_ARG);
//Fixme: Make it thread-safe
s_te_btn_obj = (te_button_obj_t *)calloc(1, sizeof(te_button_obj_t));
TE_CHECK(s_te_btn_obj != NULL, ESP_ERR_NO_MEM);
s_te_btn_obj->global_config = (touch_button_global_config_t *)calloc(1, sizeof(touch_button_global_config_t));
s_te_btn_obj->mutex = xSemaphoreCreateMutex();
TE_CHECK_GOTO(s_te_btn_obj->global_config != NULL && s_te_btn_obj->global_config != NULL, cleanup);
xSemaphoreTake(s_te_btn_obj->mutex, portMAX_DELAY);
SLIST_INIT(&s_te_btn_obj->handle_list);
memcpy(s_te_btn_obj->global_config, global_config, sizeof(touch_button_global_config_t));
te_object_methods_t button_methods = {
.handle = s_te_btn_obj,
.check_channel = button_object_check_channel,
.set_threshold = button_object_set_threshold,
.process_state = button_object_process_state,
.update_state = button_object_update_state
};
te_object_method_register(&button_methods, TE_CLS_TYPE_BUTTON);
xSemaphoreGive(s_te_btn_obj->mutex);
return ESP_OK;
cleanup:
TE_FREE_AND_NULL(s_te_btn_obj->global_config);
if (s_te_btn_obj->mutex != NULL) {
vSemaphoreDelete(s_te_btn_obj->mutex);
}
TE_FREE_AND_NULL(s_te_btn_obj);
return ESP_ERR_NO_MEM;
}
void touch_button_uninstall(void)
{
xSemaphoreTake(s_te_btn_obj->mutex, portMAX_DELAY);
if (s_te_btn_obj == NULL) {
xSemaphoreGive(s_te_btn_obj->mutex);
return;
}
te_object_method_unregister(TE_CLS_TYPE_BUTTON);
free(s_te_btn_obj->global_config);
s_te_btn_obj->global_config = NULL;
while (!SLIST_EMPTY(&s_te_btn_obj->handle_list)) {
SLIST_FIRST(&s_te_btn_obj->handle_list);
SLIST_REMOVE_HEAD(&s_te_btn_obj->handle_list, next);
}
xSemaphoreGive(s_te_btn_obj->mutex);
vSemaphoreDelete(s_te_btn_obj->mutex);
free(s_te_btn_obj);
s_te_btn_obj = NULL;
}
esp_err_t touch_button_create(const touch_button_config_t *button_config, touch_button_handle_t *button_handle)
{
TE_CHECK(s_te_btn_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(button_handle != NULL && button_config != NULL, ESP_ERR_INVALID_ARG);
TE_CHECK(button_config->channel_num > TOUCH_PAD_NUM0 &&
button_config->channel_num < TOUCH_PAD_MAX &&
button_config->channel_sens > 0,
ESP_ERR_INVALID_ARG);
TE_CHECK(te_object_check_channel(&button_config->channel_num, 1) == false, ESP_ERR_INVALID_ARG);
te_button_handle_t te_button = (te_button_handle_t)calloc(1, sizeof(struct te_button_s));
TE_CHECK(te_button != NULL, ESP_ERR_NO_MEM);
esp_err_t ret = ESP_ERR_NO_MEM;
te_button->config = (te_button_handle_config_t *)calloc(1, sizeof(te_button_handle_config_t));
te_button->device = (te_dev_t *)calloc(1, sizeof(te_dev_t));
TE_CHECK_GOTO(te_button->config != NULL && te_button->device != NULL, cleanup);
ret = te_dev_init(&te_button->device, 1, TOUCH_ELEM_TYPE_BUTTON,
&button_config->channel_num, &button_config->channel_sens, TE_DEFAULT_THRESHOLD_DIVIDER(s_te_btn_obj));
TE_CHECK_GOTO(ret == ESP_OK, cleanup);
te_button->config->event_mask = TOUCH_ELEM_EVENT_NONE;
te_button->config->dispatch_method = TOUCH_ELEM_DISP_MAX;
te_button->config->callback = NULL;
te_button->config->arg = NULL;
te_button->current_state = TE_STATE_IDLE;
te_button->last_state = TE_STATE_IDLE;
te_button->event = TOUCH_BUTTON_EVT_MAX;
te_button->trigger_cnt = 0;
te_button->trigger_thr = 0xffffffff;
ret = button_object_add_instance(te_button);
TE_CHECK_GOTO(ret == ESP_OK, cleanup);
*button_handle = (touch_elem_handle_t)te_button;
ESP_LOGD(TE_DEBUG_TAG, "channel: %d, channel_sens: %f", button_config->channel_num, button_config->channel_sens);
return ESP_OK;
cleanup:
TE_FREE_AND_NULL(te_button->config);
TE_FREE_AND_NULL(te_button->device);
TE_FREE_AND_NULL(te_button);
return ret;
}
esp_err_t touch_button_delete(touch_button_handle_t button_handle)
{
TE_CHECK(s_te_btn_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(button_handle != NULL, ESP_ERR_INVALID_ARG);
esp_err_t ret = button_object_remove_instance(button_handle);
TE_CHECK(ret == ESP_OK, ret);
te_button_handle_t te_button = (te_button_handle_t)button_handle;
te_dev_deinit(&te_button->device, 1);
free(te_button->config);
free(te_button->device);
free(te_button);
return ESP_OK;
}
esp_err_t touch_button_set_dispatch_method(touch_button_handle_t button_handle, touch_elem_dispatch_t dispatch_method)
{
TE_CHECK(s_te_btn_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(button_handle != NULL, ESP_ERR_INVALID_ARG);
TE_CHECK(dispatch_method >= TOUCH_ELEM_DISP_EVENT && dispatch_method <= TOUCH_ELEM_DISP_MAX, ESP_ERR_INVALID_ARG);
xSemaphoreTake(s_te_btn_obj->mutex, portMAX_DELAY);
te_button_handle_t te_button = (te_button_handle_t)button_handle;
te_button->config->dispatch_method = dispatch_method;
xSemaphoreGive(s_te_btn_obj->mutex);
return ESP_OK;
}
esp_err_t touch_button_subscribe_event(touch_button_handle_t button_handle, uint32_t event_mask, void *arg)
{
TE_CHECK(s_te_btn_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(button_handle != NULL, ESP_ERR_INVALID_ARG);
if (!(event_mask & TOUCH_ELEM_EVENT_ON_PRESS) && !(event_mask & TOUCH_ELEM_EVENT_ON_RELEASE) &&
!(event_mask & TOUCH_ELEM_EVENT_ON_LONGPRESS) && !(event_mask & TOUCH_ELEM_EVENT_NONE)) {
ESP_LOGE(TE_TAG, "Touch button only support TOUCH_ELEM_EVENT_ON_PRESS, "
"TOUCH_ELEM_EVENT_ON_RELEASE, TOUCH_ELEM_EVENT_ON_LONGPRESS event mask");
return ESP_ERR_INVALID_ARG;
}
if (event_mask & TOUCH_ELEM_EVENT_ON_LONGPRESS) {
touch_button_set_longpress(button_handle, TE_DEFAULT_LONGPRESS_TIME(s_te_btn_obj)); //set the default time(1000ms) for long press
}
xSemaphoreTake(s_te_btn_obj->mutex, portMAX_DELAY);
te_button_handle_t te_button = (te_button_handle_t)button_handle;
te_button->config->event_mask = event_mask;
te_button->config->arg = arg;
xSemaphoreGive(s_te_btn_obj->mutex);
return ESP_OK;
}
esp_err_t touch_button_set_callback(touch_button_handle_t button_handle, touch_button_callback_t button_callback)
{
TE_CHECK(s_te_btn_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(button_handle != NULL, ESP_ERR_INVALID_ARG);
TE_CHECK(button_callback != NULL, ESP_ERR_INVALID_ARG);
te_button_handle_t te_button = (te_button_handle_t)button_handle;
xSemaphoreTake(s_te_btn_obj->mutex, portMAX_DELAY);
te_button->config->callback = button_callback;
xSemaphoreGive(s_te_btn_obj->mutex);
return ESP_OK;
}
esp_err_t touch_button_set_longpress(touch_button_handle_t button_handle, uint32_t threshold_time)
{
TE_CHECK(s_te_btn_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(button_handle != NULL, ESP_ERR_INVALID_ARG);
TE_CHECK(threshold_time > 0, ESP_ERR_INVALID_ARG);
te_button_handle_t te_button = (te_button_handle_t)button_handle;
touch_elem_dispatch_t dispatch_method = te_button->config->dispatch_method;
if (dispatch_method == TOUCH_ELEM_DISP_EVENT) {
xSemaphoreTake(s_te_btn_obj->mutex, portMAX_DELAY);
}
uint8_t timer_period = te_get_timer_period();
te_button->trigger_thr = threshold_time / timer_period;
if (dispatch_method == TOUCH_ELEM_DISP_EVENT) {
xSemaphoreGive(s_te_btn_obj->mutex);
}
return ESP_OK;
}
const touch_button_message_t* touch_button_get_message(const touch_elem_message_t* element_message)
{
return (touch_button_message_t*)&element_message->child_msg;
_Static_assert(sizeof(element_message->child_msg) >= sizeof(touch_button_message_t), "Message size overflow");
}
static bool button_object_check_channel(touch_pad_t channel_num)
{
te_button_handle_list_t *item;
SLIST_FOREACH(item, &s_te_btn_obj->handle_list, next) {
if (button_channel_check(item->button_handle, channel_num)) {
return true;
}
}
return false;
}
static esp_err_t button_object_set_threshold(void)
{
esp_err_t ret = ESP_OK;
te_button_handle_list_t *item;
SLIST_FOREACH(item, &s_te_btn_obj->handle_list, next) {
ret = button_set_threshold(item->button_handle);
if (ret != ESP_OK) {
break;
}
}
return ret;
}
static void button_object_process_state(void)
{
te_button_handle_list_t *item;
SLIST_FOREACH(item, &s_te_btn_obj->handle_list, next) {
if (waterproof_check_mask_handle(item->button_handle)) {
button_reset_state(item->button_handle);
continue;
}
button_proc_state(item->button_handle);
}
}
static void button_object_update_state(touch_pad_t channel_num, te_state_t channel_state)
{
te_button_handle_list_t *item;
SLIST_FOREACH(item, &s_te_btn_obj->handle_list, next) {
if (waterproof_check_mask_handle(item->button_handle)) {
continue;
}
button_update_state(item->button_handle, channel_num, channel_state);
}
}
static esp_err_t button_object_add_instance(te_button_handle_t button_handle)
{
te_button_handle_list_t *item = (te_button_handle_list_t *)calloc(1, sizeof(te_button_handle_list_t));
TE_CHECK(item != NULL, ESP_ERR_NO_MEM);
item->button_handle = button_handle;
xSemaphoreTake(s_te_btn_obj->mutex, portMAX_DELAY);
SLIST_INSERT_HEAD(&s_te_btn_obj->handle_list, item, next);
xSemaphoreGive(s_te_btn_obj->mutex);
return ESP_OK;
}
static esp_err_t button_object_remove_instance(te_button_handle_t button_handle)
{
esp_err_t ret = ESP_ERR_NOT_FOUND;
te_button_handle_list_t *item;
SLIST_FOREACH(item, &s_te_btn_obj->handle_list, next) {
if (button_handle == item->button_handle) {
xSemaphoreTake(s_te_btn_obj->mutex, portMAX_DELAY);
SLIST_REMOVE(&s_te_btn_obj->handle_list, item, te_button_handle_list, next);
xSemaphoreGive(s_te_btn_obj->mutex);
free(item);
ret = ESP_OK;
break;
}
}
return ret;
}
bool is_button_object_handle(touch_elem_handle_t element_handle)
{
te_button_handle_list_t *item;
xSemaphoreTake(s_te_btn_obj->mutex, portMAX_DELAY);
SLIST_FOREACH(item, &s_te_btn_obj->handle_list, next) {
if (element_handle == item->button_handle) {
xSemaphoreGive(s_te_btn_obj->mutex);
return true;
}
}
xSemaphoreGive(s_te_btn_obj->mutex);
return false;
}
static bool button_channel_check(te_button_handle_t button_handle, touch_pad_t channel_num)
{
return (channel_num == button_handle->device->channel);
}
static esp_err_t button_set_threshold(te_button_handle_t button_handle)
{
return te_dev_set_threshold(button_handle->device);
}
static void button_update_state(te_button_handle_t button_handle, touch_pad_t channel_num, te_state_t channel_state)
{
te_dev_t *device = button_handle->device;
if (channel_num != device->channel) {
return;
}
device->state = channel_state;
}
static void button_reset_state(te_button_handle_t button_handle)
{
button_handle->trigger_cnt = 0;
button_handle->current_state = TE_STATE_IDLE;
button_handle->device->state = TE_STATE_IDLE;
}
static void button_event_give(te_button_handle_t button_handle)
{
touch_elem_message_t element_message;
touch_button_message_t button_message = {
.event = button_handle->event
};
element_message.handle = (touch_elem_handle_t)button_handle;
element_message.element_type = TOUCH_ELEM_TYPE_BUTTON;
element_message.arg = button_handle->config->arg;
memcpy(element_message.child_msg, &button_message, sizeof(button_message));
te_event_give(element_message);
}
static inline void button_dispatch(te_button_handle_t button_handle, touch_elem_dispatch_t dispatch_method)
{
if (dispatch_method == TOUCH_ELEM_DISP_EVENT) {
button_event_give(button_handle); //Event queue
} else if (dispatch_method == TOUCH_ELEM_DISP_CALLBACK) {
touch_button_message_t button_info;
button_info.event = button_handle->event;
button_handle->config->callback(button_handle, &button_info, button_handle->config->arg); //Event callback
}
}
void button_enable_wakeup_calibration(te_button_handle_t button_handle, bool en)
{
button_handle->device->is_use_last_threshold = !en;
}
/**
* @brief Button process
*
* This function will process the button state and maintain a button FSM:
* IDLE ----> Press ----> Release ----> IDLE
*
* The state transition procedure is as follow:
* (channel state ----> button state)
*
* TODO: add state transition diagram
*/
static void button_proc_state(te_button_handle_t button_handle)
{
uint32_t event_mask = button_handle->config->event_mask;
touch_elem_dispatch_t dispatch_method = button_handle->config->dispatch_method;
BaseType_t mux_ret = xSemaphoreTake(s_te_btn_obj->mutex, 0);
if (mux_ret != pdPASS) {
return;
}
button_handle->current_state = button_get_state(button_handle->device);
if (button_handle->current_state == TE_STATE_PRESS) {
if (button_handle->last_state == TE_STATE_IDLE) { //IDLE ---> Press = On_Press
ESP_LOGD(TE_DEBUG_TAG, "button press");
if (event_mask & TOUCH_ELEM_EVENT_ON_PRESS) {
button_handle->event = TOUCH_BUTTON_EVT_ON_PRESS;
button_dispatch(button_handle, dispatch_method);
}
} else if (button_handle->last_state == TE_STATE_PRESS) { //Press ---> Press = On_LongPress
if (event_mask & TOUCH_ELEM_EVENT_ON_LONGPRESS) {
if (++button_handle->trigger_cnt >= button_handle->trigger_thr) {
ESP_LOGD(TE_DEBUG_TAG, "button longpress");
button_handle->event = TOUCH_BUTTON_EVT_ON_LONGPRESS;
button_dispatch(button_handle, dispatch_method);
button_handle->trigger_cnt = 0;
}
}
}
} else if (button_handle->current_state == TE_STATE_RELEASE) {
if (button_handle->last_state == TE_STATE_PRESS) { //Press ---> Release = On_Release
ESP_LOGD(TE_DEBUG_TAG, "button release");
if (event_mask & TOUCH_ELEM_EVENT_ON_RELEASE) {
button_handle->event = TOUCH_BUTTON_EVT_ON_RELEASE;
button_dispatch(button_handle, dispatch_method);
}
} else if (button_handle->last_state == TE_STATE_RELEASE) { // Release ---> Release = On_IDLE (Not dispatch)
button_reset_state(button_handle); //Reset the button state for the next time touch action detection
}
} else if (button_handle->current_state == TE_STATE_IDLE) {
if (button_handle->last_state == TE_STATE_RELEASE) { //Release ---> IDLE = On_IDLE (Not dispatch)
//Nothing
} else if (button_handle->last_state == TE_STATE_IDLE) { //IDLE ---> IDLE = Running IDLE (Not dispatch)
//Nothing
}
}
button_handle->last_state = button_handle->current_state;
xSemaphoreGive(s_te_btn_obj->mutex);
}
static inline te_state_t button_get_state(te_dev_t *device)
{
te_state_t button_state;
if (device->state == TE_STATE_PRESS) {
button_state = TE_STATE_PRESS;
} else if (device->state == TE_STATE_RELEASE) {
button_state = TE_STATE_RELEASE;
} else {
button_state = TE_STATE_IDLE;
}
return button_state;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,647 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <sys/queue.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp_log.h"
#include "touch_element/touch_element_private.h"
#define TE_MAT_POS_MAX (0xff) //!< Matrix button startup position
typedef struct te_matrix_handle_list {
te_matrix_handle_t matrix_handle; //Matrix handle
SLIST_ENTRY(te_matrix_handle_list) next; //Matrix handle list entry
} te_matrix_handle_list_t;
typedef struct {
SLIST_HEAD(te_matrix_handle_list_head, te_matrix_handle_list) handle_list; //Matrix handle (instance) list
touch_matrix_global_config_t *global_config; //Matrix global configuration
SemaphoreHandle_t mutex; //Matrix object mutex
} te_matrix_obj_t;
te_matrix_obj_t *s_te_mat_obj = NULL;
/* ---------------------------------------- Matrix handle(instance) methods ----------------------------------------- */
static bool matrix_channel_check(te_matrix_handle_t matrix_handle, touch_pad_t channel_num);
static esp_err_t matrix_set_threshold(te_matrix_handle_t matrix_handle);
static inline te_state_t matrix_get_state(te_matrix_state_t x_axis_state, te_matrix_state_t y_axis_state);
static void matrix_reset_state(te_matrix_handle_t matrix_handle);
static void matrix_update_state(te_matrix_handle_t matrix_handle, touch_pad_t channel_num, te_state_t channel_state);
static void matrix_update_position(te_matrix_handle_t matrix_handle, touch_matrix_position_t new_pos);
static void matrix_proc_state(te_matrix_handle_t matrix_handle);
static void matrix_event_give(te_matrix_handle_t matrix_handle);
static inline void matrix_dispatch(te_matrix_handle_t matrix_handle, touch_elem_dispatch_t dispatch_method);
/* ------------------------------------------ Matrix object(class) methods ------------------------------------------ */
static esp_err_t matrix_object_add_instance(te_matrix_handle_t matrix_handle);
static esp_err_t matrix_object_remove_instance(te_matrix_handle_t matrix_handle);
static bool matrix_object_check_channel(touch_pad_t channel_num);
static esp_err_t matrix_object_set_threshold(void);
static void matrix_object_process_state(void);
static void matrix_object_update_state(touch_pad_t channel_num, te_state_t channel_state);
/* ------------------------------------------------------------------------------------------------------------------ */
esp_err_t touch_matrix_install(const touch_matrix_global_config_t *global_config)
{
TE_CHECK(te_system_check_state() == true, ESP_ERR_INVALID_STATE);
TE_CHECK(global_config != NULL, ESP_ERR_INVALID_ARG);
//Fixme: Make it thread-safe
s_te_mat_obj = (te_matrix_obj_t *)calloc(1, sizeof(te_matrix_obj_t));
TE_CHECK(s_te_mat_obj != NULL, ESP_ERR_NO_MEM);
s_te_mat_obj->global_config = (touch_matrix_global_config_t *)calloc(1, sizeof(touch_matrix_global_config_t));
s_te_mat_obj->mutex = xSemaphoreCreateMutex();
TE_CHECK_GOTO(s_te_mat_obj->global_config != NULL && s_te_mat_obj->mutex != NULL, cleanup);
xSemaphoreTake(s_te_mat_obj->mutex, portMAX_DELAY);
SLIST_INIT(&s_te_mat_obj->handle_list);
memcpy(s_te_mat_obj->global_config, global_config, sizeof(touch_matrix_global_config_t));
te_object_methods_t matrix_methods = {
.handle = s_te_mat_obj,
.check_channel = matrix_object_check_channel,
.set_threshold = matrix_object_set_threshold,
.process_state = matrix_object_process_state,
.update_state = matrix_object_update_state
};
te_object_method_register(&matrix_methods, TE_CLS_TYPE_MATRIX);
xSemaphoreGive(s_te_mat_obj->mutex);
return ESP_OK;
cleanup:
TE_FREE_AND_NULL(s_te_mat_obj->global_config);
if (s_te_mat_obj->mutex != NULL) {
vSemaphoreDelete(s_te_mat_obj->mutex);
}
TE_FREE_AND_NULL(s_te_mat_obj);
return ESP_ERR_NO_MEM;
}
void touch_matrix_uninstall(void)
{
xSemaphoreTake(s_te_mat_obj->mutex, portMAX_DELAY);
if (s_te_mat_obj == NULL) {
xSemaphoreGive(s_te_mat_obj->mutex);
return;
}
te_object_method_unregister(TE_CLS_TYPE_MATRIX);
free(s_te_mat_obj->global_config);
s_te_mat_obj->global_config = NULL;
while (!SLIST_EMPTY(&s_te_mat_obj->handle_list)) {
SLIST_FIRST(&s_te_mat_obj->handle_list);
SLIST_REMOVE_HEAD(&s_te_mat_obj->handle_list, next);
}
xSemaphoreGive(s_te_mat_obj->mutex);
vSemaphoreDelete(s_te_mat_obj->mutex);
free(s_te_mat_obj);
s_te_mat_obj = NULL;
}
esp_err_t touch_matrix_create(const touch_matrix_config_t *matrix_config, touch_matrix_handle_t *matrix_handle)
{
TE_CHECK(s_te_mat_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(matrix_handle != NULL && matrix_config != NULL, ESP_ERR_INVALID_ARG);
TE_CHECK(matrix_config->x_channel_array != NULL &&
matrix_config->y_channel_array != NULL &&
matrix_config->x_sensitivity_array != NULL &&
matrix_config->y_sensitivity_array != NULL &&
matrix_config->x_channel_num > 1 &&
matrix_config->x_channel_num < TOUCH_PAD_MAX &&
matrix_config->y_channel_num > 1 &&
matrix_config->y_channel_num < TOUCH_PAD_MAX,
ESP_ERR_INVALID_ARG);
TE_CHECK(te_object_check_channel(matrix_config->x_channel_array, matrix_config->x_channel_num) == false &&
te_object_check_channel(matrix_config->y_channel_array, matrix_config->y_channel_num) == false,
ESP_ERR_INVALID_ARG);
te_matrix_handle_t te_matrix = (te_matrix_handle_t)calloc(1, sizeof(struct te_slider_s));
TE_CHECK(te_matrix != NULL, ESP_ERR_NO_MEM);
esp_err_t ret = ESP_ERR_NO_MEM;
te_matrix->config = (te_matrix_handle_config_t *)calloc(1, sizeof(te_matrix_handle_config_t));
te_matrix->device = (te_dev_t **)calloc(matrix_config->x_channel_num + matrix_config->y_channel_num, sizeof(te_dev_t *));
TE_CHECK_GOTO(te_matrix->config != NULL && te_matrix->device != NULL, cleanup);
for (int idx = 0; idx < matrix_config->x_channel_num + matrix_config->y_channel_num; idx++) {
te_matrix->device[idx] = (te_dev_t *)calloc(1, sizeof(te_dev_t));
if (te_matrix->device[idx] == NULL) {
ret = ESP_ERR_NO_MEM;
goto cleanup;
}
}
/*< Initialize x-axis */
ret = te_dev_init(&te_matrix->device[0], matrix_config->x_channel_num, TOUCH_ELEM_TYPE_MATRIX,
matrix_config->x_channel_array, matrix_config->x_sensitivity_array,
TE_DEFAULT_THRESHOLD_DIVIDER(s_te_mat_obj));
TE_CHECK_GOTO(ret == ESP_OK, cleanup);
/*< Initialize y-axis */
ret = te_dev_init(&te_matrix->device[matrix_config->x_channel_num], matrix_config->y_channel_num,
TOUCH_ELEM_TYPE_MATRIX, matrix_config->y_channel_array, matrix_config->y_sensitivity_array,
TE_DEFAULT_THRESHOLD_DIVIDER(s_te_mat_obj));
TE_CHECK_GOTO(ret == ESP_OK, cleanup);
te_matrix->config->event_mask = TOUCH_ELEM_EVENT_NONE;
te_matrix->config->dispatch_method = TOUCH_ELEM_DISP_MAX;
te_matrix->config->callback = NULL;
te_matrix->config->arg = NULL;
te_matrix->current_state = TE_STATE_IDLE;
te_matrix->last_state = TE_STATE_IDLE;
te_matrix->event = TOUCH_MATRIX_EVT_MAX;
te_matrix->x_channel_num = matrix_config->x_channel_num;
te_matrix->y_channel_num = matrix_config->y_channel_num;
te_matrix->trigger_cnt = 0;
te_matrix->trigger_thr = 0xffffffff;
te_matrix->position.x_axis = TE_MAT_POS_MAX;
te_matrix->position.y_axis = TE_MAT_POS_MAX;
te_matrix->position.index = TE_MAT_POS_MAX;
ret = matrix_object_add_instance(te_matrix);
TE_CHECK_GOTO(ret == ESP_OK, cleanup);
*matrix_handle = (touch_elem_handle_t) te_matrix;
return ESP_OK;
cleanup:
TE_FREE_AND_NULL(te_matrix->config);
if (te_matrix->device != NULL) {
for (int idx = 0; idx < matrix_config->x_channel_num + matrix_config->y_channel_num; idx++) {
TE_FREE_AND_NULL(te_matrix->device[idx]);
}
free(te_matrix->device);
te_matrix->device = NULL;
}
TE_FREE_AND_NULL(te_matrix);
return ret;
}
esp_err_t touch_matrix_delete(touch_matrix_handle_t matrix_handle)
{
TE_CHECK(s_te_mat_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(matrix_handle != NULL, ESP_ERR_INVALID_ARG);
/*< Release touch sensor application resource */
esp_err_t ret = matrix_object_remove_instance(matrix_handle);
TE_CHECK(ret == ESP_OK, ret);
te_matrix_handle_t te_matrix = (te_matrix_handle_t)matrix_handle;
/*< Release touch sensor device resource */
te_dev_deinit(te_matrix->device, te_matrix->x_channel_num + te_matrix->y_channel_num);
for (int idx = 0; idx < te_matrix->x_channel_num + te_matrix->y_channel_num; idx++) {
free(te_matrix->device[idx]);
}
free(te_matrix->config);
free(te_matrix->device);
free(te_matrix);
return ESP_OK;
}
esp_err_t touch_matrix_set_dispatch_method(touch_matrix_handle_t matrix_handle, touch_elem_dispatch_t dispatch_method)
{
TE_CHECK(s_te_mat_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(matrix_handle != NULL, ESP_ERR_INVALID_ARG);
TE_CHECK(dispatch_method >= TOUCH_ELEM_DISP_EVENT && dispatch_method <= TOUCH_ELEM_DISP_MAX, ESP_ERR_INVALID_ARG);
xSemaphoreTake(s_te_mat_obj->mutex, portMAX_DELAY);
te_matrix_handle_t te_matrix = (te_matrix_handle_t)matrix_handle;
te_matrix->config->dispatch_method = dispatch_method;
xSemaphoreGive(s_te_mat_obj->mutex);
return ESP_OK;
}
esp_err_t touch_matrix_subscribe_event(touch_matrix_handle_t matrix_handle, uint32_t event_mask, void *arg)
{
TE_CHECK(s_te_mat_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(matrix_handle != NULL, ESP_ERR_INVALID_ARG);
if (!(event_mask & TOUCH_ELEM_EVENT_ON_PRESS) && !(event_mask & TOUCH_ELEM_EVENT_ON_RELEASE) &&
!(event_mask & TOUCH_ELEM_EVENT_ON_LONGPRESS) && !(event_mask & TOUCH_ELEM_EVENT_NONE)) {
ESP_LOGE(TE_TAG, "Touch button only support TOUCH_ELEM_EVENT_ON_PRESS, "
"TOUCH_ELEM_EVENT_ON_RELEASE, TOUCH_ELEM_EVENT_ON_LONGPRESS event mask");
return ESP_ERR_INVALID_ARG;
}
if (event_mask & TOUCH_ELEM_EVENT_ON_LONGPRESS) {
touch_matrix_set_longpress(matrix_handle, TE_DEFAULT_LONGPRESS_TIME(s_te_mat_obj)); //set the default time(1000ms) for long press
}
xSemaphoreTake(s_te_mat_obj->mutex, portMAX_DELAY);
te_matrix_handle_t te_matrix = (te_matrix_handle_t)matrix_handle;
te_matrix->config->event_mask = event_mask;
te_matrix->config->arg = arg;
xSemaphoreGive(s_te_mat_obj->mutex);
return ESP_OK;
}
esp_err_t touch_matrix_set_callback(touch_matrix_handle_t matrix_handle, touch_matrix_callback_t matrix_callback)
{
TE_CHECK(s_te_mat_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(matrix_handle != NULL, ESP_ERR_INVALID_ARG);
TE_CHECK(matrix_callback != NULL, ESP_ERR_INVALID_ARG);
te_matrix_handle_t te_matrix = (te_matrix_handle_t)matrix_handle;
xSemaphoreTake(s_te_mat_obj->mutex, portMAX_DELAY);
te_matrix->config->callback = matrix_callback;
xSemaphoreGive(s_te_mat_obj->mutex);
return ESP_OK;
}
esp_err_t touch_matrix_set_longpress(touch_matrix_handle_t matrix_handle, uint32_t threshold_time)
{
TE_CHECK(s_te_mat_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(matrix_handle != NULL, ESP_ERR_INVALID_ARG);
TE_CHECK(threshold_time > 0, ESP_ERR_INVALID_ARG);
te_matrix_handle_t te_matrix = (te_matrix_handle_t)matrix_handle;
touch_elem_dispatch_t dispatch_method = te_matrix->config->dispatch_method;
if (dispatch_method == TOUCH_ELEM_DISP_EVENT) {
xSemaphoreTake(s_te_mat_obj->mutex, portMAX_DELAY);
}
uint8_t timer_period = te_get_timer_period();
te_matrix->trigger_thr = threshold_time / timer_period;
if (dispatch_method == TOUCH_ELEM_DISP_EVENT) {
xSemaphoreGive(s_te_mat_obj->mutex);
}
return ESP_OK;
}
const touch_matrix_message_t* touch_matrix_get_message(const touch_elem_message_t* element_message)
{
return (touch_matrix_message_t*)&element_message->child_msg;
_Static_assert(sizeof(element_message->child_msg) >= sizeof(touch_matrix_message_t), "Message size overflow");
}
static bool matrix_object_check_channel(touch_pad_t channel_num)
{
te_matrix_handle_list_t *item;
SLIST_FOREACH(item, &s_te_mat_obj->handle_list, next) {
if (matrix_channel_check(item->matrix_handle, channel_num)) {
return true;
}
}
return false;
}
static esp_err_t matrix_object_set_threshold(void)
{
esp_err_t ret = ESP_OK;
te_matrix_handle_list_t *item;
SLIST_FOREACH(item, &s_te_mat_obj->handle_list, next) {
ret = matrix_set_threshold(item->matrix_handle);
if (ret != ESP_OK) {
break;
}
}
return ret;
}
static void matrix_object_process_state(void)
{
te_matrix_handle_list_t *item;
SLIST_FOREACH(item, &s_te_mat_obj->handle_list, next) {
if (waterproof_check_mask_handle(item->matrix_handle)) {
matrix_reset_state(item->matrix_handle);
continue;
}
matrix_proc_state(item->matrix_handle);
}
}
static void matrix_object_update_state(touch_pad_t channel_num, te_state_t channel_state)
{
te_matrix_handle_list_t *item;
SLIST_FOREACH(item, &s_te_mat_obj->handle_list, next) {
if (waterproof_check_mask_handle(item->matrix_handle)) {
continue;
}
matrix_update_state(item->matrix_handle, channel_num, channel_state);
}
}
static esp_err_t matrix_object_add_instance(te_matrix_handle_t matrix_handle)
{
te_matrix_handle_list_t *item = (te_matrix_handle_list_t *)calloc(1, sizeof(te_matrix_handle_list_t));
TE_CHECK(item != NULL, ESP_ERR_NO_MEM);
item->matrix_handle = matrix_handle;
xSemaphoreTake(s_te_mat_obj->mutex, portMAX_DELAY);
SLIST_INSERT_HEAD(&s_te_mat_obj->handle_list, item, next);
xSemaphoreGive(s_te_mat_obj->mutex);
return ESP_OK;
}
static esp_err_t matrix_object_remove_instance(te_matrix_handle_t matrix_handle)
{
esp_err_t ret = ESP_ERR_NOT_FOUND;
te_matrix_handle_list_t *item;
SLIST_FOREACH(item, &s_te_mat_obj->handle_list, next) {
if (matrix_handle == item->matrix_handle) {
xSemaphoreTake(s_te_mat_obj->mutex, portMAX_DELAY);
SLIST_REMOVE(&s_te_mat_obj->handle_list, item, te_matrix_handle_list, next);
xSemaphoreGive(s_te_mat_obj->mutex);
free(item);
ret = ESP_OK;
break;
}
}
return ret;
}
bool is_matrix_object_handle(touch_elem_handle_t element_handle)
{
te_matrix_handle_list_t *item;
xSemaphoreTake(s_te_mat_obj->mutex, portMAX_DELAY);
SLIST_FOREACH(item, &s_te_mat_obj->handle_list, next) {
if (element_handle == item->matrix_handle) {
xSemaphoreGive(s_te_mat_obj->mutex);
return true;
}
}
xSemaphoreGive(s_te_mat_obj->mutex);
return false;
}
static bool matrix_channel_check(te_matrix_handle_t matrix_handle, touch_pad_t channel_num)
{
te_dev_t *device;
for (int idx = 0; idx < matrix_handle->x_channel_num + matrix_handle->y_channel_num; idx++) {
device = matrix_handle->device[idx];
if (device->channel == channel_num) {
return true;
}
}
return false;
}
static esp_err_t matrix_set_threshold(te_matrix_handle_t matrix_handle)
{
esp_err_t ret = ESP_OK;
for (int idx = 0; idx < matrix_handle->x_channel_num + matrix_handle->y_channel_num; idx++) {
ret |= te_dev_set_threshold(matrix_handle->device[idx]);
}
return ret;
}
static void matrix_update_state(te_matrix_handle_t matrix_handle, touch_pad_t channel_num, te_state_t channel_state)
{
te_dev_t *device;
for (int idx = 0; idx < matrix_handle->x_channel_num + matrix_handle->y_channel_num; idx++) {
device = matrix_handle->device[idx];
if (channel_num == device->channel) {
device->state = channel_state;
}
}
}
static void matrix_reset_state(te_matrix_handle_t matrix_handle)
{
for (int idx = 0; idx < matrix_handle->x_channel_num + matrix_handle->y_channel_num; idx++) {
matrix_handle->device[idx]->state = TE_STATE_IDLE;
}
matrix_handle->trigger_cnt = 0;
matrix_handle->current_state = TE_STATE_IDLE;
}
static void matrix_event_give(te_matrix_handle_t matrix_handle)
{
touch_elem_message_t element_message;
touch_matrix_message_t matrix_message = {
.event = matrix_handle->event,
.position = matrix_handle->position
};
element_message.handle = (touch_elem_handle_t)matrix_handle;
element_message.element_type = TOUCH_ELEM_TYPE_MATRIX;
element_message.arg = matrix_handle->config->arg;
memcpy(element_message.child_msg, &matrix_message, sizeof(matrix_message));
te_event_give(element_message);
}
static inline void matrix_dispatch(te_matrix_handle_t matrix_handle, touch_elem_dispatch_t dispatch_method)
{
if (dispatch_method == TOUCH_ELEM_DISP_EVENT) {
matrix_event_give(matrix_handle); //Event queue
} else if (dispatch_method == TOUCH_ELEM_DISP_CALLBACK) {
touch_matrix_message_t matrix_info;
matrix_info.event = matrix_handle->event;
matrix_info.position = matrix_handle->position;
void *arg = matrix_handle->config->arg;
matrix_handle->config->callback(matrix_handle, &matrix_info, arg); //Event callback
}
}
void matrix_enable_wakeup_calibration(te_matrix_handle_t matrix_handle, bool en)
{
for (int idx = 0; idx < matrix_handle->x_channel_num + matrix_handle->y_channel_num; ++idx) {
matrix_handle->device[idx]->is_use_last_threshold = !en;
}
}
/**
* @brief Scan the matrix channel
*
* This function will output the press position and release position info
* so as to determine which operation(press/release) is happening, since there
* will get the invalid state if user operates multi-points at the same time.
*
*/
static void matrix_scan_axis(te_matrix_handle_t matrix_handle, touch_matrix_position_t *press_pos,
uint8_t *press_cnt, touch_matrix_position_t *release_pos, uint8_t *release_cnt)
{
press_pos->x_axis = TE_MAT_POS_MAX;
press_pos->y_axis = TE_MAT_POS_MAX;
release_pos->x_axis = TE_MAT_POS_MAX;
release_pos->y_axis = TE_MAT_POS_MAX;
for (int idx = 0; idx < matrix_handle->x_channel_num + matrix_handle->y_channel_num; idx++) {
te_dev_t *device = matrix_handle->device[idx];
if (device->state == TE_STATE_PRESS) {
if (idx < matrix_handle->x_channel_num) {
press_pos->x_axis = idx; //Write down the x axis info
} else {
press_pos->y_axis = idx - matrix_handle->x_channel_num; //Write down the y axis info
}
(*press_cnt)++;
} else if (device->state == TE_STATE_RELEASE) {
if (idx < matrix_handle->x_channel_num) {
release_pos->x_axis = idx;
} else {
release_pos->y_axis = idx - matrix_handle->x_channel_num;
}
(*release_cnt)++;
}
}
}
/**
* @brief Pre-check and fix
*
* This function will pre-check and fix the invalid state, preparing for the
* next detection.
*
*/
static void matrix_pre_fixed(te_matrix_handle_t matrix_handle, touch_matrix_position_t *press_pos,
uint8_t press_cnt, touch_matrix_position_t *release_pos, uint8_t release_cnt)
{
te_dev_t *device;
te_matrix_state_t last_state = matrix_handle->current_state;
touch_matrix_position_t last_pos = {
.x_axis = matrix_handle->position.x_axis,
.y_axis = matrix_handle->position.y_axis
};
if (last_state == TE_STATE_IDLE) {
if (release_cnt > 0) {
/*< Release is not allowed while matrix is in IDLE state, */
/*< if that happened, reset it from Release into IDLE. */
for (int idx = 0; idx < matrix_handle->x_channel_num + matrix_handle->y_channel_num; idx++) {
device = matrix_handle->device[idx];
if (device->state != TE_STATE_RELEASE) {
continue;
}
device->state = TE_STATE_IDLE; //Reset to IDLE
}
}
} else if (last_state == TE_STATE_PRESS) {
if (release_cnt > 0) {
/*< Release position must be the same as the last Press position, */
/*< if it is not, reset it into IDLE. */
if (release_pos->x_axis != TE_MAT_POS_MAX && release_pos->x_axis != last_pos.x_axis) {
device = matrix_handle->device[release_pos->x_axis];
device->state = TE_STATE_IDLE;
}
if (release_pos->y_axis != TE_MAT_POS_MAX && release_pos->y_axis != last_pos.y_axis) {
device = matrix_handle->device[release_pos->y_axis + matrix_handle->x_channel_num];
device->state = TE_STATE_IDLE;
}
}
if (press_cnt > 2) { //TODO: remove or rewrite here
/*< If the last state is Press and current press count more than 2, */
/*< there must be multi-touch occurred, reset all of the channels */
/*< into IDLE except the last position channels. */
if (press_pos->x_axis != TE_MAT_POS_MAX && press_pos->x_axis != last_pos.x_axis) {
device = matrix_handle->device[press_pos->x_axis];
device->state = TE_STATE_IDLE;
}
if (press_pos->y_axis != TE_MAT_POS_MAX && press_pos->y_axis != last_pos.y_axis) {
device = matrix_handle->device[press_pos->y_axis + matrix_handle->x_channel_num];
device->state = TE_STATE_IDLE;
}
}
}
}
//TODO: refactor this ugly implementation
static esp_err_t matrix_get_axis_state(touch_matrix_position_t *press_pos, uint8_t press_cnt, touch_matrix_position_t *release_pos,
uint8_t release_cnt, te_matrix_state_t *x_axis_state, te_matrix_state_t *y_axis_state)
{
esp_err_t ret;
if (press_cnt >= 2) {
if (press_pos->x_axis != TE_MAT_POS_MAX && press_pos->y_axis != TE_MAT_POS_MAX) {
*x_axis_state = TE_STATE_PRESS;
*y_axis_state = TE_STATE_PRESS;
ret = ESP_OK;
} else {
ret = ESP_ERR_INVALID_STATE;
}
} else if (release_cnt >= 2) {
if (release_pos->x_axis != TE_MAT_POS_MAX && release_pos->y_axis != TE_MAT_POS_MAX) {
*x_axis_state = TE_STATE_RELEASE;
*y_axis_state = TE_STATE_RELEASE;
ret = ESP_OK;
} else {
ret = ESP_ERR_INVALID_STATE;
}
} else {
ret = ESP_ERR_INVALID_STATE;
}
return ret;
}
/**
* @brief Matrix button process
*
* This function will process the matrix button state and maintain a matrix FSM:
* IDLE ----> Press ----> Release ----> IDLE
*
* The state transition procedure is as follow:
* (channel state ----> x,y axis state ----> matrix button state)
*
* TODO: add state transition diagram
*/
static void matrix_proc_state(te_matrix_handle_t matrix_handle)
{
esp_err_t ret;
uint8_t press_cnt = 0;
uint8_t release_cnt = 0;
touch_matrix_position_t press_pos;
touch_matrix_position_t release_pos;
te_matrix_state_t x_axis_state = TE_STATE_IDLE;
te_matrix_state_t y_axis_state = TE_STATE_IDLE;
uint32_t event_mask = matrix_handle->config->event_mask;
touch_elem_dispatch_t dispatch_method = matrix_handle->config->dispatch_method;
BaseType_t mux_ret = xSemaphoreTake(s_te_mat_obj->mutex, 0);
if (mux_ret != pdPASS) {
return;
}
//TODO: refactor those functions
/*< Scan the state of all the matrix buttons channel */
matrix_scan_axis(matrix_handle, &press_pos, &press_cnt, &release_pos, &release_cnt);
/*< Pre check and fixed the invalid state */
matrix_pre_fixed(matrix_handle, &press_pos, press_cnt, &release_pos, release_cnt);
/*< Figure out x,y axis state and take the position */
ret = matrix_get_axis_state(&press_pos, press_cnt, &release_pos, release_cnt, &x_axis_state, &y_axis_state);
if (ret != ESP_OK) { //TODO: remove return
xSemaphoreGive(s_te_mat_obj->mutex);
return;
}
matrix_handle->current_state = matrix_get_state(x_axis_state, y_axis_state);
if (matrix_handle->current_state == TE_STATE_PRESS) {
if (matrix_handle->last_state == TE_STATE_IDLE) { //IDLE ---> Press = On_Press
matrix_update_position(matrix_handle, press_pos);
ESP_LOGD(TE_DEBUG_TAG, "matrix press (%"PRIu8", %"PRIu8")", matrix_handle->position.x_axis, matrix_handle->position.y_axis);
if (event_mask & TOUCH_ELEM_EVENT_ON_PRESS) {
matrix_handle->event = TOUCH_MATRIX_EVT_ON_PRESS;
matrix_dispatch(matrix_handle, dispatch_method);
}
} else if (matrix_handle->last_state == TE_STATE_PRESS) { //Press ---> Press = On_LongPress
if (event_mask & TOUCH_ELEM_EVENT_ON_LONGPRESS) {
if (++matrix_handle->trigger_cnt >= matrix_handle->trigger_thr) {
ESP_LOGD(TE_DEBUG_TAG, "matrix longpress (%"PRIu8", %"PRIu8")", matrix_handle->position.x_axis, matrix_handle->position.y_axis);
matrix_handle->event = TOUCH_MATRIX_EVT_ON_LONGPRESS;
matrix_dispatch(matrix_handle, dispatch_method);
matrix_handle->trigger_cnt = 0;
}
}
}
} else if (matrix_handle->current_state == TE_STATE_RELEASE) {
if (matrix_handle->last_state == TE_STATE_PRESS) { //Press ---> Release = On_Release
ESP_LOGD(TE_DEBUG_TAG, "matrix release (%"PRIu8", %"PRIu8")", matrix_handle->position.x_axis, matrix_handle->position.y_axis);
if (event_mask & TOUCH_ELEM_EVENT_ON_RELEASE) {
matrix_handle->event = TOUCH_MATRIX_EVT_ON_RELEASE;
matrix_dispatch(matrix_handle, dispatch_method);
}
} else if (matrix_handle->last_state == TE_STATE_RELEASE) { // Release ---> Release = On_IDLE (Not dispatch)
matrix_reset_state(matrix_handle);
}
} else if (matrix_handle->current_state == TE_STATE_IDLE) {
if (matrix_handle->last_state == TE_STATE_RELEASE) { //Release ---> IDLE = On_IDLE (Not dispatch)
//Nothing
} else if (matrix_handle->last_state == TE_STATE_IDLE) { //IDLE ---> IDLE = Running IDLE (Not dispatch)
//Move Pre-fix into here
}
}
matrix_handle->last_state = matrix_handle->current_state;
xSemaphoreGive(s_te_mat_obj->mutex);
}
static inline te_state_t matrix_get_state(te_matrix_state_t x_axis_state, te_matrix_state_t y_axis_state)
{
te_state_t matrix_state;
if ((x_axis_state == TE_STATE_PRESS) && (y_axis_state == TE_STATE_PRESS)) {
matrix_state = TE_STATE_PRESS;
} else if ((x_axis_state == TE_STATE_RELEASE) && (y_axis_state == TE_STATE_RELEASE)) {
matrix_state = TE_STATE_RELEASE;
} else {
matrix_state = TE_STATE_IDLE;
}
return matrix_state;
}
static void matrix_update_position(te_matrix_handle_t matrix_handle, touch_matrix_position_t new_pos) {
matrix_handle->position.x_axis = new_pos.x_axis;
matrix_handle->position.y_axis = new_pos.y_axis;
matrix_handle->position.index = matrix_handle->position.x_axis * matrix_handle->y_channel_num + matrix_handle->position.y_axis;
}

View File

@@ -1,678 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <sys/queue.h>
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp_log.h"
#include "touch_element/touch_element_private.h"
#define TE_SLD_DEFAULT_QTF_THR(obj) ((obj)->global_config->quantify_lower_threshold)
#define TE_SLD_DEFAULT_POS_FILTER_FACTOR(obj) ((obj)->global_config->position_filter_factor)
#define TE_SLD_DEFAULT_CALCULATE_CHANNEL(obj) ((obj)->global_config->calculate_channel_count)
#define TE_SLD_DEFAULT_BCM_UPDATE_TIME(obj) ((obj)->global_config->benchmark_update_time)
#define TE_SLD_DEFAULT_FILTER_RESET_TIME(obj) ((obj)->global_config->filter_reset_time)
#define TE_SLD_DEFAULT_POS_FILTER_SIZE(obj) ((obj)->global_config->position_filter_size)
typedef struct te_slider_handle_list {
te_slider_handle_t slider_handle; //Slider handle
SLIST_ENTRY(te_slider_handle_list) next; //Slider handle list entry
} te_slider_handle_list_t;
typedef struct {
SLIST_HEAD(te_slider_handle_list_head, te_slider_handle_list) handle_list; //Slider handle (instance) list
touch_slider_global_config_t *global_config; //Slider global configuration
SemaphoreHandle_t mutex; //Slider object mutex
} te_slider_obj_t;
te_slider_obj_t *s_te_sld_obj = NULL;
/* ---------------------------------------- Slider handle(instance) methods ----------------------------------------- */
static bool slider_channel_check(te_slider_handle_t slider_handle, touch_pad_t channel_num);
static esp_err_t slider_set_threshold(te_slider_handle_t slider_handle);
static inline te_state_t slider_get_state(te_dev_t **device, int device_num);
static void slider_reset_state(te_slider_handle_t slider_handle);
static void slider_update_position(te_slider_handle_t slider_handle);
static void slider_reset_position(te_slider_handle_t slider_handle);
static void slider_update_benchmark(te_slider_handle_t slider_handle);
static void slider_update_state(te_slider_handle_t slider_handle, touch_pad_t channel_num, te_state_t channel_state);
static void slider_proc_state(te_slider_handle_t slider_handle);
static void slider_event_give(te_slider_handle_t slider_handle);
static inline void slider_dispatch(te_slider_handle_t slider_handle, touch_elem_dispatch_t dispatch_method);
/* ------------------------------------------ Slider object(class) methods ------------------------------------------ */
static esp_err_t slider_object_add_instance(te_slider_handle_t slider_handle);
static esp_err_t slider_object_remove_instance(te_slider_handle_t slider_handle);
static bool slider_object_check_channel(touch_pad_t channel_num);
static esp_err_t slider_object_set_threshold(void);
static void slider_object_process_state(void);
static void slider_object_update_state(touch_pad_t channel_num, te_state_t channel_state);
/* ------------------------------------------------------------------------------------------------------------------ */
esp_err_t touch_slider_install(const touch_slider_global_config_t *global_config)
{
TE_CHECK(te_system_check_state() == true, ESP_ERR_INVALID_STATE);
TE_CHECK(global_config != NULL, ESP_ERR_INVALID_ARG);
//Fixme: Make it thread-safe
s_te_sld_obj = (te_slider_obj_t *)calloc(1, sizeof(te_slider_obj_t));
TE_CHECK(s_te_sld_obj != NULL, ESP_ERR_NO_MEM);
s_te_sld_obj->global_config = (touch_slider_global_config_t *)calloc(1, sizeof(touch_slider_global_config_t));
s_te_sld_obj->mutex = xSemaphoreCreateMutex();
TE_CHECK_GOTO(s_te_sld_obj->global_config != NULL && s_te_sld_obj->mutex != NULL, cleanup);
xSemaphoreTake(s_te_sld_obj->mutex, portMAX_DELAY);
SLIST_INIT(&s_te_sld_obj->handle_list);
memcpy(s_te_sld_obj->global_config, global_config, sizeof(touch_slider_global_config_t));
te_object_methods_t slider_methods = {
.handle = s_te_sld_obj,
.check_channel = slider_object_check_channel,
.set_threshold = slider_object_set_threshold,
.process_state = slider_object_process_state,
.update_state = slider_object_update_state
};
te_object_method_register(&slider_methods, TE_CLS_TYPE_SLIDER);
xSemaphoreGive(s_te_sld_obj->mutex);
return ESP_OK;
cleanup:
TE_FREE_AND_NULL(s_te_sld_obj->global_config);
if (s_te_sld_obj->mutex != NULL) {
vSemaphoreDelete(s_te_sld_obj->mutex);
}
TE_FREE_AND_NULL(s_te_sld_obj);
return ESP_ERR_NO_MEM;
}
void touch_slider_uninstall(void)
{
xSemaphoreTake(s_te_sld_obj->mutex, portMAX_DELAY);
if (s_te_sld_obj == NULL) {
xSemaphoreGive(s_te_sld_obj->mutex);
return;
}
te_object_method_unregister(TE_CLS_TYPE_SLIDER);
free(s_te_sld_obj->global_config);
s_te_sld_obj->global_config = NULL;
while (!SLIST_EMPTY(&s_te_sld_obj->handle_list)) {
SLIST_FIRST(&s_te_sld_obj->handle_list);
SLIST_REMOVE_HEAD(&s_te_sld_obj->handle_list, next);
}
xSemaphoreGive(s_te_sld_obj->mutex);
vSemaphoreDelete(s_te_sld_obj->mutex);
free(s_te_sld_obj);
s_te_sld_obj = NULL;
}
esp_err_t touch_slider_create(const touch_slider_config_t *slider_config, touch_slider_handle_t *slider_handle)
{
TE_CHECK(s_te_sld_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(slider_handle != NULL && slider_config != NULL, ESP_ERR_INVALID_ARG);
TE_CHECK(slider_config->channel_num > 2 &&
slider_config->channel_num < TOUCH_PAD_MAX &&
slider_config->channel_array != NULL &&
slider_config->sensitivity_array != NULL &&
slider_config->position_range > slider_config->channel_num,
ESP_ERR_INVALID_ARG);
TE_CHECK(te_object_check_channel(slider_config->channel_array, slider_config->channel_num) == false,
ESP_ERR_INVALID_ARG);
te_slider_handle_t te_slider = (te_slider_handle_t)calloc(1, sizeof(struct te_slider_s));
TE_CHECK(te_slider != NULL, ESP_ERR_NO_MEM);
esp_err_t ret = ESP_ERR_NO_MEM;
te_slider->config = (te_slider_handle_config_t *)calloc(1, sizeof(te_slider_handle_config_t));
te_slider->pos_filter_window = calloc(TE_SLD_DEFAULT_POS_FILTER_SIZE(s_te_sld_obj), sizeof(uint8_t));
te_slider->device = (te_dev_t **)calloc(slider_config->channel_num, sizeof(te_dev_t *));
te_slider->channel_bcm = (uint32_t *)calloc(slider_config->channel_num, sizeof(uint32_t));
te_slider->quantify_signal_array = (float *)calloc(slider_config->channel_num, sizeof(float));
TE_CHECK_GOTO(te_slider->config != NULL &&
te_slider->pos_filter_window != NULL &&
te_slider->device != NULL &&
te_slider->channel_bcm &&
te_slider->quantify_signal_array,
cleanup);
for (int idx = 0; idx < slider_config->channel_num; idx++) {
te_slider->device[idx] = (te_dev_t *)calloc(1, sizeof(te_dev_t));
if (te_slider->device[idx] == NULL) {
ret = ESP_ERR_NO_MEM;
goto cleanup;
}
}
ret = te_dev_init(te_slider->device, slider_config->channel_num, TOUCH_ELEM_TYPE_SLIDER,
slider_config->channel_array, slider_config->sensitivity_array,
TE_DEFAULT_THRESHOLD_DIVIDER(s_te_sld_obj));
TE_CHECK_GOTO(ret == ESP_OK, cleanup);
te_slider->config->event_mask = TOUCH_ELEM_EVENT_NONE;
te_slider->config->dispatch_method = TOUCH_ELEM_DISP_MAX;
te_slider->config->callback = NULL;
te_slider->config->arg = NULL;
te_slider->channel_bcm_update_cnt = TE_SLD_DEFAULT_BCM_UPDATE_TIME(s_te_sld_obj); //update at first time
te_slider->filter_reset_cnt = TE_SLD_DEFAULT_FILTER_RESET_TIME(s_te_sld_obj); //reset at first time
te_slider->channel_sum = slider_config->channel_num;
te_slider->position_range = slider_config->position_range;
te_slider->position_scale = (float)(slider_config->position_range) / (slider_config->channel_num - 1);
te_slider->current_state = TE_STATE_IDLE;
te_slider->last_state = TE_STATE_IDLE;
te_slider->event = TOUCH_SLIDER_EVT_MAX;
te_slider->position = 0;
te_slider->last_position = 0;
te_slider->pos_window_idx = 0;
te_slider->is_first_sample = true;
ret = slider_object_add_instance(te_slider);
TE_CHECK_GOTO(ret == ESP_OK, cleanup);
*slider_handle = (touch_elem_handle_t)te_slider;
return ESP_OK;
cleanup:
TE_FREE_AND_NULL(te_slider->config);
TE_FREE_AND_NULL(te_slider->pos_filter_window);
TE_FREE_AND_NULL(te_slider->channel_bcm);
TE_FREE_AND_NULL(te_slider->quantify_signal_array);
if (te_slider->device != NULL) {
for (int idx = 0; idx < slider_config->channel_num; idx++) {
TE_FREE_AND_NULL(te_slider->device[idx]);
}
free(te_slider->device);
te_slider->device = NULL;
}
TE_FREE_AND_NULL(te_slider);
return ret;
}
esp_err_t touch_slider_delete(touch_slider_handle_t slider_handle)
{
TE_CHECK(s_te_sld_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(slider_handle != NULL, ESP_ERR_INVALID_ARG);
/*< Release touch sensor application resource */
esp_err_t ret = slider_object_remove_instance(slider_handle);
TE_CHECK(ret == ESP_OK, ret);
te_slider_handle_t te_slider = (te_slider_handle_t)slider_handle;
/*< Release touch sensor device resource */
te_dev_deinit(te_slider->device, te_slider->channel_sum);
for (int idx = 0; idx < te_slider->channel_sum; idx++) {
free(te_slider->device[idx]);
}
free(te_slider->config);
free(te_slider->quantify_signal_array);
free(te_slider->pos_filter_window);
free(te_slider->channel_bcm);
free(te_slider->device);
free(te_slider);
return ESP_OK;
}
esp_err_t touch_slider_set_dispatch_method(touch_slider_handle_t slider_handle, touch_elem_dispatch_t dispatch_method)
{
TE_CHECK(s_te_sld_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(slider_handle != NULL, ESP_ERR_INVALID_ARG);
TE_CHECK(dispatch_method >= TOUCH_ELEM_DISP_EVENT && dispatch_method <= TOUCH_ELEM_DISP_MAX, ESP_ERR_INVALID_ARG);
xSemaphoreTake(s_te_sld_obj->mutex, portMAX_DELAY);
te_slider_handle_t te_slider = (te_slider_handle_t)slider_handle;
te_slider->config->dispatch_method = dispatch_method;
xSemaphoreGive(s_te_sld_obj->mutex);
return ESP_OK;
}
esp_err_t touch_slider_subscribe_event(touch_slider_handle_t slider_handle, uint32_t event_mask, void *arg)
{
TE_CHECK(s_te_sld_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(slider_handle != NULL, ESP_ERR_INVALID_ARG);
if (!(event_mask & TOUCH_ELEM_EVENT_ON_PRESS) && !(event_mask & TOUCH_ELEM_EVENT_ON_RELEASE) &&
!(event_mask & TOUCH_ELEM_EVENT_NONE) && !(event_mask & TOUCH_ELEM_EVENT_ON_CALCULATION)) {
ESP_LOGE(TE_TAG, "Touch button only support TOUCH_ELEM_EVENT_ON_PRESS, "
"TOUCH_ELEM_EVENT_ON_RELEASE, TOUCH_ELEM_EVENT_ON_CALCULATION event mask");
return ESP_ERR_INVALID_ARG;
}
xSemaphoreTake(s_te_sld_obj->mutex, portMAX_DELAY);
te_slider_handle_t te_slider = (te_slider_handle_t)slider_handle;
te_slider->config->event_mask = event_mask;
te_slider->config->arg = arg;
xSemaphoreGive(s_te_sld_obj->mutex);
return ESP_OK;
}
esp_err_t touch_slider_set_callback(touch_slider_handle_t slider_handle, touch_slider_callback_t slider_callback)
{
TE_CHECK(s_te_sld_obj != NULL, ESP_ERR_INVALID_STATE);
TE_CHECK(slider_handle != NULL, ESP_ERR_INVALID_ARG);
TE_CHECK(slider_callback != NULL, ESP_ERR_INVALID_ARG);
te_slider_handle_t te_slider = (te_slider_handle_t)slider_handle;
xSemaphoreTake(s_te_sld_obj->mutex, portMAX_DELAY);
te_slider->config->callback = slider_callback;
xSemaphoreGive(s_te_sld_obj->mutex);
return ESP_OK;
}
const touch_slider_message_t* touch_slider_get_message(const touch_elem_message_t* element_message)
{
return (touch_slider_message_t*)&element_message->child_msg;
_Static_assert(sizeof(element_message->child_msg) >= sizeof(touch_slider_message_t), "Message size overflow");
}
static bool slider_object_check_channel(touch_pad_t channel_num)
{
te_slider_handle_list_t *item;
SLIST_FOREACH(item, &s_te_sld_obj->handle_list, next) {
if (slider_channel_check(item->slider_handle, channel_num)) {
return true;
}
}
return false;
}
static esp_err_t slider_object_set_threshold(void)
{
esp_err_t ret = ESP_OK;
te_slider_handle_list_t *item;
SLIST_FOREACH(item, &s_te_sld_obj->handle_list, next) {
ret = slider_set_threshold(item->slider_handle);
if (ret != ESP_OK) {
break;
}
}
return ret;
}
// workaround for compilation error on xtensa-esp32s3-elf-gcc (crosstool-NG esp-2022r1-RC1) 11.2.0 (IDF-5725)
__attribute__((optimize("-Os")))
static void slider_object_process_state(void)
{
te_slider_handle_list_t *item;
SLIST_FOREACH(item, &s_te_sld_obj->handle_list, next) {
if (waterproof_check_mask_handle(item->slider_handle)) {
slider_reset_state(item->slider_handle);
slider_reset_position(item->slider_handle);
continue;
}
slider_proc_state(item->slider_handle);
}
}
static void slider_object_update_state(touch_pad_t channel_num, te_state_t channel_state)
{
te_slider_handle_list_t *item;
SLIST_FOREACH(item, &s_te_sld_obj->handle_list, next) {
if (waterproof_check_mask_handle(item->slider_handle)) {
continue;
}
slider_update_state(item->slider_handle, channel_num, channel_state);
}
}
static esp_err_t slider_object_add_instance(te_slider_handle_t slider_handle)
{
te_slider_handle_list_t *item = (te_slider_handle_list_t *)calloc(1, sizeof(te_slider_handle_list_t));
TE_CHECK(item != NULL, ESP_ERR_NO_MEM);
item->slider_handle = slider_handle;
xSemaphoreTake(s_te_sld_obj->mutex, portMAX_DELAY);
SLIST_INSERT_HEAD(&s_te_sld_obj->handle_list, item, next);
xSemaphoreGive(s_te_sld_obj->mutex);
return ESP_OK;
}
static esp_err_t slider_object_remove_instance(te_slider_handle_t slider_handle)
{
esp_err_t ret = ESP_ERR_NOT_FOUND;
te_slider_handle_list_t *item;
SLIST_FOREACH(item, &s_te_sld_obj->handle_list, next) {
if (slider_handle == item->slider_handle) {
xSemaphoreTake(s_te_sld_obj->mutex, portMAX_DELAY);
SLIST_REMOVE(&s_te_sld_obj->handle_list, item, te_slider_handle_list, next);
xSemaphoreGive(s_te_sld_obj->mutex);
free(item);
ret = ESP_OK;
break;
}
}
return ret;
}
bool is_slider_object_handle(touch_elem_handle_t element_handle)
{
te_slider_handle_list_t *item;
xSemaphoreTake(s_te_sld_obj->mutex, portMAX_DELAY);
SLIST_FOREACH(item, &s_te_sld_obj->handle_list, next) {
if (element_handle == item->slider_handle) {
xSemaphoreGive(s_te_sld_obj->mutex);
return true;
}
}
xSemaphoreGive(s_te_sld_obj->mutex);
return false;
}
static bool slider_channel_check(te_slider_handle_t slider_handle, touch_pad_t channel_num)
{
te_dev_t *device;
for (int idx = 0; idx < slider_handle->channel_sum; idx++) {
device = slider_handle->device[idx];
if (device->channel == channel_num) {
return true;
}
}
return false;
}
static esp_err_t slider_set_threshold(te_slider_handle_t slider_handle)
{
esp_err_t ret = ESP_OK;
for (int idx = 0; idx < slider_handle->channel_sum; idx++) {
ret |= te_dev_set_threshold(slider_handle->device[idx]);
}
slider_update_benchmark(slider_handle); //Update benchmark at startup
return ret;
}
static void slider_update_benchmark(te_slider_handle_t slider_handle)
{
for (int idx = 0; idx < slider_handle->channel_sum; idx++) {
uint32_t bcm_val;
te_dev_t *device = slider_handle->device[idx];
bcm_val = te_read_smooth_signal(device->channel);
slider_handle->channel_bcm[idx] = bcm_val;
}
}
static void slider_update_state(te_slider_handle_t slider_handle, touch_pad_t channel_num, te_state_t channel_state)
{
te_dev_t *device;
for (int idx = 0; idx < slider_handle->channel_sum; idx++) {
device = slider_handle->device[idx];
if (channel_num == device->channel) {
device->state = channel_state;
}
}
}
static void slider_reset_state(te_slider_handle_t slider_handle)
{
for (int idx = 0; idx < slider_handle->channel_sum; idx++) {
slider_handle->device[idx]->state = TE_STATE_IDLE;
}
slider_handle->current_state = TE_STATE_IDLE;
}
static void slider_event_give(te_slider_handle_t slider_handle)
{
touch_elem_message_t element_message;
touch_slider_message_t slider_message = {
.event = slider_handle->event,
.position = slider_handle->position
};
element_message.handle = (touch_elem_handle_t)slider_handle;
element_message.element_type = TOUCH_ELEM_TYPE_SLIDER;
element_message.arg = slider_handle->config->arg;
memcpy(element_message.child_msg, &slider_message, sizeof(slider_message));
te_event_give(element_message);
}
static inline void slider_dispatch(te_slider_handle_t slider_handle, touch_elem_dispatch_t dispatch_method)
{
if (dispatch_method == TOUCH_ELEM_DISP_EVENT) {
slider_event_give(slider_handle); //Event queue
} else if (dispatch_method == TOUCH_ELEM_DISP_CALLBACK) {
touch_slider_message_t slider_info;
slider_info.event = slider_handle->event;
slider_info.position = slider_handle->position;
void *arg = slider_handle->config->arg;
slider_handle->config->callback(slider_handle, &slider_info, arg); //Event callback
}
}
void slider_enable_wakeup_calibration(te_slider_handle_t slider_handle, bool en)
{
for (int idx = 0; idx < slider_handle->channel_sum; ++idx) {
slider_handle->device[idx]->is_use_last_threshold = !en;
}
}
/**
* @brief Slider process
*
* This function will process the slider state and maintain a slider FSM:
* IDLE ----> Press ----> Release ----> IDLE
*
* The state transition procedure is as follow:
* (channel state ----> slider state)
*
* TODO: add state transition diagram
*/
static void slider_proc_state(te_slider_handle_t slider_handle)
{
uint32_t event_mask = slider_handle->config->event_mask;
touch_elem_dispatch_t dispatch_method = slider_handle->config->dispatch_method;
BaseType_t mux_ret = xSemaphoreTake(s_te_sld_obj->mutex, 0);
if (mux_ret != pdPASS) {
return;
}
slider_handle->current_state = slider_get_state(slider_handle->device, slider_handle->channel_sum);
if (slider_handle->current_state == TE_STATE_PRESS) {
slider_handle->channel_bcm_update_cnt = 0; // Reset benchmark update counter
slider_update_position(slider_handle);
if (slider_handle->last_state == TE_STATE_IDLE) { //IDLE ---> Press = On_Press
ESP_LOGD(TE_DEBUG_TAG, "slider press");
if (event_mask & TOUCH_ELEM_EVENT_ON_PRESS) {
slider_handle->event = TOUCH_SLIDER_EVT_ON_PRESS;
slider_dispatch(slider_handle, dispatch_method);
}
} else if (slider_handle->last_state == TE_STATE_PRESS) { //Press ---> Press = On_Calculation
ESP_LOGD(TE_DEBUG_TAG, "slider calculation");
if (event_mask & TOUCH_ELEM_EVENT_ON_CALCULATION) {
slider_handle->event = TOUCH_SLIDER_EVT_ON_CALCULATION;
slider_dispatch(slider_handle, dispatch_method);
}
}
} else if (slider_handle->current_state == TE_STATE_RELEASE) {
if (slider_handle->last_state == TE_STATE_PRESS) { //Press ---> Release = On_Release
ESP_LOGD(TE_DEBUG_TAG, "slider release");
if (event_mask & TOUCH_ELEM_EVENT_ON_RELEASE) {
slider_handle->event = TOUCH_SLIDER_EVT_ON_RELEASE;
slider_dispatch(slider_handle, dispatch_method);
}
} else if (slider_handle->last_state == TE_STATE_RELEASE) { // Release ---> Release = On_IDLE (Not dispatch)
slider_reset_state(slider_handle);//Reset the slider state for the next time touch action detection
}
} else if (slider_handle->current_state == TE_STATE_IDLE) {
if (slider_handle->last_state == TE_STATE_RELEASE) { //Release ---> IDLE = On_IDLE (Not dispatch)
//Nothing
} else if (slider_handle->last_state == TE_STATE_IDLE) { //IDLE ---> IDLE = Running IDLE (Not dispatch)
if (++slider_handle->channel_bcm_update_cnt >= TE_SLD_DEFAULT_BCM_UPDATE_TIME(s_te_sld_obj)) { //Update channel benchmark
slider_handle->channel_bcm_update_cnt = 0;
slider_update_benchmark(slider_handle);
ESP_LOGD(TE_DEBUG_TAG, "slider bcm update");
}
if (++slider_handle->filter_reset_cnt >= TE_SLD_DEFAULT_FILTER_RESET_TIME(s_te_sld_obj)) {
slider_reset_position(slider_handle); //Reset slider filter so as to speed up next time position calculation
}
}
}
slider_handle->last_state = slider_handle->current_state;
xSemaphoreGive(s_te_sld_obj->mutex);
}
static inline te_state_t slider_get_state(te_dev_t **device, int device_num)
{
/*< Scan the state of all the slider channel and calculate the number of them if the state is Press*/
uint8_t press_cnt = 0;
uint8_t idle_cnt = 0;
for (int idx = 0; idx < device_num; idx++) { //Calculate how many channel is pressed
if (device[idx]->state == TE_STATE_PRESS) {
press_cnt++;
} else if (device[idx]->state == TE_STATE_IDLE) {
idle_cnt++;
}
}
if (press_cnt > 0) {
return TE_STATE_PRESS;
} else if (idle_cnt == device_num) {
return TE_STATE_IDLE;
} else {
return TE_STATE_RELEASE;
}
}
/**
* @brief Slider channel difference-rate re-quantization
*
* This function will re-quantifies the touch sensor slider channel difference-rate
* so as to make the different size of touch pad in PCB has the same difference value
*
*/
static inline void slider_quantify_signal(te_slider_handle_t slider_handle)
{
float weight_sum = 0;
for (int idx = 0; idx < slider_handle->channel_sum; idx++) {
te_dev_t *device = slider_handle->device[idx];
weight_sum += device->sens;
uint32_t current_signal = te_read_smooth_signal(device->channel);
int ans = current_signal - slider_handle->channel_bcm[idx];
float diff_rate = (float)ans / slider_handle->channel_bcm[idx];
slider_handle->quantify_signal_array[idx] = diff_rate / device->sens;
if (slider_handle->quantify_signal_array[idx] < TE_SLD_DEFAULT_QTF_THR(s_te_sld_obj)) {
slider_handle->quantify_signal_array[idx] = 0;
}
}
for (int idx = 0; idx < slider_handle->channel_sum; idx++) {
te_dev_t *device = slider_handle->device[idx];
slider_handle->quantify_signal_array[idx] = slider_handle->quantify_signal_array[idx] * weight_sum / device->sens;
}
}
/**
* @brief Calculate max sum subarray
*
* This function will figure out the max sum subarray from the
* input array, return the max sum and max sum start index
*
*/
static inline float slider_search_max_subarray(const float *array, int array_size, int *max_array_idx)
{
*max_array_idx = 0;
float max_array_sum = 0;
float current_array_sum = 0;
for (int idx = 0; idx <= (array_size - TE_SLD_DEFAULT_CALCULATE_CHANNEL(s_te_sld_obj)); idx++) {
for (int x = idx; x < idx + TE_SLD_DEFAULT_CALCULATE_CHANNEL(s_te_sld_obj); x++) {
current_array_sum += array[x];
}
if (max_array_sum < current_array_sum) {
max_array_sum = current_array_sum;
*max_array_idx = idx;
}
current_array_sum = 0;
}
return max_array_sum;
}
/**
* @brief Calculate zero number
*
* This function will figure out the number of non-zero items from
* the subarray
*/
static inline uint8_t slider_get_non_zero_num(const float *array, uint8_t array_idx)
{
uint8_t zero_cnt = 0;
for (int idx = array_idx; idx < array_idx + TE_SLD_DEFAULT_CALCULATE_CHANNEL(s_te_sld_obj); idx++) {
zero_cnt += (array[idx] > 0) ? 1 : 0;
}
return zero_cnt;
}
static inline uint32_t slider_calculate_position(te_slider_handle_t slider_handle, int subarray_index, float subarray_sum, int non_zero_num)
{
int range = slider_handle->position_range;
int array_size = slider_handle->channel_sum;
float scale = slider_handle->position_scale;
const float *array = slider_handle->quantify_signal_array;
uint32_t position = 0;
if (non_zero_num == 0) {
position = slider_handle->position;
} else if (non_zero_num == 1) {
for (int index = subarray_index; index < subarray_index + TE_SLD_DEFAULT_CALCULATE_CHANNEL(s_te_sld_obj); index++) {
if (0 != array[index]) {
if (index == array_size - 1) {
position = range;
} else {
position = (uint32_t)((float)index * scale);
}
break;
}
}
} else {
for (int idx = subarray_index; idx < subarray_index + TE_SLD_DEFAULT_CALCULATE_CHANNEL(s_te_sld_obj); idx++) {
position += ((float)idx * array[idx]);
}
position = position * scale / subarray_sum;
}
return position;
}
static uint32_t slider_filter_average(te_slider_handle_t slider_handle, uint32_t current_position)
{
uint32_t position_average = 0;
if (slider_handle->is_first_sample) {
for (int win_idx = 0; win_idx < TE_SLD_DEFAULT_POS_FILTER_SIZE(s_te_sld_obj); win_idx++) {
slider_handle->pos_filter_window[win_idx] = current_position; //Preload filter buffer
}
slider_handle->is_first_sample = false;
} else {
slider_handle->pos_filter_window[slider_handle->pos_window_idx++] = current_position; //Moving average filter
if (slider_handle->pos_window_idx >= TE_SLD_DEFAULT_POS_FILTER_SIZE(s_te_sld_obj)) {
slider_handle->pos_window_idx = 0;
}
}
for (int win_idx = 0; win_idx < TE_SLD_DEFAULT_POS_FILTER_SIZE(s_te_sld_obj); win_idx++) { //Moving average filter
position_average += slider_handle->pos_filter_window[win_idx];
}
position_average = (uint32_t)((float)position_average / TE_SLD_DEFAULT_POS_FILTER_SIZE(s_te_sld_obj) + 0.5F);
return position_average;
}
static inline uint32_t slider_filter_iir(uint32_t in_now, uint32_t out_last, uint32_t k)
{
if (k == 0) {
return in_now;
} else {
uint32_t out_now = (in_now + (k - 1) * out_last) / k;
return out_now;
}
}
/**
* @brief touch sensor slider position update
*
* This function is the core algorithm about touch sensor slider
* position update, mainly has several steps:
* 1. Re-quantization
* 2. Figure out changed channel
* 3. Calculate position
* 4. Filter
*
*/
static void slider_update_position(te_slider_handle_t slider_handle)
{
int max_array_idx = 0;
float max_array_sum;
uint8_t non_zero_num;
uint32_t current_position;
slider_quantify_signal(slider_handle);
max_array_sum = slider_search_max_subarray(slider_handle->quantify_signal_array, slider_handle->channel_sum, &max_array_idx);
non_zero_num = slider_get_non_zero_num(slider_handle->quantify_signal_array, max_array_idx);
current_position = slider_calculate_position(slider_handle, max_array_idx, max_array_sum, non_zero_num);
uint32_t position_average = slider_filter_average(slider_handle, current_position);
slider_handle->last_position = slider_handle->last_position == 0 ? (position_average << 4) : slider_handle->last_position;
slider_handle->last_position = slider_filter_iir((position_average << 4), slider_handle->last_position, TE_SLD_DEFAULT_POS_FILTER_FACTOR(s_te_sld_obj));
slider_handle->position = ((slider_handle->last_position + 8) >> 4); //(x + 8) >> 4 ----> (x + 8) / 16 ----> x/16 + 0.5
}
static void slider_reset_position(te_slider_handle_t slider_handle)
{
slider_handle->is_first_sample = true;
slider_handle->last_position = 0;
slider_handle->pos_window_idx = 0;
}

View File

@@ -1 +0,0 @@
<mxfile host="Electron" modified="2021-02-03T06:21:33.748Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/12.3.2 Chrome/78.0.3904.113 Electron/7.1.2 Safari/537.36" etag="MjaFnCSX-tqnD9erv3wG" version="12.3.2" type="device" pages="1"><diagram id="cdp2F28X_CI_c8RY0vqN" name="第 1 页">7Vxtc6M2EP41nmk/JIMkEPAxb22v05veNO209ykjg2zTw8gFnDj99ZVA4k3Cdi6AE/dubiYgCwmeXe0+Wq00Qzfr3Y8p2aw+spDGM2iFuxm6nUEIbAhn4r8VPpclHnDLgmUahbJSXXAf/UvLQkcWbqOQZq16OWNxHm3ahQFLEhrkrTKSpuypXW3B4nanG7KkWsF9QGK99M8ozFfyIxyrLv+JRsuV6hlY8pc1UZVlQbYiIXtqFKG7GbpJGcvLq/XuhsYCOwVL+dwPPb9WL5bSJD/mgbvPj27yJVvm948fvqx/fvKu/vrtwpMwP5J4K79Yvm3+rCDgL74RlwFLE5rO0PXTKsrp/YYEovSJi52XrfJ1zO8AvwyjlEsiYgm/T1gqYLgu9AF6lrgUimBjUXMRxfENi1ladIQWC4qDgJdnecq+0MYvoevPLfGwfFua5nTXiwOo0OVaSdma5ukzryIfQPal/GipkUCB8FQL2PWk1FYN4TpKKYlUqmXVeI07v5DQv0QM7mExpGybhFS0Yh2WQRdZL6BmZOeeYzsDIYv9DrJQDYYGskih3UTWVnAPjixQ5qaBJA35EJe3Qj/ZkiUkvqtLr9tY13V+YWwjEf6b5vmzNFdkm7M2/hyx9Pkv8fylB7Aq+MwLLqxLy/JVye1O9lHePTfvPtE04iCIIVcW7qK8bBJxfSnvPxf3vu/L+7o9cfPcuOm2VqIioNgvbY4c26YB3YOxLe0ySZc03ysLZNaflMYkjx7bb2JSBfnoJxbxd2zoHWipHfZgu4nyC+RTTROpNcTFxcG1fOy6NvBRq1kX4ktR6NiyTruT8vO1Tq7SlDw3qm1EhWzPx7jtj3EtuzMIyhbrIVEB+fWjxD4L86OsjUTOdnW7DkzWpyoc3Pro3vV3tg1WvOgupmtayD2O5imRfTUB50DkbVTb6CUsoR2oZRGJo6VwvgHvoHDYAtaIc5or+cM6CsPCzpnE2Bb0EA7X63rcaoA2JWMbPC4czS0gTTIfBFjpdiNksqZZJojh2crE1ny1gwyjBU0qE50E/bOl2zOWggM6MsC6DCYdFqrhpsHirCEVPppt8yg5Y2FABLpmytHFYZoXjDcirNOQV0k01XVJMp29FDMk2aroEwzLLeGx5NL1zdJ9Gbd8KVtDVltlkBzRfQzzQP1x2B000Tsci2GbbUjS0i/8z1YEJMohd5GVY+6KV+Ez+TWJ6wr8ain+3ka8Ul5wGlpxGvpY/C374O9cdlM+sIdZgpczy8UC9oQM8Bw7eBjT4Hsdy1CJseksXTilpdYJzKeUBZy38MJgRZKkiMNlOcl1m/0OEYcmMj8p4rb3/0LchnrwZlrEgeWdxP3VsRvoNEM31Y89UZuxfKDtT+UDXzdA/G9u5nVDsDsns51TD0EHnrnRa+Ht4CpScUKj55/E6Bk5v7uf9DcspfsSQ2kMb49lPR30LqynoxO6b9bzNWPZP/VIdvRp12XxTwP3bGIowOm6MGwIK04a0nJ0VnK9zXOWaFLInqJ1TDSkuZoGAXUWC5MCI4x8FA4DnloEVjMeYFBg37R8MRp2WA8H3sdRKOKBbxs7hA3EaWLsgIbdR5Kn0e7tYYe7SwGm6MaL0ZP9/UaDnCRL/rG1lVDLP3sW6rChOxXzUL2RmNu8hDPPa2HHMk1kA4TOsM5//9iEBdk9B/qrJWzYp3aaWKdB5wS4Fkj0Tz3DwzpLOSvA25bNtMg5LdxYg1uDlSbhlUhdFLwuJlkWBb0BqlZ8qp5o9Uy7qgQiNa2rJmu9U7zZgBOxY8NY2DLLtCE0x0AhVdkrs4mA27WKSGnNS/OJuP51DWw31aQna2gw/3VEYuF7VLeTKYeWy6KlLh6rHHpTFe+aSDlcU8B2QBM/DX1Fls5iXFMYD5kYrOv0q8DrUnqPMPSvyazmalZnVtvCXRaJ1dC3Tb72NInVhhUkY2I19MeSgq7hKgEvaqR7nX1uCwbt1EiMDLTTZDZHDHNrkrmp2GayXc8NQYa3Tzcx9DsW3dVxhgac7dFw1sMQw4WVb7rzg3OJJWtyxMDkUSaVpN+fxbNgBbHQJSl+uMiKNR8hRw7BTpfi1WYTc9NU+JVagmWbPRI8G8OIHM1pmUzjpBFrf+TNQCGh3sI4hHDg0fliGGQdu717AhqSKY1MvfJDwwOr+5y7cg3M4oaMa11azE6zL+/QYjlOz5y1CTfEBns1GvXSPY+O9mKblIT2PSLeNR3Q1U3HxJjrG05+1XnU2VhvbHeU3rBkNqnp9nQLc0+TUIQ0pOr37Sx5+/qOQFffTTYGQMMsezR993Qb8yF55BjwshsSx3MSvEdjrkNtMi3TQu3rJGTKXMzqprEZYU/ssXzXQcLWyo8dDFt7PUKdJn9IbVadVj4D4qxs50Gc/Z7lgYlw1uN65+xiUZdXntrF+noavgrpkeZEtiaZ5yoax4Vdh+wZvIRpx/N40tEDrqaEt3c4fQUGbq+yo5vQdtcKB4yY6uRSxWvC6NEY/5mznQj/RMmyDADNWRrS9IIXHwgDWQELm/G8ooOD4by3K8zu1k5g2Gk7tThNkdkOtGqBaBHTnVyjvT60XPu1CL/dRVcMuuJzMBSnqNg+wq7lebjT5LFLsLbTbbaTYTbyAiyw9GynZqp2OWc8V/+FUPukE9twWpDnTei8wJ7FkmND7MAYYs8FQ3nY7XYPGc0fAjkz/e77Y+PtDWGbRBOwtbACDWVQZ5VB+YY/kHUUC5xviqrQuieJ2MLz8V5WUPMEgwWhIHSoa7IgPnYRGWjOa3fOQoAqXaiVqmXiMqNZaABHVQe5E+NBhoQeUhpQbiTfiVbcgVvnrlcrrkbSCoS9k2vFqTelOtwotoIh8vivrz9PzON+r87QKk4og7MTHigGwLF7tmyz9ox76INrtbNKJzmiCxiOLBpm/fc25UilxxqdF7H9/nyjvgylIXhF22S4agXmUBbSeFQf9O+MHsKRbEgouMU3x9FcGlLL+NWRY0cG0L/CcfDb+hjXcrzXZ+Giu/8A</diagram></mxfile>

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 38 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 83 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 269 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 86 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 124 KiB

View File

@@ -269,7 +269,6 @@ ESP32S2_DOCS = (
'hw-reference/esp32s2/**',
'api-guides/usb-console.rst',
'api-reference/peripherals/ds.rst',
'api-reference/peripherals/touch_element.rst',
'api-guides/RF_calibration.rst',
'api-guides/phy.rst',
]
@@ -284,7 +283,6 @@ ESP32S3_DOCS = (
'api-reference/system/ipc.rst',
'api-guides/flash_psram_config.rst',
'api-reference/peripherals/sd_pullup_requirements.rst',
'api-reference/peripherals/touch_element.rst',
'api-guides/RF_calibration.rst',
'api-guides/phy.rst',
]

View File

@@ -5,10 +5,6 @@ INPUT += \
$(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/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.h \
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_button.h \
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_element.h \
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_matrix.h \
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_slider.h \
$(PROJECT_PATH)/components/usb/include/usb/usb_helpers.h \
$(PROJECT_PATH)/components/usb/include/usb/usb_host.h \
$(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \

View File

@@ -4,10 +4,6 @@ INPUT += \
$(PROJECT_PATH)/components/esp_driver_touch_sens/hw_ver2/include/driver/touch_version_types.h \
$(PROJECT_PATH)/components/esp_lcd/rgb/include/esp_lcd_panel_rgb.h \
$(PROJECT_PATH)/components/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.h \
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_button.h \
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_element.h \
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_matrix.h \
$(PROJECT_PATH)/components/touch_element/include/touch_element/touch_slider.h \
$(PROJECT_PATH)/components/usb/include/usb/usb_helpers.h \
$(PROJECT_PATH)/components/usb/include/usb/usb_host.h \
$(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \

View File

@@ -44,7 +44,6 @@ Peripherals API
:SOC_LP_VAD_SUPPORTED: vad
:SOC_TEMP_SENSOR_SUPPORTED: temp_sensor
:SOC_TOUCH_SENSOR_SUPPORTED: cap_touch_sens
:esp32s2 or esp32s3: touch_element
:SOC_TWAI_SUPPORTED: twai
uart
:SOC_USB_OTG_SUPPORTED: usb_device

View File

@@ -1,486 +0,0 @@
Touch Element
=============
:link_to_translation:`zh_CN:[中文]`
Overview
--------
The Touch Element Library is a highly abstracted element library designed on the basis of the touch sensor driver. The library provides a unified and user-friendly software interface to quickly build capacitive touch sensor applications.
.. warning::
The Touch Element Library currently is still based on the legacy touch driver. Please refer to the :doc:`new driver of Capacitive Touch Sensor </api-reference/peripherals/cap_touch_sens>` if you don't need the Touch Element Library.
Architecture
^^^^^^^^^^^^
The Touch Element library configures touch sensor peripherals via the touch sensor driver. However, some necessary hardware parameters should be passed to :cpp:func:`touch_element_install` and will be configured automatically only after calling :cpp:func:`touch_element_start`. This sequential order is essential because configuring these parameters has a significant impact on the run-time system. Therefore, they must be configured after calling the start function to ensure the system functions properly.
These parameters include touch channel threshold, driver-level of waterproof shield sensor, etc. The Touch Element library sets the touch sensor interrupt and the esp_timer routine up, and the hardware information of the touch sensor (channel state, channel number) will be obtained in the touch sensor interrupt service routine. When the specified channel event occurs, the hardware information is passed to the esp_timer callback routine, which then dispatches the touch sensor channel information to the touch elements (such as button, slider, etc.). The library then runs a specified algorithm to update the touch element's state or calculate its position and dispatches the result accordingly.
So when using the Touch Element library, you are relieved from the implementation details of the touch sensor peripheral. The library handles most of the hardware information and passes the more meaningful messages to the event handler routine.
The workflow of the Touch Element library is illustrated in the picture below.
.. figure:: /../_static/touch_element/te_architecture.svg
:scale: 100 %
:align: center
Touch Element architecture
The features in relation to the Touch Element library in {IDF_TARGET_NAME} are given in the table below.
.. list-table::
:header-rows: 1
:widths: 70 30
:align: center
* - Features
- {IDF_TARGET_NAME}
* - Touch Element waterproof
- ✔
* - Touch Element button
- ✔
* - Touch Element slider
- ✔
* - Touch Element matrix button
- ✔
Peripheral
^^^^^^^^^^
{IDF_TARGET_NAME} integrates one touch sensor peripheral with several physical channels.
.. only:: esp32s2 or esp32s3
- 14 physical capacitive touch channels
- Timer or software FSM trigger mode
- Up to 5 kinds of interrupt (Upper threshold and lower threshold interrupt, measure one channel finish and measure all channels finish interrupt, measurement timeout interrupt)
- Sleep mode wakeup source
- Hardware internal de-noise
- Hardware filter
- Hardware waterproof sensor
- Hardware proximity sensor
The channels are located as follows:
.. list-table::
:header-rows: 1
:widths: 50 50
:align: center
* - Channel
- {IDF_TARGET_NAME}
* - **Channel 0**
- **GPIO 0 (reserved)**
* - **Channel 1**
- **GPIO 1**
* - **Channel 2**
- **GPIO 2**
* - **Channel 3**
- **GPIO 3**
* - **Channel 4**
- **GPIO 4**
* - **Channel 5**
- **GPIO 5**
* - **Channel 6**
- **GPIO 6**
* - **Channel 7**
- **GPIO 7**
* - **Channel 8**
- **GPIO 8**
* - **Channel 9**
- **GPIO 9**
* - **Channel 10**
- **GPIO 10**
* - **Channel 11**
- **GPIO 11**
* - **Channel 12**
- **GPIO 12**
* - **Channel 13**
- **GPIO 13**
* - **Channel 14**
- **GPIO 14**
.. only:: esp32
- 10 physical capacitive touch channels
- Timer or software FSM trigger mode
- 2 kinds of interrupt (Greater than the threshold and less than the threshold)
- Sleep mode wakeup source
The channels are located as follows:
.. list-table::
:header-rows: 1
:widths: 50 50
:align: center
* - Channel
- {IDF_TARGET_NAME}
* - **Channel 0**
- **GPIO 0 (effective)**
* - **Channel 1**
- **GPIO 1**
* - **Channel 2**
- **GPIO 2**
* - **Channel 3**
- **GPIO 3**
* - **Channel 4**
- **GPIO 4**
* - **Channel 5**
- **GPIO 5**
* - **Channel 6**
- **GPIO 6**
* - **Channel 7**
- **GPIO 7**
* - **Channel 8**
- **GPIO 8**
* - **Channel 9**
- **GPIO 9**
Terminology
-----------
The terms used in relation to the Touch Element library are given below.
.. list-table::
:header-rows: 1
:widths: 50 50
:align: center
* - Term
- Definition
* - **Touch sensor**
- Touch sensor peripheral inside the chip
* - **Touch channel**
- Touch sensor channels inside the touch sensor peripheral
* - **Touch pad**
- Off-chip physical solder pad, generally inside the PCB
* - **De-noise channel**
- Internal de-noise channel, which is always Channel 0 and is reserved
* - **Shield sensor**
- One of the waterproof sensors for detecting droplets in small areas and compensating for the influence of water drops on measurements
* - **Guard sensor**
- One of the waterproof sensors for detecting extensive wading and to temporarily disable the touch sensor
* - **Shield channel**
- The channel that waterproof shield sensor connected to, which is always Channel 14
* - **Guard channel**
- The channel that waterproof guard sensor connected to
* - **Shield pad**
- Off-chip physical solder pad, generally is grids, and is connected to shield the sensor
* - **Guard pad**
- Off-chip physical solder pad, usually a ring, and is connected to the guard sensor
.. figure:: /../_static/touch_element/te_component.svg
:scale: 100 %
:align: center
Touch sensor application system components
Touch Sensor Signal
^^^^^^^^^^^^^^^^^^^
Each touch sensor is able to provide the following types of signals:
- Raw: The Raw signal is the unfiltered signal from the touch sensor.
- Smooth: The Smooth signal is a filtered version of the Raw signal via an internal hardware filter.
- Benchmark: The Benchmark signal is also a filtered signal that filters out extremely low-frequency noise.
All of these signals can be obtained using touch sensor driver API.
.. figure:: /../_static/touch_element/te_signal.png
:scale: 40 %
:align: center
Touch sensor signals
Touch Sensor Signal Threshold
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The Touch Sensor Threshold value is a configurable threshold value used to determine when a touch sensor is touched or not. When the difference between the Smooth signal and the Benchmark signal becomes greater than the threshold value (i.e., ``(smooth - benchmark) > threshold``), the touch channel's state will be changed and a touch interrupt will be triggered simultaneously.
.. figure:: /../_static/touch_element/te_threshold.svg
:scale: 40 %
:align: center
Touch sensor signal threshold
Sensitivity
^^^^^^^^^^^
Important performance parameter of the touch sensor, the larger it is, the better touch the sensor performs. It could be calculated by the format below:
.. math::
Sensitivity = \frac{Signal_{press} - Signal_{release}}{Signal_{release}} = \frac{Signal_{delta}}{Signal_{benchmark}}
Waterproof
^^^^^^^^^^
Waterproof is the hardware feature of a touch sensor which has a guard sensor and shield sensor (always connect to Channel 14) that has the ability to resist a degree of influence of water drop and detect the water stream.
Touch Button
^^^^^^^^^^^^
The touch button consumes one channel of the touch sensor, and it looks like as the picture below:
.. figure:: /../_static/touch_element/te_button.svg
:scale: 100 %
:align: center
Touch button
Touch Slider
^^^^^^^^^^^^
The touch slider consumes several channels (at least three channels) of the touch sensor, the more channels consumed, the higher resolution and accuracy position it performs. The touch slider looks like as the picture below:
.. figure:: /../_static/touch_element/te_slider.svg
:scale: 100 %
:align: center
Touch slider
Touch Matrix
^^^^^^^^^^^^
The touch matrix button consumes several channels (at least 2 + 2 = 4 channels), and it gives a solution to use fewer channels and get more buttons. {IDF_TARGET_NAME} supports up to 49 buttons. The touch matrix button looks like as the picture below:
.. figure:: /../_static/touch_element/te_matrix.svg
:scale: 100 %
:align: center
Touch matrix
Touch Element Library Usage
---------------------------
Using this library should follow the initialization flow below:
1. To initialize the Touch Element library by calling :cpp:func:`touch_element_install`.
2. To initialize touch elements (button/slider etc) by calling :cpp:func:`touch_xxxx_install`.
3. To create a new element instance by calling :cpp:func:`touch_xxxx_create`.
4. To subscribe events by calling :cpp:func:`touch_xxxx_subscribe_event`.
5. To choose a dispatch method by calling :cpp:func:`touch_xxxx_set_dispatch_method` that tells the library how to notify you while the subscribed event occurs.
6. If dispatch by callback, call :cpp:func:`touch_xxxx_set_callback` to set the event handler function.
7. To start the Touch Element library by calling :cpp:func:`touch_element_start`.
8. If dispatch by callback, the callback will be called by the driver core when an event happens, no need to do anything; If dispatch by event task, create an event task and call :cpp:func:`touch_element_message_receive` to obtain messages in a loop.
9. (Optional) If you want to suspend the Touch Element run-time system or for some reason that could not obtain the touch element message, :cpp:func:`touch_element_stop` should be called to suspend the Touch Element system and then resume it by calling :cpp:func:`touch_element_start` again.
In code, the flow above may look like as follows:
.. code-block:: c
static touch_xxx_handle_t element_handle; //Declare a touch element handle
//Define the subscribed event handler
void event_handler(touch_xxx_handle_t out_handle, touch_xxx_message_t out_message, void *arg)
{
//Event handler logic
}
void app_main()
{
//Using the default initializer to config Touch Element library
touch_elem_global_config_t global_config = TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG();
touch_element_install(&global_config);
//Using the default initializer to config Touch elements
touch_xxx_global_config_t elem_global_config = TOUCH_XXXX_GLOBAL_DEFAULT_CONFIG();
touch_xxx_install(&elem_global_config);
//Create a new instance
touch_xxx_config_t element_config = {
...
...
};
touch_xxx_create(&element_config, &element_handle);
//Subscribe the specified events by using the event mask
touch_xxx_subscribe_event(element_handle, TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE, NULL);
//Choose CALLBACK as the dispatch method
touch_xxx_set_dispatch_method(element_handle, TOUCH_ELEM_DISP_CALLBACK);
//Register the callback routine
touch_xxx_set_callback(element_handle, event_handler);
//Start Touch Element library processing
touch_element_start();
}
Initialization
^^^^^^^^^^^^^^
1. To initialize the Touch Element library, you have to configure the touch sensor peripheral and Touch Element library by calling :cpp:func:`touch_element_install` with :cpp:type:`touch_elem_global_config_t`, the default initializer is available in :cpp:func:`TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG` and this default configuration is suitable for the most general application scene, and it is suggested not to change the default configuration before fully understanding Touch Sensor peripheral because some changes might bring several impacts to the system.
2. To initialize the specified element, all the elements will not work before its constructor :cpp:func:`touch_xxxx_install` is called so as to save memory, so you have to call the constructor of each used touch element respectively, to set up the specified element.
Touch Element Instance Startup
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1. To create a new touch element instance, call :cpp:func:`touch_xxxx_create`, select a channel, and provide its `Sensitivity`_ value for the new element instance.
2. To subscribe to events, call :cpp:func:`touch_xxxx_subscribe_event`. The Touch Element library offers several events, and the event mask is available in :idf_file:`components/touch_element/include/touch_element/touch_element.h`. You can use these event masks to subscribe to specific events individually or combine them to subscribe to multiple events.
3. To configure the dispatch method, use :cpp:func:`touch_xxxx_set_dispatch_method`. The Touch Element library provides two dispatch methods: :cpp:enumerator:`TOUCH_ELEM_DISP_EVENT` and :cpp:enumerator:`TOUCH_ELEM_DISP_CALLBACK`. These methods allow you to obtain the touch element message and handle it using different approaches.
Events Processing
^^^^^^^^^^^^^^^^^
If :cpp:enumerator:`TOUCH_ELEM_DISP_EVENT` dispatch method is configured, you need to start up an event handler task to obtain the touch element message, all the elements' raw message could be obtained by calling :cpp:func:`touch_element_message_receive`, then extract the element-class-specific message by calling the corresponding message decoder with :cpp:func:`touch_xxxx_get_message` to get the touch element's extracted message; If :cpp:enumerator:`TOUCH_ELEM_DISP_CALLBACK` dispatch method is configured, you need to pass an event handler by calling :cpp:func:`touch_xxxx_set_callback` before the touch element starts working, all the element's extracted message will be passed to the event handler function.
.. warning::
Since the event handler function runs on the core of the element library, i.e., in the esp_timer callback routine, please avoid performing operations that may cause blocking or delays, such as calling :cpp:func:`vTaskDelay`.
In code, the events handle procedure may look like as follows:
.. code-block:: c
/* ---------------------------------------------- TOUCH_ELEM_DISP_EVENT ----------------------------------------------- */
void element_handler_task(void *arg)
{
touch_elem_message_t element_message;
while(1) {
if (touch_element_message_receive(&element_message, Timeout) == ESP_OK) {
const touch_xxxx_message_t *extracted_message = touch_xxxx_get_message(&element_message); //Decode message
... //Event handler logic
}
}
}
void app_main()
{
...
touch_xxxx_set_dispatch_method(element_handle, TOUCH_ELEM_DISP_EVENT); //Set TOUCH_ELEM_DISP_EVENT as the dispatch method
xTaskCreate(&element_handler_task, "element_handler_task", 2048, NULL, 5, NULL); //Create a handler task
...
}
/* -------------------------------------------------------------------------------------------------------------- */
...
/* ---------------------------------------------- TOUCH_ELEM_DISP_CALLBACK ----------------------------------------------- */
void element_handler(touch_xxxx_handle_t out_handle, touch_xxxx_message_t out_message, void *arg)
{
//Event handler logic
}
void app_main()
{
...
touch_xxxx_set_dispatch_method(element_handle, TOUCH_ELEM_DISP_CALLBACK); //Set TOUCH_ELEM_DISP_CALLBACK as the dispatch method
touch_xxxx_set_callback(element_handle, element_handler); //Register an event handler function
...
}
/* -------------------------------------------------------------------------------------------------------------- */
Waterproof Usage
^^^^^^^^^^^^^^^^
1. The waterproof shield sensor is always-on after Touch Element waterproof is initialized, however, the waterproof guard sensor is optional, hence if the you do not need the guard sensor, ``TOUCH_WATERPROOF_GUARD_NOUSE`` has to be passed to :cpp:func:`touch_element_waterproof_install` by the configuration struct.
2. To associate the touch element with the guard sensor, pass the touch element's handle to the Touch Element waterproof's masked list by calling :cpp:func:`touch_element_waterproof_add`. By associating a touch element with the Guard sensor, the touch element will be disabled when the guard sensor is triggered by a stream of water so as to protect the touch element.
The Touch Element Waterproof example is available in :example:`peripherals/touch_sensor/touch_element/touch_element_waterproof` directory.
In code, the waterproof configuration may look as follows:
.. code-block:: c
void app_main()
{
...
touch_xxxx_install(); //Initialize instance (button, slider, etc)
touch_xxxx_create(&element_handle); //Create a new Touch element
...
touch_element_waterproof_install(); //Initialize Touch Element waterproof
touch_element_waterproof_add(element_handle); //Let an element associate with the guard sensor
...
}
Wakeup from Light/Deep-sleep Mode
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Only Touch Button can be configured as a wake-up source.
Light- or Deep-sleep modes are both supported to be wakened up by a touch sensor. For the Light-sleep mode, any installed touch button can wake it up. But only the sleep button can wake up from Deep-sleep mode, and the touch sensor will do a calibration immediately, the reference value will be calibrated to a wrong value if our finger does not remove timely. Though the wrong reference value recovers after the finger removes away and has no effect on the driver logic, if you do not want to see a wrong reference value while waking up from Deep-sleep mode, you can call :cpp:func:`touch_element_sleep_enable_wakeup_calibration` to disable the wakeup calibration.
.. code-block:: c
void app_main()
{
...
touch_element_install();
touch_button_install(); //Initialize the touch button
touch_button_create(&element_handle); //Create a new Touch element
...
// ESP_ERROR_CHECK(touch_element_enable_light_sleep(&sleep_config));
ESP_ERROR_CHECK(touch_element_enable_deep_sleep(button_handle[0], &sleep_config));
// ESP_ERROR_CHECK(touch_element_sleep_enable_wakeup_calibration(button_handle[0], false)); // (optional) Disable wakeup calibration to prevent updating the benchmark to a wrong value
touch_element_start();
...
}
Application Examples
--------------------
- :example:`peripherals/touch_sensor/touch_element/touch_element_waterproof` demonstrates how to use the Touch Element library to set up capacitive touch sensors with waterproof protection.
- :example:`peripherals/touch_sensor/touch_element/touch_slider` demonstrates how to use the Touch Element library to set up and operate a touch slider.
- :example:`peripherals/touch_sensor/touch_element/touch_elements_combination` demonstrates how to use the Touch Element library to set up multiple types of touch elements and handle all the event messages in one task.
- :example:`peripherals/touch_sensor/touch_element/touch_matrix` demonstrates how to use the Touch Element library to set up and use a touch matrix with a capacitive touch sensor on {IDF_TARGET_NAME} development boards.
- :example:`peripherals/touch_sensor/touch_element/touch_button` demonstrates how to use the Touch Element library to set up and use a touch button on {IDF_TARGET_NAME} development boards.
API Reference - Touch Element Core
----------------------------------
.. include-build-file:: inc/touch_element.inc
API Reference - Touch Button
----------------------------------
.. include-build-file:: inc/touch_button.inc
API Reference - Touch Slider
----------------------------------
.. include-build-file:: inc/touch_slider.inc
API Reference - Touch Matrix
----------------------------------
.. include-build-file:: inc/touch_matrix.inc

View File

@@ -178,3 +178,10 @@ To enable SPI master IRAM optimization:
4. Enable ``Place transmitting functions of SPI master into IRAM`` (:ref:`CONFIG_SPI_MASTER_IN_IRAM`)
Note that enabling :ref:`CONFIG_FREERTOS_IN_IRAM` will increase IRAM usage. Consider this trade-off when optimizing for SPI performance.
Touch Element
-------------
The ``touch_element`` component is moved to [ESP Component Registry](https://components.espressif.com/components/espressif/touch_element/versions/1.0.0/readme).
You can add this dependency to your project by running ``idf.py add-dependency "espressif/touch_element"``.

View File

@@ -81,6 +81,7 @@ api-reference/system/system api-reference/system/misc_system
api-reference/protocols/esp_spi_slave_protocol "https://espressif.github.io/idf-extra-components/latest/esp_serial_slave_link/spi_slave_hd_protocol.html"
api-reference/protocols/esp_sdio_slave_protocol "https://espressif.github.io/idf-extra-components/latest/esp_serial_slave_link/sdio_slave_protocol.html"
api-reference/protocols/esp_serial_slave_link "https://espressif.github.io/idf-extra-components/latest/esp_serial_slave_link/index.html"
api-reference/peripherals/touch_element "https://espressif.github.io/idf-extra-components/latest/touch_element/index.html"
# Driver-NG refactor
api-reference/peripherals/timer api-reference/peripherals/gptimer

View File

@@ -44,7 +44,6 @@
:SOC_JPEG_CODEC_SUPPORTED: jpeg
:SOC_TEMP_SENSOR_SUPPORTED: temp_sensor
:SOC_TOUCH_SENSOR_SUPPORTED: cap_touch_sens
:esp32s2 or esp32s3: touch_element
:SOC_TWAI_SUPPORTED: twai
uart
:SOC_USB_OTG_SUPPORTED: usb_device

View File

@@ -1,486 +0,0 @@
触摸元件
=============
:link_to_translation:`en:[English]`
概述
--------
触摸元件库是基于触摸传感器驱动设计的高度抽象的元件库,该库提供了统一且友好的软件接口,可以快速构建电容式触摸传感器的应用。
.. warning::
目前的触摸元件库仍然基于旧的触摸传感器驱动。如您不需要使用触摸元件库,请参考新的 :doc:`电容式触摸传感器 </api-reference/peripherals/cap_touch_sens>` 驱动。
架构
^^^^^^^^^^^^
触摸元件库通过触摸传感器驱动程序配置触摸传感器外设。使用时,部分必要的硬件参数需要传递给函数 :cpp:func:`touch_element_install`,但只有在调用 :cpp:func:`touch_element_start` 函数后,才会自动配置这些参数。这些参数配置会对实时系统产生很大的影响,因此步骤顺序很重要,必须在调用启动函数之后进行配置,确保系统正常运行。
上述参数包括触摸通道阈值、防水屏蔽传感器驱动级别等。触摸元件库会设置触摸传感器中断和 esp_timer 例程,并在触摸传感器中断服务例程中获取触摸传感器的硬件信息(通道状态、通道编号)。当特定通道事件发生时,硬件信息将传递给 esp_timer 回调例程esp_timer 回调例程将触摸传感器通道信息分配给触摸元件(例如按键、滑条等)。随后,触摸元件库运行特定算法,更新触摸元件状态或计算其位置,并将结果分派给相应的处理程序。
因此,在使用触摸元件库时,你无需关注触摸传感器外设的工作细节,该库会处理大部分硬件信息,并将更有意义的信息传递给事件处理程序。
下图展示了触摸元件库的工作流程。
.. figure:: /../_static/touch_element/te_architecture.svg
:scale: 100 %
:align: center
触摸元件库架构
下表展示了 {IDF_TARGET_NAME} 中与触摸元件库有关的功能。
.. list-table::
:header-rows: 1
:widths: 70 30
:align: center
* - 功能
- {IDF_TARGET_NAME}
* - 防水
- ✔
* - 按键
- ✔
* - 触摸滑条
- ✔
* - 矩阵按键
- ✔
外设
^^^^^^^^^^
{IDF_TARGET_NAME} 集成了一个触摸传感器外设,具有多个物理通道。
.. only:: esp32s2 or esp32s3
- 14 个物理电容触摸通道
- 定时器或软件 FSM 触发模式
- 高达 5 种中断(高阈值和低阈值中断、测量单通道完成和测量所有通道完成中断、测量超时中断)
- 睡眠模式唤醒源
- 硬件内置降噪
- 硬件滤波器
- 硬件防水传感器
- 硬件近场感应传感器
这些通道的具体位置如下:
.. list-table::
:header-rows: 1
:widths: 50 50
:align: center
* - 通道
- {IDF_TARGET_NAME}
* - **通道 0**
- **GPIO 0保留**
* - **通道 1**
- **GPIO 1**
* - **通道 2**
- **GPIO 2**
* - **通道 3**
- **GPIO 3**
* - **通道 4**
- **GPIO 4**
* - **通道 5**
- **GPIO 5**
* - **通道 6**
- **GPIO 6**
* - **通道 7**
- **GPIO 7**
* - **通道 8**
- **GPIO 8**
* - **通道 9**
- **GPIO 9**
* - **通道 10**
- **GPIO 10**
* - **通道 11**
- **GPIO 11**
* - **通道 12**
- **GPIO 12**
* - **通道 13**
- **GPIO 13**
* - **通道 14**
- **GPIO 14**
.. only:: esp32
- 10 个物理电容触摸通道
- 定时器或软件 FSM 触发模式
- 2 种中断(超过阈值和低于阈值中断)
- 睡眠模式唤醒源
这些通道的具体位置如下:
.. list-table::
:header-rows: 1
:widths: 50 50
:align: center
* - 通道
- {IDF_TARGET_NAME}
* - **通道 0**
- **GPIO 0有效**
* - **通道 1**
- **GPIO 1**
* - **通道 2**
- **GPIO 2**
* - **通道 3**
- **GPIO 3**
* - **通道 4**
- **GPIO 4**
* - **通道 5**
- **GPIO 5**
* - **通道 6**
- **GPIO 6**
* - **通道 7**
- **GPIO 7**
* - **通道 8**
- **GPIO 8**
* - **通道 9**
- **GPIO 9**
术语
-----------
触摸元件库的有关术语如下:
.. list-table::
:header-rows: 1
:widths: 50 50
:align: center
* - 术语
- 定义
* - **触摸传感器 (touch sensor)**
- 芯片内部的触摸传感器外设
* - **触摸通道 (touch channel)**
- 触摸传感器外设内的触摸通道
* - **触摸焊盘 (touch pad)**
- 外部物理触摸焊盘,通常位于 PCB 内部
* - **降噪通道 (de-noise channel)**
- 内部降噪通道,始终为通道 0 且已预留
* - **屏蔽传感器 (shield sensor)**
- 防水传感器之一,用于小面积的水滴检测,并补偿水滴对读数的影响
* - **防护传感器 (guard sensor)**
- 防水传感器之一,用于大面积的涉水检测,并临时禁用触摸传感器
* - **屏蔽通道 (shield channel)**
- 防水屏蔽传感器连接的通道,始终为通道 14
* - **防护通道 (guard channel)**
- 防水防护传感器连接的通道
* - **屏蔽焊盘 (shield pad)**
- 外部物理屏蔽焊盘,通常是网格状,与防水传感器相连
* - **防护焊盘 (guard pad)**
- 外部物理防护焊盘,通常是环状,与防护传感器相连
.. figure:: /../_static/touch_element/te_component.svg
:scale: 100 %
:align: center
触摸传感器应用程序系统组件
触摸传感器信号
^^^^^^^^^^^^^^^^^^^
触摸传感器可提供以下信号:
- 原始信号:从触摸传感器获取、未经滤波的信号。
- 平滑信号:原始信号通过内部硬件滤波器滤波后的信号。
- 基准信号:经过滤波的信号,已过滤极低频噪声。
以上信号均可通过触摸传感器驱动程序 API 获取。
.. figure:: /../_static/touch_element/te_signal.png
:scale: 40 %
:align: center
触摸传感器信号
触摸传感器信号阈值
^^^^^^^^^^^^^^^^^^^^^^
触摸传感器阈值支持重新配置,可用于确定触摸传感器状态。当平滑信号和基准信号间的差值大于阈值,即 ``(平滑信号 - 基准信号)> 信号阈值`` 时,触摸通道状态改变,并触发触摸中断。
.. figure:: /../_static/touch_element/te_threshold.svg
:scale: 40 %
:align: center
触摸传感器信号阈值
灵敏度
^^^^^^^^^^^^^^^^
触摸传感器的一个重要性能参数,该值越大,表明触摸传感器越灵敏。可以通过以下公式计算:
.. math::
Sensitivity = \frac{Signal_{press} - Signal_{release}}{Signal_{release}} = \frac{Signal_{delta}}{Signal_{benchmark}}
防水性能
^^^^^^^^^^^^^^^^^^
防水性能是触摸传感器的硬件功能,包括防护传感器和屏蔽传感器(始终连接到通道 14可以抵御一定程度的水滴影响并检测水流。
触摸按键
^^^^^^^^^^^^^^^^^^
触摸按键占用触摸传感器的一个通道,外观如下图所示:
.. figure:: /../_static/touch_element/te_button.svg
:scale: 100 %
:align: center
触摸按键
触摸滑条
^^^^^^^^^^^^^^^^^^
触摸滑条占用触摸传感器的多个通道(至少三个),占用的通道越多,滑条的采样分辨率和准确度越高。触摸滑条外观如下图所示:
.. figure:: /../_static/touch_element/te_slider.svg
:scale: 100 %
:align: center
触摸滑条
触摸矩阵
^^^^^^^^^^^^^^^^^^
触摸矩阵按键占用触摸传感器的多个通道(至少 2 + 2 = 4 个通道),它支持通过较少通道获取更多按键。{IDF_TARGET_NAME} 最多支持 49 个按键。触摸矩阵按键外观如下图所示:
.. figure:: /../_static/touch_element/te_matrix.svg
:scale: 100 %
:align: center
触摸矩阵
使用触摸元件库
--------------
使用触摸元件库时,请遵循以下初始化流程:
1. 调用 :cpp:func:`touch_element_install`,初始化触摸元件库。
2. 调用 :cpp:func:`touch_xxxx_install`,初始化触摸元件(按键、滑条等)。
3. 调用 :cpp:func:`touch_xxxx_create`,创建新元件实例。
4. 调用 :cpp:func:`touch_xxxx_subscribe_event`,订阅事件通知。
5. 调用 :cpp:func:`touch_xxxx_set_dispatch_method`,选择事件通知的传递方式。
6. 选择使用回调函数传递事件通知时,调用 :cpp:func:`touch_xxxx_set_callback`,设置事件处理函数。
7. 调用 :cpp:func:`touch_element_start`,启用触摸元件库。
8. 选择使用回调函数传递事件通知时,若事件发生,驱动核心会调用回调函数,你无需做任何处理;选择使用事件任务传递事件通知时,你需要创建一个事件任务,并调用 :cpp:func:`touch_element_message_receive`,循环获取信息。
9. (可选)如果要暂停触摸元件的实时系统,或因某种原因无法获取触摸元件信息,应调用 :cpp:func:`touch_element_stop`,暂停触摸元件系统,然后再次调用 :cpp:func:`touch_element_start` 恢复系统。
上述流程代码如下所示:
.. code-block:: c
static touch_xxx_handle_t element_handle; //声明一个触摸元件句柄
//定义订阅的事件处理函数
void event_handler(touch_xxx_handle_t out_handle, touch_xxx_message_t out_message, void *arg)
{
//事件处理逻辑
}
void app_main()
{
//使用默认初始化器配置触摸元件库
touch_elem_global_config_t global_config = TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG();
touch_element_install(&global_config);
//使用默认初始化器配置触摸元件
touch_xxx_global_config_t elem_global_config = TOUCH_XXXX_GLOBAL_DEFAULT_CONFIG();
touch_xxx_install(&elem_global_config);
//创建新的实例
touch_xxx_config_t element_config = {
...
...
};
touch_xxx_create(&element_config, &element_handle);
//通过事件掩码订阅特定事件
touch_xxx_subscribe_event(element_handle, TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE, NULL);
//选择使用回调函数传递事件通知
touch_xxx_set_dispatch_method(element_handle, TOUCH_ELEM_DISP_CALLBACK);
//注册回调函数
touch_xxx_set_callback(element_handle, event_handler);
//启用触摸元件库处理
touch_element_start();
}
初始化
^^^^^^^^^^^^^^
1. 要初始化触摸元件库,请调用 :cpp:func:`touch_element_install` 函数,并传递一个 :cpp:type:`touch_elem_global_config_t` 类型的实例作为参数,以配置触摸传感器外设和触摸元件库。默认初始化器位于 :cpp:func:`TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG` 中,此默认配置适用于多数常见应用场景。建议在充分了解触摸传感器外设前,不要更改默认配置,以免影响系统。
2. 要初始化特定的触摸元件,需要调用其构造函数 :cpp:func:`touch_xxxx_install`。在调用此构造函数前,所有触摸元件都不会工作,以节省内存。因此,若要设置所需元件,需要为每个要使用的触摸元件分别调用构造函数。
启动触摸元件实例
^^^^^^^^^^^^^^^^
1. 要创建新的触摸元件实例,请调用 :cpp:func:`touch_xxxx_create`,选择一个通道,并将其 `灵敏度`_ 传递给新的元件实例。
2. 要订阅事件通知,请调用 :cpp:func:`touch_xxxx_subscribe_event`。触摸元件库提供了多个事件,事件掩码存放在 :idf_file:`components/touch_element/include/touch_element/touch_element.h` 中。通过使用这些事件掩码,可以订阅单个特定事件,或将单个事件组合在一起,订阅多个事件。
3. 要配置传递事件通知的方式,请调用 :cpp:func:`touch_xxxx_subscribe_event`。触摸元件库提供了两种方式: :cpp:enumerator:`TOUCH_ELEM_DISP_EVENT`:cpp:enumerator:`TOUCH_ELEM_DISP_CALLBACK`,支持以不同方式获取并处理触摸元件信息。
事件处理
^^^^^^^^^^^^^^^^^
如果配置的是 :cpp:enumerator:`TOUCH_ELEM_DISP_EVENT`,需要启用一个事件处理任务获取触摸元件信息。调用 :cpp:func:`touch_element_message_receive` 可以获取所有元件的原始信息,随后通过调用相应的信息解码器 :cpp:func:`touch_xxxx_get_message`,提取特定类型元件的信息,获取有关触摸操作的详细数据。如果配置的是 :cpp:enumerator:`TOUCH_ELEM_DISP_CALLBACK`,在触摸元件开始工作之前,需要调用 :cpp:func:`touch_xxxx_set_callback`,传递一个事件处理函数,有关触摸操作的详细数据都会传递到该事件处理函数。
.. warning::
由于事件处理函数在元件库的核心运行,即在 esp-timer 回调中运行,请避免执行可能导致阻塞或延迟的操作,如调用 :cpp:func:`vTaskDelay`
事件处理过程代码如下所示:
.. code-block:: c
/* ---------------------------------------------- TOUCH_ELEM_DISP_EVENT ----------------------------------------------- */
void element_handler_task(void *arg)
{
touch_elem_message_t element_message;
while(1) {
if (touch_element_message_receive(&element_message, Timeout) == ESP_OK) {
const touch_xxxx_message_t *extracted_message = touch_xxxx_get_message(&element_message); //信息解码
... //事件处理逻辑
}
}
}
void app_main()
{
...
touch_xxxx_set_dispatch_method(element_handle, TOUCH_ELEM_DISP_EVENT); //设置以 TOUCH_ELEM_DISP_EVENT 传递事件通知
xTaskCreate(&element_handler_task, "element_handler_task", 2048, NULL, 5, NULL); //创建一个事件处理任务
...
}
/* -------------------------------------------------------------------------------------------------------------- */
...
/* ---------------------------------------------- TOUCH_ELEM_DISP_CALLBACK ----------------------------------------------- */
void element_handler(touch_xxxx_handle_t out_handle, touch_xxxx_message_t out_message, void *arg)
{
//事件处理逻辑
}
void app_main()
{
...
touch_xxxx_set_dispatch_method(element_handle, TOUCH_ELEM_DISP_CALLBACK); //设置以 ``TOUCH_ELEM_DISP_CALLBACK`` 传递事件通知
touch_xxxx_set_callback(element_handle, element_handler); //注册事件处理函数
...
}
/* -------------------------------------------------------------------------------------------------------------- */
使用防水功能
^^^^^^^^^^^^^^^^
1. 一旦初始化触摸元件的防水功能,防水屏蔽传感器会始终处于开启状态。防水屏蔽传感器为可选项,如果不需要,可以通过配置结构体,将 ``TOUCH_WATERPROOF_GUARD_NOUSE`` 传递给 :cpp:func:`touch_element_waterproof_install`
2. 要关联触摸元件与防护传感器,请调用 :cpp:func:`touch_element_waterproof_add`,将触摸元件句柄添加到触摸元件防水功能的掩码列表中。触摸元件与防护传感器关联后,水流触发防护传感器时会关闭触摸元件,为其提供保护。
查看使用触摸元件防水功能的示例代码,请前往 ESP-IDF 示例的 :example:`peripherals/touch_sensor/touch_element/touch_element_waterproof` 目录。
配置防水功能的代码如下所示:
.. code-block:: c
void app_main()
{
...
touch_xxxx_install(); //初始化实例(按键、滑条等)
touch_xxxx_create(&element_handle); //创建新的触摸元件
...
touch_element_waterproof_install(); //初始化触摸元件防水功能
touch_element_waterproof_add(element_handle); //关联触摸元件与防护传感器
...
}
从 Light/Deep-sleep 模式唤醒
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
仅触摸按键可配置为唤醒源。
使用触摸传感器,可以唤醒从 Light-sleep 或 Deep-sleep 模式中唤醒芯片。在 Light-sleep 模式下,任何已安装的触摸按键都可以唤醒芯片。但在 Deep-sleep 模式下,只有睡眠按键可以唤醒芯片,触摸传感器还会立即进行校准。如果手指没有及时离开,可能导致校准参考值出错。尽管在手指离开后,校准参考值会自行恢复,不会影响驱动逻辑,但如果你不想在从 Deep-sleep 模式唤醒时看到错误的校准参考值,可以调用 :cpp:func:`touch_element_sleep_enable_wakeup_calibration`,禁用唤醒校准功能。
.. code-block:: c
void app_main()
{
...
touch_element_install();
touch_button_install(); //初始化触摸按键
touch_button_create(&element_handle); //创建新的触摸元件
...
// ESP_ERROR_CHECK(touch_element_enable_light_sleep(&sleep_config));
ESP_ERROR_CHECK(touch_element_enable_deep_sleep(button_handle[0], &sleep_config));
// ESP_ERROR_CHECK(touch_element_sleep_enable_wakeup_calibration(button_handle[0], false)); //(可选)禁用唤醒校准,防止基准值更新为错误值
touch_element_start();
...
}
应用示例
--------
- :example:`peripherals/touch_sensor/touch_element/touch_element_waterproof` 演示了如何使用触摸元件库来设置带有防水保护的电容式触摸传感器。
- :example:`peripherals/touch_sensor/touch_element/touch_slider` 演示了如何使用触摸元件库来设置和操作触摸滑条。
- :example:`peripherals/touch_sensor/touch_element/touch_elements_combination` 演示了如何使用触摸元件库来设置多种类型的触摸元件,并在一个任务中处理所有的事件消息。
- :example:`peripherals/touch_sensor/touch_element/touch_matrix` 演示了如何通过触摸元件库,在 {IDF_TARGET_NAME} 开发板上使用电容式触摸传感器来构建触摸矩阵。
- :example:`peripherals/touch_sensor/touch_element/touch_button` 演示了如何通过触摸元件库,在 {IDF_TARGET_NAME} 开发板上设置和使用触摸按键。
API 参考 - 触摸元件核心
----------------------------------
.. include-build-file:: inc/touch_element.inc
API 参考 - 触摸按键
----------------------------------
.. include-build-file:: inc/touch_button.inc
API 参考 - 触摸滑条
----------------------------------
.. include-build-file:: inc/touch_slider.inc
API 参考 - 触摸矩阵
----------------------------------
.. include-build-file:: inc/touch_matrix.inc

View File

@@ -178,3 +178,11 @@ SPI
4. 启用 ``Place transmitting functions of SPI master into IRAM`` (:ref:`CONFIG_SPI_MASTER_IN_IRAM`)
请注意,启用 :ref:`CONFIG_FREERTOS_IN_IRAM` 会显著增加 IRAM 使用量。在优化 SPI 性能时,需进行权衡。
Touch Element
-------------
``touch_element`` 组件已移至 [ESP Component Registry](https://components.espressif.com/components/espressif/touch_element/versions/1.0.0/readme)。
您可以通过运行 ``idf.py add-dependency "espressif/touch_element"`` 将这个依赖添加到您的项目中。

View File

@@ -104,7 +104,6 @@ examples/bluetooth/esp_ble_mesh:
- if: CI_COMMIT_REF_NAME == "master" and (NIGHTLY_RUN == 0 and CONFIG_NAME not in ["default", "bluedroid", "nimble"])
depends_components+:
- esp_console
- touch_element
- esp_driver_gpio
depends_components-:
- esp_coex

View File

@@ -486,11 +486,6 @@ examples/peripherals/touch_sensor:
disable:
- if: SOC_TOUCH_SENSOR_SUPPORTED != 1
examples/peripherals/touch_sensor/touch_element:
enable:
- if: IDF_TARGET in ["esp32s2", "esp32s3"]
reason: only supports esp32s2 and esp32s3
examples/peripherals/touch_sensor/touch_sens_basic:
disable:
- if: SOC_TOUCH_SENSOR_SUPPORTED != 1

View File

@@ -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.22)
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_button)

View File

@@ -1,71 +0,0 @@
| Supported Targets | ESP32-S2 | ESP32-S3 |
| ----------------- | -------- | -------- |
# Touch button example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use the Touch Element library of capacitive touch sensor and set up touch button.
## How to use example
### Hardware Required
* A development board with ESP32-S2 or ESP32-S3 chip
* A touch extension board like [esp32-s2-touch-devkit-1](https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32s2/esp32-s2-touch-devkit-1/user_guide.html)
### Configure the project
* Set the target of the build by following command, where TARGET can be `esp32s2` or `esp32s3`.
```
idf.py set-target TARGET
```
* Run `idf.py menuconfig` to select a dispatch method for the example.
### 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
```
I (331) Touch Button Example: Touch element library installed
I (331) Touch Button Example: Touch button installed
I (341) Touch Button Example: Touch buttons created
I (341) Touch Button Example: Touch element library start
I (1481) Touch Button Example: Button[1] Press
I (1701) Touch Button Example: Button[1] Release
I (2731) Touch Button Example: Button[2] Press
I (2921) Touch Button Example: Button[2] Release
I (3581) Touch Button Example: Button[5] Press
I (3781) Touch Button Example: Button[5] Release
I (3931) Touch Button Example: Button[4] Press
I (4121) Touch Button Example: Button[4] Release
I (4271) Touch Button Example: Button[3] Press
I (4491) Touch Button Example: Button[3] Release
I (4671) Touch Button Example: Button[6] Press
I (4891) Touch Button Example: Button[6] Release
I (5091) Touch Button Example: Button[7] Press
I (5311) Touch Button Example: Button[7] Release
I (5491) Touch Button Example: Button[8] Press
I (5741) Touch Button Example: Button[8] Release
I (5991) Touch Button Example: Button[9] Press
I (7991) Touch Button Example: Button[9] LongPress
I (9991) Touch Button Example: Button[9] LongPress
I (11991) Touch Button Example: Button[9] LongPress
I (12881) Touch Button Example: Button[9] Release
```
## 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.

View File

@@ -1,3 +0,0 @@
idf_component_register(SRCS "touch_button_example_main.c"
INCLUDE_DIRS "."
PRIV_REQUIRES touch_element)

View File

@@ -1,15 +0,0 @@
menu "Example Configuration"
choice TOUCH_SENSOR_EXAMPLE_TYPE
bool "Select touch element dispatch method"
default TOUCH_ELEM_EVENT
help
Select touch element dispatch method (event task or callback) for this example.
config TOUCH_ELEM_EVENT
bool "Dispatch by event task"
config TOUCH_ELEM_CALLBACK
bool "Dispatch by callback"
endchoice
endmenu

View File

@@ -1,134 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "touch_element/touch_button.h"
#include "esp_log.h"
static const char *TAG = "Touch Button Example";
#define TOUCH_BUTTON_NUM 14
/* 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_PAD_NUM6,
TOUCH_PAD_NUM7,
TOUCH_PAD_NUM8,
TOUCH_PAD_NUM9,
TOUCH_PAD_NUM10,
TOUCH_PAD_NUM11,
TOUCH_PAD_NUM12,
TOUCH_PAD_NUM13,
TOUCH_PAD_NUM14,
};
/* Touch buttons channel sensitivity array */
static const float channel_sens_array[TOUCH_BUTTON_NUM] = {
0.1F,
0.1F,
0.1F,
0.1F,
0.1F,
0.1F,
0.1F,
0.1F,
0.1F,
0.1F,
0.1F,
0.1F,
0.1F,
0.1F,
};
#ifdef CONFIG_TOUCH_ELEM_EVENT
/* 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[%d] Press", (int)element_message.arg);
} else if (button_message->event == TOUCH_BUTTON_EVT_ON_RELEASE) {
ESP_LOGI(TAG, "Button[%d] Release", (int)element_message.arg);
} else if (button_message->event == TOUCH_BUTTON_EVT_ON_LONGPRESS) {
ESP_LOGI(TAG, "Button[%d] LongPress", (int)element_message.arg);
}
}
}
#elif CONFIG_TOUCH_ELEM_CALLBACK
/* Button callback routine */
static void button_handler(touch_button_handle_t out_handle, touch_button_message_t *out_message, void *arg)
{
(void) out_handle; //Unused
if (out_message->event == TOUCH_BUTTON_EVT_ON_PRESS) {
ESP_LOGI(TAG, "Button[%d] Press", (int)arg);
} else if (out_message->event == TOUCH_BUTTON_EVT_ON_RELEASE) {
ESP_LOGI(TAG, "Button[%d] Release", (int)arg);
} else if (out_message->event == TOUCH_BUTTON_EVT_ON_LONGPRESS) {
ESP_LOGI(TAG, "Button[%d] LongPress", (int)arg);
}
}
#endif
void app_main(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]));
/* 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]));
#ifdef CONFIG_TOUCH_ELEM_EVENT
/* Set EVENT as the dispatch method */
ESP_ERROR_CHECK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_EVENT));
#elif CONFIG_TOUCH_ELEM_CALLBACK
/* Set EVENT as the dispatch method */
ESP_ERROR_CHECK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_CALLBACK));
/* Register a handler function to handle event messages */
ESP_ERROR_CHECK(touch_button_set_callback(button_handle[i], button_handler));
#endif
/* Set LongPress event trigger threshold time */
ESP_ERROR_CHECK(touch_button_set_longpress(button_handle[i], 2000));
}
ESP_LOGI(TAG, "Touch buttons created");
#ifdef CONFIG_TOUCH_ELEM_EVENT
/* Create a handler task to handle event messages */
xTaskCreate(&button_handler_task, "button_handler_task", 4 * 1024, NULL, 5, NULL);
#endif
touch_element_start();
ESP_LOGI(TAG, "Touch element library start");
}

View File

@@ -1,14 +0,0 @@
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
@pytest.mark.generic
@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target'])
def test_touch_button(dut: Dut) -> None:
dut.expect_exact('Touch Button Example: Touch element library installed')
dut.expect_exact('Touch Button Example: Touch button installed')
dut.expect_exact('Touch Button Example: Touch buttons created')
dut.expect_exact('Touch Button Example: Touch element library start')

View File

@@ -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.22)
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_element_waterproof)

View File

@@ -1,59 +0,0 @@
| Supported Targets | ESP32-S2 | ESP32-S3 |
| ----------------- | -------- | -------- |
# Touch Element waterproof Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use the Touch Element library of capacitive Touch Sensor and setup the touch elements with touch element waterproof protection.
## How to use example
### Hardware Required
* A development board with ESP32-S2 or ESP32-S3 chip
* A touch extension board like [esp32-s2-touch-devkit-1](https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32s2/esp32-s2-touch-devkit-1/user_guide.html)
### Configure the project
* Set the target of the build by following command, where TARGET can be `esp32s2` or `esp32s3`.
```
idf.py set-target TARGET
```
* Run `idf.py menuconfig` to select weather to enable waterproof function.
### 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
This example's output maybe could not give a strong feeling to user since the waterproof function works
automatically and silently inside the Touch Element library
```
I (331) Touch Element Waterproof Example: Touch Element library install
I (331) Touch Element Waterproof Example: Touch Element waterproof install
I (341) Touch Element Waterproof Example: Touch button install
I (351) Touch Element Waterproof Example: Touch buttons create
I (3191) Touch Element Waterproof Example: Button[7] Press
I (4191) Touch Element Waterproof Example: Button[7] LongPress
I (5191) Touch Element Waterproof Example: Button[7] LongPress
I (5671) Touch Element Waterproof Example: Button[7] Release
I (12561) Touch Element Waterproof Example: Button[9] Press
I (12811) Touch Element Waterproof Example: Button[9] Release
```
## 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.

View File

@@ -1,3 +0,0 @@
idf_component_register(SRCS "waterproof_example_main.c"
INCLUDE_DIRS "."
PRIV_REQUIRES touch_element)

View File

@@ -1,10 +0,0 @@
menu "Example Configuration"
config TOUCH_WATERPROOF_GUARD_ENABLE
bool "Enable touch sense waterproof guard sensor"
default y
help
This option enables touch sense waterproof guard sensor,
while the shield sensor is not optional.
endmenu

View File

@@ -1,91 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "touch_element/touch_button.h"
static const char *TAG = "Touch Element Waterproof Example";
#define TOUCH_BUTTON_NUM 3
/*< Touch buttons handle */
static touch_button_handle_t button_handle[TOUCH_BUTTON_NUM]; //Button handler
/* Touch buttons channel array */
static const touch_pad_t channel_array[TOUCH_BUTTON_NUM] = {
TOUCH_PAD_NUM7,
TOUCH_PAD_NUM9,
TOUCH_PAD_NUM11,
};
/* Touch buttons channel sensitivity array */
static const float channel_sens_array[TOUCH_BUTTON_NUM] = {
0.15F,
0.15F,
0.15F,
};
static void button_handler_task(void *arg)
{
touch_elem_message_t element_message;
while (1) {
touch_element_message_receive(&element_message, portMAX_DELAY); //Block take
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[%d] Press", (int)element_message.arg);
} else if (button_message->event == TOUCH_BUTTON_EVT_ON_RELEASE) {
ESP_LOGI(TAG, "Button[%d] Release", (int)element_message.arg);
} else if (button_message->event == TOUCH_BUTTON_EVT_ON_LONGPRESS) {
ESP_LOGI(TAG, "Button[%d] LongPress", (int)element_message.arg);
}
}
}
void app_main(void)
{
/*< Initialize Touch Element library */
touch_elem_global_config_t element_global_config = TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG();
ESP_ERROR_CHECK(touch_element_install(&element_global_config));
ESP_LOGI(TAG, "Touch Element library install");
/*< Create and configure touch element waterproof */
touch_elem_waterproof_config_t waterproof_config = {
#ifdef CONFIG_TOUCH_WATERPROOF_GUARD_ENABLE
.guard_channel = TOUCH_PAD_NUM13,
#else
.guard_channel = TOUCH_WATERPROOF_GUARD_NOUSE,
#endif
.guard_sensitivity = 0.05F //The guard sensor sensitivity has to be explored in experiments
};
ESP_ERROR_CHECK(touch_element_waterproof_install(&waterproof_config));
ESP_LOGI(TAG, "Touch Element waterproof install");
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 install");
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 button */
ESP_ERROR_CHECK(touch_button_create(&button_config, &button_handle[i]));
/* Subscribe touch button event(Press, Release, 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]));
/* Button set dispatch method */
ESP_ERROR_CHECK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_EVENT));
#ifdef CONFIG_TOUCH_WATERPROOF_GUARD_ENABLE
/* Add button element into waterproof guard sensor's protection */
ESP_ERROR_CHECK(touch_element_waterproof_add(button_handle[i]));
#endif
}
ESP_LOGI(TAG, "Touch buttons create");
/*< Create a monitor task to take Touch Button event */
xTaskCreate(&button_handler_task, "button_handler_task", 4 * 1024, NULL, 5, NULL);
touch_element_start();
}

View File

@@ -1,14 +0,0 @@
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
@pytest.mark.generic
@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target'])
def test_touch_element_waterproof(dut: Dut) -> None:
dut.expect_exact('Touch Element Waterproof Example: Touch Element library install')
dut.expect_exact('Touch Element Waterproof Example: Touch Element waterproof install')
dut.expect_exact('Touch Element Waterproof Example: Touch button install')
dut.expect_exact('Touch Element Waterproof Example: Touch buttons create')

View File

@@ -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.22)
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_elements_combination)

View File

@@ -1,150 +0,0 @@
| Supported Targets | ESP32-S2 | ESP32-S3 |
| ----------------- | -------- | -------- |
# Touch button example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use the Touch Element library of capacitive touch sensor and set up more than one type of touch elements and handle all the event messages in one task.
## How to use example
### Hardware Required
* A development board with ESP32-S2 or ESP32-S3 chip
* A touch extension board like [esp32-s2-touch-devkit-1](https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32s2/esp32-s2-touch-devkit-1/user_guide.html)
### Configure the project
* Set the target of the build by following command, where TARGET can be `esp32s2` or `esp32s3`.
```
idf.py set-target TARGET
```
### 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
```
I (331) Touch Elements Combination Example: Touch element library installed
I (331) Touch Elements Combination Example: Touch button installed
I (341) Touch Elements Combination Example: Touch buttons created
I (351) Touch Elements Combination Example: Touch slider installed
I (351) Touch Elements Combination Example: Touch slider created
I (361) Touch Elements Combination Example: Touch element library start
I (1841) Touch Elements Combination Example: Button[6] Press
I (1971) Touch Elements Combination Example: Button[6] Release
I (2201) Touch Elements Combination Example: Button[8] Press
I (2351) Touch Elements Combination Example: Button[8] Release
I (2561) Touch Elements Combination Example: Button[10] Press
I (2721) Touch Elements Combination Example: Button[10] Release
I (3431) Touch Elements Combination Example: Slider Press, position: 0
I (3441) Touch Elements Combination Example: Slider Calculate, position: 0
I (3451) Touch Elements Combination Example: Slider Calculate, position: 0
I (3461) Touch Elements Combination Example: Slider Calculate, position: 0
I (3471) Touch Elements Combination Example: Slider Calculate, position: 0
I (3481) Touch Elements Combination Example: Slider Calculate, position: 0
I (3491) Touch Elements Combination Example: Slider Calculate, position: 0
I (3501) Touch Elements Combination Example: Slider Calculate, position: 1
I (3511) Touch Elements Combination Example: Slider Calculate, position: 1
I (3521) Touch Elements Combination Example: Slider Calculate, position: 2
I (3531) Touch Elements Combination Example: Slider Calculate, position: 2
I (3541) Touch Elements Combination Example: Slider Calculate, position: 3
I (3551) Touch Elements Combination Example: Slider Calculate, position: 4
I (3561) Touch Elements Combination Example: Slider Calculate, position: 5
I (3571) Touch Elements Combination Example: Slider Calculate, position: 6
I (3581) Touch Elements Combination Example: Slider Calculate, position: 7
I (3591) Touch Elements Combination Example: Slider Calculate, position: 8
I (3601) Touch Elements Combination Example: Slider Calculate, position: 10
I (3611) Touch Elements Combination Example: Slider Calculate, position: 11
I (3621) Touch Elements Combination Example: Slider Calculate, position: 12
I (3631) Touch Elements Combination Example: Slider Calculate, position: 13
I (3641) Touch Elements Combination Example: Slider Calculate, position: 15
I (3651) Touch Elements Combination Example: Slider Calculate, position: 16
I (3661) Touch Elements Combination Example: Slider Calculate, position: 17
I (3671) Touch Elements Combination Example: Slider Calculate, position: 19
I (3681) Touch Elements Combination Example: Slider Calculate, position: 20
I (3691) Touch Elements Combination Example: Slider Calculate, position: 21
I (3701) Touch Elements Combination Example: Slider Calculate, position: 23
I (3711) Touch Elements Combination Example: Slider Calculate, position: 24
I (3721) Touch Elements Combination Example: Slider Calculate, position: 26
I (3731) Touch Elements Combination Example: Slider Calculate, position: 27
I (3741) Touch Elements Combination Example: Slider Calculate, position: 28
I (3751) Touch Elements Combination Example: Slider Calculate, position: 29
I (3761) Touch Elements Combination Example: Slider Calculate, position: 31
I (3771) Touch Elements Combination Example: Slider Calculate, position: 32
I (3781) Touch Elements Combination Example: Slider Calculate, position: 33
I (3791) Touch Elements Combination Example: Slider Calculate, position: 34
I (3801) Touch Elements Combination Example: Slider Calculate, position: 36
I (3811) Touch Elements Combination Example: Slider Calculate, position: 37
I (3821) Touch Elements Combination Example: Slider Calculate, position: 38
I (3831) Touch Elements Combination Example: Slider Calculate, position: 39
I (3841) Touch Elements Combination Example: Slider Calculate, position: 41
I (3851) Touch Elements Combination Example: Slider Calculate, position: 42
I (3861) Touch Elements Combination Example: Slider Calculate, position: 43
I (3871) Touch Elements Combination Example: Slider Calculate, position: 45
I (3881) Touch Elements Combination Example: Slider Calculate, position: 47
I (3891) Touch Elements Combination Example: Slider Calculate, position: 48
I (3901) Touch Elements Combination Example: Slider Calculate, position: 50
I (3911) Touch Elements Combination Example: Slider Calculate, position: 52
I (3921) Touch Elements Combination Example: Slider Calculate, position: 53
I (3931) Touch Elements Combination Example: Slider Calculate, position: 55
I (3941) Touch Elements Combination Example: Slider Calculate, position: 57
I (3951) Touch Elements Combination Example: Slider Calculate, position: 58
I (3961) Touch Elements Combination Example: Slider Calculate, position: 60
I (3971) Touch Elements Combination Example: Slider Calculate, position: 61
I (3981) Touch Elements Combination Example: Slider Calculate, position: 62
I (3991) Touch Elements Combination Example: Slider Calculate, position: 64
I (4001) Touch Elements Combination Example: Slider Calculate, position: 65
I (4011) Touch Elements Combination Example: Slider Calculate, position: 66
I (4021) Touch Elements Combination Example: Slider Calculate, position: 68
I (4031) Touch Elements Combination Example: Slider Calculate, position: 69
I (4041) Touch Elements Combination Example: Slider Calculate, position: 70
I (4051) Touch Elements Combination Example: Slider Calculate, position: 72
I (4061) Touch Elements Combination Example: Slider Calculate, position: 73
I (4071) Touch Elements Combination Example: Slider Calculate, position: 75
I (4081) Touch Elements Combination Example: Slider Calculate, position: 76
I (4091) Touch Elements Combination Example: Slider Calculate, position: 77
I (4101) Touch Elements Combination Example: Slider Calculate, position: 79
I (4111) Touch Elements Combination Example: Slider Calculate, position: 80
I (4121) Touch Elements Combination Example: Slider Calculate, position: 81
I (4131) Touch Elements Combination Example: Slider Calculate, position: 83
I (4141) Touch Elements Combination Example: Slider Calculate, position: 84
I (4151) Touch Elements Combination Example: Slider Calculate, position: 85
I (4161) Touch Elements Combination Example: Slider Calculate, position: 86
I (4171) Touch Elements Combination Example: Slider Calculate, position: 88
I (4181) Touch Elements Combination Example: Slider Calculate, position: 89
I (4191) Touch Elements Combination Example: Slider Calculate, position: 90
I (4201) Touch Elements Combination Example: Slider Calculate, position: 91
I (4211) Touch Elements Combination Example: Slider Calculate, position: 92
I (4221) Touch Elements Combination Example: Slider Calculate, position: 93
I (4231) Touch Elements Combination Example: Slider Calculate, position: 94
I (4241) Touch Elements Combination Example: Slider Calculate, position: 95
I (4251) Touch Elements Combination Example: Slider Calculate, position: 96
I (4261) Touch Elements Combination Example: Slider Calculate, position: 96
I (4271) Touch Elements Combination Example: Slider Calculate, position: 97
I (4281) Touch Elements Combination Example: Slider Calculate, position: 98
I (4291) Touch Elements Combination Example: Slider Calculate, position: 99
I (4301) Touch Elements Combination Example: Slider Calculate, position: 99
I (4311) Touch Elements Combination Example: Slider Calculate, position: 100
I (4321) Touch Elements Combination Example: Slider Calculate, position: 100
I (4331) Touch Elements Combination Example: Slider Calculate, position: 100
I (4341) Touch Elements Combination Example: Slider Calculate, position: 101
I (4351) Touch Elements Combination Example: Slider Release, position: 101
```
## 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.

View File

@@ -1,3 +0,0 @@
idf_component_register(SRCS "touch_elements_example_main.c"
INCLUDE_DIRS "."
PRIV_REQUIRES touch_element)

View File

@@ -1,157 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "touch_element/touch_button.h"
#include "touch_element/touch_slider.h"
#include "esp_log.h"
static const char *TAG = "Touch Elements Combination Example";
#define TOUCH_BUTTON_NUM 3
#define TOUCH_SLIDER_CHANNEL_NUM 5
static touch_button_handle_t button_handle[TOUCH_BUTTON_NUM]; //Touch buttons handle
static touch_slider_handle_t slider_handle; //Touch slider handle
/* Touch buttons channel array */
static const touch_pad_t button_channel_array[TOUCH_BUTTON_NUM] = {
TOUCH_PAD_NUM6,
TOUCH_PAD_NUM8,
TOUCH_PAD_NUM10
};
/* Touch buttons channel sensitivity array */
static const float button_channel_sens_array[TOUCH_BUTTON_NUM] = {
0.1F,
0.1F,
0.1F
};
/* Touch slider channels array */
static const touch_pad_t slider_channel_array[TOUCH_SLIDER_CHANNEL_NUM] = {
TOUCH_PAD_NUM5,
TOUCH_PAD_NUM7,
TOUCH_PAD_NUM9,
TOUCH_PAD_NUM11,
TOUCH_PAD_NUM12,
};
/* Touch slider channels sensitivity array */
static const float slider_channel_sens_array[TOUCH_SLIDER_CHANNEL_NUM] = {
0.252F,
0.246F,
0.277F,
0.250F,
0.257F,
};
static void button_handler(touch_elem_message_t element_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[%d] Press", (int)element_message.arg);
} else if (button_message->event == TOUCH_BUTTON_EVT_ON_RELEASE) {
ESP_LOGI(TAG, "Button[%d] Release", (int)element_message.arg);
} else if (button_message->event == TOUCH_BUTTON_EVT_ON_LONGPRESS) {
ESP_LOGI(TAG, "Button[%d] LongPress", (int)element_message.arg);
}
}
static void slider_handler(touch_elem_message_t element_message)
{
const touch_slider_message_t *slider_message = touch_slider_get_message(&element_message);
if (slider_message->event == TOUCH_SLIDER_EVT_ON_PRESS) {
ESP_LOGI(TAG, "Slider Press, position: %"PRIu32, slider_message->position);
} else if (slider_message->event == TOUCH_SLIDER_EVT_ON_RELEASE) {
ESP_LOGI(TAG, "Slider Release, position: %"PRIu32, slider_message->position);
} else if (slider_message->event == TOUCH_SLIDER_EVT_ON_CALCULATION) {
ESP_LOGI(TAG, "Slider Calculate, position: %"PRIu32, slider_message->position);
}
}
static void event_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);
switch (element_message.element_type) {
case TOUCH_ELEM_TYPE_BUTTON:
button_handler(element_message);
break;
case TOUCH_ELEM_TYPE_SLIDER:
slider_handler(element_message);
break;
default:
ESP_LOGW(TAG, "Unknown element message");
break;
}
}
}
void button_example_init(void)
{
touch_button_global_config_t global_config = TOUCH_BUTTON_GLOBAL_DEFAULT_CONFIG();
ESP_ERROR_CHECK(touch_button_install(&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 = button_channel_array[i],
.channel_sens = button_channel_sens_array[i]
};
/* Create Touch buttons */
ESP_ERROR_CHECK(touch_button_create(&button_config, &button_handle[i]));
/* 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 *)button_channel_array[i]));
/* Set EVENT as the dispatch method */
ESP_ERROR_CHECK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_EVENT));
/* Set LongPress event trigger threshold time */
ESP_ERROR_CHECK(touch_button_set_longpress(button_handle[i], 2000));
}
ESP_LOGI(TAG, "Touch buttons created");
}
void slider_example_init(void)
{
touch_slider_global_config_t global_config = TOUCH_SLIDER_GLOBAL_DEFAULT_CONFIG();
ESP_ERROR_CHECK(touch_slider_install(&global_config));
ESP_LOGI(TAG, "Touch slider installed");
/* Create Touch slider */
touch_slider_config_t slider_config = {
.channel_array = slider_channel_array,
.sensitivity_array = slider_channel_sens_array,
.channel_num = (sizeof(slider_channel_array) / sizeof(slider_channel_array[0])),
.position_range = 101
};
ESP_ERROR_CHECK(touch_slider_create(&slider_config, &slider_handle));
/* Subscribe touch slider events (On Press, On Release, On Calculation) */
ESP_ERROR_CHECK(touch_slider_subscribe_event(slider_handle,
TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_CALCULATION, NULL));
/* Set EVENT as the dispatch method */
ESP_ERROR_CHECK(touch_slider_set_dispatch_method(slider_handle, TOUCH_ELEM_DISP_EVENT));
ESP_LOGI(TAG, "Touch slider created");
}
void app_main(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");
button_example_init();
slider_example_init();
touch_element_start();
ESP_LOGI(TAG, "Touch element library start");
/* Create a handler task to handle event messages */
xTaskCreate(&event_handler_task, "event_handler_task", 4 * 1024, NULL, 5, NULL);
}

View File

@@ -1,16 +0,0 @@
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
@pytest.mark.generic
@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target'])
def test_touch_elements_combination(dut: Dut) -> None:
dut.expect_exact('Touch Elements Combination Example: Touch element library installed')
dut.expect_exact('Touch Elements Combination Example: Touch button installed')
dut.expect_exact('Touch Elements Combination Example: Touch buttons created')
dut.expect_exact('Touch Elements Combination Example: Touch slider installed')
dut.expect_exact('Touch Elements Combination Example: Touch slider created')
dut.expect_exact('Touch Elements Combination Example: Touch element library start')

View File

@@ -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.22)
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_matrix)

View File

@@ -1,65 +0,0 @@
| Supported Targets | ESP32-S2 | ESP32-S3 |
| ----------------- | -------- | -------- |
# Touch Element matrix example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use the Touch Element library of capacitive touch sensor and set up touch matrix.
## How to use example
### Hardware Required
* A development board with ESP32-S2 or ESP32-S3 chip
* A touch extension board like [esp32-s2-touch-devkit-1](https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32s2/esp32-s2-touch-devkit-1/user_guide.html)
### Configure the project
* Set the target of the build by following command, where TARGET can be `esp32s2` or `esp32s3`.
```
idf.py set-target TARGET
```
* Run `idf.py menuconfig` to select a dispatch method for the example.
### 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
```
I (331) Touch Matrix Example: Touch element library installed
I (331) Touch Matrix Example: Touch matrix installed
I (341) Touch Matrix Example: Touch matrix created
I (341) Touch Matrix Example: Touch element library start
I (1951) Touch Matrix Example: Matrix Press, axis: (0, 0) index: 0
I (2131) Touch Matrix Example: Matrix Release, axis: (0, 0) index: 0
I (3121) Touch Matrix Example: Matrix Press, axis: (1, 1) index: 4
I (3281) Touch Matrix Example: Matrix Release, axis: (1, 1) index: 4
I (4621) Touch Matrix Example: Matrix Press, axis: (2, 0) index: 6
I (4801) Touch Matrix Example: Matrix Release, axis: (2, 0) index: 6
I (5381) Touch Matrix Example: Matrix Press, axis: (2, 2) index: 8
I (5571) Touch Matrix Example: Matrix Release, axis: (2, 2) index: 8
I (6221) Touch Matrix Example: Matrix Press, axis: (0, 2) index: 2
I (6441) Touch Matrix Example: Matrix Release, axis: (0, 2) index: 2
I (7551) Touch Matrix Example: Matrix Press, axis: (1, 1) index: 4
I (8551) Touch Matrix Example: Matrix LongPress, axis: (1, 1) index: 4
I (9551) Touch Matrix Example: Matrix LongPress, axis: (1, 1) index: 4
I (10551) Touch Matrix Example: Matrix LongPress, axis: (1, 1) index: 4
I (11031) Touch Matrix Example: Matrix Release, axis: (1, 1) index: 4
```
## 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.

View File

@@ -1,3 +0,0 @@
idf_component_register(SRCS "touch_matrix_example_main.c"
INCLUDE_DIRS "."
PRIV_REQUIRES touch_element)

View File

@@ -1,15 +0,0 @@
menu "Example Configuration"
choice TOUCH_SENSOR_EXAMPLE_TYPE
bool "Select touch element dispatch method"
default TOUCH_ELEM_EVENT
help
Select touch element dispatch method (event task or callback) for this example.
config TOUCH_ELEM_EVENT
bool "Dispatch by event task"
config TOUCH_ELEM_CALLBACK
bool "Dispatch by callback"
endchoice
endmenu

View File

@@ -1,132 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "touch_element/touch_matrix.h"
#include "esp_log.h"
static const char *TAG = "Touch Matrix Example";
#define X_AXIS_CHANNEL_NUM 3
#define Y_AXIS_CHANNEL_NUM 3
static touch_matrix_handle_t matrix_handle;
/* Touch Matrix Button x-axis channels array */
static const touch_pad_t x_axis_channel[X_AXIS_CHANNEL_NUM] = {
TOUCH_PAD_NUM5,
TOUCH_PAD_NUM7,
TOUCH_PAD_NUM9,
};
/* Touch Matrix Button y-axis channels array */
static const touch_pad_t y_axis_channel[Y_AXIS_CHANNEL_NUM] = {
TOUCH_PAD_NUM11,
TOUCH_PAD_NUM12,
TOUCH_PAD_NUM14,
};
/* Touch Matrix Button x-axis channels sensitivity array */
static const float x_axis_channel_sens[X_AXIS_CHANNEL_NUM] = {
0.1F,
0.1F,
0.1F,
};
/* Touch Matrix Button y-axis channel sensitivity array */
static const float y_axis_channel_sens[Y_AXIS_CHANNEL_NUM] = {
0.1F,
0.1F,
0.1F,
};
#ifdef CONFIG_TOUCH_ELEM_EVENT
/* Matrix event handler task */
static void matrix_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); //Block take
if (element_message.element_type != TOUCH_ELEM_TYPE_MATRIX) {
continue;
}
/* Decode message */
const touch_matrix_message_t *matrix_message = touch_matrix_get_message(&element_message);
if (matrix_message->event == TOUCH_MATRIX_EVT_ON_PRESS) {
ESP_LOGI(TAG, "Matrix Press, axis: (%"PRIu8", %"PRIu8") index: %"PRIu8, matrix_message->position.x_axis,
matrix_message->position.y_axis, matrix_message->position.index);
} else if (matrix_message->event == TOUCH_MATRIX_EVT_ON_RELEASE) {
ESP_LOGI(TAG, "Matrix Release, axis: (%"PRIu8", %"PRIu8") index: %"PRIu8, matrix_message->position.x_axis,
matrix_message->position.y_axis, matrix_message->position.index);
} else if (matrix_message->event == TOUCH_MATRIX_EVT_ON_LONGPRESS) {
ESP_LOGI(TAG, "Matrix LongPress, axis: (%"PRIu8", %"PRIu8") index: %"PRIu8, matrix_message->position.x_axis,
matrix_message->position.y_axis, matrix_message->position.index);
}
}
}
#elif CONFIG_TOUCH_ELEM_CALLBACK
/* Matrix callback routine */
void matrix_handler(touch_matrix_handle_t out_handle, touch_matrix_message_t *out_message, void *arg)
{
(void) arg; //Unused
if (out_handle != matrix_handle) {
return;
}
if (out_message->event == TOUCH_MATRIX_EVT_ON_PRESS) {
ESP_LOGI(TAG, "Matrix Press, axis: (%"PRIu8", %"PRIu8") index: %"PRIu8, out_message->position.x_axis,
out_message->position.y_axis, out_message->position.index);
} else if (out_message->event == TOUCH_MATRIX_EVT_ON_RELEASE) {
ESP_LOGI(TAG, "Matrix Release, axis: (%"PRIu8", %"PRIu8") index: %"PRIu8, out_message->position.x_axis,
out_message->position.y_axis, out_message->position.index);
} else if (out_message->event == TOUCH_MATRIX_EVT_ON_LONGPRESS) {
ESP_LOGI(TAG, "Matrix LongPress, axis: (%"PRIu8", %"PRIu8") index: %"PRIu8, out_message->position.x_axis,
out_message->position.y_axis, out_message->position.index);
}
}
#endif
void app_main(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_matrix_global_config_t matrix_global_config = TOUCH_MATRIX_GLOBAL_DEFAULT_CONFIG();
ESP_ERROR_CHECK(touch_matrix_install(&matrix_global_config));
ESP_LOGI(TAG, "Touch matrix installed");
/* Create Touch Matrix Button */
touch_matrix_config_t matrix_config = {
.x_channel_array = x_axis_channel,
.y_channel_array = y_axis_channel,
.x_sensitivity_array = x_axis_channel_sens,
.y_sensitivity_array = y_axis_channel_sens,
.x_channel_num = (sizeof(x_axis_channel) / sizeof(x_axis_channel[0])),
.y_channel_num = (sizeof(y_axis_channel) / sizeof(y_axis_channel[0]))
};
ESP_ERROR_CHECK(touch_matrix_create(&matrix_config, &matrix_handle));
/* Subscribe touch matrix events (On Press, On Release, On LongPress) */
ESP_ERROR_CHECK(touch_matrix_subscribe_event(matrix_handle,
TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_LONGPRESS, NULL));
#ifdef CONFIG_TOUCH_ELEM_EVENT
/* Set EVENT as the dispatch method */
ESP_ERROR_CHECK(touch_matrix_set_dispatch_method(matrix_handle, TOUCH_ELEM_DISP_EVENT));
/* Create a handler task to handle event messages */
xTaskCreate(&matrix_handler_task, "matrix_handler_task", 4 * 1024, NULL, 5, NULL);
#elif CONFIG_TOUCH_ELEM_CALLBACK
/* Set CALLBACK as the dispatch method */
ESP_ERROR_CHECK(touch_matrix_set_dispatch_method(matrix_handle, TOUCH_ELEM_DISP_CALLBACK));
/* Register a handler function to handle event messages */
ESP_ERROR_CHECK(touch_matrix_set_callback(matrix_handle, matrix_handler));
#endif
ESP_LOGI(TAG, "Touch matrix created");
touch_element_start();
ESP_LOGI(TAG, "Touch element library start");
}

View File

@@ -1,14 +0,0 @@
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
@pytest.mark.generic
@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target'])
def test_touch_matrix(dut: Dut) -> None:
dut.expect_exact('Touch Matrix Example: Touch element library installed')
dut.expect_exact('Touch Matrix Example: Touch matrix installed')
dut.expect_exact('Touch Matrix Example: Touch matrix created')
dut.expect_exact('Touch Matrix Example: Touch element library start')

View File

@@ -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.22)
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_slider)

View File

@@ -1,96 +0,0 @@
| Supported Targets | ESP32-S2 | ESP32-S3 |
| ----------------- | -------- | -------- |
# Touch Element slider example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use the Touch Element library of capacitive touch sensor and set up touch slider.
## How to use example
### Hardware Required
* A development board with ESP32-S2 or ESP32-S3 chip
* A touch extension board like [esp32-s2-touch-devkit-1](https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32s2/esp32-s2-touch-devkit-1/user_guide.html)
### Configure the project
* Set the target of the build by following command, where TARGET can be `esp32s2` or `esp32s3`.
```
idf.py set-target TARGET
```
* Run `idf.py menuconfig` to select a dispatch method for the example.
### 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
```
I (331) Touch Slider Example: Touch element library installed
I (331) Touch Slider Example: Touch slider installed
I (341) Touch Slider Example: Touch slider created
I (341) Touch Slider Example: Touch element library start
I (1911) Touch Slider Example: Slider Press, position: 0
I (1921) Touch Slider Example: Slider Calculate, position: 0
I (1931) Touch Slider Example: Slider Calculate, position: 0
I (1941) Touch Slider Example: Slider Calculate, position: 0
I (1951) Touch Slider Example: Slider Calculate, position: 0
I (1961) Touch Slider Example: Slider Calculate, position: 0
I (1971) Touch Slider Example: Slider Calculate, position: 0
I (1981) Touch Slider Example: Slider Calculate, position: 0
I (1991) Touch Slider Example: Slider Calculate, position: 0
I (2001) Touch Slider Example: Slider Calculate, position: 0
I (2011) Touch Slider Example: Slider Calculate, position: 0
I (2021) Touch Slider Example: Slider Calculate, position: 1
I (2031) Touch Slider Example: Slider Calculate, position: 1
I (2041) Touch Slider Example: Slider Calculate, position: 2
I (2051) Touch Slider Example: Slider Calculate, position: 2
I (2061) Touch Slider Example: Slider Calculate, position: 4
I (2071) Touch Slider Example: Slider Calculate, position: 5
I (2081) Touch Slider Example: Slider Calculate, position: 6
I (2091) Touch Slider Example: Slider Calculate, position: 8
I (2101) Touch Slider Example: Slider Calculate, position: 10
I (2111) Touch Slider Example: Slider Calculate, position: 12
I (2121) Touch Slider Example: Slider Calculate, position: 15
I (2131) Touch Slider Example: Slider Calculate, position: 17
I (2141) Touch Slider Example: Slider Calculate, position: 19
I (2151) Touch Slider Example: Slider Calculate, position: 22
I (2161) Touch Slider Example: Slider Calculate, position: 24
I (2171) Touch Slider Example: Slider Calculate, position: 26
I (2181) Touch Slider Example: Slider Calculate, position: 29
I (2191) Touch Slider Example: Slider Calculate, position: 31
I (2201) Touch Slider Example: Slider Calculate, position: 33
I (2211) Touch Slider Example: Slider Calculate, position: 35
I (2221) Touch Slider Example: Slider Calculate, position: 37
I (2231) Touch Slider Example: Slider Calculate, position: 40
I (2241) Touch Slider Example: Slider Calculate, position: 42
I (2251) Touch Slider Example: Slider Calculate, position: 44
I (2261) Touch Slider Example: Slider Calculate, position: 46
I (2271) Touch Slider Example: Slider Calculate, position: 48
I (2281) Touch Slider Example: Slider Calculate, position: 50
I (2291) Touch Slider Example: Slider Calculate, position: 52
I (2301) Touch Slider Example: Slider Calculate, position: 54
I (2311) Touch Slider Example: Slider Calculate, position: 56
I (2321) Touch Slider Example: Slider Calculate, position: 57
I (2331) Touch Slider Example: Slider Calculate, position: 59
I (2341) Touch Slider Example: Slider Calculate, position: 60
I (2351) Touch Slider Example: Slider Calculate, position: 61
I (2361) Touch Slider Example: Slider Release, position: 61
```
## 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.

View File

@@ -1,3 +0,0 @@
idf_component_register(SRCS "touch_slider_example_main.c"
INCLUDE_DIRS "."
PRIV_REQUIRES touch_element)

View File

@@ -1,15 +0,0 @@
menu "Example Configuration"
choice TOUCH_SENSOR_EXAMPLE_TYPE
bool "Select touch element dispatch method"
default TOUCH_ELEM_EVENT
help
Select touch element dispatch method (event task or callback) for this example.
config TOUCH_ELEM_EVENT
bool "Dispatch by event task"
config TOUCH_ELEM_CALLBACK
bool "Dispatch by callback"
endchoice
endmenu

View File

@@ -1,117 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "touch_element/touch_slider.h"
#include "esp_log.h"
static const char *TAG = "Touch Slider Example";
#define TOUCH_SLIDER_CHANNEL_NUM 5
static touch_slider_handle_t slider_handle; //Touch slider handle
static const touch_pad_t channel_array[TOUCH_SLIDER_CHANNEL_NUM] = { //Touch slider channels array
TOUCH_PAD_NUM5,
TOUCH_PAD_NUM7,
TOUCH_PAD_NUM9,
TOUCH_PAD_NUM11,
TOUCH_PAD_NUM12,
};
/**
* Using finger slide from slider's beginning to the ending, and output the RAW channel signal, then calculate all the
* channels sensitivity of the slider, and you can decrease or increase the detection sensitivity by adjusting the threshold divider
* which locates in touch_slider_global_config_t. Please keep in mind that the real sensitivity totally depends on the
* physical characteristics, if you want to decrease or increase the detection sensitivity, keep the ratio of those channels the same.
*/
static const float channel_sens_array[TOUCH_SLIDER_CHANNEL_NUM] = { //Touch slider channels sensitivity array
0.252F,
0.246F,
0.277F,
0.250F,
0.257F,
};
#ifdef CONFIG_TOUCH_ELEM_EVENT
/* Slider event handler task */
static void slider_handler_task(void *arg)
{
(void) arg; //Unused
touch_elem_message_t element_message;
while (1) {
/* Waiting for touch element messages */
if (touch_element_message_receive(&element_message, portMAX_DELAY) == ESP_OK) {
if (element_message.element_type != TOUCH_ELEM_TYPE_SLIDER) {
continue;
}
/* Decode message */
const touch_slider_message_t *slider_message = touch_slider_get_message(&element_message);
if (slider_message->event == TOUCH_SLIDER_EVT_ON_PRESS) {
ESP_LOGI(TAG, "Slider Press, position: %"PRIu32, slider_message->position);
} else if (slider_message->event == TOUCH_SLIDER_EVT_ON_RELEASE) {
ESP_LOGI(TAG, "Slider Release, position: %"PRIu32, slider_message->position);
} else if (slider_message->event == TOUCH_SLIDER_EVT_ON_CALCULATION) {
ESP_LOGI(TAG, "Slider Calculate, position: %"PRIu32, slider_message->position);
}
}
}
}
#elif CONFIG_TOUCH_ELEM_CALLBACK
/* Slider callback routine */
void slider_handler(touch_slider_handle_t out_handle, touch_slider_message_t *out_message, void *arg)
{
(void) arg; //Unused
if (out_handle != slider_handle) {
return;
}
if (out_message->event == TOUCH_SLIDER_EVT_ON_PRESS) {
ESP_LOGI(TAG, "Slider Press, position: %"PRIu32, out_message->position);
} else if (out_message->event == TOUCH_SLIDER_EVT_ON_RELEASE) {
ESP_LOGI(TAG, "Slider Release, position: %"PRIu32, out_message->position);
} else if (out_message->event == TOUCH_SLIDER_EVT_ON_CALCULATION) {
ESP_LOGI(TAG, "Slider Calculate, position: %"PRIu32, out_message->position);
}
}
#endif
void app_main(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_slider_global_config_t slider_global_config = TOUCH_SLIDER_GLOBAL_DEFAULT_CONFIG();
ESP_ERROR_CHECK(touch_slider_install(&slider_global_config));
ESP_LOGI(TAG, "Touch slider installed");
/* Create Touch slider */
touch_slider_config_t slider_config = {
.channel_array = channel_array,
.sensitivity_array = channel_sens_array,
.channel_num = (sizeof(channel_array) / sizeof(channel_array[0])),
.position_range = 101
};
ESP_ERROR_CHECK(touch_slider_create(&slider_config, &slider_handle));
/* Subscribe touch slider events (On Press, On Release, On Calculation) */
ESP_ERROR_CHECK(touch_slider_subscribe_event(slider_handle,
TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_CALCULATION, NULL));
#ifdef CONFIG_TOUCH_ELEM_EVENT
/* Set EVENT as the dispatch method */
ESP_ERROR_CHECK(touch_slider_set_dispatch_method(slider_handle, TOUCH_ELEM_DISP_EVENT));
/* Create a handler task to handle event messages */
xTaskCreate(&slider_handler_task, "slider_handler_task", 4 * 1024, NULL, 5, NULL);
#elif CONFIG_TOUCH_ELEM_CALLBACK
/* Set CALLBACK as the dispatch method */
ESP_ERROR_CHECK(touch_slider_set_dispatch_method(slider_handle, TOUCH_ELEM_DISP_CALLBACK));
/* Register a handler function to handle event messages */
ESP_ERROR_CHECK(touch_slider_set_callback(slider_handle, slider_handler));
#endif
ESP_LOGI(TAG, "Touch slider created");
touch_element_start();
ESP_LOGI(TAG, "Touch element library start");
}

View File

@@ -1,14 +0,0 @@
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
@pytest.mark.generic
@idf_parametrize('target', ['esp32s2', 'esp32s3'], indirect=['target'])
def test_touch_slider(dut: Dut) -> None:
dut.expect_exact('Touch Slider Example: Touch element library installed')
dut.expect_exact('Touch Slider Example: Touch slider installed')
dut.expect_exact('Touch Slider Example: Touch slider created')
dut.expect_exact('Touch Slider Example: Touch element library start')

View File

@@ -86,7 +86,6 @@ components_not_formatted_temporary:
- "/components/spi_flash/"
- "/components/spiffs/"
- "/components/tcp_transport/"
- "/components/touch_element/"
- "/components/unity/"
- "/components/vfs/"
- "/components/wear_levelling/"

View File

@@ -203,8 +203,15 @@
hint: "The issue is better to resolve by replacing format specifiers to 'PRI'-family macros (include <inttypes.h> header file)."
-
re: "Failed to resolve component 'esp_ipc'"
hint: "IPC component has been moved to esp_system. Any `REQUIRES esp_ipc` can simply be deleted as esp_system is REQUIRED by default."
re: "Failed to resolve component '{}'"
hint: "The {} component has been moved to {}. You can {}."
variables:
-
re_variables: ['esp_ipc']
hint_variables: ['IPC', 'esp_system', 'simply delete any `REQUIRES esp_ipc` as esp_system is REQUIRED by default']
-
re_variables: ['touch_element']
hint_variables: ['touch_element', 'ESP Component Registry', 'add this dependency by running `idf.py add-dependency "espressif/touch_element"`']
-
re: "error: invalid use of incomplete typedef 'esp_tls_t'"