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)
@@ -156,7 +156,6 @@
|
|||||||
/components/spi_flash/ @esp-idf-codeowners/peripherals
|
/components/spi_flash/ @esp-idf-codeowners/peripherals
|
||||||
/components/spiffs/ @esp-idf-codeowners/storage
|
/components/spiffs/ @esp-idf-codeowners/storage
|
||||||
/components/tcp_transport/ @esp-idf-codeowners/network
|
/components/tcp_transport/ @esp-idf-codeowners/network
|
||||||
/components/touch_element/ @esp-idf-codeowners/peripherals
|
|
||||||
/components/ulp/ @esp-idf-codeowners/system
|
/components/ulp/ @esp-idf-codeowners/system
|
||||||
/components/unity/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
/components/unity/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||||
/components/usb/ @esp-idf-codeowners/peripherals/usb
|
/components/usb/ @esp-idf-codeowners/peripherals/usb
|
||||||
|
@@ -23,6 +23,19 @@ components/driver/test_apps/legacy_twai:
|
|||||||
depends_components:
|
depends_components:
|
||||||
- esp_driver_gpio
|
- 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:
|
components/driver/test_apps/touch_sensor_v1:
|
||||||
disable:
|
disable:
|
||||||
- if: SOC_TOUCH_SENSOR_VERSION != 1
|
- if: SOC_TOUCH_SENSOR_VERSION != 1
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
idf_component_register(SRCS "test_app_main.c" "test_touch_element.c" "test_touch_button.c"
|
idf_component_register(SRCS "test_app_main.c" "test_touch_element.c" "test_touch_button.c"
|
||||||
"test_touch_slider.c" "test_touch_matrix.c"
|
"test_touch_slider.c" "test_touch_matrix.c"
|
||||||
PRIV_REQUIRES unity touch_element
|
PRIV_REQUIRES unity touch_element esp_pm
|
||||||
WHOLE_ARCHIVE
|
WHOLE_ARCHIVE
|
||||||
)
|
)
|
@@ -0,0 +1,2 @@
|
|||||||
|
dependencies:
|
||||||
|
espressif/touch_element: ^1.0.0
|
@@ -10,7 +10,6 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.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)
|
#define TEST_MEMORY_LEAK_THRESHOLD (-400)
|
||||||
|
|
||||||
static size_t before_free_8bit;
|
static size_t before_free_8bit;
|
@@ -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
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
*/
|
*/
|
||||||
@@ -14,7 +14,8 @@
|
|||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "esp_random.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"
|
#include "touch_element/touch_button.h"
|
||||||
|
|
||||||
static portMUX_TYPE test_button_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
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;
|
te_button_handle_t te_button = (te_button_handle_t) button_handle;
|
||||||
touch_pad_t channel = te_button->device->channel;
|
touch_pad_t channel = te_button->device->channel;
|
||||||
if (button_event == TOUCH_BUTTON_EVT_ON_PRESS) {
|
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) {
|
} 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 {
|
} 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)
|
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 = {
|
touch_elem_message_t valid_message = {
|
||||||
.handle = handle,
|
.handle = handle,
|
||||||
.element_type = TOUCH_ELEM_TYPE_BUTTON,
|
.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");
|
printf("Touch button event change longtime test start\n");
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
printf("Touch button event change longtime test... (%d/10)\n", i + 1);
|
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;
|
uint8_t channel_index = random() % BUTTON_CHANNEL_NUM;
|
||||||
touch_elem_message_t valid_message = {
|
touch_elem_message_t valid_message = {
|
||||||
.handle = button_handle[channel_index],
|
.handle = button_handle[channel_index],
|
||||||
@@ -412,7 +417,7 @@ static void test_button_event_concurrent(void)
|
|||||||
printf("Touch button event concurrent test start\n");
|
printf("Touch button event concurrent test start\n");
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
printf("Touch button event concurrent test... (%d/10)\n", i + 1);
|
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;
|
uint32_t message_count = 0;
|
||||||
touch_elem_message_t current_message;
|
touch_elem_message_t current_message;
|
||||||
|
|
||||||
@@ -488,7 +493,6 @@ static void test_button_random_trigger_concurrent(void)
|
|||||||
TEST_ASSERT(os_ret == pdPASS);
|
TEST_ASSERT(os_ret == pdPASS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t run_count = 0;
|
uint32_t run_count = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (run_count++ % 1000 == 0) {
|
if (run_count++ % 1000 == 0) {
|
@@ -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
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
*/
|
*/
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
#include "touch_element/touch_button.h"
|
#include "touch_element/touch_button.h"
|
||||||
#include "touch_element/touch_slider.h"
|
#include "touch_element/touch_slider.h"
|
||||||
#include "touch_element/touch_matrix.h"
|
#include "touch_element/touch_matrix.h"
|
||||||
|
#include "esp_private/touch_sensor_legacy_ll.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
QueueHandle_t valid_msg_handle;
|
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");
|
printf("Touch Element waterproof guard sensor test start\n");
|
||||||
|
|
||||||
srandom((unsigned int)time(NULL));
|
srandom((unsigned int)time(NULL));
|
||||||
{//No use waterproof guard sensor
|
{
|
||||||
|
//No use waterproof guard sensor
|
||||||
touch_elem_waterproof_config_t waterproof_config = {
|
touch_elem_waterproof_config_t waterproof_config = {
|
||||||
.guard_channel = TOUCH_WATERPROOF_GUARD_NOUSE,
|
.guard_channel = TOUCH_WATERPROOF_GUARD_NOUSE,
|
||||||
.guard_sensitivity = 0.0F
|
.guard_sensitivity = 0.0F
|
||||||
@@ -128,7 +130,8 @@ static void test_system_waterproof_guard(void)
|
|||||||
touch_element_waterproof_uninstall();
|
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 = {
|
touch_elem_waterproof_config_t waterproof_config = {
|
||||||
.guard_channel = TOUCH_PAD_NUM13,
|
.guard_channel = TOUCH_PAD_NUM13,
|
||||||
.guard_sensitivity = 0.1F
|
.guard_sensitivity = 0.1F
|
||||||
@@ -158,7 +161,8 @@ static void test_system_waterproof_guard(void)
|
|||||||
touch_element_waterproof_uninstall();
|
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;
|
const uint8_t protect_handle_threshold = BUTTON_CHANNEL_NUM / 2;
|
||||||
touch_elem_waterproof_config_t waterproof_config = {
|
touch_elem_waterproof_config_t waterproof_config = {
|
||||||
.guard_channel = TOUCH_PAD_NUM13,
|
.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)
|
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) {
|
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) {
|
} 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 {
|
} else {
|
||||||
printf("guard sensor simulator doesn't support this operation\n");
|
printf("guard sensor simulator doesn't support this operation\n");
|
||||||
}
|
}
|
@@ -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
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
*/
|
*/
|
||||||
@@ -13,7 +13,8 @@
|
|||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "unity.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"
|
#include "touch_element/touch_matrix.h"
|
||||||
|
|
||||||
static const touch_pad_t x_axis_channel[3] = {
|
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 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;
|
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) {
|
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_ll_set_slope(x_channel, TOUCH_PAD_SLOPE_3);
|
||||||
touch_pad_set_cnt_mode(y_channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT);
|
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) {
|
} 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_ll_set_slope(x_channel, TOUCH_PAD_SLOPE_7);
|
||||||
touch_pad_set_cnt_mode(y_channel, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT);
|
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 {
|
} else {
|
||||||
touch_pad_set_cnt_mode(x_channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT); // LongPress
|
touch_ll_set_slope(x_channel, TOUCH_PAD_SLOPE_3);
|
||||||
touch_pad_set_cnt_mode(y_channel, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT);
|
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)
|
static void test_matrix_channel_simulator(touch_pad_t channel, touch_matrix_event_t matrix_event)
|
||||||
{
|
{
|
||||||
if (matrix_event == TOUCH_MATRIX_EVT_ON_PRESS) {
|
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) {
|
} 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@@ -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
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
*/
|
*/
|
||||||
@@ -13,7 +13,8 @@
|
|||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "unity.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"
|
#include "touch_element/touch_slider.h"
|
||||||
|
|
||||||
static const touch_pad_t slider_channel_array[5] = {
|
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;
|
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;
|
touch_pad_t channel = te_slider->device[random % te_slider->channel_sum]->channel;
|
||||||
if (slider_event == TOUCH_SLIDER_EVT_ON_PRESS) {
|
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) {
|
} 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)
|
static void test_slider_disp_event(void)
|
||||||
{
|
{
|
||||||
touch_slider_handle_t slider_handle;
|
touch_slider_handle_t slider_handle;
|
||||||
@@ -161,7 +163,6 @@ static void test_slider_disp_event(void)
|
|||||||
touch_slider_uninstall();
|
touch_slider_uninstall();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void test_slider_disp_callback(void)
|
static void test_slider_disp_callback(void)
|
||||||
{
|
{
|
||||||
test_monitor_t monitor;
|
test_monitor_t monitor;
|
@@ -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()
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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;
|
|
||||||
}
|
|
@@ -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;
|
|
||||||
}
|
|
@@ -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;
|
|
||||||
}
|
|
@@ -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>
|
|
BIN
docs/_static/touch_element/source/te_button.odg
vendored
BIN
docs/_static/touch_element/source/te_component.odg
vendored
BIN
docs/_static/touch_element/source/te_matrix.odg
vendored
BIN
docs/_static/touch_element/source/te_slider.odg
vendored
BIN
docs/_static/touch_element/source/te_threshold.odg
vendored
Before Width: | Height: | Size: 38 KiB |
244
docs/_static/touch_element/te_button.svg
vendored
Before Width: | Height: | Size: 83 KiB |
669
docs/_static/touch_element/te_component.svg
vendored
Before Width: | Height: | Size: 269 KiB |
393
docs/_static/touch_element/te_matrix.svg
vendored
Before Width: | Height: | Size: 94 KiB |
BIN
docs/_static/touch_element/te_signal.png
vendored
Before Width: | Height: | Size: 122 KiB |
297
docs/_static/touch_element/te_slider.svg
vendored
Before Width: | Height: | Size: 86 KiB |
299
docs/_static/touch_element/te_threshold.svg
vendored
Before Width: | Height: | Size: 124 KiB |
@@ -269,7 +269,6 @@ ESP32S2_DOCS = (
|
|||||||
'hw-reference/esp32s2/**',
|
'hw-reference/esp32s2/**',
|
||||||
'api-guides/usb-console.rst',
|
'api-guides/usb-console.rst',
|
||||||
'api-reference/peripherals/ds.rst',
|
'api-reference/peripherals/ds.rst',
|
||||||
'api-reference/peripherals/touch_element.rst',
|
|
||||||
'api-guides/RF_calibration.rst',
|
'api-guides/RF_calibration.rst',
|
||||||
'api-guides/phy.rst',
|
'api-guides/phy.rst',
|
||||||
]
|
]
|
||||||
@@ -284,7 +283,6 @@ ESP32S3_DOCS = (
|
|||||||
'api-reference/system/ipc.rst',
|
'api-reference/system/ipc.rst',
|
||||||
'api-guides/flash_psram_config.rst',
|
'api-guides/flash_psram_config.rst',
|
||||||
'api-reference/peripherals/sd_pullup_requirements.rst',
|
'api-reference/peripherals/sd_pullup_requirements.rst',
|
||||||
'api-reference/peripherals/touch_element.rst',
|
|
||||||
'api-guides/RF_calibration.rst',
|
'api-guides/RF_calibration.rst',
|
||||||
'api-guides/phy.rst',
|
'api-guides/phy.rst',
|
||||||
]
|
]
|
||||||
|
@@ -5,10 +5,6 @@ INPUT += \
|
|||||||
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/dac_channel.h \
|
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/dac_channel.h \
|
||||||
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/rtc_io_channel.h \
|
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/rtc_io_channel.h \
|
||||||
$(PROJECT_PATH)/components/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.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_helpers.h \
|
||||||
$(PROJECT_PATH)/components/usb/include/usb/usb_host.h \
|
$(PROJECT_PATH)/components/usb/include/usb/usb_host.h \
|
||||||
$(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \
|
$(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \
|
||||||
|
@@ -4,10 +4,6 @@ INPUT += \
|
|||||||
$(PROJECT_PATH)/components/esp_driver_touch_sens/hw_ver2/include/driver/touch_version_types.h \
|
$(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/esp_lcd/rgb/include/esp_lcd_panel_rgb.h \
|
||||||
$(PROJECT_PATH)/components/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.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_helpers.h \
|
||||||
$(PROJECT_PATH)/components/usb/include/usb/usb_host.h \
|
$(PROJECT_PATH)/components/usb/include/usb/usb_host.h \
|
||||||
$(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \
|
$(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \
|
||||||
|
@@ -44,7 +44,6 @@ Peripherals API
|
|||||||
:SOC_LP_VAD_SUPPORTED: vad
|
:SOC_LP_VAD_SUPPORTED: vad
|
||||||
:SOC_TEMP_SENSOR_SUPPORTED: temp_sensor
|
:SOC_TEMP_SENSOR_SUPPORTED: temp_sensor
|
||||||
:SOC_TOUCH_SENSOR_SUPPORTED: cap_touch_sens
|
:SOC_TOUCH_SENSOR_SUPPORTED: cap_touch_sens
|
||||||
:esp32s2 or esp32s3: touch_element
|
|
||||||
:SOC_TWAI_SUPPORTED: twai
|
:SOC_TWAI_SUPPORTED: twai
|
||||||
uart
|
uart
|
||||||
:SOC_USB_OTG_SUPPORTED: usb_device
|
:SOC_USB_OTG_SUPPORTED: usb_device
|
||||||
|
@@ -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
|
|
@@ -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`)
|
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.
|
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"``.
|
||||||
|
@@ -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_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_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/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
|
# Driver-NG refactor
|
||||||
api-reference/peripherals/timer api-reference/peripherals/gptimer
|
api-reference/peripherals/timer api-reference/peripherals/gptimer
|
||||||
|
@@ -44,7 +44,6 @@
|
|||||||
:SOC_JPEG_CODEC_SUPPORTED: jpeg
|
:SOC_JPEG_CODEC_SUPPORTED: jpeg
|
||||||
:SOC_TEMP_SENSOR_SUPPORTED: temp_sensor
|
:SOC_TEMP_SENSOR_SUPPORTED: temp_sensor
|
||||||
:SOC_TOUCH_SENSOR_SUPPORTED: cap_touch_sens
|
:SOC_TOUCH_SENSOR_SUPPORTED: cap_touch_sens
|
||||||
:esp32s2 or esp32s3: touch_element
|
|
||||||
:SOC_TWAI_SUPPORTED: twai
|
:SOC_TWAI_SUPPORTED: twai
|
||||||
uart
|
uart
|
||||||
:SOC_USB_OTG_SUPPORTED: usb_device
|
:SOC_USB_OTG_SUPPORTED: usb_device
|
||||||
|
@@ -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
|
|
@@ -178,3 +178,11 @@ SPI
|
|||||||
4. 启用 ``Place transmitting functions of SPI master into IRAM`` (:ref:`CONFIG_SPI_MASTER_IN_IRAM`)
|
4. 启用 ``Place transmitting functions of SPI master into IRAM`` (:ref:`CONFIG_SPI_MASTER_IN_IRAM`)
|
||||||
|
|
||||||
请注意,启用 :ref:`CONFIG_FREERTOS_IN_IRAM` 会显著增加 IRAM 使用量。在优化 SPI 性能时,需进行权衡。
|
请注意,启用 :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"`` 将这个依赖添加到您的项目中。
|
||||||
|
|
||||||
|
@@ -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"])
|
- if: CI_COMMIT_REF_NAME == "master" and (NIGHTLY_RUN == 0 and CONFIG_NAME not in ["default", "bluedroid", "nimble"])
|
||||||
depends_components+:
|
depends_components+:
|
||||||
- esp_console
|
- esp_console
|
||||||
- touch_element
|
|
||||||
- esp_driver_gpio
|
- esp_driver_gpio
|
||||||
depends_components-:
|
depends_components-:
|
||||||
- esp_coex
|
- esp_coex
|
||||||
|
@@ -486,11 +486,6 @@ examples/peripherals/touch_sensor:
|
|||||||
disable:
|
disable:
|
||||||
- if: SOC_TOUCH_SENSOR_SUPPORTED != 1
|
- 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:
|
examples/peripherals/touch_sensor/touch_sens_basic:
|
||||||
disable:
|
disable:
|
||||||
- if: SOC_TOUCH_SENSOR_SUPPORTED != 1
|
- if: SOC_TOUCH_SENSOR_SUPPORTED != 1
|
||||||
|
@@ -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)
|
|
@@ -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.
|
|
@@ -1,3 +0,0 @@
|
|||||||
idf_component_register(SRCS "touch_button_example_main.c"
|
|
||||||
INCLUDE_DIRS "."
|
|
||||||
PRIV_REQUIRES touch_element)
|
|
@@ -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
|
|
@@ -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");
|
|
||||||
}
|
|
@@ -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')
|
|
@@ -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)
|
|
@@ -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.
|
|
@@ -1,3 +0,0 @@
|
|||||||
idf_component_register(SRCS "waterproof_example_main.c"
|
|
||||||
INCLUDE_DIRS "."
|
|
||||||
PRIV_REQUIRES touch_element)
|
|
@@ -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
|
|
@@ -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();
|
|
||||||
}
|
|
@@ -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')
|
|
@@ -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)
|
|
@@ -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.
|
|
@@ -1,3 +0,0 @@
|
|||||||
idf_component_register(SRCS "touch_elements_example_main.c"
|
|
||||||
INCLUDE_DIRS "."
|
|
||||||
PRIV_REQUIRES touch_element)
|
|
@@ -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);
|
|
||||||
}
|
|
@@ -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')
|
|
@@ -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)
|
|
@@ -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.
|
|
@@ -1,3 +0,0 @@
|
|||||||
idf_component_register(SRCS "touch_matrix_example_main.c"
|
|
||||||
INCLUDE_DIRS "."
|
|
||||||
PRIV_REQUIRES touch_element)
|
|
@@ -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
|
|
@@ -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");
|
|
||||||
}
|
|
@@ -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')
|
|
@@ -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)
|
|
@@ -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.
|
|
@@ -1,3 +0,0 @@
|
|||||||
idf_component_register(SRCS "touch_slider_example_main.c"
|
|
||||||
INCLUDE_DIRS "."
|
|
||||||
PRIV_REQUIRES touch_element)
|
|
@@ -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
|
|
@@ -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");
|
|
||||||
}
|
|
@@ -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')
|
|
@@ -86,7 +86,6 @@ components_not_formatted_temporary:
|
|||||||
- "/components/spi_flash/"
|
- "/components/spi_flash/"
|
||||||
- "/components/spiffs/"
|
- "/components/spiffs/"
|
||||||
- "/components/tcp_transport/"
|
- "/components/tcp_transport/"
|
||||||
- "/components/touch_element/"
|
|
||||||
- "/components/unity/"
|
- "/components/unity/"
|
||||||
- "/components/vfs/"
|
- "/components/vfs/"
|
||||||
- "/components/wear_levelling/"
|
- "/components/wear_levelling/"
|
||||||
|
@@ -203,8 +203,15 @@
|
|||||||
hint: "The issue is better to resolve by replacing format specifiers to 'PRI'-family macros (include <inttypes.h> header file)."
|
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'"
|
re: "Failed to resolve component '{}'"
|
||||||
hint: "IPC component has been moved to esp_system. Any `REQUIRES esp_ipc` can simply be deleted as esp_system is REQUIRED by default."
|
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'"
|
re: "error: invalid use of incomplete typedef 'esp_tls_t'"
|
||||||
|