// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /* 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" #if !DISABLED_FOR_TARGETS(ESP8266, ESP32S2) // This testcase for ESP32 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 (100) #define TEST_TOUCH_COUNT_NUM (10) #define TEST_TOUCH_CHANNEL (3) 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_press_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 smaller 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_test_runner(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++) { printf("test T%d\n", touch_list[i]); touch_pad_read(touch_list[i], &touch_value); printf("T%d:[%4d] ", touch_list[i], touch_value); } printf("\n"); TEST_ESP_OK( touch_pad_deinit() ); return ESP_OK; } 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++) { printf("test T%d\n", touch_list[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_ASSERT_NOT_EQUAL(TOUCH_READ_INVALID_VAL, 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_touch_sw_read_test_runner(); 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_press_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() ); } #endif // !DISABLED_FOR_TARGETS(ESP8266, ESP32)