Bläddra i källkod

add skip calibration and wakeup channel, fix isr in sleep mode

Kang Zuoling 4 år sedan
förälder
incheckning
82bf6c0935

+ 10 - 0
components/touch_element/Kconfig

@@ -0,0 +1,10 @@
+menu "Touch Element"
+
+    config TE_SKIP_DSLEEP_WAKEUP_CALIBRATION
+        bool "Enable skip deep sleep wakeup calibration"
+        default n
+        help
+            This option allows to store all Touch Sensor channels' threshold into RTC Fast Memory. So that Touch Sensor
+            threshold will only be configured once after Power-on Reset.
+
+endmenu

+ 15 - 0
components/touch_element/include/touch_element/touch_element.h

@@ -256,6 +256,21 @@ esp_err_t touch_element_waterproof_add(touch_elem_handle_t element_handle);
  */
 esp_err_t touch_element_waterproof_remove(touch_elem_handle_t element_handle);
 
+typedef struct {
+    uint16_t scan_time;
+    uint16_t sleep_time;
+} touch_elem_sleep_config_t;
+
+esp_err_t touch_element_sleep_install(touch_elem_sleep_config_t *sleep_config);
+void touch_element_sleep_uninstall(void);
+esp_err_t touch_element_sleep_add_wakeup(touch_elem_handle_t element_handle);
+esp_err_t touch_element_sleep_remove_wakeup(touch_elem_handle_t element_handle);
+esp_err_t touch_element_sleep_add_wakeup_channel(touch_pad_t wakeup_channel);
+esp_err_t touch_element_sleep_remove_wakeup_channel(touch_pad_t wakeup_channel);
+#ifdef CONFIG_TE_SKIP_DSLEEP_WAKEUP_CALIBRATION
+esp_err_t touch_element_sleep_config_wakeup_calibration(touch_elem_handle_t element_handle, bool en);
+#endif
+
 #ifdef __cplusplus
 }
 #endif

+ 28 - 0
components/touch_element/include/touch_element/touch_element_private.h

@@ -10,6 +10,8 @@
 #include "touch_element/touch_button.h"
 #include "touch_element/touch_slider.h"
 #include "touch_element/touch_matrix.h"
+#include "esp_pm.h"
+#include "sdkconfig.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -54,6 +56,9 @@ typedef struct {
     touch_pad_t channel;          //!< Touch channel number(index)
     te_dev_type_t type;           //!< Touch channel type  TODO: need to refactor as te_class_type_t
     te_dev_state_t state;         //!< Touch channel current state
+#ifdef  CONFIG_TE_SKIP_DSLEEP_WAKEUP_CALIBRATION
+    bool is_use_last_threshold;
+#endif
 } te_dev_t;
 
 typedef enum {
@@ -69,6 +74,7 @@ typedef struct  {
     esp_err_t (*set_threshold) (void);
     void (*process_state) (void);
     void (*update_state) (touch_pad_t, te_state_t);
+    touch_elem_handle_t (*search_channel_handle) (touch_pad_t);
 } te_object_methods_t;
 
 /* -------------------------------------------- Waterproof basic type --------------------------------------------- */
@@ -79,6 +85,16 @@ struct te_waterproof_s {
     bool is_shield_level_set;                   //Waterproof shield level setting bit
 };
 typedef struct te_waterproof_s* te_waterproof_handle_t;
+/* -------------------------------------------- Sleep basic type --------------------------------------------- */
+struct te_sleep_s {
+    touch_elem_handle_t wakeup_handle;
+    esp_pm_lock_handle_t pm_lock;
+#ifdef  CONFIG_TE_SKIP_DSLEEP_WAKEUP_CALIBRATION
+    uint32_t *non_volatile_threshold;
+#endif
+};
+
+typedef struct te_sleep_s* te_sleep_handle_t;
 /* -------------------------------------------- Button basic type --------------------------------------------- */
 typedef struct {
     touch_elem_dispatch_t dispatch_method;      //Button dispatch method
@@ -170,6 +186,18 @@ void te_object_method_register(te_object_methods_t *object_methods, te_class_typ
 void te_object_method_unregister(te_class_type_t object_type);
 bool te_object_check_channel(const touch_pad_t *channel_array, uint8_t channel_sum);
 bool waterproof_check_mask_handle(touch_elem_handle_t te_handle);
+bool te_is_touch_dsleep_wakeup(void);
+inline touch_pad_t te_get_sleep_channel(void);
+
+bool button_object_handle_check(touch_elem_handle_t element_handle);
+bool slider_object_handle_check(touch_elem_handle_t element_handle);
+bool matrix_object_handle_check(touch_elem_handle_t element_handle);
+
+#ifdef CONFIG_TE_SKIP_DSLEEP_WAKEUP_CALIBRATION
+void button_config_wakeup_calibration(te_button_handle_t button_handle, bool en);
+void slider_config_wakeup_calibration(te_slider_handle_t slider_handle, bool en);
+void matrix_config_wakeup_calibration(te_matrix_handle_t matrix_handle, bool en);
+#endif
 /* ------------------------------------------------------------------------------------------------------------------ */
 
 #ifdef __cplusplus

+ 37 - 0
components/touch_element/touch_button.c

@@ -40,6 +40,7 @@ static bool button_object_check_channel(touch_pad_t channel_num);
 static esp_err_t button_object_set_threshold(void);
 static void button_object_process_state(void);
 static void button_object_update_state(touch_pad_t channel_num, te_state_t channel_state);
+static te_button_handle_t button_object_search_channel_handle(touch_pad_t channel_num);
 /* ------------------------------------------------------------------------------------------------------------------ */
 
 esp_err_t touch_button_install(const touch_button_global_config_t *global_config)
@@ -268,6 +269,21 @@ static void button_object_update_state(touch_pad_t channel_num, te_state_t chann
     }
 }
 
+static te_button_handle_t button_object_search_channel_handle(touch_pad_t channel_num)
+{
+    te_button_handle_list_t *item;
+    te_button_handle_t button_handle = NULL;
+    SLIST_FOREACH(item, &s_te_btn_obj->handle_list, next) {
+        touch_pad_t button_channel = item->button_handle->device->channel;
+        if (channel_num == button_channel) {
+            button_handle = item->button_handle;
+            break;
+        }
+    }
+
+    return button_handle;
+}
+
 static esp_err_t button_object_add_instance(te_button_handle_t button_handle)
 {
     te_button_handle_list_t *item = (te_button_handle_list_t *)calloc(1, sizeof(te_button_handle_list_t));
@@ -296,6 +312,20 @@ static esp_err_t button_object_remove_instance(te_button_handle_t button_handle)
     return ret;
 }
 
+bool button_object_handle_check(touch_elem_handle_t element_handle)
+{
+    te_button_handle_list_t *item;
+    xSemaphoreTake(s_te_btn_obj->mutex, portMAX_DELAY);
+    SLIST_FOREACH(item, &s_te_btn_obj->handle_list, next) {
+        if (element_handle == item->button_handle) {
+            xSemaphoreGive(s_te_btn_obj->mutex);
+            return true;
+        }
+    }
+    xSemaphoreGive(s_te_btn_obj->mutex);
+    return false;
+}
+
 static bool button_channel_check(te_button_handle_t button_handle, touch_pad_t channel_num)
 {
     return (channel_num == button_handle->device->channel);
@@ -346,6 +376,13 @@ static inline void button_dispatch(te_button_handle_t button_handle, touch_elem_
     }
 }
 
+#ifdef CONFIG_TE_SKIP_DSLEEP_WAKEUP_CALIBRATION
+void button_config_wakeup_calibration(te_button_handle_t button_handle, bool en)
+{
+    button_handle->device->is_use_last_threshold = en;
+}
+#endif
+
 /**
  * @brief Button process
  *

+ 261 - 12
components/touch_element/touch_element.c

@@ -9,11 +9,15 @@
 #include "freertos/FreeRTOS.h"
 #include "freertos/semphr.h"
 #include "freertos/queue.h"
+#include "esp_sleep.h"
 #include "esp_timer.h"
 #include "esp_log.h"
 #include "hal/touch_sensor_hal.h"  //TODO: remove hal
 #include "touch_element/touch_element_private.h"
 
+#include "esp32s2/rom/rtc.h"
+
+
 #define TE_CLASS_ITEM(cls, cls_type, cls_item)  ((&((cls)[cls_type]))->cls_item)
 
 #define TE_CLASS_FOREACH(cls_var, cls_start, cls_end)                         \
@@ -87,15 +91,21 @@ typedef struct {
     te_object_methods_t object_methods[TE_CLS_TYPE_MAX];    //Class(object) methods
     touch_elem_global_config_t *global_config;              //Global initialization
     te_waterproof_handle_t waterproof_handle;               //Waterproof configuration
+    te_sleep_handle_t sleep_handle;
     esp_timer_handle_t proc_timer;                          //Processing timer handle
     QueueHandle_t event_msg_queue;                          //Application event message queue (for user)
     QueueHandle_t intr_msg_queue;                           //Interrupt message (for internal)
     SemaphoreHandle_t mutex;                                //Global resource mutex
     bool is_set_threshold;                                  //Threshold configuration state bit
     uint32_t denoise_channel_raw;                           //De-noise channel(TO) raw signal
+//    touch_elem_sleep_config_t *sleep_config;
+//    esp_pm_lock_handle_t pm_lock_handle;
 } te_obj_t;
 
 static te_obj_t *s_te_obj = NULL;
+#ifdef  CONFIG_TE_SKIP_DSLEEP_WAKEUP_CALIBRATION
+RTC_FAST_ATTR uint32_t threshold_shadow[TOUCH_PAD_MAX - 1] = {0};
+#endif
 
 /**
  * Internal de-noise channel(Touch channel 0) equivalent capacitance table, depends on hardware design
@@ -313,6 +323,36 @@ esp_err_t te_event_give(touch_elem_message_t te_message)
     return ESP_OK;
 }
 
+uint32_t te_get_threshold(touch_pad_t channel_num)
+{
+    uint32_t threshold = 0;
+    touch_pad_sleep_channel_t sleep_channel_info;
+    touch_pad_sleep_channel_get_info(&sleep_channel_info);
+    if (channel_num != sleep_channel_info.touch_num) {
+        touch_pad_get_thresh(channel_num, &threshold);
+    } else {
+        touch_pad_sleep_get_threshold(channel_num, &threshold);
+    }
+    return threshold;
+}
+
+bool te_is_touch_dsleep_wakeup(void)
+{
+    RESET_REASON rtc_reset_reason = rtc_get_reset_reason(0);
+    if (rtc_reset_reason != DEEPSLEEP_RESET) {
+        return false;
+    }
+    esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
+    return wakeup_reason == ESP_SLEEP_WAKEUP_TOUCHPAD;
+}
+
+inline touch_pad_t te_get_sleep_channel(void)
+{
+    touch_pad_sleep_channel_t sleep_channel_info;
+    touch_pad_sleep_channel_get_info(&sleep_channel_info);
+    return sleep_channel_info.touch_num;
+}
+
 /**
  * @brief Touch sensor interrupt service routine
  *
@@ -323,22 +363,39 @@ static void te_intr_cb(void *arg)
 {
     TE_UNUSED(arg);
     static int scan_done_cnt = 0;
+    static uint32_t touch_pre_trig_status = 0;
     int task_awoken = pdFALSE;
     te_intr_msg_t te_intr_msg;
     /*< Figure out which touch sensor channel is triggered and the trigger type */
     uint32_t intr_mask = touch_pad_read_intr_status_mask();
-    te_intr_msg.channel_num = touch_pad_get_current_meas_channel();
     if (intr_mask == 0x0) {  //For dummy interrupt
         return;
     }
+
     bool need_send_queue = true;
-    if (intr_mask & TOUCH_PAD_INTR_MASK_ACTIVE) {
-        te_intr_msg.channel_state = TE_STATE_PRESS;
-        te_intr_msg.intr_type = TE_INTR_PRESS;
-    } else if (intr_mask & TOUCH_PAD_INTR_MASK_INACTIVE) {
-        te_intr_msg.channel_state = TE_STATE_RELEASE;
-        te_intr_msg.intr_type = TE_INTR_RELEASE;
-    } else if (intr_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) {
+    uint8_t pad_num = 0;
+    uint32_t touch_trig_status = touch_pad_get_status();
+    uint32_t touch_trig_diff = touch_trig_status ^ touch_pre_trig_status;
+    while (touch_trig_diff) {
+        if (touch_trig_diff & 0x1) {
+            if (touch_trig_status & BIT(pad_num)) {
+                if (s_te_obj->sleep_handle != NULL) {
+                    esp_pm_lock_acquire(s_te_obj->sleep_handle->pm_lock);
+                }
+                te_intr_msg.channel_state = TE_STATE_PRESS;
+                te_intr_msg.intr_type = TE_INTR_PRESS;
+            } else {
+                te_intr_msg.channel_state = TE_STATE_RELEASE;
+                te_intr_msg.intr_type = TE_INTR_RELEASE;
+            }
+            touch_pre_trig_status = touch_trig_status;
+            te_intr_msg.channel_num = pad_num;
+        }
+        pad_num++;
+        touch_trig_diff >>= 1;
+    }
+
+    if (intr_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) {
         te_intr_msg.channel_state = TE_STATE_IDLE;
         te_intr_msg.intr_type = TE_INTR_TIMEOUT;
     } else if (intr_mask & TOUCH_PAD_INTR_MASK_SCAN_DONE) {
@@ -355,7 +412,7 @@ static void te_intr_cb(void *arg)
         /*< De-noise channel signal must be read at the time between SCAN_DONE and next measurement beginning(sleep)!!! */
         touch_pad_denoise_read_data(&s_te_obj->denoise_channel_raw); //Update de-noise signal
     } else {
-        te_intr_msg.intr_type = TE_INTR_MAX;  // Unknown Exception
+//        te_intr_msg.intr_type = TE_INTR_MAX;  // Unknown Exception
     }
     if (need_send_queue) {
         xQueueSendFromISR(s_te_obj->intr_msg_queue, &te_intr_msg, &task_awoken);
@@ -385,11 +442,19 @@ static void te_proc_timer_cb(void *arg)
     if (ret == pdPASS) {
         if (te_intr_msg.intr_type == TE_INTR_PRESS || te_intr_msg.intr_type == TE_INTR_RELEASE) {
             te_object_update_state(te_intr_msg);
+            if (te_intr_msg.intr_type == TE_INTR_RELEASE) {
+                if (s_te_obj->sleep_handle != NULL) {
+                    esp_pm_lock_release(s_te_obj->sleep_handle->pm_lock);
+                }
+            }
         } else if (te_intr_msg.intr_type == TE_INTR_SCAN_DONE) {
             if (s_te_obj->is_set_threshold != true) {
                 s_te_obj->is_set_threshold = true;
                 te_object_set_threshold();  //TODO: add set threshold error processing
                 ESP_LOGD(TE_DEBUG_TAG, "Set threshold");
+                if (s_te_obj->sleep_handle != NULL) {
+                    esp_pm_lock_release(s_te_obj->sleep_handle->pm_lock);
+                }
             }
             if (waterproof_check_state()) {
                 te_waterproof_handle_t waterproof_handle = s_te_obj->waterproof_handle;
@@ -500,6 +565,9 @@ esp_err_t te_dev_init(te_dev_t **device, uint8_t device_num, te_dev_type_t type,
         device[idx]->sens = sens[idx] * divider;
         device[idx]->type = type;
         device[idx]->state = TE_STATE_IDLE;
+#ifdef CONFIG_TE_SKIP_DSLEEP_WAKEUP_CALIBRATION
+        device[idx]->is_use_last_threshold = false;
+#endif
         esp_err_t ret = touch_pad_config(device[idx]->channel);
         TE_CHECK(ret == ESP_OK, ret);
     }
@@ -513,10 +581,48 @@ void te_dev_deinit(te_dev_t **device, uint8_t device_num)
     }
 }
 
+esp_err_t te_config_thresh(touch_pad_t channel_num, uint32_t threshold)
+{
+    esp_err_t ret;
+    touch_pad_sleep_channel_t sleep_channel_info;
+    touch_pad_sleep_channel_get_info(&sleep_channel_info);
+    if (channel_num != sleep_channel_info.touch_num) {
+        ret = touch_pad_set_thresh(channel_num, threshold);
+    } else {
+        ret = touch_pad_sleep_set_threshold(channel_num, threshold);
+    }
+    return ret;
+}
+
 esp_err_t te_dev_set_threshold(te_dev_t *device)
 {
-    uint32_t smo_val = te_read_smooth_signal(device->channel);
-    esp_err_t ret = touch_pad_set_thresh(device->channel, device->sens * smo_val);
+    esp_err_t ret = ESP_OK;
+    uint32_t smo_val = 0;
+#ifdef CONFIG_TE_SKIP_DSLEEP_WAKEUP_CALIBRATION
+    if (s_te_obj->sleep_handle == NULL) {
+        ESP_LOGE(TE_TAG, "Touch Element sleep is not installed");
+        return ESP_ERR_INVALID_STATE;
+    }
+    if (device->is_use_last_threshold) {
+        if (te_is_touch_dsleep_wakeup()) {  //Deep sleep wakeup reset
+            touch_pad_t sleep_channel = te_get_sleep_channel();
+            ets_printf("----config rtc %ld   %ld\n", s_te_obj->sleep_handle->non_volatile_threshold[device->channel - 1], sleep_channel);
+            ret = te_config_thresh(device->channel, s_te_obj->sleep_handle->non_volatile_threshold[device->channel - 1]);
+        } else {  //Other reset
+            smo_val = te_read_smooth_signal(device->channel);
+            ret = te_config_thresh(device->channel, device->sens * smo_val);
+            uint32_t threshold = te_get_threshold(device->channel);
+            s_te_obj->sleep_handle->non_volatile_threshold[device->channel - 1] = threshold;  //Write threshold into RTC Fast Memory
+        }
+    } else {
+        smo_val = te_read_smooth_signal(device->channel);
+        ret = te_config_thresh(device->channel, device->sens * smo_val);
+    }
+
+#else
+    smo_val = te_read_smooth_signal(device->channel);
+    ret = te_config_thresh(device->channel, device->sens * smo_val);
+#endif
     ESP_LOGD(TE_DEBUG_TAG, "channel: %"PRIu8", smo_val: %"PRIu32, device->channel, smo_val);
     return ret;
 }
@@ -648,7 +754,8 @@ static esp_err_t te_sw_init(const touch_elem_sw_config_t *software_init)
     const esp_timer_create_args_t te_proc_timer_args = {
         .name = "te_proc_timer_cb",
         .arg  = NULL,
-        .callback = &te_proc_timer_cb
+        .callback = &te_proc_timer_cb,
+        .skip_unhandled_events = true,
     };
     ret = esp_timer_create(&te_proc_timer_args, &s_te_obj->proc_timer);
     TE_CHECK_GOTO(ret == ESP_OK, cleanup);
@@ -879,3 +986,145 @@ static void waterproof_guard_update_state(touch_pad_t current_channel, te_state_
     }
     ESP_LOGD(TE_DEBUG_TAG, "waterproof guard state update  %d", guard_device->state);
 }
+
+esp_err_t touch_element_sleep_install(touch_elem_sleep_config_t *sleep_config)
+{
+    TE_CHECK(s_te_obj != NULL, ESP_ERR_INVALID_STATE);
+    TE_CHECK(s_te_obj->sleep_handle == NULL, ESP_ERR_INVALID_STATE);
+    TE_CHECK(sleep_config != NULL, ESP_ERR_INVALID_ARG);
+
+    s_te_obj->sleep_handle = calloc(1, sizeof(struct te_sleep_s));
+    if (s_te_obj->sleep_handle == NULL) {
+        return ESP_ERR_NO_MEM;
+    }
+
+    esp_err_t ret;
+    touch_pad_sleep_channel_set_work_time(sleep_config->sleep_time, sleep_config->scan_time);
+    ret = esp_sleep_enable_touchpad_wakeup();
+    TE_CHECK_GOTO(ret == ESP_OK, cleanup);
+
+#ifdef CONFIG_TE_SKIP_DSLEEP_WAKEUP_CALIBRATION
+    ret = esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_ON);
+    TE_CHECK_GOTO(ret == ESP_OK, cleanup);
+    s_te_obj->sleep_handle->non_volatile_threshold = threshold_shadow;
+#endif
+
+    ret = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "touch_element", &s_te_obj->sleep_handle->pm_lock);
+    TE_CHECK_GOTO(ret == ESP_OK, cleanup);
+    ret = esp_pm_lock_acquire(s_te_obj->sleep_handle->pm_lock);
+    TE_CHECK_GOTO(ret == ESP_OK, cleanup);
+    return ESP_OK;
+
+cleanup:
+    if (s_te_obj->sleep_handle->pm_lock != NULL) {
+        esp_err_t del_ret = esp_pm_lock_delete(s_te_obj->sleep_handle->pm_lock);
+        if (del_ret != ESP_OK) {
+            abort();
+        }
+    }
+    TE_FREE_AND_NULL(s_te_obj->sleep_handle);
+    return ret;
+}
+
+void touch_element_sleep_uninstall(void)
+{
+    esp_err_t ret;
+    if (s_te_obj->sleep_handle->pm_lock != NULL) {
+        ret = esp_pm_lock_delete(s_te_obj->sleep_handle->pm_lock);
+        if (ret != ESP_OK) {
+            abort();
+        }
+    }
+    if (s_te_obj->sleep_handle->wakeup_handle != NULL) {
+        te_button_handle_t button_handle = s_te_obj->sleep_handle->wakeup_handle;
+        ret = touch_pad_sleep_channel_enable(button_handle->device->channel, false);
+        if (ret != ESP_OK) {
+            abort();
+        }
+    }
+    s_te_obj->sleep_handle->pm_lock = NULL;
+    s_te_obj->sleep_handle->wakeup_handle = NULL;
+    TE_FREE_AND_NULL(s_te_obj->sleep_handle);
+}
+
+esp_err_t touch_element_sleep_add_wakeup(touch_elem_handle_t element_handle)
+{
+    TE_CHECK(s_te_obj->sleep_handle != NULL, ESP_ERR_INVALID_STATE);
+    TE_CHECK(element_handle != NULL, ESP_ERR_INVALID_ARG);
+    if (s_te_obj->sleep_handle->wakeup_handle != NULL) {
+        ESP_LOGE(TE_TAG, "sleep not null");
+        return ESP_ERR_NOT_SUPPORTED;   //Only support one channel/element as the deep sleep wakeup channel/element
+    }
+    if (!button_object_handle_check(element_handle)) {
+        ESP_LOGE(TE_TAG, "not button handle");
+        return ESP_ERR_NOT_SUPPORTED;  //Only support button element as the deep sleep wakeup channel
+    }
+    s_te_obj->sleep_handle->wakeup_handle = element_handle;
+    te_button_handle_t button_handle = element_handle;
+    esp_err_t ret = touch_pad_sleep_channel_enable(button_handle->device->channel, true);
+    if (ret != ESP_OK) {
+        return ret;
+    }
+    return ESP_OK;
+}
+
+esp_err_t touch_element_sleep_remove_wakeup(touch_elem_handle_t element_handle)
+{
+    TE_CHECK(s_te_obj->sleep_handle != NULL, ESP_ERR_INVALID_STATE);
+    TE_CHECK(element_handle != NULL, ESP_ERR_INVALID_ARG);
+    TE_CHECK(s_te_obj->sleep_handle->wakeup_handle != NULL &&
+             s_te_obj->sleep_handle->wakeup_handle == element_handle,
+             ESP_ERR_NOT_FOUND);
+    s_te_obj->sleep_handle->wakeup_handle = NULL;
+
+    te_button_handle_t button_handle = element_handle;  //Now we are sure it's absolutely a button element
+    esp_err_t ret = touch_pad_sleep_channel_enable(button_handle->device->channel, false);
+    if (ret != ESP_OK) {
+        return ret;
+    }
+    return ESP_OK;
+}
+
+esp_err_t touch_element_sleep_add_wakeup_channel(touch_pad_t wakeup_channel)
+{
+    TE_CHECK(s_te_obj->sleep_handle != NULL, ESP_ERR_INVALID_STATE);
+    TE_CHECK(wakeup_channel > TOUCH_PAD_NUM0 && wakeup_channel < TOUCH_PAD_MAX, ESP_ERR_INVALID_ARG);
+    touch_pad_sleep_channel_t sleep_channel_info;
+    touch_pad_sleep_channel_get_info(&sleep_channel_info);
+    if (sleep_channel_info.touch_num == wakeup_channel) {
+        return ESP_ERR_INVALID_ARG;
+    }
+    esp_err_t ret = touch_pad_sleep_channel_enable(wakeup_channel, true);
+    if (ret != ESP_OK) {
+        return ret;
+    }
+    return ESP_OK;
+}
+
+esp_err_t touch_element_sleep_remove_wakeup_channel(touch_pad_t wakeup_channel)
+{
+    TE_CHECK(s_te_obj->sleep_handle != NULL, ESP_ERR_INVALID_STATE);
+    TE_CHECK(wakeup_channel > TOUCH_PAD_NUM0 && wakeup_channel < TOUCH_PAD_MAX, ESP_ERR_INVALID_ARG);
+    esp_err_t ret = touch_pad_sleep_channel_enable(wakeup_channel, false);
+    if (ret != ESP_OK) {
+        return ret;
+    }
+    return ESP_OK;
+}
+
+#ifdef CONFIG_TE_SKIP_DSLEEP_WAKEUP_CALIBRATION
+esp_err_t touch_element_sleep_config_wakeup_calibration(touch_elem_handle_t element_handle, bool en)
+{
+    TE_CHECK(element_handle != NULL, ESP_ERR_INVALID_ARG);
+    if (button_object_handle_check(element_handle)) {
+        button_config_wakeup_calibration(element_handle, en);
+    } else if (slider_object_handle_check(element_handle)) {
+        slider_config_wakeup_calibration(element_handle, en);
+    } else if (matrix_object_handle_check(element_handle)) {
+        matrix_config_wakeup_calibration(element_handle, en);
+    } else {
+        return ESP_ERR_NOT_FOUND;
+    }
+    return ESP_OK;
+}
+#endif

+ 42 - 0
components/touch_element/touch_matrix.c

@@ -43,6 +43,7 @@ static bool matrix_object_check_channel(touch_pad_t channel_num);
 static esp_err_t matrix_object_set_threshold(void);
 static void matrix_object_process_state(void);
 static void matrix_object_update_state(touch_pad_t channel_num, te_state_t channel_state);
+static te_matrix_handle_t matrix_object_search_channel_handle(touch_pad_t channel_num);
 /* ------------------------------------------------------------------------------------------------------------------ */
 
 esp_err_t touch_matrix_install(const touch_matrix_global_config_t *global_config)
@@ -307,6 +308,24 @@ static void matrix_object_update_state(touch_pad_t channel_num, te_state_t chann
     }
 }
 
+static te_matrix_handle_t matrix_object_search_channel_handle(touch_pad_t channel_num)
+{
+    te_matrix_handle_list_t *item;
+    te_matrix_handle_t matrix_handle = NULL;
+    SLIST_FOREACH(item, &s_te_mat_obj->handle_list, next) {
+        for (int idx = 0; idx < item->matrix_handle->x_channel_num + item->matrix_handle->y_channel_num; idx++) {
+            touch_pad_t matrix_channel = item->matrix_handle->device[idx]->channel;
+            if (channel_num == matrix_channel) {
+                matrix_handle = item->matrix_handle;
+                goto found;
+            }
+        }
+    }
+
+found:
+    return matrix_handle;
+}
+
 static esp_err_t matrix_object_add_instance(te_matrix_handle_t matrix_handle)
 {
     te_matrix_handle_list_t *item = (te_matrix_handle_list_t *)calloc(1, sizeof(te_matrix_handle_list_t));
@@ -335,6 +354,20 @@ static esp_err_t matrix_object_remove_instance(te_matrix_handle_t matrix_handle)
     return ret;
 }
 
+bool matrix_object_handle_check(touch_elem_handle_t element_handle)
+{
+    te_matrix_handle_list_t *item;
+    xSemaphoreTake(s_te_mat_obj->mutex, portMAX_DELAY);
+    SLIST_FOREACH(item, &s_te_mat_obj->handle_list, next) {
+        if (element_handle == item->matrix_handle) {
+            xSemaphoreGive(s_te_mat_obj->mutex);
+            return true;
+        }
+    }
+    xSemaphoreGive(s_te_mat_obj->mutex);
+    return false;
+}
+
 static bool matrix_channel_check(te_matrix_handle_t matrix_handle, touch_pad_t channel_num)
 {
     te_dev_t *device;
@@ -403,6 +436,15 @@ static inline void matrix_dispatch(te_matrix_handle_t matrix_handle, touch_elem_
     }
 }
 
+#ifdef CONFIG_TE_SKIP_DSLEEP_WAKEUP_CALIBRATION
+void matrix_config_wakeup_calibration(te_matrix_handle_t matrix_handle, bool en)
+{
+    for (int idx = 0; idx < matrix_handle->x_channel_num + matrix_handle->y_channel_num; ++idx) {
+        matrix_handle->device[idx]->is_use_last_threshold = en;
+    }
+}
+#endif
+
 /**
  * @brief   Scan the matrix channel
  *

+ 42 - 0
components/touch_element/touch_slider.c

@@ -49,6 +49,7 @@ static bool slider_object_check_channel(touch_pad_t channel_num);
 static esp_err_t slider_object_set_threshold(void);
 static void slider_object_process_state(void);
 static void slider_object_update_state(touch_pad_t channel_num, te_state_t channel_state);
+static te_slider_handle_t slider_object_search_channel_handle(touch_pad_t channel_num);
 /* ------------------------------------------------------------------------------------------------------------------ */
 
 esp_err_t touch_slider_install(const touch_slider_global_config_t *global_config)
@@ -300,6 +301,24 @@ static void slider_object_update_state(touch_pad_t channel_num, te_state_t chann
     }
 }
 
+static te_slider_handle_t slider_object_search_channel_handle(touch_pad_t channel_num)
+{
+    te_slider_handle_list_t *item;
+    te_slider_handle_t slider_handle = NULL;
+    SLIST_FOREACH(item, &s_te_sld_obj->handle_list, next) {
+        for (int idx = 0; idx < item->slider_handle->channel_sum; idx++) {
+            touch_pad_t slider_channel = item->slider_handle->device[idx]->channel;
+            if (channel_num == slider_channel) {
+                slider_handle = item->slider_handle;
+                goto found;
+            }
+        }
+    }
+
+found:
+    return slider_handle;
+}
+
 static esp_err_t slider_object_add_instance(te_slider_handle_t slider_handle)
 {
     te_slider_handle_list_t *item = (te_slider_handle_list_t *)calloc(1, sizeof(te_slider_handle_list_t));
@@ -328,6 +347,20 @@ static esp_err_t slider_object_remove_instance(te_slider_handle_t slider_handle)
     return ret;
 }
 
+bool slider_object_handle_check(touch_elem_handle_t element_handle)
+{
+    te_slider_handle_list_t *item;
+    xSemaphoreTake(s_te_sld_obj->mutex, portMAX_DELAY);
+    SLIST_FOREACH(item, &s_te_sld_obj->handle_list, next) {
+        if (element_handle == item->slider_handle) {
+            xSemaphoreGive(s_te_sld_obj->mutex);
+            return true;
+        }
+    }
+    xSemaphoreGive(s_te_sld_obj->mutex);
+    return false;
+}
+
 static bool slider_channel_check(te_slider_handle_t slider_handle, touch_pad_t channel_num)
 {
     te_dev_t *device;
@@ -406,6 +439,15 @@ static inline void slider_dispatch(te_slider_handle_t slider_handle, touch_elem_
     }
 }
 
+#ifdef CONFIG_TE_SKIP_DSLEEP_WAKEUP_CALIBRATION
+void slider_config_wakeup_calibration(te_slider_handle_t slider_handle, bool en)
+{
+    for (int idx = 0; idx < slider_handle->channel_sum; ++idx) {
+        slider_handle->device[idx]->is_use_last_threshold = en;
+    }
+}
+#endif
+
 /**
  * @brief Slider process
  *

+ 8 - 0
examples/peripherals/touch_element/touch_element_sleep/CMakeLists.txt

@@ -0,0 +1,8 @@
+# For more information about build system see
+# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
+# The following five lines of boilerplate have to be in your project's
+# CMakeLists in this exact order for cmake to work correctly
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(touch_element_sleep)

+ 2 - 0
examples/peripherals/touch_element/touch_element_sleep/main/CMakeLists.txt

@@ -0,0 +1,2 @@
+idf_component_register(SRCS "touch_element_sleep.c"
+                    INCLUDE_DIRS ".")

+ 15 - 0
examples/peripherals/touch_element/touch_element_sleep/main/Kconfig.projbuild

@@ -0,0 +1,15 @@
+menu "Example Configuration"
+
+    choice TOUCH_SENSOR_EXAMPLE_TYPE
+        bool "Select touch element dispatch method"
+        default TOUCH_ELEM_EVENT
+        help
+            Select touch element dispatch method (event task or callback) for this example.
+
+        config TOUCH_ELEM_EVENT
+            bool "Dispatch by event task"
+        config TOUCH_ELEM_CALLBACK
+            bool "Dispatch by callback"
+    endchoice
+
+endmenu

+ 143 - 0
examples/peripherals/touch_element/touch_element_sleep/main/touch_element_sleep.c

@@ -0,0 +1,143 @@
+/* Touch Sensor - Example
+
+   For other examples please check:
+   https://github.com/espressif/esp-idf/tree/master/examples
+
+   See README.md file to get detailed usage of this example.
+
+   This example code is in the Public Domain (or CC0 licensed, at your option.)
+
+   Unless required by applicable law or agreed to in writing, this
+   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+   CONDITIONS OF ANY KIND, either express or implied.
+*/
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "touch_element/touch_button.h"
+#include "esp_log.h"
+#include "esp_sleep.h"
+#include "soc/soc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "esp_pm.h"
+
+static const char *TAG = "Touch Button Example";
+#define TOUCH_BUTTON_NUM     5
+
+/* Touch buttons handle */
+static touch_button_handle_t button_handle[TOUCH_BUTTON_NUM];
+
+/* Touch buttons channel array */
+static const touch_pad_t channel_array[TOUCH_BUTTON_NUM] = {
+    TOUCH_PAD_NUM1,
+    TOUCH_PAD_NUM2,
+    TOUCH_PAD_NUM3,
+    TOUCH_PAD_NUM4,
+    TOUCH_PAD_NUM5,
+};
+
+/* Touch buttons channel sensitivity array */
+static const float channel_sens_array[TOUCH_BUTTON_NUM] = {
+    0.03F,
+    0.03F,
+    0.03F,
+    0.03F,
+    0.03F,
+};
+
+#ifdef CONFIG_TOUCH_ELEM_EVENT
+/* Button event handler task */
+static void button_handler_task(void *arg)
+{
+    (void) arg; //Unused
+    touch_elem_message_t element_message;
+    while (1) {
+        /* Waiting for touch element messages */
+        touch_element_message_receive(&element_message, portMAX_DELAY);
+        if (element_message.element_type != TOUCH_ELEM_TYPE_BUTTON) {
+            continue;
+        }
+        /* Decode message */
+        const touch_button_message_t *button_message = touch_button_get_message(&element_message);
+        if (button_message->event == TOUCH_BUTTON_EVT_ON_PRESS) {
+            ESP_LOGI(TAG, "Button[%d] Press", (uint32_t)element_message.arg);
+        } else if (button_message->event == TOUCH_BUTTON_EVT_ON_RELEASE) {
+            ESP_LOGI(TAG, "Button[%d] Release", (uint32_t)element_message.arg);
+        } else if (button_message->event == TOUCH_BUTTON_EVT_ON_LONGPRESS) {
+            ESP_LOGI(TAG, "Button[%d] LongPress", (uint32_t)element_message.arg);
+        }
+    }
+}
+#elif CONFIG_TOUCH_ELEM_CALLBACK
+/* Button callback routine */
+static void button_handler(touch_button_handle_t out_handle, touch_button_message_t *out_message, void *arg)
+{
+    (void) out_handle; //Unused
+    if (out_message->event == TOUCH_BUTTON_EVT_ON_PRESS) {
+        ESP_LOGI(TAG, "Button[%d] Press", (uint32_t)arg);
+        if (out_handle == button_handle[0]) {
+//            esp_deep_sleep_start();
+        } else if (out_handle == button_handle[1]) {
+            esp_deep_sleep_start();
+        }
+    } else if (out_message->event == TOUCH_BUTTON_EVT_ON_RELEASE) {
+        ESP_LOGI(TAG, "Button[%d] Release", (uint32_t)arg);
+    } else if (out_message->event == TOUCH_BUTTON_EVT_ON_LONGPRESS) {
+        ESP_LOGI(TAG, "Button[%d] LongPress", (uint32_t)arg);
+    }
+}
+#endif
+
+void app_main(void)
+{
+//    esp_pm_config_esp32s2_t pm_config = {
+//        .max_freq_mhz = 160,
+//        .min_freq_mhz = 160,
+//        .light_sleep_enable = true
+//    };
+//    ESP_ERROR_CHECK( esp_pm_configure(&pm_config) );
+    /* Initialize Touch Element library */
+    touch_elem_global_config_t global_config = TOUCH_ELEM_GLOBAL_DEFAULT_CONFIG();
+    ESP_ERROR_CHECK(touch_element_install(&global_config));
+    ESP_LOGI(TAG, "Touch element library installed");
+
+    touch_button_global_config_t button_global_config = TOUCH_BUTTON_GLOBAL_DEFAULT_CONFIG();
+    ESP_ERROR_CHECK(touch_button_install(&button_global_config));
+    ESP_LOGI(TAG, "Touch button installed");
+    for (int i = 0; i < TOUCH_BUTTON_NUM; i++) {
+        touch_button_config_t button_config = {
+            .channel_num = channel_array[i],
+            .channel_sens = channel_sens_array[i]
+        };
+        /* Create Touch buttons */
+        ESP_ERROR_CHECK(touch_button_create(&button_config, &button_handle[i]));
+        /* Subscribe touch button events (On Press, On Release, On LongPress) */
+        ESP_ERROR_CHECK(touch_button_subscribe_event(button_handle[i], TOUCH_ELEM_EVENT_ON_PRESS | TOUCH_ELEM_EVENT_ON_RELEASE | TOUCH_ELEM_EVENT_ON_LONGPRESS,
+                                                     (void *)channel_array[i]));
+#ifdef CONFIG_TOUCH_ELEM_EVENT
+        /* Set EVENT as the dispatch method */
+        ESP_ERROR_CHECK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_EVENT));
+#elif CONFIG_TOUCH_ELEM_CALLBACK
+        /* Set EVENT as the dispatch method */
+        ESP_ERROR_CHECK(touch_button_set_dispatch_method(button_handle[i], TOUCH_ELEM_DISP_CALLBACK));
+        /* Register a handler function to handle event messages */
+        ESP_ERROR_CHECK(touch_button_set_callback(button_handle[i], button_handler));
+#endif
+        /* Set LongPress event trigger threshold time */
+        ESP_ERROR_CHECK(touch_button_set_longpress(button_handle[i], 1000));
+    }
+    ESP_LOGI(TAG, "Touch buttons created");
+    touch_elem_sleep_config_t sleep_config = {
+        .scan_time = global_config.hardware.sample_count,
+        .sleep_time = global_config.hardware.sleep_cycle,
+    };
+    ESP_ERROR_CHECK(touch_element_sleep_install(&sleep_config));
+    ESP_ERROR_CHECK(touch_element_sleep_add_wakeup(button_handle[0]));
+    ESP_ERROR_CHECK(touch_element_sleep_config_wakeup_calibration(button_handle[0], true));
+    touch_pad_sleep_channel_t sleep_channel_info;
+    touch_pad_sleep_channel_get_info(&sleep_channel_info);
+    printf("----------%d\n", sleep_channel_info.touch_num);
+    touch_element_start();
+    ESP_LOGI(TAG, "Touch element library start");
+    vTaskDelay(pdMS_TO_TICKS(1000));
+}

+ 9 - 0
examples/peripherals/touch_sensor/touch_sensor_v2/touch_pad_interrupt/main/tp_interrupt_main.c

@@ -144,6 +144,8 @@ static void tp_example_read_task(void *pvParameter)
     }
 }
 
+#include "esp_sleep.h"
+#include "hal/touch_sensor_ll.h"
 void app_main(void)
 {
     if (que_touch == NULL) {
@@ -209,4 +211,11 @@ void app_main(void)
 
     // Start a task to show what pads have been touched
     xTaskCreate(&tp_example_read_task, "touch_pad_read_task", 4096, NULL, 5, NULL);
+
+    touch_ll_sleep_low_power(true);
+    while (1) {
+        esp_sleep_enable_timer_wakeup(100 * 1000);
+        esp_light_sleep_start();
+        vTaskDelay(pdMS_TO_TICKS(100));
+    }
 }