feat(ulp_touch): add example for lp_touch

This commit is contained in:
laokaiyao
2025-02-27 17:45:33 +08:00
parent ffb8adcf49
commit c9cc7bb216
17 changed files with 436 additions and 70 deletions

View File

@@ -32,7 +32,7 @@
#include "esp_check.h"
#include "touch_sens_private.h"
#define TOUCH_CHANNEL_CHECK(num) ESP_RETURN_ON_FALSE(num >= TOUCH_MIN_CHAN_ID && num <= TOUCH_MAX_CHAN_ID, \
#define TOUCH_CHANNEL_CHECK(num) ESP_RETURN_ON_FALSE((int)(num) >= (int)TOUCH_MIN_CHAN_ID && num <= TOUCH_MAX_CHAN_ID, \
ESP_ERR_INVALID_ARG, TAG, "The channel number is out of supported range");
static const char *TAG = "touch";

View File

@@ -736,8 +736,8 @@ config SOC_TOUCH_SENSOR_NUM
default 10
config SOC_TOUCH_MIN_CHAN_ID
bool
default n
int
default 0
config SOC_TOUCH_MAX_CHAN_ID
int

View File

@@ -336,7 +336,7 @@
/*-------------------------- TOUCH SENSOR CAPS -------------------------------*/
#define SOC_TOUCH_SENSOR_VERSION (1U) /*!<Hardware version of touch sensor */
#define SOC_TOUCH_SENSOR_NUM (10)
#define SOC_TOUCH_MIN_CHAN_ID (0) /*!< Touch minimum channel number */
#define SOC_TOUCH_MIN_CHAN_ID (0U) /*!< Touch minimum channel number */
#define SOC_TOUCH_MAX_CHAN_ID (9) /*!< Touch maximum channel number */
#define SOC_TOUCH_SUPPORT_SLEEP_WAKEUP (1)
#define SOC_TOUCH_SAMPLE_CFG_NUM (1U) /*!< The sample configuration number in total, each sampler can be used to sample on one frequency */

View File

@@ -1724,8 +1724,8 @@ config SOC_TOUCH_SENSOR_NUM
default 14
config SOC_TOUCH_MIN_CHAN_ID
bool
default n
int
default 0
config SOC_TOUCH_MAX_CHAN_ID
int

View File

@@ -635,7 +635,7 @@
/*-------------------------- TOUCH SENSOR CAPS -------------------------------*/
#define SOC_TOUCH_SENSOR_VERSION (3) /*!< Hardware version of touch sensor */
#define SOC_TOUCH_SENSOR_NUM (14) /*!< Touch available channel number. Actually there are 15 Touch channels, but channel 14 is not pinned out, limit to 14 channels */
#define SOC_TOUCH_MIN_CHAN_ID (0) /*!< Touch minimum channel number */
#define SOC_TOUCH_MIN_CHAN_ID (0U) /*!< Touch minimum channel number */
#define SOC_TOUCH_MAX_CHAN_ID (13) /*!< Touch maximum channel number */
/* Touch Sensor Features */

View File

@@ -46,11 +46,7 @@ if(CONFIG_ULP_COPROC_TYPE_FSM OR CONFIG_ULP_COPROC_TYPE_RISCV)
"ulp_riscv/ulp_riscv.c"
"ulp_riscv/ulp_riscv_lock.c"
"ulp_riscv/ulp_riscv_i2c.c")
if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED)
list(APPEND srcs "ulp_riscv/ulp_riscv_touch.c")
endif()
endif()
endif()
if(CONFIG_ULP_COPROC_TYPE_LP_CORE)
@@ -81,10 +77,6 @@ if(CONFIG_ULP_COPROC_TYPE_LP_CORE)
list(APPEND srcs "lp_core/lp_core_etm.c")
endif()
if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED)
list(APPEND srcs "lp_core/lp_core_touch.c")
endif()
if(CONFIG_SOC_LP_ADC_SUPPORTED)
list(APPEND srcs "lp_core/shared/ulp_lp_core_lp_adc_shared.c")
endif()

View File

@@ -132,6 +132,11 @@ function(ulp_apply_default_sources ulp_app_name)
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_vad_shared.c"
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_critical_section_shared.c")
if(CONFIG_SOC_TOUCH_SENSOR_SUPPORTED)
list(APPEND ULP_S_SOURCES
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_touch.c")
endif()
set(target_folder ${IDF_TARGET})
target_link_options(${ulp_app_name}

View File

@@ -13,81 +13,80 @@ extern "C" {
#endif
/**
* @brief Read raw data of touch sensor on the ULP RISC-V core
* @note Refer `touch_pad_read_raw_data()` for more details
* @brief Read raw data of touch sensor on the LP core
*
* @param touch_num Touch pad index
* @param raw_data Pointer to accept touch sensor value
* @return esp_err_t ESP_OK when successful
* @param[in] touch_num Touch pad index
* @param[out] raw_data Raw data buffer pointer to accept touch sensor raw value,
* buffer size should be equal to the number of enabled sampling frequencies
* @return esp_err_t ESP_OK when successful
*/
esp_err_t lp_core_touch_pad_read_raw_data(int touch_num, uint32_t *raw_data);
/**
* @brief Read benchmark of touch sensor on the ULP RISC-V core
* @note Refer `touch_pad_read_benchmark()` for more details
* @brief Read benchmark of touch sensor on the LP core
*
* @param touch_num Touch pad index
* @param benchmark Pointer to accept touch sensor benchmark value
* @return esp_err_t ESP_OK when successful
* @param[in] touch_num Touch pad index
* @param[out] benchmark Benchmark data buffer pointer to accept touch sensor benchmark value,
* buffer size should be equal to the number of enabled sampling frequencies
* @return esp_err_t ESP_OK when successful
*/
esp_err_t lp_core_touch_pad_read_benchmark(int touch_num, uint32_t *benchmark);
/**
* @brief Read the filtered (smoothened) touch sensor data on the ULP RISC-V core
* @note Refer `touch_pad_filter_read_smooth()` for more details
* @brief Read the filtered (smoothened) touch sensor data on the LP core
*
* @param touch_num Touch pad index
* @param smooth_data Pointer to accept smoothened touch sensor value
* @return esp_err_t ESP_OK when successful
* @param[in] touch_num Touch pad index
* @param[out] smooth_data Smooth data buffer pointer to accept touch sensor smooth value,
* buffer size should be equal to the number of enabled sampling frequencies
* @return esp_err_t ESP_OK when successful
*/
esp_err_t lp_core_touch_pad_filter_read_smooth(int touch_num, uint32_t *smooth_data);
/**
* @brief Force reset benchmark to raw data of touch sensor.
* @note Refer `touch_pad_reset_benchmark()` for more details
*
* @param touch_num Touch pad index (TOUCH_PAD_MAX resets basaline of all channels)
* @param[in] touch_num Touch pad index
* @param[in] mask Mask of the sample freuqencies that need to be reset
* @return esp_err_t ESP_OK when successful
*/
esp_err_t lp_core_touch_pad_reset_benchmark(int touch_num);
esp_err_t lp_core_touch_pad_reset_benchmark(int touch_num, uint32_t mask);
/**
* @brief Read raw data of touch sensor sleep channel on the ULP RISC-V core
* @note Refer `touch_pad_sleep_channel_read_data()` for more details
* @brief Read raw data of touch sensor sleep channel on the LP core
*
* @param touch_num Touch pad index (Only one touch sensor channel is supported in deep sleep)
* @param raw_data Pointer to accept touch sensor value
* @return esp_err_t ESP_OK when successful
* @param[in] touch_num Touch pad index that has been registered as sleep channel
* @param[out] raw_data Raw data buffer pointer to accept touch sensor raw value,
* buffer size should be equal to the number of enabled sampling frequencies
* @return esp_err_t ESP_OK when successful
*/
esp_err_t lp_core_touch_pad_sleep_channel_read_data(int touch_num, uint32_t *raw_data);
/**
* @brief Read benchmark of touch sensor sleep channel on the ULP RISC-V core
* @note Refer `touch_pad_sleep_channel_read_benchmark()` for more details
* @brief Read benchmark of touch sensor sleep channel on the LP core
*
* @param touch_num Touch pad index (Only one touch sensor channel is supported in deep sleep)
* @param benchmark Pointer to accept touch sensor benchmark value
* @return esp_err_t ESP_OK when successful
* @param[in] touch_num Touch pad index that has been registered as sleep channel
* @param[out] benchmark Benchmark data buffer pointer to accept touch sensor benchmark value,
* buffer size should be equal to the number of enabled sampling frequencies
* @return esp_err_t ESP_OK when successful
*/
esp_err_t lp_core_touch_pad_sleep_channel_read_benchmark(int touch_num, uint32_t *benchmark);
/**
* @brief Read the filtered (smoothened) touch sensor sleep channel data on the ULP RISC-V core
* @note Refer `touch_pad_sleep_channel_read_smooth()` for more details
* @brief Read the filtered (smoothened) touch sensor sleep channel data on the LP core
*
* @param touch_num Touch pad index (Only one touch sensor channel is supported in deep sleep)
* @param smooth_data Pointer to accept smoothened touch sensor value
* @return esp_err_t ESP_OK when successful
* @param[in] touch_num Touch pad index that has been registered as sleep channel
* @param[out] smooth_dat Smooth data buffer pointer to accept touch sensor smooth value,
* buffer size should be equal to the number of enabled sampling frequencies
* @return esp_err_t ESP_OK when successful
*/
esp_err_t lp_core_touch_pad_sleep_channel_read_smooth(int touch_num, uint32_t *smooth_data);
/**
* @brief Reset benchmark of touch sensor sleep channel.
* @note Refer `touch_pad_sleep_channel_reset_benchmark()` for more details
*
* @param[in] mask Mask of the sample freuqencies that need to be reset
* @return esp_err_t ESP_OK when successful
*/
esp_err_t lp_core_touch_pad_sleep_channel_reset_benchmark(void);
esp_err_t lp_core_touch_pad_sleep_channel_reset_benchmark(uint32_t mask);
#ifdef __cplusplus
}

View File

@@ -4,12 +4,12 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "ulp_riscv_touch_ulp_core.h"
#include "soc/soc_caps.h"
#include "hal/touch_sensor_ll.h"
#include "esp_err.h"
/* Check Touch Channel correctness */
#define ULP_RISCV_TOUCH_CHANNEL_CHECK_AND_RETURN(channel) \
#define LP_CORE_TOUCH_CHANNEL_CHECK_AND_RETURN(channel) \
{ \
if (channel >= SOC_TOUCH_MAX_CHAN_ID || \
channel < SOC_TOUCH_MIN_CHAN_ID) { \
@@ -17,13 +17,13 @@
} \
} \
esp_err_t ulp_riscv_touch_pad_read_raw_data(touch_pad_t touch_num, uint32_t *raw_data)
esp_err_t lp_core_touch_pad_read_raw_data(int touch_num, uint32_t *raw_data)
{
/* Check Arguments */
if (!raw_data) {
return ESP_ERR_INVALID_ARG;
}
ULP_RISCV_TOUCH_CHANNEL_CHECK_AND_RETURN(touch_num);
LP_CORE_TOUCH_CHANNEL_CHECK_AND_RETURN(touch_num);
/* Read raw touch data */
uint32_t engaged_sampler_cnt = touch_ll_sample_cfg_get_engaged_num();
@@ -35,13 +35,13 @@ esp_err_t ulp_riscv_touch_pad_read_raw_data(touch_pad_t touch_num, uint32_t *raw
return ESP_OK;
}
esp_err_t ulp_riscv_touch_pad_read_benchmark(touch_pad_t touch_num, uint32_t *benchmark)
esp_err_t lp_core_touch_pad_read_benchmark(int touch_num, uint32_t *benchmark)
{
/* Check Arguments */
if (!benchmark) {
return ESP_ERR_INVALID_ARG;
}
ULP_RISCV_TOUCH_CHANNEL_CHECK_AND_RETURN(touch_num);
LP_CORE_TOUCH_CHANNEL_CHECK_AND_RETURN(touch_num);
/* Read benchmark data */
uint32_t engaged_sampler_cnt = touch_ll_sample_cfg_get_engaged_num();
@@ -52,13 +52,13 @@ esp_err_t ulp_riscv_touch_pad_read_benchmark(touch_pad_t touch_num, uint32_t *be
return ESP_OK;
}
esp_err_t ulp_riscv_touch_pad_filter_read_smooth(touch_pad_t touch_num, uint32_t *smooth_data)
esp_err_t lp_core_touch_pad_filter_read_smooth(int touch_num, uint32_t *smooth_data)
{
/* Check Arguments */
if (!smooth_data) {
return ESP_ERR_INVALID_ARG;
}
ULP_RISCV_TOUCH_CHANNEL_CHECK_AND_RETURN(touch_num);
LP_CORE_TOUCH_CHANNEL_CHECK_AND_RETURN(touch_num);
/* Read smoothened touch sensor data */
uint32_t engaged_sampler_cnt = touch_ll_sample_cfg_get_engaged_num();
@@ -69,12 +69,11 @@ esp_err_t ulp_riscv_touch_pad_filter_read_smooth(touch_pad_t touch_num, uint32_t
return ESP_OK;
}
esp_err_t ulp_riscv_touch_pad_reset_benchmark(touch_pad_t touch_num)
esp_err_t lp_core_touch_pad_reset_benchmark(int touch_num, uint32_t mask)
{
(void) mask; // Currently not support, reserved for future use
/* Check Arguments */
if (touch_num > TOUCH_PAD_MAX || touch_num < 0) {
return ESP_ERR_INVALID_ARG;
}
LP_CORE_TOUCH_CHANNEL_CHECK_AND_RETURN(touch_num);
/* Reset benchmark */
touch_ll_reset_chan_benchmark(BIT(touch_num));
@@ -82,13 +81,13 @@ esp_err_t ulp_riscv_touch_pad_reset_benchmark(touch_pad_t touch_num)
return ESP_OK;
}
esp_err_t ulp_riscv_touch_pad_sleep_channel_read_data(touch_pad_t touch_num, uint32_t *raw_data)
esp_err_t lp_core_touch_pad_sleep_channel_read_data(int touch_num, uint32_t *raw_data)
{
/* Check Arguments */
if (!raw_data) {
return ESP_ERR_INVALID_ARG;
}
ULP_RISCV_TOUCH_CHANNEL_CHECK_AND_RETURN(touch_num);
LP_CORE_TOUCH_CHANNEL_CHECK_AND_RETURN(touch_num);
/* Read raw touch data */
uint32_t engaged_sampler_cnt = touch_ll_sample_cfg_get_engaged_num();
@@ -100,13 +99,13 @@ esp_err_t ulp_riscv_touch_pad_sleep_channel_read_data(touch_pad_t touch_num, uin
return ESP_OK;
}
esp_err_t ulp_riscv_touch_pad_sleep_channel_read_benchmark(touch_pad_t touch_num, uint32_t *benchmark)
esp_err_t lp_core_touch_pad_sleep_channel_read_benchmark(int touch_num, uint32_t *benchmark)
{
/* Check Arguments */
if (!benchmark) {
return ESP_ERR_INVALID_ARG;
}
ULP_RISCV_TOUCH_CHANNEL_CHECK_AND_RETURN(touch_num);
LP_CORE_TOUCH_CHANNEL_CHECK_AND_RETURN(touch_num);
/* Read benchmark data */
uint32_t engaged_sampler_cnt = touch_ll_sample_cfg_get_engaged_num();
@@ -117,13 +116,13 @@ esp_err_t ulp_riscv_touch_pad_sleep_channel_read_benchmark(touch_pad_t touch_num
return ESP_OK;
}
esp_err_t ulp_riscv_touch_pad_sleep_channel_read_smooth(touch_pad_t touch_num, uint32_t *smooth_data)
esp_err_t lp_core_touch_pad_sleep_channel_read_smooth(int touch_num, uint32_t *smooth_data)
{
/* Check Arguments */
if (!smooth_data) {
return ESP_ERR_INVALID_ARG;
}
ULP_RISCV_TOUCH_CHANNEL_CHECK_AND_RETURN(touch_num);
LP_CORE_TOUCH_CHANNEL_CHECK_AND_RETURN(touch_num);
/* Read smoothened touch sensor data */
uint32_t engaged_sampler_cnt = touch_ll_sample_cfg_get_engaged_num();
@@ -134,8 +133,9 @@ esp_err_t ulp_riscv_touch_pad_sleep_channel_read_smooth(touch_pad_t touch_num, u
return ESP_OK;
}
esp_err_t ulp_riscv_touch_pad_sleep_channel_reset_benchmark(void)
esp_err_t lp_core_touch_pad_sleep_channel_reset_benchmark(uint32_t mask)
{
(void) mask; // Currently not support, reserved for future use
/* Reset benchmark */
touch_ll_sleep_reset_benchmark();

View File

@@ -334,6 +334,12 @@ examples/system/ulp/lp_core/lp_spi:
depends_components:
- ulp
examples/system/ulp/lp_core/lp_touch:
enable:
- if: SOC_TOUCH_SENSOR_SUPPORTED == 1 and (SOC_DEEP_SLEEP_SUPPORTED == 1 and SOC_LP_CORE_SUPPORTED == 1)
depends_components:
- ulp
examples/system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup:
disable:
- if: (SOC_ULP_LP_UART_SUPPORTED != 1)

View File

@@ -0,0 +1,8 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
idf_build_set_property(MINIMAL_BUILD ON)
project(lp_touch_example)

View File

@@ -0,0 +1,58 @@
| Supported Targets | ESP32-P4 |
| ----------------- | -------- |
# LP Core Touch Sensor example:
This example demonstrates how to program the LP coprocessor to read touch pad sensors.
LP Core program written in C can be found across `lp_core/main.c`. The build system compiles and links this program, converts it into binary format, and embeds it into the .rodata section of the ESP-IDF application.
At runtime, the application running inside the main CPU loads ULP program into the `LP SRAM` memory region using `ulp_lp_core_load_binary` function. The main code then configures the ULP wakeup period and starts the coprocessor by using `ulp_lp_core_run`. Once the LP core program is started, it runs periodically, with the period set by the main program. The main program enables LP Core wakeup source and puts the chip into deep sleep mode.
The LP core program scans all touch pad sensors periodically. When the program finds a touch pad is active (touched), it captures the touch pad number in a variable and wakes up the main CPU. The main CPU reports which touch pad sensor was touched.
## How to use the example
### Hardware Required
* A development board with ESP32-P4
### 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
```
Not an LP core wakeup. Cause = 0
Initializing...
Touch [CH 0] enabled on GPIO2
Touch [CH 1] enabled on GPIO3
Touch [CH 2] enabled on GPIO4
Touch [CH 3] enabled on GPIO5
=================================
Initial benchmark and new threshold are:
Touch [CH 0] 0: 5177, 77 1: 5131, 76 2: 2541, 38
Touch [CH 1] 0: 5021, 75 1: 5043, 75 2: 2471, 37
Touch [CH 2] 0: 5103, 76 1: 5064, 75 2: 2495, 37
Touch [CH 3] 0: 4981, 74 1: 4999, 74 2: 2440, 36
LP core loaded with firmware successfully
Entering in deep sleep
// Touched channel 0, then wake-up by the LP core
LP core woke up the main CPU
T0 touched
Entering in deep sleep
```

View File

@@ -0,0 +1,26 @@
# Register the component
idf_component_register(SRCS "lp_touch_main.c"
INCLUDE_DIRS ""
REQUIRES ulp esp_driver_touch_sens)
#
# ULP support additions to component CMakeLists.txt.
#
# 1. The LP Core app name must be unique (if multiple components use LP Core).
set(ulp_app_name lp_core_${COMPONENT_NAME})
#
# 2. Specify all C files.
# Files should be placed into a separate directory (in this case, lp_core/),
# which should not be added to COMPONENT_SRCS.
set(ulp_lp_core_sources "lp_core/main.c")
#
# 3. List all the component source files which include automatically
# generated ULP export file, ${ulp_app_name}.h:
set(ulp_exp_dep_srcs "lp_touch_main.c")
#
# 4. Call function to build ULP binary and embed in project using the argument
# values above.
ulp_embed_binary(${ulp_app_name} "${ulp_lp_core_sources}" "${ulp_exp_dep_srcs}")

View File

@@ -0,0 +1,3 @@
dependencies:
touch_sens_examples_common:
path: ${IDF_PATH}/examples/peripherals/touch_sensor/touch_sens_examples_common

View File

@@ -0,0 +1,70 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/*
* LP touch sensor example
* This code runs on LP coprocessor
*/
#include <stdint.h>
#include "soc/soc_caps.h"
#include "ulp_lp_core_utils.h"
#include "ulp_lp_core_print.h"
#include "ulp_lp_core_touch.h"
/* This variable will be exported as a public symbol, visible from main CPU: */
uint32_t touch_data = 0;
/* Touch pad threshold */
#define TOUCH_PAD_THRESHOLD 100U
#define EXAMPLE_TOUCH_CHANNEL_NUM 4
static int s_channel_id[EXAMPLE_TOUCH_CHANNEL_NUM] = {
SOC_TOUCH_MIN_CHAN_ID,
SOC_TOUCH_MIN_CHAN_ID + 1,
SOC_TOUCH_MIN_CHAN_ID + 2,
SOC_TOUCH_MIN_CHAN_ID + 3,
};
int main (void)
{
esp_err_t err = ESP_OK;
uint32_t benchmark = 0;
uint32_t smooth = 0;
uint32_t touch_value = 0;
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
/* Read the benchmark and the filtered (smooth) touch data */
if (lp_core_touch_pad_read_benchmark(s_channel_id[i], &benchmark) != ESP_OK) {
/* Skip channel this time */
continue;
}
if (lp_core_touch_pad_filter_read_smooth(s_channel_id[i], &smooth) != ESP_OK) {
/* Skip channel this time */
continue;
}
/* The difference between the benchmark and the smooth touch data
* is used to determine an active touch pad.
* Check if the touch value breaches the wakeup threshold.
*/
if (smooth > benchmark) {
if ((smooth - benchmark) > TOUCH_PAD_THRESHOLD) {
touch_value |= (1 << s_channel_id[i]);
}
}
}
/* Wake up the main CPU by LP core if a touch pad is active */
if (touch_value) {
touch_data = touch_value;
ulp_lp_core_wakeup_main_processor();
touch_value = 0;
}
/* lp_core_halt() is called automatically when main exits */
return 0;
}

View File

@@ -0,0 +1,189 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* ULP RISC-V touch sensor example */
#include <stdio.h>
#include "esp_sleep.h"
#include "ulp_lp_core.h"
#include "lp_core_main.h"
#include "driver/touch_sens.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "touch_sens_example_config.h"
#include "esp_sleep.h"
extern const uint8_t lp_core_main_bin_start[] asm("_binary_lp_core_main_bin_start");
extern const uint8_t lp_core_main_bin_end[] asm("_binary_lp_core_main_bin_end");
// Touch version 3 supports multiple sample configurations (i.e. supports frequency hopping),
// others only have one set of sample configurations.
#define EXAMPLE_TOUCH_SAMPLE_CFG_NUM TOUCH_SAMPLE_CFG_NUM // Up to 'TOUCH_SAMPLE_CFG_NUM'
#define EXAMPLE_TOUCH_CHANNEL_NUM 4
#define EXAMPLE_TOUCH_CHAN_INIT_SCAN_TIMES 3
ESP_STATIC_ASSERT(EXAMPLE_TOUCH_SAMPLE_CFG_NUM <= TOUCH_SAMPLE_CFG_NUM, "sample configuration number exceed the supported number");
ESP_STATIC_ASSERT(EXAMPLE_TOUCH_CHANNEL_NUM <= (TOUCH_MAX_CHAN_ID - TOUCH_MIN_CHAN_ID + 1), "touch channel number exceed the max supported number ");
// Active threshold to benchmark ratio. (i.e., touch will be activated when data >= benchmark * (1 + ratio))
static float s_thresh2bm_ratio[EXAMPLE_TOUCH_CHANNEL_NUM] = {
[0 ... EXAMPLE_TOUCH_CHANNEL_NUM - 1] = 0.015f, // 1.5%
};
// The touch channel IDs that used in this example
// For the corresponding GPIOs of these channel, please refer to 'touch_sensor_channel.h'
static int s_channel_id[EXAMPLE_TOUCH_CHANNEL_NUM] = {
TOUCH_MIN_CHAN_ID,
TOUCH_MIN_CHAN_ID + 1,
TOUCH_MIN_CHAN_ID + 2,
TOUCH_MIN_CHAN_ID + 3,
};
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("Touch [CH %d]", s_channel_id[i]);
/* Generate the default channel configuration and then update the active threshold based on the real benchmark */
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
for (int j = 0; j < EXAMPLE_TOUCH_SAMPLE_CFG_NUM; j++) {
chan_cfg.active_thresh[j] = (uint32_t)(benchmark[j] * s_thresh2bm_ratio[i]);
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));
}
}
static void init_touch_pad(void)
{
touch_sensor_handle_t sens_handle = NULL;
touch_channel_handle_t chan_handle[EXAMPLE_TOUCH_CHANNEL_NUM];
/* Step 1: Create a new touch sensor controller handle with default sample configuration */
touch_sensor_sample_config_t sample_cfg[TOUCH_SAMPLE_CFG_NUM] = {
TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG2(3, 29, 8, 3),
TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG2(2, 88, 31, 7),
TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG2(3, 10, 31, 7)
};
touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(EXAMPLE_TOUCH_SAMPLE_CFG_NUM, sample_cfg);
ESP_ERROR_CHECK(touch_sensor_new_controller(&sens_cfg, &sens_handle));
/* Step 2: Create and enable the new touch channel handles with default configurations */
touch_channel_config_t chan_cfg = EXAMPLE_TOUCH_CHAN_CFG_DEFAULT();
/* Allocate new touch channel on the touch controller */
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
ESP_ERROR_CHECK(touch_sensor_new_channel(sens_handle, s_channel_id[i], &chan_cfg, &chan_handle[i]));
/* Display the touch channel corresponding GPIO number, you can also know from `touch_sensor_channel.h` */
touch_chan_info_t chan_info = {};
ESP_ERROR_CHECK(touch_sensor_get_channel_info(chan_handle[i], &chan_info));
printf("Touch [CH %d] enabled on GPIO%d\n", s_channel_id[i], chan_info.chan_gpio);
}
printf("=================================\n");
/* Step 3: Confiture the default filter for the touch sensor (Note: Touch V1 uses software filter) */
touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG();
ESP_ERROR_CHECK(touch_sensor_config_filter(sens_handle, &filter_cfg));
/* Step 4: Keep the RTC_PERIPH domain power on to ensure the touch sensor works during the deep sleep */
/* Note: Here we don't need to enable the Touch Sensor wake-up by calling `touch_sensor_config_sleep_wakeup`
* because we want to decide whether to wake up in the LP program, instead of by the touch sensor hardware directly */
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
/* Step 5: 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);
/* Step 6: Enable the touch sensor */
ESP_ERROR_CHECK(touch_sensor_enable(sens_handle));
/* Step 7: Start continuous scanning, you can also trigger oneshot scanning manually */
ESP_ERROR_CHECK(touch_sensor_start_continuous_scanning(sens_handle));
}
static void lp_core_init(void)
{
esp_err_t ret = ESP_OK;
/* Set the time to wake up the LP core periodically */
ulp_lp_core_cfg_t cfg = {
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER,
.lp_timer_sleep_duration_us = 300*1000, // 300 ms
};
ret = ulp_lp_core_load_binary(lp_core_main_bin_start, (lp_core_main_bin_end - lp_core_main_bin_start));
if (ret != ESP_OK) {
printf("LP Core load failed\n");
abort();
}
ret = ulp_lp_core_run(&cfg);
if (ret != ESP_OK) {
printf("LP Core run failed\n");
abort();
}
printf("LP core loaded with firmware successfully\n");
}
void app_main(void)
{
/* If user is using USB-serial-jtag then idf monitor needs some time to
* re-connect to the USB port. We wait 1 sec here to allow for it to make the reconnection
* before we print anything. Otherwise the chip will go back to sleep again before the user
* has time to monitor any output.
*/
vTaskDelay(pdMS_TO_TICKS(1000));
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
/* Woke up by LP core, i.e., wake up the main CPU in the LP program */
if (cause == ESP_SLEEP_WAKEUP_ULP) {
printf("LP core woke up the main CPU\n");
// We can access the LP core global variable by adding `ulp_` prefix
uint32_t touch_data = ulp_touch_data;
for (int i = 0; i < EXAMPLE_TOUCH_CHANNEL_NUM; i++) {
if ((touch_data >> s_channel_id[i]) & 0x1) {
printf("T%d touched\n", s_channel_id[i]);
}
}
printf("\n");
}
/* Woke up by other source, like power_on */
else {
printf("Not an LP core wakeup. Cause = %d\n", cause);
printf("Initializing...\n");
/* Initialize Touch sensor from the main processor */
init_touch_pad();
/* Load LP Core binary and start the coprocessor */
lp_core_init();
}
/* Go to sleep, only the ULP RISC-V will run */
printf("Entering in deep sleep\n\n");
/* Small delay to ensure the messages are printed */
vTaskDelay(100);
ESP_ERROR_CHECK(esp_sleep_enable_ulp_wakeup());
esp_deep_sleep_start();
}

View File

@@ -0,0 +1,10 @@
# Enable LP Core
CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_TYPE_LP_CORE=y
CONFIG_ULP_COPROC_RESERVE_MEM=4096
# Set log level to Warning to produce clean output
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
CONFIG_BOOTLOADER_LOG_LEVEL=2
CONFIG_LOG_DEFAULT_LEVEL_WARN=y
CONFIG_LOG_DEFAULT_LEVEL=2