From e8b29653c0f807afd6a86ff1ccb4756b8c9a1eeb Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Fri, 7 Jun 2024 17:25:35 +0800 Subject: [PATCH] feat(touch_sens): add example for the touch sensor v3 --- examples/peripherals/.build-test-rules.yml | 10 ++ .../touch_sensor_v3/CMakeLists.txt | 6 + .../touch_sensor/touch_sensor_v3/README.md | 125 +++++++++++++ .../touch_sensor_v3/main/CMakeLists.txt | 3 + .../main/touch_sens_v3_example_main.c | 169 ++++++++++++++++++ .../touch_sensor_v3/pytest_touch_sens_v3.py | 14 ++ .../system/deep_sleep/main/touch_wakeup.c | 4 +- .../system/light_sleep/main/CMakeLists.txt | 4 + .../light_sleep/main/light_sleep_example.h | 9 +- .../main/light_sleep_example_main.c | 4 +- .../light_sleep/main/touch_sens_wakeup.c | 107 +++++++++++ 11 files changed, 450 insertions(+), 5 deletions(-) create mode 100644 examples/peripherals/touch_sensor/touch_sensor_v3/CMakeLists.txt create mode 100644 examples/peripherals/touch_sensor/touch_sensor_v3/README.md create mode 100644 examples/peripherals/touch_sensor/touch_sensor_v3/main/CMakeLists.txt create mode 100644 examples/peripherals/touch_sensor/touch_sensor_v3/main/touch_sens_v3_example_main.c create mode 100644 examples/peripherals/touch_sensor/touch_sensor_v3/pytest_touch_sens_v3.py create mode 100644 examples/system/light_sleep/main/touch_sens_wakeup.c diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index 7397280ae0..16a6e4fc82 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -425,6 +425,16 @@ examples/peripherals/touch_sensor/touch_sensor_v2: disable: - if: SOC_TOUCH_SENSOR_VERSION != 2 +examples/peripherals/touch_sensor/touch_sensor_v3: + disable: + - if: SOC_TOUCH_SENSOR_VERSION != 3 + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: the runners do not support the pins for touch sensor + depends_components: + - esp_driver_touch_sens + examples/peripherals/twai/twai_alert_and_recovery: disable: - if: SOC_TWAI_SUPPORTED != 1 diff --git a/examples/peripherals/touch_sensor/touch_sensor_v3/CMakeLists.txt b/examples/peripherals/touch_sensor/touch_sensor_v3/CMakeLists.txt new file mode 100644 index 0000000000..dc484f27e8 --- /dev/null +++ b/examples/peripherals/touch_sensor/touch_sensor_v3/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(touch_sens_example) diff --git a/examples/peripherals/touch_sensor/touch_sensor_v3/README.md b/examples/peripherals/touch_sensor/touch_sensor_v3/README.md new file mode 100644 index 0000000000..650d3a24a6 --- /dev/null +++ b/examples/peripherals/touch_sensor/touch_sensor_v3/README.md @@ -0,0 +1,125 @@ +| Supported Targets | ESP32-P4 | +| ----------------- | -------- | + +# Capacity Touch Sensor Example (for hardware version 3) + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example is going to demonstrate how to register the touch channels and read the data. + +## How to Use Example + +### Hardware Required + +* A development board with any supported Espressif SOC chip (see `Supported Targets` table above) +* A USB cable for power supply and programming +* (Optional) Touch board with touch buttons on it. + - If you don't have a touch board, you can connect the touch pins with male jump wires and touch it directly for testing. + +### Configure the Project + +You can determine the touch channel number by ``EXAMPLE_TOUCH_CHANNEL_NUM`` in the example. And adjust the active threshold by ``s_thresh2bm_ratio``. + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT build flash monitor +``` + +(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 + +You can see the following output in the monitor if the example runs successfully: + +``` +W (461) touch: [sample_cfg_id 0] clock precision loss, expect 4000000 hz, got 4006725 hz +W (461) touch: [sample_cfg_id 1] clock precision loss, expect 8000000 hz, got 8013450 hz +W (461) touch: [sample_cfg_id 2] clock precision loss, expect 16000000 hz, got 16026900 hz +Initial benchmark and new threshold are: +[CH 0] 0: 4114, 411 1: 2057, 205 2: 1028, 102 +[CH 1] 0: 4643, 464 1: 2322, 232 2: 1160, 116 +[CH 2] 0: 4848, 484 1: 2424, 242 2: 1211, 121 +[CH 3] 0: 4340, 434 1: 2170, 217 2: 1085, 108 +================================= +benchmark [CH 0]: 4115 2056 1028 +chan_data [CH 0]: 4115 2056 1028 + +benchmark [CH 1]: 4644 2322 1160 +chan_data [CH 1]: 4644 2322 1160 + +benchmark [CH 2]: 4848 2423 1211 +chan_data [CH 2]: 4848 2423 1211 + +benchmark [CH 3]: 4337 2168 1084 +chan_data [CH 3]: 4337 2168 1084 + +================================= +benchmark [CH 0]: 4109 2054 1027 +chan_data [CH 0]: 4109 2054 1027 + +benchmark [CH 1]: 4638 2318 1158 +chan_data [CH 1]: 4638 2318 1158 + +benchmark [CH 2]: 4843 2421 1210 +chan_data [CH 2]: 4845 2421 1210 + +benchmark [CH 3]: 4334 2167 1084 +chan_data [CH 3]: 4334 2167 1083 +... +``` + +And if you touch and release a button, you will see the following output: + +``` +... +I (1321) touch_callback: [CH 1] active +================================= +benchmark [CH 0]: 4111 2055 1027 +chan_data [CH 0]: 4111 2055 1027 + +benchmark [CH 1]: 4676 2339 1168 +chan_data [CH 1]: 17701 8798 4399 + +benchmark [CH 2]: 4870 2434 1217 +chan_data [CH 2]: 4867 2433 1217 + +benchmark [CH 3]: 4333 2165 1082 +chan_data [CH 3]: 4333 2165 1082 + +================================= +benchmark [CH 0]: 4109 2053 1027 +chan_data [CH 0]: 4108 2053 1027 + +benchmark [CH 1]: 4676 2339 1168 +chan_data [CH 1]: 11256 8817 4363 + +benchmark [CH 2]: 4868 2434 1217 +chan_data [CH 2]: 4862 2429 1214 + +benchmark [CH 3]: 4332 2165 1082 +chan_data [CH 3]: 4330 2164 1081 + +I (1931) touch_callback: [CH 1] inactive +================================= +benchmark [CH 0]: 4106 2052 1026 +chan_data [CH 0]: 4106 2052 1026 + +benchmark [CH 1]: 4649 2323 1161 +chan_data [CH 1]: 4650 2323 1161 + +benchmark [CH 2]: 4847 2422 1211 +chan_data [CH 2]: 4846 2422 1211 + +benchmark [CH 3]: 4329 2163 1082 +chan_data [CH 3]: 4329 2164 1082 +... +``` + +## 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. diff --git a/examples/peripherals/touch_sensor/touch_sensor_v3/main/CMakeLists.txt b/examples/peripherals/touch_sensor/touch_sensor_v3/main/CMakeLists.txt new file mode 100644 index 0000000000..b88a846c5a --- /dev/null +++ b/examples/peripherals/touch_sensor/touch_sensor_v3/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "touch_sens_v3_example_main.c" + PRIV_REQUIRES esp_driver_touch_sens + INCLUDE_DIRS ".") diff --git a/examples/peripherals/touch_sensor/touch_sensor_v3/main/touch_sens_v3_example_main.c b/examples/peripherals/touch_sensor/touch_sensor_v3/main/touch_sens_v3_example_main.c new file mode 100644 index 0000000000..4eeb1c91bc --- /dev/null +++ b/examples/peripherals/touch_sensor/touch_sensor_v3/main/touch_sens_v3_example_main.c @@ -0,0 +1,169 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/touch_sens.h" +#include "soc/lp_analog_peri_struct.h" +#include "esp_check.h" + +// Touch version 3 supports multiple sample configurations +#define EXAMPLE_TOUCH_SAMPLE_CFG_NUM TOUCH_SAMPLE_CFG_NUM +#define EXAMPLE_TOUCH_CHANNEL_NUM 4 +#define EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES 3 + +static touch_sensor_handle_t s_sens_handle = NULL; +static touch_channel_handle_t s_chan_handle[EXAMPLE_TOUCH_CHANNEL_NUM] = {}; +// Active threshold to benchmark ratio. (i.e., touch will be activated when data >= benchmark * (1 + ratio)) +static float s_thresh2bm_ratio[EXAMPLE_TOUCH_CHANNEL_NUM] = { + [0 ... EXAMPLE_TOUCH_CHANNEL_NUM - 1] = 0.02f, // 2% +}; + +bool example_touch_on_active_callback(touch_sensor_handle_t sens_handle, const touch_active_event_data_t *event, void *user_ctx) +{ + ESP_EARLY_LOGI("touch_callback", "[CH %d] active", (int)event->chan_id); + return false; +} + +bool example_touch_on_inactive_callback(touch_sensor_handle_t sens_handle, const touch_inactive_event_data_t *event, void *user_ctx) +{ + ESP_EARLY_LOGI("touch_callback", "[CH %d] inactive", (int)event->chan_id); + return false; +} + +static void example_touch_do_initial_scanning(void) +{ + /* Enable the touch sensor to do the initial scanning, so that to initialize the channel data */ + ESP_ERROR_CHECK(touch_sensor_enable(s_sens_handle)); + + /* Scan the enabled touch channels for several times, to make sure the initial channel data is stable */ + for (int i = 0; i < EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES; i++) { + ESP_ERROR_CHECK(touch_sensor_trigger_oneshot_scanning(s_sens_handle, 2000)); + } + + /* Disable the touch channel to rollback the state */ + ESP_ERROR_CHECK(touch_sensor_disable(s_sens_handle)); + + /* (Optional) Read the initial channel benchmark and reconfig the channel active threshold accordingly */ + printf("Initial benchmark and new threshold are:\n"); + for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) { + /* Read the initial benchmark of the touch channel */ + uint32_t benchmark[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {}; + ESP_ERROR_CHECK(touch_channel_read_data(s_chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark)); + /* Calculate the proper active thresholds regarding the initial benchmark */ + printf("[CH %d]", i); + touch_channel_config_t chan_cfg = {}; + for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) { + chan_cfg.active_thresh[j] = (uint32_t)(benchmark[j] * s_thresh2bm_ratio[j]); + printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.active_thresh[j]); + } + printf("\n"); + /* Update the channel configuration */ + ESP_ERROR_CHECK(touch_sensor_reconfig_channel(s_chan_handle[i], &chan_cfg)); + } +} + +void app_main(void) +{ + /* Use the default sample configurations */ + touch_sensor_sample_config_t sample_cfg[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = { + TOUCH_SENSOR_DEFAULT_SAMPLE_CONFIG0(), +#if EXAMPLE_TOUCH_SAMPLE_CFG_NUM > 1 + TOUCH_SENSOR_DEFAULT_SAMPLE_CONFIG1(), +#endif +#if EXAMPLE_TOUCH_SAMPLE_CFG_NUM > 2 + TOUCH_SENSOR_DEFAULT_SAMPLE_CONFIG2(), +#endif + }; + /* Allocate new touch controller handle */ + touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(EXAMPLE_TOUCH_SAMPLE_CFG_NUM, sample_cfg); + ESP_ERROR_CHECK(touch_sensor_new_controller(&sens_cfg, &s_sens_handle)); + + /* Configure the touch sensor filter */ + touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG(); + ESP_ERROR_CHECK(touch_sensor_config_filter(s_sens_handle, &filter_cfg)); + + /* Allocate new touch channel on the touch controller */ + touch_channel_config_t chan_cfg = { + /** Set the touch channel active threshold of each sample configuration. + * + * @How to Determine: + * As the actual threshold is affected by various factors in real application, + * we need to run the touch app first to get the `benchmark` and the `smooth_data` that being touched. + * + * @Formula: + * threshold = benchmark * coeff, (coeff for example, 0.1%~20%) + * Please adjust the coeff to guarantee the threshold < smooth_data - benchmark + * + * @Typical Practice: + * Normally, we can't determine a fixed threshold at the beginning, + * but we can give them estimated values first and update them after an initial scanning (like this example), + * Step1: set an estimated value for each sample configuration first. (i.e., here) + * Step2: then reconfig the threshold after the initial scanning.(see `example_touch_do_initial_scanning`) + * Step3: adjust the `s_thresh2bm_ratio` to a proper value to trigger the active callback + */ + .active_thresh = { + 5000, // estimated active threshold of sample configuration 0 +#if EXAMPLE_TOUCH_SAMPLE_CFG_NUM > 1 + 2500, // estimated active threshold of sample configuration 1 +#endif +#if EXAMPLE_TOUCH_SAMPLE_CFG_NUM > 2 + 1000, // estimated active threshold of sample configuration 2 +#endif + }, + }; + for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) { + ESP_ERROR_CHECK(touch_sensor_new_channel(s_sens_handle, i, &chan_cfg, &s_chan_handle[i])); + } + + /* Do the initial scanning to initialize the touch channel data + * Without this step, the channel data in the first read will be invalid + */ + example_touch_do_initial_scanning(); + + /* Register the touch sensor callbacks, here only take `active` and `deactivate` event for example */ + touch_event_callbacks_t callbacks = { + .on_active = example_touch_on_active_callback, + .on_inactive = example_touch_on_inactive_callback, + .on_measure_done = NULL, + .on_scan_done = NULL, + .on_timeout = NULL, + .on_proximity_meas_done = NULL, + }; + ESP_ERROR_CHECK(touch_sensor_register_callbacks(s_sens_handle, &callbacks, NULL)); + + /* Enable the touch sensor */ + ESP_ERROR_CHECK(touch_sensor_enable(s_sens_handle)); + + /* Start continuous scanning, you can also trigger oneshot scanning manually */ + ESP_ERROR_CHECK(touch_sensor_start_continuous_scanning(s_sens_handle)); + + uint32_t benchmark[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {}; + uint32_t chan_data[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {}; + while (1) { + printf("=================================\n"); + for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) { + /* Read and print the benchmark of each sample configuration */ + ESP_ERROR_CHECK(touch_channel_read_data(s_chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark)); + printf("benchmark [CH %d]:", i); + for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) { + printf(" %"PRIu32, benchmark[j]); + } + printf("\n"); + /* Read and print the channel data of each sample configuration */ + ESP_ERROR_CHECK(touch_channel_read_data(s_chan_handle[i], TOUCH_CHAN_DATA_TYPE_SMOOTH, chan_data)); + printf("chan_data [CH %d]:", i); + for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) { + printf(" %"PRIu32, chan_data[j]); + } + printf("\n\n"); + } + /* Read and display the data every 300 ms */ + vTaskDelay(pdMS_TO_TICKS(300)); + } +} diff --git a/examples/peripherals/touch_sensor/touch_sensor_v3/pytest_touch_sens_v3.py b/examples/peripherals/touch_sensor/touch_sensor_v3/pytest_touch_sens_v3.py new file mode 100644 index 0000000000..f03c56c2ff --- /dev/null +++ b/examples/peripherals/touch_sensor/touch_sensor_v3/pytest_touch_sens_v3.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32p4 +@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 runners do not support touch pins') +@pytest.mark.generic +def test_touch_sens_v3(dut: Dut) -> None: + dut.expect_exact('Initial benchmark and new threshold are:') + dut.expect(r'\[CH [0-9]+\] 0: [0-9]+, [0-9]+') + dut.expect(r'benchmark \[CH [0-9]+\]: [0-9]+') + dut.expect(r'chan_data \[CH [0-9]+\]: [0-9]+') diff --git a/examples/system/deep_sleep/main/touch_wakeup.c b/examples/system/deep_sleep/main/touch_wakeup.c index c2dd41daf8..13d4ff64d4 100644 --- a/examples/system/deep_sleep/main/touch_wakeup.c +++ b/examples/system/deep_sleep/main/touch_wakeup.c @@ -50,7 +50,7 @@ void example_deep_sleep_register_touch_wakeup(void) // If use touch pad wake up, should set touch sensor FSM mode at 'TOUCH_FSM_MODE_TIMER'. touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); // Set reference voltage for charging/discharging - // In this case, the high reference valtage will be 2.4V - 1V = 1.4V + // In this case, the high reference voltage will be 2.4V - 1V = 1.4V // The low reference voltage will be 0.5 // The larger the range, the larger the pulse count value. touch_pad_set_voltage(TOUCH_HVOLT_2V4, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V); @@ -104,6 +104,8 @@ void example_deep_sleep_register_touch_wakeup(void) #endif printf("Enabling touch pad wakeup\n"); ESP_ERROR_CHECK(esp_sleep_enable_touchpad_wakeup()); +#if SOC_PM_SUPPORT_RTC_PERIPH_PD ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON)); +#endif } #endif // CONFIG_EXAMPLE_TOUCH_WAKEUP diff --git a/examples/system/light_sleep/main/CMakeLists.txt b/examples/system/light_sleep/main/CMakeLists.txt index 25d2112b95..f36ab83fd8 100644 --- a/examples/system/light_sleep/main/CMakeLists.txt +++ b/examples/system/light_sleep/main/CMakeLists.txt @@ -9,5 +9,9 @@ if(IDF_TARGET IN_LIST TOUCH_ELEMENT_COMPATIBLE_TARGETS) list(APPEND srcs "touch_wakeup.c") endif() +if(IDF_TARGET STREQUAL "esp32p4") + list(APPEND srcs "touch_sens_wakeup.c") +endif() + idf_component_register(SRCS ${srcs} INCLUDE_DIRS ".") diff --git a/examples/system/light_sleep/main/light_sleep_example.h b/examples/system/light_sleep/main/light_sleep_example.h index c3401c4aed..cb62682502 100644 --- a/examples/system/light_sleep/main/light_sleep_example.h +++ b/examples/system/light_sleep/main/light_sleep_example.h @@ -1,15 +1,20 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ #pragma once +#include "sdkconfig.h" + #ifdef __cplusplus extern "C" { #endif +// TODO: [ESP32P4] add P4 when runner is ready +#define EXAMPLE_TOUCH_LSLEEP_WAKEUP_SUPPORT (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3) + void example_wait_gpio_inactive(void); esp_err_t example_register_gpio_wakeup(void); @@ -18,7 +23,7 @@ esp_err_t example_register_timer_wakeup(void); esp_err_t example_register_uart_wakeup(void); -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#if EXAMPLE_TOUCH_LSLEEP_WAKEUP_SUPPORT void example_register_touch_wakeup(void); #endif diff --git a/examples/system/light_sleep/main/light_sleep_example_main.c b/examples/system/light_sleep/main/light_sleep_example_main.c index 8791d4de6e..989cfea24b 100644 --- a/examples/system/light_sleep/main/light_sleep_example_main.c +++ b/examples/system/light_sleep/main/light_sleep_example_main.c @@ -50,7 +50,7 @@ static void light_sleep_task(void *args) * Otherwise the chip may fall sleep again before running uart task */ vTaskDelay(1); break; -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#if EXAMPLE_TOUCH_LSLEEP_WAKEUP_SUPPORT case ESP_SLEEP_WAKEUP_TOUCHPAD: wakeup_reason = "touch"; break; @@ -83,7 +83,7 @@ void app_main(void) example_register_timer_wakeup(); /* Enable wakeup from light sleep by uart */ example_register_uart_wakeup(); -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#if EXAMPLE_TOUCH_LSLEEP_WAKEUP_SUPPORT /* Enable wakeup from light sleep by touch element */ example_register_touch_wakeup(); #endif diff --git a/examples/system/light_sleep/main/touch_sens_wakeup.c b/examples/system/light_sleep/main/touch_sens_wakeup.c new file mode 100644 index 0000000000..fbf6c6fcc5 --- /dev/null +++ b/examples/system/light_sleep/main/touch_sens_wakeup.c @@ -0,0 +1,107 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include "freertos/FreeRTOS.h" +#include "esp_log.h" +#include "driver/touch_sens.h" + +static const char *TAG = "touch_wakeup"; + +#define EXAMPLE_TOUCH_SAMPLE_CFG_NUM 1 +#define EXAMPLE_TOUCH_CHANNEL_NUM 5 +#define EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES 3 + +// Active threshold to benchmark ratio. (i.e., touch will be activated when data >= benchmark * (1 + ratio)) +static float s_thresh2bm_ratio[EXAMPLE_TOUCH_CHANNEL_NUM] = { + [0 ... EXAMPLE_TOUCH_CHANNEL_NUM - 1] = 0.02f, // 2% +}; + +static bool example_touch_on_active_cb(touch_sensor_handle_t sens_handle, const touch_active_event_data_t *event, void *user_ctx) +{ + ESP_EARLY_LOGW("isr", "ch %d active", (int)event->chan_id); + return false; +} + +static bool example_touch_on_inactive_cb(touch_sensor_handle_t sens_handle, const touch_inactive_event_data_t *event, void *user_ctx) +{ + ESP_EARLY_LOGW("isr", "ch %d inactive", (int)event->chan_id); + return false; +} + +static void example_touch_do_initial_scanning(touch_sensor_handle_t sens_handle, touch_channel_handle_t chan_handle[]) +{ + /* Enable the touch sensor to do the initial scanning, so that to initialize the channel data */ + ESP_ERROR_CHECK(touch_sensor_enable(sens_handle)); + + /* Scan the enabled touch channels for several times, to make sure the initial channel data is stable */ + for (int i = 0; i < EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES; i++) { + ESP_ERROR_CHECK(touch_sensor_trigger_oneshot_scanning(sens_handle, 2000)); + } + + /* Disable the touch channel to rollback the state */ + ESP_ERROR_CHECK(touch_sensor_disable(sens_handle)); + + /* (Optional) Read the initial channel benchmark and reconfig the channel active threshold accordingly */ + printf("Initial benchmark and new threshold are:\n"); + for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) { + /* Read the initial benchmark of the touch channel */ + uint32_t benchmark[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = {}; + ESP_ERROR_CHECK(touch_channel_read_data(chan_handle[i], TOUCH_CHAN_DATA_TYPE_BENCHMARK, benchmark)); + /* Calculate the proper active thresholds regarding the initial benchmark */ + printf("[CH %d]", i); + touch_channel_config_t chan_cfg = {}; + for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) { + chan_cfg.active_thresh[j] = (uint32_t)(benchmark[j] * s_thresh2bm_ratio[j]); + printf(" %d: %"PRIu32", %"PRIu32"\t", j, benchmark[j], chan_cfg.active_thresh[j]); + } + printf("\n"); + /* Update the channel configuration */ + ESP_ERROR_CHECK(touch_sensor_reconfig_channel(chan_handle[i], &chan_cfg)); + } +} + +esp_err_t example_register_touch_wakeup(void) +{ + touch_sensor_handle_t sens_handle = NULL; + touch_sensor_sample_config_t sample_cfg[EXAMPLE_TOUCH_SAMPLE_CFG_NUM] = { + TOUCH_SENSOR_DEFAULT_SAMPLE_CONFIG0(), + }; + touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(EXAMPLE_TOUCH_SAMPLE_CFG_NUM, sample_cfg); + ESP_ERROR_CHECK(touch_sensor_new_controller(&sens_cfg, &sens_handle)); + + touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG(); + ESP_ERROR_CHECK(touch_sensor_config_filter(sens_handle, &filter_cfg)); + + touch_channel_handle_t chan_handle[EXAMPLE_TOUCH_CHANNEL_NUM]; + touch_channel_config_t chan_cfg = { + .active_thresh = {5000}, // Initial threshold + + }; + for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) { + ESP_ERROR_CHECK(touch_sensor_new_channel(sens_handle, i, &chan_cfg, &chan_handle[i])); + } + + /* (Optional) Do the initial scanning to initialize the touch channel data + * Without this step, the channel data in the first read will be invalid + */ + example_touch_do_initial_scanning(sens_handle, chan_handle); + + touch_event_callbacks_t callbacks = { + .on_active = example_touch_on_active_cb, + .on_inactive = example_touch_on_inactive_cb, + }; + ESP_ERROR_CHECK(touch_sensor_register_callbacks(sens_handle, &callbacks, NULL)); + + touch_sleep_config_t light_slp_cfg = { + .slp_wakeup_lvl = TOUCH_LIGHT_SLEEP_WAKEUP, + }; + ESP_ERROR_CHECK(touch_sensor_config_sleep_wakeup(sens_handle, &light_slp_cfg)); + + ESP_ERROR_CHECK(touch_sensor_enable(sens_handle)); + ESP_ERROR_CHECK(touch_sensor_start_continuous_scanning(sens_handle)); + + ESP_LOGI(TAG, "touch wakeup source is ready"); + return ESP_OK; +}