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

This commit is contained in:
Kang Zuoling 2021-03-31 19:57:54 +08:00 committed by laokaiyao
parent 24e63fd2c0
commit 82bf6c0935
12 changed files with 612 additions and 12 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
*

View File

@ -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

View File

@ -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
*

View File

@ -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
*

View File

@ -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)

View File

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

View File

@ -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

View File

@ -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));
}

View File

@ -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));
}
}