From dfbb108ab4c98f97946aae6f4184aea137962594 Mon Sep 17 00:00:00 2001 From: fuzhibo Date: Tue, 18 Feb 2020 20:29:20 +0800 Subject: [PATCH] Driver(touch): fix touch sensor driver for esp32s2. 1.update touch sensor driver for esp32s2; 2.update unit test for touch sensor; 3.update register files about touch sensor; --- .../driver/test/esp32/test_touch_sensor.c | 330 +++ .../driver/test/esp32s2/test_touch_sensor.c | 2200 +++++++++++++++++ components/driver/test/esp32s2/touch_scope.c | 186 ++ components/driver/test/esp32s2/touch_scope.h | 4 + .../esp32s2/include/hal/touch_sensor_hal.h | 6 + .../src/esp32s2/include/hal/touch_sensor_ll.h | 20 + 6 files changed, 2746 insertions(+) create mode 100644 components/driver/test/esp32/test_touch_sensor.c create mode 100644 components/driver/test/esp32s2/test_touch_sensor.c create mode 100644 components/driver/test/esp32s2/touch_scope.c create mode 100644 components/driver/test/esp32s2/touch_scope.h diff --git a/components/driver/test/esp32/test_touch_sensor.c b/components/driver/test/esp32/test_touch_sensor.c new file mode 100644 index 0000000000..c713d1d7ba --- /dev/null +++ b/components/driver/test/esp32/test_touch_sensor.c @@ -0,0 +1,330 @@ +/* + Tests for the touch sensor device driver +*/ +#include "esp_system.h" +#include "driver/touch_pad.h" +#include "unity.h" +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "test_utils.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/rtc_cntl_struct.h" +#include "soc/sens_reg.h" +#include "soc/sens_struct.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/rtc_cntl_struct.h" +#include "soc/rtc_io_reg.h" +#include "soc/rtc_io_struct.h" + +static const char *TAG = "test_touch"; + +#define TOUCH_READ_INVALID_VAL (0) +#define TOUCHPAD_FILTER_TOUCH_PERIOD (10) + +#define TOUCH_REG_BASE_TEST() ({ \ + TEST_ASSERT_EQUAL_UINT32(RTC_CNTL_BROWN_OUT_REG, &RTCCNTL.brown_out.val); \ + TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(SENS_SARDATE_REG, SENS_SAR_DATE), SENS.sardate.sar_date); \ + TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(RTC_IO_DATE_REG, RTC_IO_IO_DATE), RTCIO.date.date); \ +}) + +#define TOUCH_READ_ERROR (50) +#define TEST_TOUCH_COUNT_NUM (10) +#define TEST_TOUCH_CHANNEL (9) +static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = { + TOUCH_PAD_NUM0, + // TOUCH_PAD_NUM1 is GPIO0, for download. + TOUCH_PAD_NUM2, + TOUCH_PAD_NUM3, + TOUCH_PAD_NUM4, + TOUCH_PAD_NUM5, + TOUCH_PAD_NUM6, + TOUCH_PAD_NUM7, + TOUCH_PAD_NUM8, + TOUCH_PAD_NUM9, +}; + +static void printf_touch_hw_read(const char *str) +{ + uint16_t touch_value; + printf("[%s] ", str); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + while (!touch_pad_meas_is_done()) ; + touch_pad_read_raw_data(touch_list[i], &touch_value); + printf("[%d]%d ", touch_list[i], touch_value); + } + printf("\r\n"); +} + +/* + * Change the slope to get larger value from touch sensor. + */ +static void test_push_fake(touch_pad_t pad_num) +{ + touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_2, TOUCH_PAD_TIE_OPT_DEFAULT); +} + +/* + * Change the slope to get larger value from touch sensor. + */ +static void test_release_fake(touch_pad_t pad_num) +{ + touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT); +} + +static esp_err_t test_touch_sw_read(void) +{ + ESP_LOGI(TAG, "%s", __func__); + uint16_t touch_value; + + TEST_ESP_OK( touch_pad_init() ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_SW) ); + + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i], TOUCH_READ_INVALID_VAL) ); + } + + // Start task to read values sensed by pads + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_read(touch_list[i], &touch_value) ); + printf("T%d:[%4d] ", touch_list[i], touch_value); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_value); + } + printf("\n"); + + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +static esp_err_t test_touch_timer_read(void) +{ + ESP_LOGI(TAG, "%s", __func__); + uint16_t touch_value[TEST_TOUCH_CHANNEL], touch_temp[TEST_TOUCH_CHANNEL]; + int t_cnt = TEST_TOUCH_COUNT_NUM; + + TEST_ESP_OK( touch_pad_init() ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i], TOUCH_READ_INVALID_VAL) ); + } + // Start task to read values sensed by pads + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_read(touch_list[i], &touch_value[i]) ); + printf("T%d:[%4d] ", touch_list[i], touch_value[i]); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_value[i]); + } + while (t_cnt--) { + // Start task to read values sensed by pads + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_read(touch_list[i], &touch_temp[i]) ); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_temp[i]); + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_temp[i], touch_value[i]); + } + vTaskDelay(50 / portTICK_PERIOD_MS); + } + + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +static esp_err_t test_touch_filtered_read(void) +{ + ESP_LOGI(TAG, "%s", __func__); + uint16_t touch_value, touch_temp; + int t_cnt = TEST_TOUCH_COUNT_NUM; + + TEST_ESP_OK( touch_pad_init() ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i], TOUCH_READ_INVALID_VAL) ); + } + // Initialize and start a software filter to detect slight change of capacitance. + touch_pad_filter_start(TOUCHPAD_FILTER_TOUCH_PERIOD); + vTaskDelay(10 / portTICK_PERIOD_MS); + + while (t_cnt--) { + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_read(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_read_raw_data(touch_list[i], &touch_value) ); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_value); + TEST_ESP_OK( touch_pad_read_filtered(touch_list[i], &touch_temp) ); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_temp); + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_temp, touch_value); + printf("T%d:[%4d] ", touch_list[i], touch_value); + } + vTaskDelay(50 / portTICK_PERIOD_MS); + } + printf("\n"); + + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +// test the basic configuration function with right parameters and error parameters +TEST_CASE("Touch Sensor all channel read test", "[touch]") +{ + TOUCH_REG_BASE_TEST(); + TEST_ESP_OK( test_touch_sw_read() ); + TEST_ESP_OK( test_touch_timer_read() ); + TEST_ESP_OK( test_touch_filtered_read() ); +} + +static int test_touch_parameter(touch_pad_t pad_num, int meas_time, int slp_time, int vol_h, int vol_l, int vol_a, int slope) +{ + ESP_LOGI(TAG, "%s", __func__); + uint16_t touch_value; + TEST_ESP_OK( touch_pad_init() ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + TEST_ESP_OK( touch_pad_config(pad_num, TOUCH_READ_INVALID_VAL) ); + + touch_pad_set_meas_time(slp_time, meas_time); + touch_pad_set_voltage(vol_h, vol_l, vol_a); + touch_pad_set_cnt_mode(pad_num, slope, TOUCH_PAD_TIE_OPT_DEFAULT); + + // Initialize and start a software filter to detect slight change of capacitance. + touch_pad_filter_start(TOUCHPAD_FILTER_TOUCH_PERIOD); + vTaskDelay(500 / portTICK_PERIOD_MS); + + // Start task to read values sensed by pads + TEST_ESP_OK( touch_pad_read(pad_num, &touch_value) ); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_value); + printf("T%d:[%4d] ", pad_num, touch_value); + TEST_ESP_OK( touch_pad_read_raw_data(pad_num, &touch_value) ); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_value); + printf("T%d:[%4d] ", pad_num, touch_value); + TEST_ESP_OK( touch_pad_read_filtered(pad_num, &touch_value) ); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_value); + printf("T%d:[%4d] \n", pad_num, touch_value); + + TEST_ESP_OK( touch_pad_deinit() ); + + return touch_value; +} + +TEST_CASE("Touch Sensor parameters test", "[touch]") +{ + int touch_val[5] = {0}; + + ESP_LOGI(TAG, "Charge / incharge voltage level test"); + touch_val[0] = test_touch_parameter(touch_list[2], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V, + TOUCH_PAD_SLOPE_DEFAULT); + touch_val[1] = test_touch_parameter(touch_list[2], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_HVOLT_2V5, TOUCH_LVOLT_0V6, TOUCH_HVOLT_ATTEN_1V, + TOUCH_PAD_SLOPE_DEFAULT); + touch_val[2] = test_touch_parameter(touch_list[0], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_HVOLT_2V4, TOUCH_LVOLT_0V8, TOUCH_HVOLT_ATTEN_1V5, + TOUCH_PAD_SLOPE_DEFAULT); + + TEST_ASSERT_GREATER_OR_EQUAL(touch_val[0], touch_val[1]); + TEST_ASSERT_GREATER_OR_EQUAL(touch_val[1], touch_val[2]); + + ESP_LOGI(TAG, "Measure time / sleep time test"); + touch_val[0] = test_touch_parameter(touch_list[0], 0xff, 0xa, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, TOUCH_PAD_SLOPE_DEFAULT); + touch_val[1] = test_touch_parameter(touch_list[0], 0x1ff, 0xf, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, TOUCH_PAD_SLOPE_DEFAULT); + touch_val[2] = test_touch_parameter(touch_list[0], 0x2fff, 0x1f, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, TOUCH_PAD_SLOPE_DEFAULT); + + TEST_ASSERT_GREATER_OR_EQUAL(touch_val[0], touch_val[1]); + TEST_ASSERT_GREATER_OR_EQUAL(touch_val[1], touch_val[2]); + + ESP_LOGI(TAG, "Charge / incharge slope level test"); + touch_val[0] = test_touch_parameter(touch_list[1], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, 1); + touch_val[1] = test_touch_parameter(touch_list[1], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, 3); + touch_val[2] = test_touch_parameter(touch_list[1], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, 7); + + TEST_ASSERT_GREATER_OR_EQUAL(touch_val[0], touch_val[1]); + TEST_ASSERT_GREATER_OR_EQUAL(touch_val[1], touch_val[2]); +} + +static bool s_pad_activated[TOUCH_PAD_MAX]; + +static void test_touch_intr_cb(void *arg) +{ + uint32_t pad_intr = touch_pad_get_status(); + ets_printf("T%x ", pad_intr); + //clear interrupt + touch_pad_clear_status(); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + if ((pad_intr >> touch_list[i]) & 0x1) { + s_pad_activated[touch_list[i]] = true; + } + } +} + +static esp_err_t test_touch_interrupt(void) +{ + ESP_LOGI(TAG, "%s", __func__); + uint16_t touch_value; + + TEST_ESP_OK( touch_pad_init() ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V); + + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i], TOUCH_READ_INVALID_VAL) ); + } + // Initialize and start a software filter to detect slight change of capacitance. + touch_pad_filter_start(TOUCHPAD_FILTER_TOUCH_PERIOD); + vTaskDelay(10 / portTICK_PERIOD_MS); + + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + //read filtered value + TEST_ESP_OK( touch_pad_read_filtered(touch_list[i], &touch_value) ); + ESP_LOGI(TAG, "test init: touch pad [%d] val is %d", touch_list[i], touch_value); + //set interrupt threshold. + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * 2 / 3) ); + } + + // Register touch interrupt ISR + TEST_ESP_OK( touch_pad_isr_register(test_touch_intr_cb, NULL) ); + TEST_ESP_OK( touch_pad_clear_status() ); + TEST_ESP_OK( touch_pad_intr_enable() ); + + int test_cnt = TEST_TOUCH_COUNT_NUM; + while (test_cnt--) { + ESP_LOGI(TAG, "touch push"); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + test_push_fake(touch_list[i]); + } + vTaskDelay(100 / portTICK_PERIOD_MS); + printf_touch_hw_read("push"); + + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + if (s_pad_activated[touch_list[i]] == false) { + ESP_LOGE(TAG, "touch%d not active", touch_list[i]); + TEST_FAIL(); + } + } + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + s_pad_activated[touch_list[i]] = 0; + } + + ESP_LOGI(TAG, "touch release"); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + test_release_fake(touch_list[i]); + } + printf_touch_hw_read("release"); + } + + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +TEST_CASE("Touch Sensor interrupt test", "[touch]") +{ + TEST_ESP_OK( test_touch_interrupt() ); +} \ No newline at end of file diff --git a/components/driver/test/esp32s2/test_touch_sensor.c b/components/driver/test/esp32s2/test_touch_sensor.c new file mode 100644 index 0000000000..49a622f023 --- /dev/null +++ b/components/driver/test/esp32s2/test_touch_sensor.c @@ -0,0 +1,2200 @@ +/* + Tests for the touch sensor device driver +*/ +#include +#include "esp_system.h" +#include "driver/touch_pad.h" +#include "unity.h" +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +// #include "esp_event.h" +// #include "esp_wifi.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "test_utils.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/rtc_cntl_struct.h" +#include "soc/sens_reg.h" +#include "soc/sens_struct.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/rtc_cntl_struct.h" +#include "soc/rtc_io_reg.h" +#include "soc/rtc_io_struct.h" +#include "soc/apb_ctrl_reg.h" +#include "driver/rtc_io.h" + +static const char *TAG = "test_touch"; + +#define PLATFORM_SELECT (1) //0: pxp; 1: chip +#if (PLATFORM_SELECT == 0) //PXP platform +#define SET_BREAK_POINT(flag) REG_WRITE(APB_CTRL_DATE_REG, flag) +//PXP clk is slower. +#define SYS_DELAY_TIME_MOM (1/40) +#define RTC_SLOW_CLK_FLAG 1 // Slow clock is 32KHz. +void test_pxp_deinit_io(void) +{ + for (int i = 0; i < 22; i++) { + rtc_gpio_init(i); + } +} +#else +//PXP clk is slower. +#define SET_BREAK_POINT(flag) +#define SYS_DELAY_TIME_MOM (1) +#define RTC_SLOW_CLK_FLAG 0 // Slow clock is 32KHz. +void test_pxp_deinit_io(void) +{ + ; +} +#endif + +#define TOUCH_READ_INVALID_VAL (SOC_TOUCH_PAD_THRESHOLD_MAX) +#define TOUCH_READ_ERROR (100) +#define TOUCH_INTR_THRESHOLD (0.1) +#define TOUCH_EXCEED_TIME_MS (1000) + +#define TOUCH_REG_BASE_TEST() ({ \ + TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_CNTL_DATE), RTCCNTL.date.date); \ + TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(SENS_SARDATE_REG, SENS_SAR_DATE), SENS.sardate.sar_date); \ + TEST_ASSERT_EQUAL_UINT32(REG_GET_FIELD(RTC_IO_DATE_REG, RTC_IO_IO_DATE), RTCIO.date.date); \ +}) + +#define TEST_TOUCH_COUNT_NUM (10) +#define TEST_TOUCH_CHANNEL (14) +static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = { + // TOUCH_PAD_NUM0, is GPIO0, for download. + 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 +}; +// static touch_pad_t touch_list[TEST_TOUCH_CHANNEL] = { +// // TOUCH_PAD_NUM0, is GPIO0, for download. +// TOUCH_PAD_NUM2, +// TOUCH_PAD_NUM4, +// TOUCH_PAD_NUM6, +// TOUCH_PAD_NUM10, +// TOUCH_PAD_NUM11, +// TOUCH_PAD_NUM12, +// TOUCH_PAD_NUM13, +// }; +#define TOUCH_WATERPROOF_RING_PAD TOUCH_PAD_NUM1 +static touch_pad_t proximity_pad[3] = { + TOUCH_PAD_NUM2, + TOUCH_PAD_NUM3, + TOUCH_PAD_NUM4, +}; + +static QueueHandle_t que_touch = NULL; +typedef struct touch_msg { + touch_pad_intr_mask_t intr_mask; + uint32_t pad_num; + uint32_t pad_status; + uint32_t pad_val; + uint32_t slp_proxi_cnt; + uint32_t slp_proxi_base; +} touch_event_t; + +static uint32_t s_touch_timeout_mask = 0; + +static void printf_touch_hw_read(const char *str) +{ + uint32_t touch_value; + printf("[%s] ", str); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + touch_pad_read_raw_data(touch_list[i], &touch_value); + printf("[%d]%d ", touch_list[i], touch_value); + } + printf("\r\n"); +} + +static void printf_touch_baseline_read(const char *str) +{ + uint32_t touch_value; + printf("[%s] ", str); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + printf("[%d]%d ", touch_list[i], touch_value); + } + printf("\r\n"); +} + +static void printf_touch_smooth_read(const char *str) +{ + uint32_t touch_value; + printf("[%s] ", str); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + touch_pad_filter_read_smooth(touch_list[i], &touch_value); + printf("[%d]%d ", touch_list[i], touch_value); + } + printf("\r\n"); +} + + +static void test_timeout_trigger_fake(touch_pad_t pad_num) +{ + touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_0, TOUCH_PAD_TIE_OPT_DEFAULT); +} + +static void test_timeout_normal(touch_pad_t pad_num) +{ + touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT); +} + +/* + * Change the slope to get larger value from touch sensor. + */ +static void test_push_fake(touch_pad_t pad_num) +{ + touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_3, TOUCH_PAD_TIE_OPT_DEFAULT); +} + +/* + * Change the slope to get larger value from touch sensor. + */ +static void test_release_fake(touch_pad_t pad_num) +{ + touch_pad_set_cnt_mode(pad_num, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_DEFAULT); +} + +static void test_touch_push_all(void) +{ + ESP_LOGI(TAG, "touch push"); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + test_push_fake(touch_list[i]); + } +} + +static void test_touch_release_all(void) +{ + ESP_LOGI(TAG, "touch release"); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + test_release_fake(touch_list[i]); + } +} + +/* Test: if the raw data exceed noise threshold, the baseline should not be updated. */ +static void test_touch_baseline_not_update(void) +{ + uint32_t touch_val[TEST_TOUCH_CHANNEL] = {0}; + uint32_t touch_temp[TEST_TOUCH_CHANNEL] = {0}; + + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_val[i]) ); + } + for (int i = 0; i < 10; i++) { + vTaskDelay(20 / portTICK_PERIOD_MS); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_temp[i]) ); + TEST_ASSERT_EQUAL(touch_temp[i], touch_val[i]); + } + } +} + +/* + * Test the stable and change of touch sensor reading in SW mode. + */ +esp_err_t test_touch_sw_read(void) +{ + uint32_t touch_value[TEST_TOUCH_CHANNEL] = {0}; + uint32_t touch_temp[TEST_TOUCH_CHANNEL] = {0}; + uint32_t touch_push[TEST_TOUCH_CHANNEL] = {0}; + int test_cnt = TEST_TOUCH_COUNT_NUM; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_SW) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + while (test_cnt--) { + test_touch_release_all(); + + /* Read the touch sensor raw data in SW mode. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_sw_start() ); + while (!touch_pad_meas_is_done()) ; + TEST_ESP_OK( touch_pad_read_raw_data(touch_list[i], &touch_value[i]) ); + printf("T%d:[%4d] ", touch_list[i], touch_value[i]); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_value[i]); + } + printf("\n"); + /* Check the stable of reading. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + if (touch_temp[i]) { + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_temp[i], touch_value[i]); + } + touch_temp[i] = touch_value[i]; + } + + test_touch_push_all(); + + /* Read the touch sensor raw data in SW mode. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_sw_start() ); + while (!touch_pad_meas_is_done()) ; + TEST_ESP_OK( touch_pad_read_raw_data(touch_list[i], &touch_push[i]) ); + printf("T%d:[%4d] ", touch_list[i], touch_push[i]); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_push[i]); + } + printf("\n"); + /* Check the change of reading. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ASSERT_GREATER_THAN(touch_value[i], touch_push[i]); + } + } + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +/* + * Test the stable and change of touch sensor reading in timer mode. + * TEST POINT: + * 1. Timer mode for FSM. + * 2. Touch channel slope setting. + * 3. Touch reading stable. + */ +esp_err_t test_touch_timer_read(void) +{ + uint32_t touch_value[TEST_TOUCH_CHANNEL] = {0}; + uint32_t touch_temp[TEST_TOUCH_CHANNEL] = {0}; + uint32_t touch_push[TEST_TOUCH_CHANNEL] = {0}; + int test_cnt = TEST_TOUCH_COUNT_NUM; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + TEST_ESP_OK( touch_pad_init() ); + /* Set different slope for channels to test slope function. */ + printf("Set slope for channel: "); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + TEST_ESP_OK( touch_pad_set_cnt_mode(touch_list[i], i % 7 ? i % 7 : 1, TOUCH_PAD_TIE_OPT_DEFAULT) ); + printf("[ch%d-%d] ", touch_list[i], i % 7 ? i % 7 : 1); + } + printf("\n"); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + /* Wait touch sensor stable */ + vTaskDelay(50 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + + while (test_cnt--) { + test_touch_release_all(); + vTaskDelay(50 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + + // Start task to read values sensed by pads + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_read_raw_data(touch_list[i], &touch_value[i]) ); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_value[i]); + printf("T%d:[%4d] ", touch_list[i], touch_value[i]); + } + printf("\n"); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + if (touch_temp[i]) { + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_temp[i], touch_value[i]); + } + touch_temp[i] = touch_value[i]; + } + + test_touch_push_all(); + vTaskDelay(50 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + + /* Read the touch sensor raw data in FSM mode. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_read_raw_data(touch_list[i], &touch_push[i]) ); + printf("T%d:[%4d] ", touch_list[i], touch_push[i]); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_push[i]); + } + printf("\n"); + /* Check the change of reading. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ASSERT_GREATER_THAN(touch_value[i], touch_push[i]); + } + } + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +/* + * Test the filter mode. + * TEST POINT: + * 1. Timer mode for FSM. + * 2. Touch reading stable. + * 3. Touch reading init value. + * 4. Touch reading filtered value equal to raw data. + */ +esp_err_t test_touch_filtered_read(void) +{ + uint32_t touch_value[TEST_TOUCH_CHANNEL] = {0}; + uint32_t touch_temp[TEST_TOUCH_CHANNEL] = {0}; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_32, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = 4, // use for jitter mode. + .smh_lvl = TOUCH_PAD_SMOOTH_IIR_2, + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + /* Wait touch pad init done. */ + vTaskDelay(50 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + /* Test the stable for init value of touch reading. + * Ideal: baseline == raw data == smooth data. + */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value[i]) ); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_value[i]); + TEST_ESP_OK( touch_pad_read_raw_data(touch_list[i], &touch_temp[i]) ); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_temp[i]); + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_temp[i], touch_value[i]); + TEST_ESP_OK( touch_pad_filter_read_smooth(touch_list[i], &touch_temp[i]) ); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_temp[i]); + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_temp[i], touch_value[i]); + } + printf("touch filter init value:\n"); + printf_touch_hw_read("raw "); + printf_touch_baseline_read("base "); + printf_touch_smooth_read("smooth"); + printf("\n"); + + int test_cnt = TEST_TOUCH_COUNT_NUM; + while (test_cnt--) { + /* Touch reading filtered value equal to raw data. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_read_raw_data(touch_list[i], &touch_value[i]) ); + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_temp[i]) ); + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_temp[i], touch_value[i]); + TEST_ESP_OK( touch_pad_filter_read_smooth(touch_list[i], &touch_temp[i]) ); + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_temp[i], touch_value[i]); + } + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + if (touch_temp[i]) { + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_temp[i], touch_value[i]); + } + touch_temp[i] = touch_value[i]; + } + vTaskDelay(20 / portTICK_PERIOD_MS); + } + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +TEST_CASE("Touch Sensor reading test (SW, Timer, filter)", "[touch]") +{ + TOUCH_REG_BASE_TEST(); + TEST_ESP_OK( test_touch_sw_read() ); + TEST_ESP_OK( test_touch_timer_read() ); + TEST_ESP_OK( test_touch_filtered_read() ); +} + +/* + * Test the base patameter mode. + * TEST POINT: + * 1. measure time and sleep time setting. + * 2. Charge / incharge voltage threshold setting. + * 3. Touch slope setting. + * 4. Touch reading filtered value equal to raw data. + */ +int test_touch_base_parameter(touch_pad_t pad_num, int meas_time, int slp_time, + int vol_h, int vol_l, int vol_a, int slope, bool is_conn_gnd) +{ + uint32_t touch_value = 0; + uint32_t touch_temp = 0, touch_filter; + uint64_t val_sum = 0; + int test_cnt = TEST_TOUCH_COUNT_NUM; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + TEST_ESP_OK( touch_pad_init() ); + /* Note: init all channel, but test one channel. */ + // TEST_ESP_OK( touch_pad_config(pad_num) ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + + TEST_ESP_OK( touch_pad_set_cnt_mode(pad_num, slope, TOUCH_PAD_TIE_OPT_DEFAULT) ); + TEST_ESP_OK( touch_pad_set_meas_time(slp_time, meas_time) ); + TEST_ESP_OK( touch_pad_set_voltage(vol_h, vol_l, vol_a) ); + TEST_ESP_OK( touch_pad_set_inactive_connect(is_conn_gnd) ); + ESP_LOGI(TAG, "meas_time[%d]_slp_time[%d]_vol_h[%d]_vol_l[%d]_vol_a[%d]_slope[%d]_is_conn_gnd[%d]", + meas_time, slp_time, vol_h, vol_l, vol_a, slope, is_conn_gnd); + + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_32, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = 4, // use for jitter mode. + .smh_lvl = TOUCH_PAD_SMOOTH_IIR_2, + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + /* Some parameters will delay the init time. so wait longger time */ + vTaskDelay(100 / portTICK_PERIOD_MS); + + while (test_cnt--) { + /* Correctness of reading. Ideal: baseline == raw data == smooth data. */ + TEST_ESP_OK( touch_pad_read_raw_data(pad_num, &touch_value) ); + TEST_ESP_OK( touch_pad_filter_read_baseline(pad_num, &touch_filter) ); + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_filter, touch_value); + TEST_ESP_OK( touch_pad_filter_read_smooth(pad_num, &touch_filter) ); + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_filter, touch_value); + + /* Stable of reading */ + TEST_ESP_OK( touch_pad_read_raw_data(pad_num, &touch_value) ); + TEST_ESP_OK( touch_pad_read_raw_data(pad_num, &touch_value) ); + TEST_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, touch_value); + if (touch_temp) { + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_temp, touch_value); + } + touch_temp = touch_value; + + printf("T%d:[%4d] ", pad_num, touch_value); + val_sum += touch_value; // For check. + vTaskDelay(20 / portTICK_PERIOD_MS); + } + printf("\n"); + + TEST_ESP_OK( touch_pad_deinit() ); + return (uint32_t)(val_sum / TEST_TOUCH_COUNT_NUM); +} + +TEST_CASE("Touch Sensor base parameters test (meas_time, voltage, slope, inv_conn)", "[touch]") +{ + int touch_val[5] = {0}; + + ESP_LOGI(TAG, "Charge / incharge voltage level test"); + touch_val[0] = test_touch_base_parameter(touch_list[2], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_HVOLT_2V4, TOUCH_LVOLT_0V8, TOUCH_HVOLT_ATTEN_1V5, + TOUCH_PAD_SLOPE_DEFAULT, true); + touch_val[1] = test_touch_base_parameter(touch_list[2], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_HVOLT_2V5, TOUCH_LVOLT_0V6, TOUCH_HVOLT_ATTEN_1V, + TOUCH_PAD_SLOPE_DEFAULT, true); + touch_val[2] = test_touch_base_parameter(touch_list[2], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V, + TOUCH_PAD_SLOPE_DEFAULT, true); + + TEST_ASSERT_GREATER_THAN(touch_val[0], touch_val[1]); + TEST_ASSERT_GREATER_THAN(touch_val[1], touch_val[2]); + + ESP_LOGI(TAG, "Measure time / sleep time test"); + touch_val[0] = test_touch_base_parameter(touch_list[1], 0xff, 0x1ff, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, TOUCH_PAD_SLOPE_DEFAULT, true); + touch_val[1] = test_touch_base_parameter(touch_list[1], 0xfff, 0xff, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, TOUCH_PAD_SLOPE_DEFAULT, true); + touch_val[2] = test_touch_base_parameter(touch_list[1], 0x1fff, 0xf, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, TOUCH_PAD_SLOPE_DEFAULT, true); + + TEST_ASSERT_GREATER_THAN(touch_val[0], touch_val[1]); + TEST_ASSERT_GREATER_THAN(touch_val[1], touch_val[2]); + + ESP_LOGI(TAG, "Charge / incharge slope level test"); + touch_val[0] = test_touch_base_parameter(touch_list[0], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, 7, true); + touch_val[1] = test_touch_base_parameter(touch_list[0], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, 5, true); + touch_val[2] = test_touch_base_parameter(touch_list[0], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, 3, true); + + TEST_ASSERT_GREATER_THAN(touch_val[0], touch_val[1]); + TEST_ASSERT_GREATER_THAN(touch_val[1], touch_val[2]); + + /* The GND option causes larger parasitic capacitance and larger reading */ + ESP_LOGI(TAG, "Inactive connect test"); + touch_val[0] = test_touch_base_parameter(touch_list[3], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, TOUCH_PAD_SLOPE_DEFAULT, + false); + touch_val[1] = test_touch_base_parameter(touch_list[3], TOUCH_PAD_MEASURE_CYCLE_DEFAULT, TOUCH_PAD_SLEEP_CYCLE_DEFAULT, + TOUCH_PAD_HIGH_VOLTAGE_THRESHOLD, TOUCH_PAD_LOW_VOLTAGE_THRESHOLD, TOUCH_PAD_ATTEN_VOLTAGE_THRESHOLD, TOUCH_PAD_SLOPE_DEFAULT, + true); + TEST_ASSERT_GREATER_THAN(touch_val[0], touch_val[1]); +} + +/* + * Check active interrupt of touch channels. + */ +static esp_err_t test_touch_check_ch_touched(uint32_t test_ch_num, uint32_t exceed_time_ms) +{ + touch_event_t evt = {0}; + int ret = ESP_FAIL; + printf("Active: "); + while (1) { + if (pdTRUE == xQueueReceive(que_touch, &evt, exceed_time_ms / portTICK_PERIOD_MS)) { + if (evt.intr_mask & TOUCH_PAD_INTR_MASK_ACTIVE) { + printf("0x%x, ", evt.pad_status); + if (test_ch_num == __builtin_popcount(evt.pad_status)) { + ret = ESP_OK; + break; + } + } else if (evt.intr_mask & (TOUCH_PAD_INTR_MASK_DONE | TOUCH_PAD_INTR_MASK_SCAN_DONE)) { + continue; + } else { // If the interrupt type error, test error. + ESP_LOGI(TAG, "Touch[%d] intr error, status %d, evt_msk0x%x", evt.pad_num, evt.pad_status, evt.intr_mask); + break; + } + } else { + ESP_LOGI(TAG, "Touch intr exceed time"); + break; + } + } + printf("\n"); + return (esp_err_t)ret; +} + +/* + * Check inactive interrupt of touch channels. + */ +static esp_err_t test_touch_check_ch_released(uint32_t test_ch_num, uint32_t exceed_time_ms) +{ + touch_event_t evt = {0}; + int ret = ESP_FAIL; + printf("Inactive: "); + while (1) { + if (pdTRUE == xQueueReceive(que_touch, &evt, exceed_time_ms / portTICK_PERIOD_MS)) { + if (evt.intr_mask & TOUCH_PAD_INTR_MASK_INACTIVE) { + printf("0x%x, ", evt.pad_status); + if ((TEST_TOUCH_CHANNEL - test_ch_num) == __builtin_popcount(evt.pad_status)) { + ret = ESP_OK; + break; + } + } else if (evt.intr_mask & (TOUCH_PAD_INTR_MASK_DONE | TOUCH_PAD_INTR_MASK_SCAN_DONE)) { + continue; + } else { // If the interrupt type error, test error. + ESP_LOGI(TAG, "Touch[%d] intr error, status %d, evt_msk0x%x", evt.pad_num, evt.pad_status, evt.intr_mask); + break; + } + } else { + ESP_LOGI(TAG, "Touch intr exceed time"); + break; + } + } + printf("\n"); + return (esp_err_t)ret; +} + +static esp_err_t test_touch_check_ch_touched_with_proximity(uint32_t test_ch_num, uint32_t exceed_time_ms) +{ + touch_pad_proximity_t proximity; + uint16_t ch_mask = 0; + touch_event_t evt = {0}; + int ret = ESP_FAIL; + + TEST_ESP_OK( touch_pad_proximity_get_config(&proximity) ); + printf("Active: "); + while (1) { + if (pdTRUE == xQueueReceive(que_touch, &evt, exceed_time_ms / portTICK_PERIOD_MS)) { + if (evt.intr_mask & TOUCH_PAD_INTR_MASK_ACTIVE) { + printf("0x%x, ", evt.pad_status); + if (test_ch_num == __builtin_popcount(evt.pad_status)) { + ret = ESP_OK; + break; + } + } else if (evt.intr_mask & (TOUCH_PAD_INTR_MASK_SCAN_DONE)) { + touch_pad_get_channel_mask(&ch_mask); + for (int i = TOUCH_PAD_MAX - 1; i >= 0; i--) { + if (BIT(i) & ch_mask) { + if (evt.pad_num == i) { + if (proximity.meas_num == evt.slp_proxi_cnt) { + ets_printf("priximity base(%d) cnt(%d)\n", evt.slp_proxi_base, evt.slp_proxi_cnt); + } + } + } + } + continue; + } else { // If the interrupt type error, test error. + ESP_LOGI(TAG, "Touch[%d] intr error, status %d, evt_msk0x%x", evt.pad_num, evt.pad_status, evt.intr_mask); + continue;; + } + } else { + ESP_LOGI(TAG, "Touch intr exceed time"); + break; + } + } + printf("\n"); + return (esp_err_t)ret; +} + +static esp_err_t test_touch_check_ch_released_with_proximity(uint32_t test_ch_num, uint32_t exceed_time_ms) +{ + touch_pad_proximity_t proximity; + uint16_t ch_mask = 0; + touch_event_t evt = {0}; + int ret = ESP_FAIL; + + touch_pad_proximity_get_config(&proximity); + printf("Inactive: "); + while (1) { + if (pdTRUE == xQueueReceive(que_touch, &evt, exceed_time_ms / portTICK_PERIOD_MS)) { + if (evt.intr_mask & TOUCH_PAD_INTR_MASK_INACTIVE) { + printf("0x%x, ", evt.pad_status); + if ((TEST_TOUCH_CHANNEL - test_ch_num) == __builtin_popcount(evt.pad_status)) { + ret = ESP_OK; + break; + } + } else if (evt.intr_mask & (TOUCH_PAD_INTR_MASK_SCAN_DONE)) { + touch_pad_get_channel_mask(&ch_mask); + for (int i = TOUCH_PAD_MAX - 1; i >= 0; i--) { + if (BIT(i) & ch_mask) { + if (evt.pad_num == i) { + if (proximity.meas_num == evt.slp_proxi_cnt) { + ets_printf("priximity base(%d) cnt(%d)\n", evt.slp_proxi_base, evt.slp_proxi_cnt); + } + } + } + } + continue; + } else { // If the interrupt type error, test error. + ESP_LOGI(TAG, "Touch[%d] intr error, status %d, evt_msk0x%x", evt.pad_num, evt.pad_status, evt.intr_mask); + continue;; + } + } else { + ESP_LOGI(TAG, "Touch intr exceed time"); + break; + } + } + printf("\n"); + return (esp_err_t)ret; +} + +/* + * Check scan done interrupt of touch channels. + */ +static esp_err_t test_touch_check_ch_intr_scan_done(void) +{ + touch_event_t evt = {0}; + uint16_t ch_mask = 0; + int ret = ESP_FAIL; + /* Check the scan done interrupt. */ + while (1) { + if (pdTRUE == xQueueReceive(que_touch, &evt, 1000 / portTICK_PERIOD_MS)) { + /* Scan done interrupt have bug that be trigger by last two channel. */ + if (evt.intr_mask & TOUCH_PAD_INTR_MASK_SCAN_DONE) { + touch_pad_get_channel_mask(&ch_mask); + for (int i = TOUCH_PAD_MAX - 1; i >= 0; i--) { + if (BIT(i) & ch_mask) { + if (evt.pad_num == i) { + ESP_LOGI(TAG, "touch _SCAN_DONE INTR be triggered"); + ret = ESP_OK; + } + goto NEXT_TEST; + } + } + } else if (evt.intr_mask & (TOUCH_PAD_INTR_MASK_DONE | TOUCH_PAD_INTR_MASK_SCAN_DONE)) { + continue; + } else { // If the interrupt type error, test error. + ESP_LOGI(TAG, "Touch[%d] intr error, status %d, evt_msk0x%x", evt.pad_num, evt.pad_status, evt.intr_mask); + break; + } + } else { + ESP_LOGI(TAG, "Touch intr exceed time"); + break; + } + } +NEXT_TEST: + printf("\n"); + return (esp_err_t)ret; +} + +/* + * Check timeout interrupt of touch channels. + */ +static esp_err_t test_touch_check_ch_intr_timeout(touch_pad_t pad_num) +{ + int ret = ESP_FAIL; + touch_event_t evt = {0}; + + while (1) { + if (pdTRUE == xQueueReceive(que_touch, &evt, 1000 / portTICK_PERIOD_MS)) { + /* Scan done interrupt have bug that be trigger by last two channel. */ + if (evt.intr_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) { + if (pad_num == evt.pad_num) { + ESP_LOGI(TAG, "touch TIMEOUT be triggered"); + s_touch_timeout_mask = 0; + ret = ESP_OK; + break; + } else { + ets_printf("-timeout %x T[%d] status %d, evt_msk %x -\n", + s_touch_timeout_mask, evt.pad_num, evt.pad_status, evt.intr_mask); + } + } else { + continue; + } + } else { + ESP_LOGI(TAG, "Touch intr exceed time"); + break; + } + } + printf("\n"); + return (esp_err_t)ret; +} + +static void test_touch_intr_cb(void *arg) +{ + uint32_t cnt, touch_value; + int task_awoken = pdFALSE; + touch_event_t evt; + evt.intr_mask = touch_pad_read_intr_status_mask(); + evt.pad_status = touch_pad_get_status(); + evt.pad_num = touch_pad_get_current_meas_channel(); + + if (!evt.intr_mask) { + ets_printf("."); + return; + } + if (evt.intr_mask & TOUCH_PAD_INTR_MASK_SCAN_DONE) { + touch_pad_filter_read_baseline(evt.pad_num, &evt.pad_val); + touch_pad_sleep_channel_read_baseline(&touch_value); + touch_pad_sleep_channel_read_proximity_cnt(&cnt); + evt.slp_proxi_cnt = cnt; + evt.slp_proxi_base = touch_value; + // ets_printf("[intr] base(%d) cnt(%d)\n", touch_value, cnt); + } + if (evt.intr_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) { + s_touch_timeout_mask |= (BIT(evt.pad_num)); + ets_printf("-%dtout-", SENS.sar_touch_status0.touch_scan_curr); + } + + xQueueSendFromISR(que_touch, &evt, &task_awoken); + if (task_awoken == pdTRUE) { + portYIELD_FROM_ISR(); + } +} + +/* + * Test the touch active/inactive interrupt. + * TEST POINT: + * 1. Touch interrupt. + * 2. Raw data noise. + * 3. smooth data and baseline data. + */ +esp_err_t test_touch_interrupt(void) +{ + uint32_t touch_value, smooth; + int test_cnt = TEST_TOUCH_COUNT_NUM; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + if (que_touch == NULL) { + que_touch = xQueueCreate(TEST_TOUCH_CHANNEL, sizeof(touch_event_t)); + /* Should register once. */ + touch_pad_isr_register(test_touch_intr_cb, NULL, TOUCH_PAD_INTR_MASK_ALL); + } else { + xQueueReset(que_touch); + } + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_16, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = 4, // use for jitter mode. + .smh_lvl = TOUCH_PAD_SMOOTH_IIR_2, + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + /* Register touch interrupt ISR, enable intr type. */ + TEST_ESP_OK( touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE) ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + // Initialize and start a software filter to detect slight change of capacitance. + vTaskDelay(50 / portTICK_PERIOD_MS); + + /* Set threshold of touch sensor */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_filter_read_smooth(touch_list[i], &smooth) ); + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_INTR_THRESHOLD) ); + ESP_LOGI(TAG, "test init: touch pad [%d] base %d, smooth %d, thresh %d", \ + touch_list[i], touch_value, smooth, (uint32_t)(touch_value * TOUCH_INTR_THRESHOLD)); + } + + while (test_cnt--) { + test_touch_push_all(); + TEST_ESP_OK( test_touch_check_ch_touched(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("push"); + + /* Test: if the raw data exceed noise threshold, the baseline should not be updated. */ + test_touch_baseline_not_update(); + + test_touch_release_all(); + TEST_ESP_OK( test_touch_check_ch_released(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("release"); + } + + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +/* + * Test the touch active/inactive, scan_done interrupt. + * TEST POINT: + * 1. Touch interrupt. + * 2. Raw data noise. + * 3. smooth data and baseline data. + */ +esp_err_t test_touch_scan_done_interrupt(void) +{ + ESP_LOGI(TAG, " >> %s << \n", __func__); + uint32_t touch_value, smooth; + int test_cnt = TEST_TOUCH_COUNT_NUM; + + if (que_touch == NULL) { + que_touch = xQueueCreate(TEST_TOUCH_CHANNEL, sizeof(touch_event_t)); + /* Should register once. */ + TEST_ESP_OK( touch_pad_isr_register(test_touch_intr_cb, NULL, TOUCH_PAD_INTR_MASK_ALL) ); + } else { + xQueueReset(que_touch); + } + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_16, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = 4, // use for jitter mode. + .smh_lvl = TOUCH_PAD_SMOOTH_IIR_2, + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + /* Register touch interrupt ISR, enable intr type. */ + TEST_ESP_OK( touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_SCAN_DONE | TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE) ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + /* Check the scan done interrupt */ + TEST_ESP_OK( test_touch_check_ch_intr_scan_done() ); + + vTaskDelay(50 / portTICK_PERIOD_MS); + + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_filter_read_smooth(touch_list[i], &smooth) ); + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_INTR_THRESHOLD) ); + ESP_LOGI(TAG, "test init: touch pad [%d] base %d, smooth %d, thresh %d", \ + touch_list[i], touch_value, smooth, (uint32_t)(touch_value * TOUCH_INTR_THRESHOLD)); + } + + while (test_cnt--) { + test_touch_push_all(); + TEST_ESP_OK( test_touch_check_ch_touched(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("push"); + + /* Test: if the raw data exceed noise threshold, the baseline should not be updated. */ + test_touch_baseline_not_update(); + + test_touch_release_all(); + TEST_ESP_OK( test_touch_check_ch_released(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("release"); + } + + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +/* + * Test the touch active/inactive, timeout interrupt. + * TEST POINT: + * 1. Touch interrupt. + * 2. Raw data noise. + * 3. smooth data and baseline data. + */ +esp_err_t test_touch_timeout_interrupt(void) +{ + ESP_LOGI(TAG, " >> %s << \n", __func__); + uint32_t touch_value, smooth; + + if (que_touch == NULL) { + que_touch = xQueueCreate(TEST_TOUCH_CHANNEL, sizeof(touch_event_t)); + /* Should register once. */ + TEST_ESP_OK( touch_pad_isr_register(test_touch_intr_cb, NULL, TOUCH_PAD_INTR_MASK_ALL) ); + } else { + xQueueReset(que_touch); + } + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_16, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = 4, // use for jitter mode. + .smh_lvl = TOUCH_PAD_SMOOTH_IIR_2, + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + /* Register touch interrupt ISR, enable intr type. */ + TEST_ESP_OK( touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_TIMEOUT | TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE) ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + // Initialize and start a software filter to detect slight change of capacitance. + vTaskDelay(50 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_filter_read_smooth(touch_list[i], &smooth) ); + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_INTR_THRESHOLD) ); + ESP_LOGI(TAG, "test init: touch pad [%d] base %d, smooth %d, thresh %d", + touch_list[i], touch_value, smooth, (uint32_t)(touch_value * TOUCH_INTR_THRESHOLD)); + } + /* Set timeout parameter */ + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[0], &touch_value) ); + TEST_ESP_OK( touch_pad_timeout_disable() ); + TEST_ESP_OK( touch_pad_timeout_set_threshold(touch_value * 10) ); + TEST_ESP_OK( touch_pad_timeout_enable() ); + + // Only fake push one touch pad. + vTaskDelay(50 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + test_timeout_trigger_fake(touch_list[0]); + TEST_ESP_OK( test_touch_check_ch_intr_timeout(touch_list[0]) ); + test_timeout_normal(touch_list[0]); + + vTaskDelay(50 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + printf_touch_hw_read("raw "); + printf_touch_baseline_read("base "); + printf_touch_smooth_read("smooth"); + + int test_cnt = TEST_TOUCH_COUNT_NUM; + while (test_cnt--) { + test_touch_push_all(); + TEST_ESP_OK( test_touch_check_ch_touched(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("push"); + + /* Test: if the raw data exceed noise threshold, the baseline should not be updated. */ + test_touch_baseline_not_update(); + + test_touch_release_all(); + TEST_ESP_OK( test_touch_check_ch_released(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("release"); + } + + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +TEST_CASE("Touch Sensor interrupt test (active, inactive, scan_done, timeout)", "[touch]") +{ + TEST_ESP_OK( test_touch_interrupt() ); + TEST_ESP_OK( test_touch_scan_done_interrupt() ); + TEST_ESP_OK( test_touch_timeout_interrupt() ); +} + +static void test_touch_measure_step(uint32_t step) +{ + /* Fake the process of debounce. */ + // printf("measure cnt %d: [ ", step); + for (int i = 0; i < step; i++) { + for (int j = 0; j < TEST_TOUCH_CHANNEL; j++) { + TEST_ESP_OK( touch_pad_sw_start() ); + while (!touch_pad_meas_is_done()) ; + } + // printf("."); + } + // printf(" ]\n"); +} + +/* + * Test the touch active/inactive, scan_done interrupt. + * TEST POINT: + * 1. Touch interrupt. + * 2. Raw data noise. + * 3. smooth data and baseline data. + */ +esp_err_t test_touch_filter_parameter_debounce(int deb_cnt) +{ + uint32_t touch_value; + int test_cnt = 2; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + if (que_touch == NULL) { + que_touch = xQueueCreate(TEST_TOUCH_CHANNEL, sizeof(touch_event_t)); + /* Should register once. */ + TEST_ESP_OK( touch_pad_isr_register(test_touch_intr_cb, NULL, TOUCH_PAD_INTR_MASK_ALL) ); + } else { + xQueueReset(que_touch); + } + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_128, // Test jitter and filter 1/4. + .debounce_cnt = ((deb_cnt < 0) ? 1 : deb_cnt) , // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = 4, // use for jitter mode. + .smh_lvl = TOUCH_PAD_SMOOTH_OFF, + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + /* Register touch interrupt ISR, enable intr type. */ + TEST_ESP_OK( touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE) ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_SW) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + /* Run to wait the data become stable. */ + test_touch_measure_step(20); // 2 scan loop + + /* Set the threshold. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_INTR_THRESHOLD) ); + ESP_LOGI(TAG, "test init: touch pad [%d] base %d, thresh %d", \ + touch_list[i], touch_value, (uint32_t)(touch_value * TOUCH_INTR_THRESHOLD)); + } + + while (test_cnt--) { + test_touch_push_all(); + /* Fake the process of push debounce. */ + test_touch_measure_step(deb_cnt); // measure n times. touch state not changed. + TEST_ESP_ERR( ESP_FAIL, test_touch_check_ch_touched(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + test_touch_measure_step(1); // measure n+1 times. touch state changed. + TEST_ESP_OK( test_touch_check_ch_touched(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("push"); + + test_touch_release_all(); + /* Fake the process of release debounce. */ + test_touch_measure_step(deb_cnt); // measure n times. touch state not changed. + TEST_ESP_ERR( ESP_FAIL, test_touch_check_ch_released(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + test_touch_measure_step(1); // measure n+1 times. touch state changed. + TEST_ESP_OK( test_touch_check_ch_released(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("release"); + } + + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +esp_err_t test_touch_filter_parameter_neg_reset(int reset_cnt) +{ + uint32_t touch_value, base_value; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + if (que_touch == NULL) { + que_touch = xQueueCreate(TEST_TOUCH_CHANNEL, sizeof(touch_event_t)); + /* Should register once. */ + TEST_ESP_OK( touch_pad_isr_register(test_touch_intr_cb, NULL, TOUCH_PAD_INTR_MASK_ALL) ); + } else { + xQueueReset(que_touch); + } + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + reset_cnt = ((reset_cnt < 0) ? 10 : reset_cnt); + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_16, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = reset_cnt, // 10 time count. + .jitter_step = 4, // use for jitter mode. + .smh_lvl = TOUCH_PAD_SMOOTH_OFF, + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + /* Register touch interrupt ISR, enable intr type. */ + TEST_ESP_OK( touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE) ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_SW) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + /* Run to wait the data become stable. */ + test_touch_measure_step(20); // 2 scan loop + + /* Set the threshold. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_INTR_THRESHOLD) ); + ESP_LOGI(TAG, "test init: touch pad [%d] base %d, thresh %d", \ + touch_list[i], touch_value, (uint32_t)(touch_value * TOUCH_INTR_THRESHOLD)); + } + + /* 1. Fake init status is touched. */ + test_touch_push_all(); + TEST_ESP_OK( touch_pad_filter_reset_baseline(TOUCH_PAD_MAX) ); + /* Run to wait the data become stable. */ + test_touch_measure_step(20); // 2 scan loop + printf_touch_hw_read("[raw ] reset:"); + printf_touch_baseline_read("[base] reset:"); + + /* 2. Fake the touch status is released. */ + test_touch_release_all(); + /* 3. Fake measure `reset_cnt + 1` times to reset the baseline. */ + test_touch_measure_step(reset_cnt); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_read_raw_data(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &base_value) ); + if ((base_value - touch_value) < (base_value * TOUCH_INTR_THRESHOLD)) { + ESP_LOGE(TAG, "neg reset cnt err"); + TEST_FAIL(); + } + } + printf_touch_hw_read("[raw ] neg_cnt:"); + printf_touch_baseline_read("[base] neg_cnt:"); + + test_touch_measure_step(1); + /* ESP32S2 neg reset baseline to raw data */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_read_raw_data(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &base_value) ); + TEST_ASSERT_EQUAL_UINT32(base_value, touch_value); + } + printf_touch_hw_read("[raw ] neg_cnt+1:"); + printf_touch_baseline_read("[base] neg_cnt+1:"); + + int test_cnt = 2; + while (test_cnt--) { + test_touch_push_all(); + /* Fake the process of push debounce. */ + test_touch_measure_step(filter_info.debounce_cnt + 1); + TEST_ESP_OK( test_touch_check_ch_touched(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("push"); + + test_touch_release_all(); + /* Fake the process of release debounce. */ + test_touch_measure_step(filter_info.debounce_cnt + 1); + TEST_ESP_OK( test_touch_check_ch_released(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("release"); + } + + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +esp_err_t test_touch_filter_parameter_jitter(int jitter_step) +{ + uint32_t touch_value, base_value = 0; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + if (que_touch == NULL) { + que_touch = xQueueCreate(TEST_TOUCH_CHANNEL, sizeof(touch_event_t)); + /* Should register once. */ + TEST_ESP_OK( touch_pad_isr_register(test_touch_intr_cb, NULL, TOUCH_PAD_INTR_MASK_ALL) ); + } else { + xQueueReset(que_touch); + } + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + jitter_step = ((jitter_step < 0) ? 4 : jitter_step); + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_JITTER, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = jitter_step, // use for jitter mode. + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + /* Register touch interrupt ISR, enable intr type. */ + TEST_ESP_OK( touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE) ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_SW) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + /* Run to wait the data become stable. */ + test_touch_measure_step(20); // 2 scan loop + + /* Check the jitter step. */ + printf_touch_baseline_read("[smooth] t1:"); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + test_touch_measure_step(1); + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + test_push_fake(touch_list[i]); + test_touch_measure_step(1); + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &base_value) ); + TEST_ASSERT_EQUAL_UINT32(jitter_step, (base_value - touch_value)); + } + printf_touch_baseline_read("[smooth] t2:"); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + test_touch_measure_step(1); + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + test_release_fake(touch_list[i]); + test_touch_measure_step(1); + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &base_value) ); + TEST_ASSERT_EQUAL_UINT32(jitter_step, (touch_value - base_value)); + } + printf_touch_baseline_read("[smooth] t3:"); + + /* Set the threshold. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + //read baseline value + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + //set interrupt threshold. + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_INTR_THRESHOLD) ); + ESP_LOGI(TAG, "test init: touch pad [%d] base %d, thresh %d", \ + touch_list[i], touch_value, (uint32_t)(touch_value * TOUCH_INTR_THRESHOLD)); + } + + int test_cnt = 2; + while (test_cnt--) { + test_touch_push_all(); + /* Fake the process of push debounce. */ + test_touch_measure_step(filter_info.debounce_cnt + 1); + TEST_ESP_OK( test_touch_check_ch_touched(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_smooth_read("push"); + + test_touch_release_all(); + /* Fake the process of release debounce. */ + test_touch_measure_step(filter_info.debounce_cnt + 1); + TEST_ESP_OK( test_touch_check_ch_released(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_smooth_read("release"); + } + + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +TEST_CASE("Touch Sensor filter paramter test (debounce, neg_reset, jitter)", "[touch]") +{ + ESP_LOGI(TAG, "*********** touch filter debounce test ********************"); + TEST_ESP_OK( test_touch_filter_parameter_debounce(0) ); + TEST_ESP_OK( test_touch_filter_parameter_debounce(3) ); + TEST_ESP_OK( test_touch_filter_parameter_debounce(7) ); + + ESP_LOGI(TAG, "*********** touch filter neg threshold reset limit test ********************"); + TEST_ESP_OK( test_touch_filter_parameter_neg_reset(1) ); + TEST_ESP_OK( test_touch_filter_parameter_neg_reset(5) ); + TEST_ESP_OK( test_touch_filter_parameter_neg_reset(15) ); + + ESP_LOGI(TAG, "*********** touch filter jitter test ********************"); + TEST_ESP_OK( test_touch_filter_parameter_jitter(1) ); + TEST_ESP_OK( test_touch_filter_parameter_jitter(5) ); + TEST_ESP_OK( test_touch_filter_parameter_jitter(15) ); +} + +esp_err_t test_touch_denoise(uint32_t out_val[], uint32_t *denoise_val, touch_pad_denoise_grade_t grade, touch_pad_denoise_cap_t cap) +{ + uint32_t touch_value; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + ESP_LOGI(TAG, "Denoise level (%d), cap level (%d) \n", grade, cap); + if (que_touch == NULL) { + que_touch = xQueueCreate(TEST_TOUCH_CHANNEL, sizeof(touch_event_t)); + /* Should register once. */ + TEST_ESP_OK( touch_pad_isr_register(test_touch_intr_cb, NULL, TOUCH_PAD_INTR_MASK_ALL) ); + } else { + xQueueReset(que_touch); + } + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + /* Denoise setting at TouchSensor 0. */ + touch_pad_denoise_t denoise = { + /* The bits to be cancelled are determined according to the noise level. */ + .grade = (grade < 0) ? TOUCH_PAD_DENOISE_BIT4 : grade, + .cap_level = (cap < 0) ? TOUCH_PAD_DENOISE_CAP_L4 : cap, + }; + TEST_ESP_OK( touch_pad_denoise_set_config(&denoise) ); + TEST_ESP_OK( touch_pad_denoise_enable() ); + ESP_LOGI(TAG, "Denoise function init"); + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_16, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = 4, // use for jitter mode. + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + /* Register touch interrupt ISR, enable intr type. */ + TEST_ESP_OK( touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE) ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_SW) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + /* Run to wait the data become stable. */ + test_touch_measure_step(20); // 2 scan loop + + /* Set the threshold. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_INTR_THRESHOLD) ); + if (out_val) { + /* Output value for check. */ + out_val[i] = touch_value; + } + } + printf_touch_baseline_read("Denoise"); + if (denoise_val) { + touch_pad_denoise_read_data(denoise_val); + } + + int test_cnt = 1; + while (test_cnt--) { + test_touch_push_all(); + /* Fake the process of push debounce. */ + test_touch_measure_step(filter_info.debounce_cnt + 1); + TEST_ESP_OK( test_touch_check_ch_touched(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + + test_touch_release_all(); + /* Fake the process of release debounce. */ + test_touch_measure_step(filter_info.debounce_cnt + 1); + TEST_ESP_OK( test_touch_check_ch_released(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + } + + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +TEST_CASE("Touch Sensor denoise test (cap, level)", "[touch]") +{ + uint32_t val_1[TEST_TOUCH_CHANNEL]; + uint32_t val_2[TEST_TOUCH_CHANNEL]; + uint32_t val_3[TEST_TOUCH_CHANNEL]; + uint32_t denoise_val[TOUCH_PAD_DENOISE_CAP_MAX]; + + ESP_LOGI(TAG, "*********** touch filter denoise level test ********************"); + TEST_ESP_OK( test_touch_denoise(val_1, NULL, TOUCH_PAD_DENOISE_BIT4, TOUCH_PAD_DENOISE_CAP_L0) ); + TEST_ESP_OK( test_touch_denoise(val_2, NULL, TOUCH_PAD_DENOISE_BIT8, TOUCH_PAD_DENOISE_CAP_L0) ); + TEST_ESP_OK( test_touch_denoise(val_3, NULL, TOUCH_PAD_DENOISE_BIT12, TOUCH_PAD_DENOISE_CAP_L0) ); + + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ASSERT_GREATER_OR_EQUAL(val_3[i], val_2[i]); + TEST_ASSERT_GREATER_OR_EQUAL(val_2[i], val_1[i]); + } + + ESP_LOGI(TAG, "*********** touch filter denoise cap level test ********************"); + TEST_ESP_OK( test_touch_denoise(NULL, &denoise_val[0], TOUCH_PAD_DENOISE_BIT8, TOUCH_PAD_DENOISE_CAP_L0) ); + TEST_ESP_OK( test_touch_denoise(NULL, &denoise_val[1], TOUCH_PAD_DENOISE_BIT8, TOUCH_PAD_DENOISE_CAP_L1) ); + TEST_ESP_OK( test_touch_denoise(NULL, &denoise_val[2], TOUCH_PAD_DENOISE_BIT8, TOUCH_PAD_DENOISE_CAP_L2) ); + TEST_ESP_OK( test_touch_denoise(NULL, &denoise_val[3], TOUCH_PAD_DENOISE_BIT8, TOUCH_PAD_DENOISE_CAP_L3) ); + TEST_ESP_OK( test_touch_denoise(NULL, &denoise_val[4], TOUCH_PAD_DENOISE_BIT8, TOUCH_PAD_DENOISE_CAP_L4) ); + TEST_ESP_OK( test_touch_denoise(NULL, &denoise_val[5], TOUCH_PAD_DENOISE_BIT8, TOUCH_PAD_DENOISE_CAP_L5) ); + TEST_ESP_OK( test_touch_denoise(NULL, &denoise_val[6], TOUCH_PAD_DENOISE_BIT8, TOUCH_PAD_DENOISE_CAP_L6) ); + TEST_ESP_OK( test_touch_denoise(NULL, &denoise_val[7], TOUCH_PAD_DENOISE_BIT8, TOUCH_PAD_DENOISE_CAP_L7) ); + + printf("denoise read: "); + for (int i = 0; i < TOUCH_PAD_DENOISE_CAP_MAX - 1; i++) { + TEST_ASSERT_GREATER_OR_EQUAL(denoise_val[i], denoise_val[i + 1]); + printf("%d ", denoise_val[i]); + } + printf("\n"); +} + +esp_err_t test_touch_waterproof(void) +{ + uint32_t touch_value; + int test_cnt = TEST_TOUCH_COUNT_NUM; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + if (que_touch == NULL) { + que_touch = xQueueCreate(TEST_TOUCH_CHANNEL, sizeof(touch_event_t)); + /* Should register once. */ + touch_pad_isr_register(test_touch_intr_cb, NULL, TOUCH_PAD_INTR_MASK_ALL); + } else { + xQueueReset(que_touch); + } + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + /* Denoise setting at TouchSensor 0. */ + touch_pad_denoise_t denoise = { + /* The bits to be cancelled are determined according to the noise level. */ + .grade = TOUCH_PAD_DENOISE_BIT4, + .cap_level = TOUCH_PAD_DENOISE_CAP_L4, + }; + TEST_ESP_OK( touch_pad_denoise_set_config(&denoise) ); + TEST_ESP_OK( touch_pad_denoise_enable() ); + ESP_LOGI(TAG, "Denoise function init"); + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_16, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = 4, // use for jitter mode. + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + /* Register touch interrupt ISR, enable intr type. */ + TEST_ESP_OK( touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE) ); + /* Waterproof function */ + touch_pad_waterproof_t waterproof = { + .guard_ring_pad = TOUCH_WATERPROOF_RING_PAD, // If no ring pad, set 0; + /* It depends on the number of the parasitic capacitance of the shield pad. */ + .shield_driver = TOUCH_PAD_SHIELD_DRV_L0, //40pf + }; + TEST_ESP_OK( touch_pad_waterproof_set_config(&waterproof) ); + TEST_ESP_OK( touch_pad_waterproof_enable() ); + ESP_LOGI(TAG, "touch pad waterproof init"); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + vTaskDelay(50 / portTICK_PERIOD_MS); + + /* Set the threshold. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_INTR_THRESHOLD) ); + } + + while (test_cnt--) { + test_touch_push_all(); + vTaskDelay(20 / portTICK_PERIOD_MS); + TEST_ESP_OK( test_touch_check_ch_touched(TEST_TOUCH_CHANNEL - 1, TOUCH_EXCEED_TIME_MS) ); // take off shield pad + printf_touch_hw_read("push"); + + test_touch_release_all(); + vTaskDelay(20 / portTICK_PERIOD_MS); + TEST_ESP_OK( test_touch_check_ch_released(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("release"); + } + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +TEST_CASE("Touch Sensor waterproof guard test", "[touch]") +{ + ESP_LOGI(TAG, "*********** touch filter waterproof guard test ********************"); + TEST_ESP_OK( test_touch_waterproof() ); +} + +esp_err_t test_touch_proximity(int meas_num) +{ + ESP_LOGI(TAG, " >> %s << \n", __func__); + + uint32_t touch_value; + if (que_touch == NULL) { + que_touch = xQueueCreate(TEST_TOUCH_CHANNEL, sizeof(touch_event_t)); + /* Should register once. */ + TEST_ESP_OK( touch_pad_isr_register(test_touch_intr_cb, NULL, TOUCH_PAD_INTR_MASK_ALL) ); + } else { + xQueueReset(que_touch); + } + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + /* Denoise setting at TouchSensor 0. */ + touch_pad_denoise_t denoise = { + /* The bits to be cancelled are determined according to the noise level. */ + .grade = TOUCH_PAD_DENOISE_BIT4, + .cap_level = TOUCH_PAD_DENOISE_CAP_L4, + }; + TEST_ESP_OK( touch_pad_denoise_set_config(&denoise) ); + TEST_ESP_OK( touch_pad_denoise_enable() ); + ESP_LOGI(TAG, "Denoise function init"); + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_16, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = 4, // use for jitter mode. + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + /* Register touch interrupt ISR, enable intr type. */ + TEST_ESP_OK( touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE) ); + /* Waterproof function */ + touch_pad_waterproof_t waterproof = { + .guard_ring_pad = TOUCH_WATERPROOF_RING_PAD,// If no ring pad, set 0; + /* It depends on the number of the parasitic capacitance of the shield pad. */ + .shield_driver = TOUCH_PAD_SHIELD_DRV_L0, //40pf + }; + TEST_ESP_OK( touch_pad_waterproof_set_config(&waterproof) ); + TEST_ESP_OK( touch_pad_waterproof_enable() ); + ESP_LOGI(TAG, "touch pad waterproof init"); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + vTaskDelay(50 / portTICK_PERIOD_MS); + + touch_pad_proximity_t proximity = { + .select_pad[0] = proximity_pad[0], + .select_pad[1] = proximity_pad[1], + .select_pad[2] = proximity_pad[2], + .meas_num = meas_num < 0 ? 16 : meas_num, + }; + /* Set the threshold. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + if (touch_list[i] == proximity.select_pad[0] || + touch_list[i] == proximity.select_pad[1] || + touch_list[i] == proximity.select_pad[2]) { + /* The threshold of proximity pad is the sum of touch reading `meas_num` times */ + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], + proximity.meas_num * touch_value * (1 + TOUCH_INTR_THRESHOLD)) ); + ESP_LOGI(TAG, "proximity pad [%d] base %d, thresh %d", touch_list[i], touch_value, + (uint32_t)(proximity.meas_num * touch_value * (1 + TOUCH_INTR_THRESHOLD))); + } else { + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_INTR_THRESHOLD) ); + ESP_LOGI(TAG, "touch pad [%d] base %d, thresh %d", \ + touch_list[i], touch_value, (uint32_t)(touch_value * TOUCH_INTR_THRESHOLD)); + } + } + /* Should stop the measure, then change the config. */ + while (!touch_pad_meas_is_done()); + TEST_ESP_OK( touch_pad_fsm_stop() ); + /* Proximity function */ + TEST_ESP_OK( touch_pad_proximity_set_config(&proximity) ); + ESP_LOGI(TAG, "touch pad proximity init"); + TEST_ESP_OK( touch_pad_fsm_start() ); + + vTaskDelay(20 / portTICK_PERIOD_MS); + int test_cnt = TEST_TOUCH_COUNT_NUM; + while (test_cnt--) { + test_touch_push_all(); + vTaskDelay(20 / portTICK_PERIOD_MS); + TEST_ESP_OK( test_touch_check_ch_touched(TEST_TOUCH_CHANNEL - 1, TOUCH_EXCEED_TIME_MS) ); // take off shield pad + printf_touch_hw_read("push"); + + test_touch_release_all(); + vTaskDelay(20 / portTICK_PERIOD_MS); + TEST_ESP_OK( test_touch_check_ch_released(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("release"); + } + + TEST_ESP_OK( touch_pad_deinit() ); + + return ESP_OK; +} + +TEST_CASE("Touch Sensor proximity test", "[touch]") +{ + ESP_LOGI(TAG, "*********** touch proximity test ********************"); + + TEST_ESP_OK( test_touch_proximity(5) ); + TEST_ESP_OK( test_touch_proximity(1) ); +} + +esp_err_t test_touch_sleep_reading_stable(touch_pad_t sleep_pad) +{ + uint32_t touch_temp = 0; + uint32_t touch_value, smooth, ret_val; + int test_cnt = TEST_TOUCH_COUNT_NUM; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + if (que_touch == NULL) { + que_touch = xQueueCreate(TEST_TOUCH_CHANNEL, sizeof(touch_event_t)); + /* Should register once. */ + TEST_ESP_OK( touch_pad_isr_register(test_touch_intr_cb, NULL, TOUCH_PAD_INTR_MASK_ALL) ); + } else { + xQueueReset(que_touch); + } + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + // /* Denoise setting at TouchSensor 0. */ + touch_pad_denoise_t denoise = { + /* The bits to be cancelled are determined according to the noise level. */ + .grade = TOUCH_PAD_DENOISE_BIT4, + .cap_level = TOUCH_PAD_DENOISE_CAP_L4, + }; + TEST_ESP_OK( touch_pad_denoise_set_config(&denoise) ); + TEST_ESP_OK( touch_pad_denoise_enable() ); + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_16, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = 4, // use for jitter mode. + .smh_lvl = TOUCH_PAD_SMOOTH_OFF, + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + touch_pad_sleep_channel_t slp_config = { + .touch_num = sleep_pad, + .en_proximity = false, + }; + TEST_ESP_OK( touch_pad_sleep_channel_set_config(&slp_config) ); + /* Register touch interrupt ISR, enable intr type. */ + TEST_ESP_OK( touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE) ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + // Initialize and start a software filter to detect slight change of capacitance. + vTaskDelay(50 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + + /* Set threshold of touch sensor */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_filter_read_smooth(touch_list[i], &smooth) ); + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_INTR_THRESHOLD) ); + ESP_LOGI(TAG, "test init: touch pad [%d] base %d, smooth %d, thresh %d", + touch_list[i], touch_value, smooth, (uint32_t)(touch_value * TOUCH_INTR_THRESHOLD)); + } + + /* Sleep channel setting */ + TEST_ESP_OK( touch_pad_sleep_channel_read_baseline(&touch_value) ); + TEST_ESP_OK( touch_pad_sleep_set_threshold(touch_value * TOUCH_INTR_THRESHOLD) ); + vTaskDelay(50 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + + while (test_cnt--) { + /* Touch reading filtered value equal to raw data. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_sleep_channel_read_data(&touch_value) ); + TEST_ESP_OK( touch_pad_sleep_channel_read_baseline(&touch_temp) ); + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_temp, touch_value); + TEST_ESP_OK( touch_pad_sleep_channel_read_smooth(&touch_temp) ); + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_temp, touch_value); + } + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + if (touch_temp) { + TEST_ASSERT_UINT32_WITHIN(TOUCH_READ_ERROR, touch_temp, touch_value); + } + touch_temp = touch_value; + } + vTaskDelay(20 / portTICK_PERIOD_MS); + } + TEST_ESP_OK( touch_pad_sleep_channel_read_baseline(&ret_val) ); + + TEST_ESP_OK( touch_pad_deinit() ); + + return ret_val; +} + + +TEST_CASE("Touch Sensor sleep pad reading stable test", "[touch]") +{ + ESP_LOGI(TAG, "*********** touch sleep pad low power (wakeup) test ********************"); + test_touch_sleep_reading_stable(touch_list[0]); +} + +/* + * Test the touch sleep pad interrupt in normal mode. + * TEST POINT: + * 1. Touch sleep pad interrupt. + * 2. sleep pad reading. + * 3. sleep pad enable proximity. + */ +uint32_t test_touch_sleep_pad_proximity(touch_pad_t sleep_pad, bool is_proximity, uint32_t meas_num) +{ + uint32_t touch_value, smooth, ret_val, dbc; + uint32_t measure_out; + uint32_t proximity_cnt; + uint32_t touch_thres; + int test_cnt = TEST_TOUCH_COUNT_NUM; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + if (que_touch == NULL) { + que_touch = xQueueCreate(TEST_TOUCH_CHANNEL, sizeof(touch_event_t)); + /* Should register once. */ + TEST_ESP_OK( touch_pad_isr_register(test_touch_intr_cb, NULL, TOUCH_PAD_INTR_MASK_ALL) ); + } else { + xQueueReset(que_touch); + } + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + /* Denoise setting at TouchSensor 0. */ + touch_pad_denoise_t denoise = { + /* The bits to be cancelled are determined according to the noise level. */ + .grade = TOUCH_PAD_DENOISE_BIT4, + .cap_level = TOUCH_PAD_DENOISE_CAP_L4, + }; + TEST_ESP_OK( touch_pad_denoise_set_config(&denoise) ); + TEST_ESP_OK( touch_pad_denoise_enable() ); + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_16, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = 4, // use for jitter mode. + .smh_lvl = TOUCH_PAD_SMOOTH_OFF, + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + /* Sleep channel setting */ + touch_pad_sleep_channel_t slp_config = { + .touch_num = sleep_pad, + .en_proximity = is_proximity, + }; + TEST_ESP_OK( touch_pad_sleep_channel_set_config(&slp_config) ); + /* Register touch interrupt ISR, enable intr type. */ + TEST_ESP_OK( touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_SCAN_DONE | TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE) ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + // Initialize and start a software filter to detect slight change of capacitance. + vTaskDelay(100 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + + if (is_proximity) { + touch_pad_proximity_t proximity = { + .select_pad[0] = sleep_pad, + .select_pad[1] = 0, + .select_pad[2] = 0, + .meas_num = meas_num == 0 ? 16 : meas_num, + }; + /* Set the threshold. */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + if (touch_list[i] == sleep_pad) { + touch_pad_sleep_channel_read_smooth(&touch_value); + touch_pad_sleep_set_threshold(proximity.meas_num * touch_value * (1 + TOUCH_INTR_THRESHOLD)); + ESP_LOGI(TAG, "Sleep pad [%d] base %d, thresh %d", touch_list[i], touch_value, + (uint32_t)(proximity.meas_num * touch_value * (1 + TOUCH_INTR_THRESHOLD))); + } else if (touch_list[i] == proximity.select_pad[0] || + touch_list[i] == proximity.select_pad[1] || + touch_list[i] == proximity.select_pad[2]) { + // TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + touch_pad_sleep_channel_read_smooth(&touch_value); + /* The threshold of proximity pad is the sum of touch reading `meas_num` times */ + touch_pad_sleep_set_threshold( proximity.meas_num * touch_value * (1 + TOUCH_INTR_THRESHOLD)); + ESP_LOGI(TAG, "proximity pad [%d] base %d, thresh %d", touch_list[i], touch_value, + (uint32_t)(proximity.meas_num * touch_value * (1 + TOUCH_INTR_THRESHOLD))); + } else { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_INTR_THRESHOLD) ); + ESP_LOGI(TAG, "touch pad [%d] base %d, thresh %d", \ + touch_list[i], touch_value, (uint32_t)(touch_value * TOUCH_INTR_THRESHOLD)); + } + } + /* Should stop the measure, then change the config. */ + while (!touch_pad_meas_is_done()); + TEST_ESP_OK( touch_pad_fsm_stop() ); + /* Proximity function */ + TEST_ESP_OK( touch_pad_proximity_set_config(&proximity) ); + ESP_LOGI(TAG, "touch pad proximity init"); + TEST_ESP_OK( touch_pad_fsm_start() ); + vTaskDelay(100 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + } else { + /* Set threshold of touch sensor */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_filter_read_smooth(touch_list[i], &smooth) ); + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_INTR_THRESHOLD) ); + ESP_LOGI(TAG, "test init: touch pad [%d] base %d, smooth %d, thresh %d", + touch_list[i], touch_value, smooth, (uint32_t)(touch_value * TOUCH_INTR_THRESHOLD)); + } + /* Sleep channel setting */ + TEST_ESP_OK( touch_pad_sleep_channel_read_smooth(&touch_value) ); + TEST_ESP_OK( touch_pad_sleep_set_threshold(touch_value * TOUCH_INTR_THRESHOLD) ); + vTaskDelay(50 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + } + + TEST_ESP_OK( touch_pad_sleep_channel_read_smooth(&ret_val) ); + + while (test_cnt--) { + test_touch_push_all(); + TEST_ESP_OK( test_touch_check_ch_touched_with_proximity(TEST_TOUCH_CHANNEL, 5000) ); + printf_touch_hw_read("push"); + if (is_proximity) { + TEST_ESP_OK( touch_pad_sleep_channel_read_smooth(&smooth) ); + TEST_ESP_OK( touch_pad_sleep_channel_read_baseline(&touch_value) ); + TEST_ESP_OK( touch_pad_proximity_data_get(sleep_pad, &measure_out) ); + TEST_ESP_OK( touch_pad_sleep_channel_read_proximity_cnt(&proximity_cnt) ); + TEST_ESP_OK( touch_pad_sleep_channel_read_debounce(&dbc) ); + TEST_ESP_OK( touch_pad_sleep_get_threshold(&touch_thres) ); + printf("touch slp smooth %d, base %d, proxi %d cnt %d dbc %d thres%d status 0x%x\n", + smooth, touch_value, measure_out, proximity_cnt, dbc, + touch_thres, touch_pad_get_status()); + } + test_touch_release_all(); + TEST_ESP_OK( test_touch_check_ch_released_with_proximity(TEST_TOUCH_CHANNEL, 5000) ); + printf_touch_hw_read("release"); + if (is_proximity) { + TEST_ESP_OK( touch_pad_sleep_channel_read_smooth(&smooth) ); + TEST_ESP_OK( touch_pad_sleep_channel_read_baseline(&touch_value) ); + TEST_ESP_OK( touch_pad_proximity_data_get(sleep_pad, &measure_out) ); + TEST_ESP_OK( touch_pad_sleep_channel_read_proximity_cnt(&proximity_cnt) ); + TEST_ESP_OK( touch_pad_sleep_channel_read_debounce(&dbc) ); + printf("touch slp smooth %d, base %d, proxi %d cnt %d dbc %d status 0x%x\n", + smooth, touch_value, measure_out, proximity_cnt, dbc, touch_pad_get_status()); + } + } + + TEST_ESP_OK( touch_pad_deinit() ); + + return ret_val; +} + +TEST_CASE("Touch Sensor sleep pad and proximity interrupt test", "[touch]") +{ + ESP_LOGI(TAG, "*********** touch sleep pad interrupt test ********************"); + test_touch_sleep_pad_proximity(touch_list[0], false, 0); + test_touch_sleep_pad_proximity(touch_list[0], false, 0); + test_touch_sleep_pad_proximity(touch_list[0], false, 0); + + ESP_LOGI(TAG, "*********** touch sleep pad interrupt (proximity) test ********************"); + test_touch_sleep_pad_proximity(touch_list[0], true, 1); + test_touch_sleep_pad_proximity(touch_list[0], true, 3); + test_touch_sleep_pad_proximity(touch_list[0], true, 5); +} + +/* + * Test the touch sleep pad interrupt in normal mode. + * TEST POINT: + * 1. Touch sleep pad interrupt. + * 2. sleep pad reading. + * 3. denoise, waterproof + */ +esp_err_t test_touch_sleep_pad_interrupt_wakeup_deep_sleep(touch_pad_t sleep_pad) +{ + uint32_t touch_value, smooth, raw; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + if (que_touch == NULL) { + que_touch = xQueueCreate(TEST_TOUCH_CHANNEL, sizeof(touch_event_t)); + /* Should register once. */ + TEST_ESP_OK( touch_pad_isr_register(test_touch_intr_cb, NULL, TOUCH_PAD_INTR_MASK_ALL) ); + } else { + xQueueReset(que_touch); + } + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + // /* Denoise setting at TouchSensor 0. */ + touch_pad_denoise_t denoise = { + /* The bits to be cancelled are determined according to the noise level. */ + .grade = TOUCH_PAD_DENOISE_BIT4, + .cap_level = TOUCH_PAD_DENOISE_CAP_L4, + }; + TEST_ESP_OK( touch_pad_denoise_set_config(&denoise) ); + TEST_ESP_OK( touch_pad_denoise_disable() ); + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_16, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 3, // 0% + .noise_thr = 0, // 50% + .noise_neg_thr = 0, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = 4, // use for jitter mode. + .smh_lvl = TOUCH_PAD_SMOOTH_OFF, + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + /* Sleep channel setting */ + touch_pad_sleep_channel_t slp_config = { + .touch_num = sleep_pad, + .en_proximity = false, + }; + TEST_ESP_OK( touch_pad_sleep_channel_set_config(&slp_config) ); + /* Register touch interrupt ISR, enable intr type. */ + TEST_ESP_OK( touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE) ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + + // Initialize and start a software filter to detect slight change of capacitance. + vTaskDelay(50 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + + /* Set threshold of touch sensor */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_filter_read_smooth(touch_list[i], &smooth) ); + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_INTR_THRESHOLD) ); + ESP_LOGI(TAG, "test init: touch pad [%d] base %d, smooth %d, thresh %d", + touch_list[i], touch_value, smooth, (uint32_t)(touch_value * TOUCH_INTR_THRESHOLD)); + } + + /* Sleep channel setting */ + TEST_ESP_OK( touch_pad_sleep_channel_read_baseline(&touch_value) ); + TEST_ESP_OK( touch_pad_sleep_set_threshold(touch_value * TOUCH_INTR_THRESHOLD) ); + + vTaskDelay(50 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + + test_touch_push_all(); + TEST_ESP_OK( test_touch_check_ch_touched(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("push"); + TEST_ESP_OK( touch_pad_sleep_channel_read_smooth(&smooth) ); + TEST_ESP_OK( touch_pad_sleep_channel_read_data(&raw) ); + TEST_ESP_OK( touch_pad_sleep_channel_read_baseline(&touch_value) ); + printf("touch slp raw %d, smooth %d, base %d, status 0x%x\n", raw, smooth, touch_value, touch_pad_get_status()); + + test_touch_release_all(); + TEST_ESP_OK( test_touch_check_ch_released(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("release"); + TEST_ESP_OK( touch_pad_sleep_channel_read_smooth(&smooth) ); + TEST_ESP_OK( touch_pad_sleep_channel_read_data(&raw) ); + TEST_ESP_OK( touch_pad_sleep_channel_read_baseline(&touch_value) ); + printf("touch slp raw %d, smooth %d, base %d, status 0x%x\n", raw, smooth, touch_value, touch_pad_get_status()); + + return ESP_OK; +} + +#include +#include "esp_sleep.h" + +static RTC_DATA_ATTR struct timeval sleep_enter_time; + +static void test_deep_sleep_init(void) +{ + struct timeval now; + gettimeofday(&now, NULL); + int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000; + printf("RTC_CNTL_SLP_WAKEUP_CAUSE_REG %x\n", REG_READ(RTC_CNTL_SLP_WAKEUP_CAUSE_REG)); + switch (esp_sleep_get_wakeup_cause()) { + case ESP_SLEEP_WAKEUP_EXT1: { + uint64_t wakeup_pin_mask = esp_sleep_get_ext1_wakeup_status(); + if (wakeup_pin_mask != 0) { + int pin = __builtin_ffsll(wakeup_pin_mask) - 1; + printf("Wake up from GPIO %d\n", pin); + } else { + printf("Wake up from GPIO\n"); + } + break; + } + case ESP_SLEEP_WAKEUP_TIMER: { + printf("Wake up from timer. Time spent in deep sleep: %dms\n", sleep_time_ms); + break; + } + case ESP_SLEEP_WAKEUP_TOUCHPAD: { + printf("Wake up from touch on pad %d\n", esp_sleep_get_touchpad_wakeup_status()); + break; + } + case ESP_SLEEP_WAKEUP_UNDEFINED: + default: { + printf("Not a deep sleep reset\n"); + ESP_LOGI(TAG, "*********** touch sleep pad wakeup test ********************"); + /* Sleep pad should be init once. */ + test_touch_sleep_pad_interrupt_wakeup_deep_sleep(touch_list[0]); + } + } + + vTaskDelay(100 * SYS_DELAY_TIME_MOM / portTICK_PERIOD_MS); + + // const int wakeup_time_sec = 10; + // printf("Enabling timer wakeup, %ds\n", wakeup_time_sec); + // esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000); + + // const int ext_wakeup_pin_1 = 2; + // const uint64_t ext_wakeup_pin_1_mask = 1ULL << ext_wakeup_pin_1; + // const int ext_wakeup_pin_2 = 4; + // const uint64_t ext_wakeup_pin_2_mask = 1ULL << ext_wakeup_pin_2; + + // printf("Enabling EXT1 wakeup on pins GPIO%d, GPIO%d\n", ext_wakeup_pin_1, ext_wakeup_pin_2); + // esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask | ext_wakeup_pin_2_mask, ESP_EXT1_WAKEUP_ANY_HIGH); + + printf("Enabling touch pad wakeup\n"); + esp_sleep_enable_touchpad_wakeup(); + // esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); + + printf("Entering deep sleep\n"); + gettimeofday(&sleep_enter_time, NULL); +} + +// TEST_CASE("Touch Sensor sleep pad wakeup deep sleep test", "[touch]") +void test_touch_sleep_wakeup(void) +{ + test_deep_sleep_init(); + + /* Change the work duty of touch sensor to reduce current. */ + touch_pad_set_meas_time(100, TOUCH_PAD_MEASURE_CYCLE_DEFAULT); + + /* Close PD current in deep sleep. */ + RTCCNTL.bias_conf.pd_cur_deep_slp = 1; + RTCCNTL.bias_conf.pd_cur_monitor = 1; + RTCCNTL.bias_conf.bias_sleep_deep_slp = 1; + RTCCNTL.bias_conf.bias_sleep_monitor = 1; + + esp_deep_sleep_start(); +} + +#include "touch_scope.h" +/* + * 0: 10 channels raw/smooth/baseline data debug. + * 1: 5 channges smooth + baseline data debug. + * 2: 1 channels filter data. + */ +#define SCOPE_DEBUG_TYPE 2 +#define TOUCH_THRESHOLD 0.5 +#define TOUCH_SHELD_PAD (1) +#define SCOPE_DEBUG_CHANNEL_MAX (10) +#define SCOPE_DEBUG_ENABLE (0) +#define SCOPE_UART_BUADRATE (256000) +#define SCOPE_DEBUG_FREQ_MS (50) + +void test_touch_slope_debug(int pad_num) +{ + touch_event_t evt; + uint32_t touch_value, smooth; + + ESP_LOGI(TAG, " >> %s << \n", __func__); + if (que_touch == NULL) { + que_touch = xQueueCreate(TEST_TOUCH_CHANNEL, sizeof(touch_event_t)); + /* Should register once. */ + touch_pad_isr_register(test_touch_intr_cb, NULL, TOUCH_PAD_INTR_MASK_ALL); + } else { + xQueueReset(que_touch); + } + TEST_ESP_OK( touch_pad_init() ); + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_config(touch_list[i]) ); + } + touch_filter_config_t filter_info = { + .mode = TOUCH_PAD_FILTER_IIR_32, // Test jitter and filter 1/4. + .debounce_cnt = 1, // 1 time count. + .hysteresis_thr = 2, // 6.25% + .noise_thr = 3, // 50% + .noise_neg_thr = 3, // 50% + .neg_noise_limit = 10, // 10 time count. + .jitter_step = 4, // use for jitter mode. + .smh_lvl = TOUCH_PAD_SMOOTH_IIR_2, + }; + TEST_ESP_OK( touch_pad_filter_set_config(&filter_info) ); + TEST_ESP_OK( touch_pad_filter_enable() ); + /* Register touch interrupt ISR, enable intr type. */ + TEST_ESP_OK( touch_pad_intr_enable(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_INACTIVE) ); + TEST_ESP_OK( touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER) ); + TEST_ESP_OK( touch_pad_fsm_start() ); + /* Waterproof function */ + touch_pad_waterproof_t waterproof = { + .guard_ring_pad = 0, // If no ring pad, set 0; + /* It depends on the number of the parasitic capacitance of the shield pad. */ + .shield_driver = TOUCH_PAD_SHIELD_DRV_L2, //40pf + }; + TEST_ESP_OK( touch_pad_waterproof_set_config(&waterproof) ); + TEST_ESP_OK( touch_pad_waterproof_enable() ); + ESP_LOGI(TAG, "touch pad waterproof init"); + + // Initialize and start a software filter to detect slight change of capacitance. + vTaskDelay(50 / portTICK_PERIOD_MS); + + /* Set threshold of touch sensor */ + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + TEST_ESP_OK( touch_pad_filter_read_baseline(touch_list[i], &touch_value) ); + TEST_ESP_OK( touch_pad_filter_read_smooth(touch_list[i], &smooth) ); + TEST_ESP_OK( touch_pad_set_thresh(touch_list[i], touch_value * TOUCH_THRESHOLD) ); + ESP_LOGI(TAG, "test init: touch pad [%d] base %d, smooth %d, thresh %d", \ + touch_list[i], touch_value, smooth, (uint32_t)(touch_value * TOUCH_THRESHOLD)); + } + + float scope_temp[SCOPE_DEBUG_CHANNEL_MAX] = {0}; // max scope channel is 10. + uint32_t scope_data[SCOPE_DEBUG_CHANNEL_MAX] = {0}; // max scope channel is 10. + test_tp_scope_debug_init(0, -1, -1, SCOPE_UART_BUADRATE); + +#if SCOPE_DEBUG_TYPE == 0 + while (1) { + for (int i = 0; i < TEST_TOUCH_CHANNEL; i++) { + touch_pad_read_raw_data(touch_list[i], &scope_data[i]); + // touch_pad_filter_read_smooth(touch_list[i], &scope_data[i]); + // touch_pad_filter_read_baseline(touch_list[i], &scope_data[i]); + scope_temp[i] = scope_data[i]; + } + test_tp_print_to_scope(scope_temp, TEST_TOUCH_CHANNEL); + vTaskDelay(SCOPE_DEBUG_FREQ_MS / portTICK_RATE_MS); + } +#elif SCOPE_DEBUG_TYPE == 1 + while (1) { + int cnt = 0; + for (int i = 0; i < 5; i++) { + touch_pad_read_raw_data(touch_list[i], &scope_data[i]); + scope_temp[i] = scope_data[i]; + } + for (int i = 0; i < 5; i++) { + touch_pad_filter_read_smooth(touch_list[i], &scope_data[i]); + scope_temp[i + SCOPE_DEBUG_CHANNEL_MAX / 2] = scope_data[i]; + } + test_tp_print_to_scope(scope_temp, SCOPE_DEBUG_CHANNEL_MAX); + vTaskDelay(SCOPE_DEBUG_FREQ_MS / portTICK_RATE_MS); + } +#elif SCOPE_DEBUG_TYPE == 2 + uint32_t status; + touch_pad_filter_read_baseline(pad_num, &status); + while (1) { + xQueueReceive(que_touch, &evt, SCOPE_DEBUG_FREQ_MS / portTICK_RATE_MS); + //read filtered value + touch_pad_read_raw_data(pad_num, &scope_data[0]); + touch_pad_filter_read_baseline(pad_num, &scope_data[1]); + touch_pad_get_thresh(pad_num, &scope_data[2]); + touch_pad_filter_read_smooth(pad_num, &scope_data[8]); + // raw data + scope_temp[0] = scope_data[0]; + // baseline + scope_temp[1] = scope_data[1]; + // smooth data + scope_temp[8] = scope_data[8]; + // noise neg thr + scope_temp[2] = scope_temp[1] - scope_data[2] * 0.5; + // noise thr + scope_temp[3] = scope_temp[1] + scope_data[2] * 0.5; + // touch thr + scope_temp[4] = scope_temp[1] + scope_data[2]; + // hysteresis_thr thr + scope_temp[5] = scope_temp[4] - scope_data[2] * 0.0625; + // hysteresis_thr thr + scope_temp[6] = scope_temp[4] + scope_data[2] * 0.0625; + // touch status + if (touch_pad_get_status() & BIT(pad_num)) { + scope_temp[7] = status + 100; + } else { + scope_temp[7] = status - 100; //0:release; 1:push; + } + test_tp_print_to_scope(scope_temp, 9); + } +#elif SCOPE_DEBUG_TYPE == 3 + while (1) { + test_touch_push_all(); + TEST_ESP_OK( test_touch_check_ch_touched(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("push"); + + /* Test: if the raw data exceed noise threshold, the baseline should not be updated. */ + test_touch_baseline_not_update(); + + test_touch_release_all(); + TEST_ESP_OK( test_touch_check_ch_released(TEST_TOUCH_CHANNEL, TOUCH_EXCEED_TIME_MS) ); + printf_touch_hw_read("release"); + } +#endif + TEST_ESP_OK( touch_pad_deinit() ); +} \ No newline at end of file diff --git a/components/driver/test/esp32s2/touch_scope.c b/components/driver/test/esp32s2/touch_scope.c new file mode 100644 index 0000000000..cc9a4d3757 --- /dev/null +++ b/components/driver/test/esp32s2/touch_scope.c @@ -0,0 +1,186 @@ +#include "esp_err.h" +#include "driver/uart.h" +#include "esp32s2/rom/uart.h" + +#define ROM_UART_DRIVER_ENABLE 0 + +#if ROM_UART_DRIVER_ENABLE +static uint8_t scope_uart_num = 0; +static int8_t uart_used = 0; +#else +static uint8_t scope_uart_num = 255; +static int8_t uart_used = -1; +#endif +static int scope_tx_io_num = 0; +static int scope_rx_io_num = 0; +static int scope_debug_baud_rate = 256000; +static unsigned char datascope_output_buffer[42] = {0}; // Data buff. + +/** + * @brief Translate a float data to four unsigned char data for uart TX. + * @param target target float data address. + * @param buf save translated data. + * @param offset the start position in buf. + * @return + * - void + */ +static void Float2Byte(float *target, unsigned char *buf, unsigned char offset) +{ + unsigned char *point; + point = (unsigned char*)target; //Get the address of float. + buf[offset] = point[0]; + buf[offset+1] = point[1]; + buf[offset+2] = point[2]; + buf[offset+3] = point[3]; +} + +/** + * @brief Add data to channal buff. + * @param Data target data. + * @param Channel target channel (1 - 10). + * @return + * - void + */ +static void datascope_get_channel_data(float data, unsigned char channel) +{ + if ( (channel > 10) || (channel == 0) ) { + return; + } else { + switch (channel) { + case 1: Float2Byte(&data,datascope_output_buffer,1); break; + case 2: Float2Byte(&data,datascope_output_buffer,5); break; + case 3: Float2Byte(&data,datascope_output_buffer,9); break; + case 4: Float2Byte(&data,datascope_output_buffer,13); break; + case 5: Float2Byte(&data,datascope_output_buffer,17); break; + case 6: Float2Byte(&data,datascope_output_buffer,21); break; + case 7: Float2Byte(&data,datascope_output_buffer,25); break; + case 8: Float2Byte(&data,datascope_output_buffer,29); break; + case 9: Float2Byte(&data,datascope_output_buffer,33); break; + case 10: Float2Byte(&data,datascope_output_buffer,37); break; + } + } +} + +/** + * @brief Transform float data to DataScopeV1.0 data format. + * @param channel_num the number of channel that wait to be translated. + * @return + * - The number of the UART TX data. + */ +static unsigned char datascope_data_generate(unsigned char channel_num) +{ + if ( (channel_num > 10) || (channel_num == 0) ) { + return 0; + } else { + datascope_output_buffer[0] = '$'; //frame header + switch(channel_num) { + case 1: datascope_output_buffer[5] = 5; return 6; break; + case 2: datascope_output_buffer[9] = 9; return 10; break; + case 3: datascope_output_buffer[13] = 13; return 14; break; + case 4: datascope_output_buffer[17] = 17; return 18; break; + case 5: datascope_output_buffer[21] = 21; return 22; break; + case 6: datascope_output_buffer[25] = 25; return 26; break; + case 7: datascope_output_buffer[29] = 29; return 30; break; + case 8: datascope_output_buffer[33] = 33; return 34; break; + case 9: datascope_output_buffer[37] = 37; return 38; break; + case 10: datascope_output_buffer[41] = 41; return 42; break; + } + } + return 0; +} + +/** + * @brief Send touch sensor data to HMI in PC via UART. + * @param uart_num Choose uart port (0, 1, 2). + * @param data The addr of the touch sensor data. + * @param channel_num The number of channel that wait to be translated. + * @return + * - ESP_FAIL Error + * - The number of the UART TX data. + */ +int test_tp_print_to_scope(float *data, unsigned char channel_num) +{ + uint8_t uart_num = scope_uart_num; + + if (uart_num >= UART_NUM_MAX) { + return ESP_FAIL; + } + if ( (channel_num > 10) || (channel_num == 0) || (NULL == data) ) { + return ESP_FAIL; + } + for(uint8_t i = 0 ; i < channel_num; i++) { + datascope_get_channel_data(data[i] , i+1); // write data x into channel 1~10. + } + unsigned char out_len = datascope_data_generate(channel_num); // Generate n number data. + unsigned char *out_data = datascope_output_buffer; + // Init uart. + if(uart_num != uart_used) { + return 0; + } else { +#if ROM_UART_DRIVER_ENABLE + uart_tx_wait_idle(uart_num); // Default print uart mumber is 0. + for(int i=0; i= UART_NUM_MAX) { + return ESP_FAIL; + } + scope_uart_num = uart_num; + scope_tx_io_num = tx_io_num; + scope_rx_io_num = rx_io_num; + scope_debug_baud_rate = baud_rate; + uart_config_t uart_config = { + .baud_rate = scope_debug_baud_rate, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + }; + uart_param_config(uart_num, &uart_config); + // Set UART pins using UART0 default pins i.e. no changes + uart_set_pin(uart_num, scope_tx_io_num, scope_rx_io_num, + UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); + uart_driver_install(uart_num, 1024, 2048, 0, NULL, 0); + uart_used = uart_num; +#endif + return ESP_OK; +} diff --git a/components/driver/test/esp32s2/touch_scope.h b/components/driver/test/esp32s2/touch_scope.h new file mode 100644 index 0000000000..936d6ada2a --- /dev/null +++ b/components/driver/test/esp32s2/touch_scope.h @@ -0,0 +1,4 @@ +#pragma once + +int test_tp_print_to_scope(float *data, unsigned char channel_num); +esp_err_t test_tp_scope_debug_init(uint8_t uart_num, int tx_io_num, int rx_io_num, int baud_rate); \ No newline at end of file diff --git a/components/soc/src/esp32s2/include/hal/touch_sensor_hal.h b/components/soc/src/esp32s2/include/hal/touch_sensor_hal.h index 5aab11106e..9074d6b4ba 100644 --- a/components/soc/src/esp32s2/include/hal/touch_sensor_hal.h +++ b/components/soc/src/esp32s2/include/hal/touch_sensor_hal.h @@ -623,6 +623,12 @@ void touch_hal_sleep_channel_enable(touch_pad_t pad_num, bool enable); */ #define touch_hal_sleep_read_baseline(baseline) touch_ll_sleep_read_baseline(baseline) +#define touch_hal_sleep_read_smooth(smooth_data) touch_ll_sleep_read_smooth(smooth_data) + +#define touch_hal_sleep_read_data(raw_data) touch_ll_sleep_read_data(raw_data) + +#define touch_hal_sleep_reset_baseline() touch_ll_sleep_reset_baseline() + /** * Read smooth data of touch sensor for sleep pad. */ diff --git a/components/soc/src/esp32s2/include/hal/touch_sensor_ll.h b/components/soc/src/esp32s2/include/hal/touch_sensor_ll.h index 992066c5a1..d4bfece451 100644 --- a/components/soc/src/esp32s2/include/hal/touch_sensor_ll.h +++ b/components/soc/src/esp32s2/include/hal/touch_sensor_ll.h @@ -231,6 +231,26 @@ static inline void touch_ll_get_fsm_mode(touch_fsm_mode_t *mode) *mode = (touch_fsm_mode_t)RTCCNTL.touch_ctrl2.touch_start_force; } +static inline void touch_ll_clk_enable(void) +{ + RTCCNTL.touch_ctrl2.touch_clkgate_en = 1; //enable touch clock for FSM. or force enable. +} + +static inline void touch_ll_clk_disable(void) +{ + RTCCNTL.touch_ctrl2.touch_clkgate_en = 0; //enable touch clock for FSM. or force enable. +} + +/** + * Touch timer trigger measurement and always wait measurement done. + * Force done for touch timer ensures that the timer always can get the measurement done signal. + */ +static inline void touch_ll_timer_force_done(void) +{ + RTCCNTL.touch_ctrl2.touch_timer_force_done = TOUCH_LL_TIMER_FORCE_DONE; + RTCCNTL.touch_ctrl2.touch_timer_force_done = TOUCH_LL_TIMER_DONE; +} + /** * Enable/disable clock gate of touch sensor. *