Updated libraries (button and audio player) (#16)
This PR updates two dependency libraries to their latest versions: ## espressif/button: v3.5.0 to v4.1.5 [Version 4](https://components.espressif.com/components/espressif/button/versions/4.1.5/changelog?language=en) changed the API. This code makes use of the new API, with no change to the existing behavior. ## chmorgan/esp-audio-player: v1.0.7 to v1.1.0 [Version 1.1.0](https://github.com/chmorgan/esp-audio-player/releases/tag/v1.1.0) introduces the possibility of multiple simultaneous audio streams. This feature is as yet unused by KTag. Co-authored-by: Joe Kearney <joe@clubk.club> Reviewed-on: #16
This commit is contained in:
parent
d86c494d45
commit
89166c8a02
101 changed files with 5845 additions and 2391 deletions
|
|
@ -1,4 +1,4 @@
|
|||
/* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
/* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
|
@ -12,11 +12,10 @@
|
|||
#include "driver/gpio.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_log.h"
|
||||
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||
#include "esp_pm.h"
|
||||
#endif
|
||||
#include "esp_check.h"
|
||||
#include "iot_button.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "button_interface.h"
|
||||
|
||||
static const char *TAG = "button";
|
||||
static portMUX_TYPE s_button_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
|
@ -45,6 +44,14 @@ static const char *button_event_str[] = {
|
|||
"BUTTON_NONE_PRESS",
|
||||
};
|
||||
|
||||
enum {
|
||||
PRESS_DOWN_CHECK = 0,
|
||||
PRESS_UP_CHECK,
|
||||
PRESS_REPEAT_DOWN_CHECK,
|
||||
PRESS_REPEAT_UP_CHECK,
|
||||
PRESS_LONG_PRESS_UP_CHECK,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structs to store callback info
|
||||
*
|
||||
|
|
@ -52,48 +59,41 @@ static const char *button_event_str[] = {
|
|||
typedef struct {
|
||||
button_cb_t cb;
|
||||
void *usr_data;
|
||||
button_event_data_t event_data;
|
||||
button_event_args_t event_args;
|
||||
} button_cb_info_t;
|
||||
|
||||
/**
|
||||
* @brief Structs to record individual key parameters
|
||||
*
|
||||
*/
|
||||
typedef struct Button {
|
||||
uint32_t ticks; /*!< Count for the current button state. */
|
||||
uint32_t long_press_ticks; /*!< Trigger ticks for long press, */
|
||||
uint32_t short_press_ticks; /*!< Trigger ticks for repeat press */
|
||||
uint32_t long_press_hold_cnt; /*!< Record long press hold count */
|
||||
uint8_t repeat;
|
||||
uint8_t state: 3;
|
||||
uint8_t debounce_cnt: 3;
|
||||
uint8_t active_level: 1;
|
||||
uint8_t button_level: 1;
|
||||
uint8_t enable_power_save: 1;
|
||||
button_event_t event;
|
||||
uint8_t (*hal_button_Level)(void *hardware_data);
|
||||
esp_err_t (*hal_button_deinit)(void *hardware_data);
|
||||
void *hardware_data;
|
||||
button_type_t type;
|
||||
button_cb_info_t *cb_info[BUTTON_EVENT_MAX];
|
||||
size_t size[BUTTON_EVENT_MAX];
|
||||
int count[2];
|
||||
struct Button *next;
|
||||
typedef struct button_dev_t {
|
||||
uint32_t ticks; /*!< Count for the current button state. */
|
||||
uint32_t long_press_ticks; /*!< Trigger ticks for long press, */
|
||||
uint32_t short_press_ticks; /*!< Trigger ticks for repeat press */
|
||||
uint32_t long_press_hold_cnt; /*!< Record long press hold count */
|
||||
uint8_t repeat;
|
||||
uint8_t state: 3;
|
||||
uint8_t debounce_cnt: 4; /*!< Max 15 */
|
||||
uint8_t button_level: 1;
|
||||
button_event_t event;
|
||||
button_driver_t *driver;
|
||||
button_cb_info_t *cb_info[BUTTON_EVENT_MAX];
|
||||
size_t size[BUTTON_EVENT_MAX];
|
||||
int count[2];
|
||||
struct button_dev_t *next;
|
||||
} button_dev_t;
|
||||
|
||||
//button handle list head.
|
||||
static button_dev_t *g_head_handle = NULL;
|
||||
static esp_timer_handle_t g_button_timer_handle = NULL;
|
||||
static bool g_is_timer_running = false;
|
||||
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||
static button_power_save_config_t power_save_usr_cfg = {0};
|
||||
#endif
|
||||
|
||||
#define TICKS_INTERVAL CONFIG_BUTTON_PERIOD_TIME_MS
|
||||
#define DEBOUNCE_TICKS CONFIG_BUTTON_DEBOUNCE_TICKS //MAX 8
|
||||
#define SHORT_TICKS (CONFIG_BUTTON_SHORT_PRESS_TIME_MS /TICKS_INTERVAL)
|
||||
#define LONG_TICKS (CONFIG_BUTTON_LONG_PRESS_TIME_MS /TICKS_INTERVAL)
|
||||
#define SERIAL_TICKS (CONFIG_BUTTON_SERIAL_TIME_MS /TICKS_INTERVAL)
|
||||
#define SERIAL_TICKS (CONFIG_BUTTON_LONG_PRESS_HOLD_SERIAL_TIME_MS /TICKS_INTERVAL)
|
||||
#define TOLERANCE (CONFIG_BUTTON_PERIOD_TIME_MS*4)
|
||||
|
||||
#define CALL_EVENT_CB(ev) \
|
||||
|
|
@ -110,7 +110,7 @@ static button_power_save_config_t power_save_usr_cfg = {0};
|
|||
*/
|
||||
static void button_handler(button_dev_t *btn)
|
||||
{
|
||||
uint8_t read_gpio_level = btn->hal_button_Level(btn->hardware_data);
|
||||
uint8_t read_gpio_level = btn->driver->get_key_level(btn->driver);
|
||||
|
||||
/** ticks counter working.. */
|
||||
if ((btn->state) > 0) {
|
||||
|
|
@ -129,54 +129,54 @@ static void button_handler(button_dev_t *btn)
|
|||
|
||||
/** State machine */
|
||||
switch (btn->state) {
|
||||
case 0:
|
||||
if (btn->button_level == btn->active_level) {
|
||||
case PRESS_DOWN_CHECK:
|
||||
if (btn->button_level == BUTTON_ACTIVE) {
|
||||
btn->event = (uint8_t)BUTTON_PRESS_DOWN;
|
||||
CALL_EVENT_CB(BUTTON_PRESS_DOWN);
|
||||
btn->ticks = 0;
|
||||
btn->repeat = 1;
|
||||
btn->state = 1;
|
||||
btn->state = PRESS_UP_CHECK;
|
||||
} else {
|
||||
btn->event = (uint8_t)BUTTON_NONE_PRESS;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (btn->button_level != btn->active_level) {
|
||||
case PRESS_UP_CHECK:
|
||||
if (btn->button_level != BUTTON_ACTIVE) {
|
||||
btn->event = (uint8_t)BUTTON_PRESS_UP;
|
||||
CALL_EVENT_CB(BUTTON_PRESS_UP);
|
||||
btn->ticks = 0;
|
||||
btn->state = 2;
|
||||
btn->state = PRESS_REPEAT_DOWN_CHECK;
|
||||
|
||||
} else if (btn->ticks >= btn->long_press_ticks) {
|
||||
btn->event = (uint8_t)BUTTON_LONG_PRESS_START;
|
||||
btn->state = 4;
|
||||
btn->state = PRESS_LONG_PRESS_UP_CHECK;
|
||||
/** Calling callbacks for BUTTON_LONG_PRESS_START */
|
||||
uint32_t ticks_time = iot_button_get_ticks_time(btn);
|
||||
int32_t diff = ticks_time - btn->long_press_ticks * TICKS_INTERVAL;
|
||||
uint32_t pressed_time = iot_button_get_pressed_time(btn);
|
||||
int32_t diff = pressed_time - btn->long_press_ticks * TICKS_INTERVAL;
|
||||
if (btn->cb_info[btn->event] && btn->count[0] == 0) {
|
||||
if (abs(diff) <= TOLERANCE && btn->cb_info[btn->event][btn->count[0]].event_data.long_press.press_time == (btn->long_press_ticks * TICKS_INTERVAL)) {
|
||||
if (abs(diff) <= TOLERANCE && btn->cb_info[btn->event][btn->count[0]].event_args.long_press.press_time == (btn->long_press_ticks * TICKS_INTERVAL)) {
|
||||
do {
|
||||
btn->cb_info[btn->event][btn->count[0]].cb(btn, btn->cb_info[btn->event][btn->count[0]].usr_data);
|
||||
btn->count[0]++;
|
||||
if (btn->count[0] >= btn->size[btn->event]) {
|
||||
break;
|
||||
}
|
||||
} while (btn->cb_info[btn->event][btn->count[0]].event_data.long_press.press_time == btn->long_press_ticks * TICKS_INTERVAL);
|
||||
} while (btn->cb_info[btn->event][btn->count[0]].event_args.long_press.press_time == btn->long_press_ticks * TICKS_INTERVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (btn->button_level == btn->active_level) {
|
||||
case PRESS_REPEAT_DOWN_CHECK:
|
||||
if (btn->button_level == BUTTON_ACTIVE) {
|
||||
btn->event = (uint8_t)BUTTON_PRESS_DOWN;
|
||||
CALL_EVENT_CB(BUTTON_PRESS_DOWN);
|
||||
btn->event = (uint8_t)BUTTON_PRESS_REPEAT;
|
||||
btn->repeat++;
|
||||
CALL_EVENT_CB(BUTTON_PRESS_REPEAT); // repeat hit
|
||||
btn->ticks = 0;
|
||||
btn->state = 3;
|
||||
btn->state = PRESS_REPEAT_UP_CHECK;
|
||||
} else if (btn->ticks > btn->short_press_ticks) {
|
||||
if (btn->repeat == 1) {
|
||||
btn->event = (uint8_t)BUTTON_SINGLE_CLICK;
|
||||
|
|
@ -190,14 +190,8 @@ static void button_handler(button_dev_t *btn)
|
|||
|
||||
/** Calling the callbacks for MULTIPLE BUTTON CLICKS */
|
||||
for (int i = 0; i < btn->size[btn->event]; i++) {
|
||||
if (btn->repeat == btn->cb_info[btn->event][i].event_data.multiple_clicks.clicks) {
|
||||
do {
|
||||
btn->cb_info[btn->event][i].cb(btn, btn->cb_info[btn->event][i].usr_data);
|
||||
i++;
|
||||
if (i >= btn->size[btn->event]) {
|
||||
break;
|
||||
}
|
||||
} while (btn->cb_info[btn->event][i].event_data.multiple_clicks.clicks == btn->repeat);
|
||||
if (btn->repeat == btn->cb_info[btn->event][i].event_args.multiple_clicks.clicks) {
|
||||
btn->cb_info[btn->event][i].cb(btn, btn->cb_info[btn->event][i].usr_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -211,75 +205,75 @@ static void button_handler(button_dev_t *btn)
|
|||
break;
|
||||
|
||||
case 3:
|
||||
if (btn->button_level != btn->active_level) {
|
||||
if (btn->button_level != BUTTON_ACTIVE) {
|
||||
btn->event = (uint8_t)BUTTON_PRESS_UP;
|
||||
CALL_EVENT_CB(BUTTON_PRESS_UP);
|
||||
if (btn->ticks < btn->short_press_ticks) {
|
||||
btn->ticks = 0;
|
||||
btn->state = 2; //repeat press
|
||||
btn->state = PRESS_REPEAT_DOWN_CHECK; //repeat press
|
||||
} else {
|
||||
btn->state = 0;
|
||||
btn->state = PRESS_DOWN_CHECK;
|
||||
btn->event = (uint8_t)BUTTON_PRESS_END;
|
||||
CALL_EVENT_CB(BUTTON_PRESS_END);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (btn->button_level == btn->active_level) {
|
||||
case PRESS_LONG_PRESS_UP_CHECK:
|
||||
if (btn->button_level == BUTTON_ACTIVE) {
|
||||
//continue hold trigger
|
||||
if (btn->ticks >= (btn->long_press_hold_cnt + 1) * SERIAL_TICKS + btn->long_press_ticks) {
|
||||
btn->event = (uint8_t)BUTTON_LONG_PRESS_HOLD;
|
||||
btn->long_press_hold_cnt++;
|
||||
CALL_EVENT_CB(BUTTON_LONG_PRESS_HOLD);
|
||||
}
|
||||
|
||||
/** Calling callbacks for BUTTON_LONG_PRESS_START based on press_time */
|
||||
uint32_t ticks_time = iot_button_get_ticks_time(btn);
|
||||
if (btn->cb_info[BUTTON_LONG_PRESS_START]) {
|
||||
button_cb_info_t *cb_info = btn->cb_info[BUTTON_LONG_PRESS_START];
|
||||
uint16_t time = cb_info[btn->count[0]].event_data.long_press.press_time;
|
||||
if (btn->long_press_ticks * TICKS_INTERVAL > time) {
|
||||
for (int i = btn->count[0] + 1; i < btn->size[BUTTON_LONG_PRESS_START]; i++) {
|
||||
time = cb_info[i].event_data.long_press.press_time;
|
||||
if (btn->long_press_ticks * TICKS_INTERVAL <= time) {
|
||||
btn->count[0] = i;
|
||||
break;
|
||||
}
|
||||
/** Calling callbacks for BUTTON_LONG_PRESS_START based on press_time */
|
||||
uint32_t pressed_time = iot_button_get_pressed_time(btn);
|
||||
if (btn->cb_info[BUTTON_LONG_PRESS_START]) {
|
||||
button_cb_info_t *cb_info = btn->cb_info[BUTTON_LONG_PRESS_START];
|
||||
uint16_t time = cb_info[btn->count[0]].event_args.long_press.press_time;
|
||||
if (btn->long_press_ticks * TICKS_INTERVAL > time) {
|
||||
for (int i = btn->count[0] + 1; i < btn->size[BUTTON_LONG_PRESS_START]; i++) {
|
||||
time = cb_info[i].event_args.long_press.press_time;
|
||||
if (btn->long_press_ticks * TICKS_INTERVAL <= time) {
|
||||
btn->count[0] = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (btn->count[0] < btn->size[BUTTON_LONG_PRESS_START] && abs((int)ticks_time - (int)time) <= TOLERANCE) {
|
||||
btn->event = (uint8_t)BUTTON_LONG_PRESS_START;
|
||||
do {
|
||||
cb_info[btn->count[0]].cb(btn, cb_info[btn->count[0]].usr_data);
|
||||
btn->count[0]++;
|
||||
if (btn->count[0] >= btn->size[BUTTON_LONG_PRESS_START]) {
|
||||
break;
|
||||
}
|
||||
} while (time == cb_info[btn->count[0]].event_data.long_press.press_time);
|
||||
}
|
||||
}
|
||||
if (btn->count[0] < btn->size[BUTTON_LONG_PRESS_START] && abs((int)pressed_time - (int)time) <= TOLERANCE) {
|
||||
btn->event = (uint8_t)BUTTON_LONG_PRESS_START;
|
||||
do {
|
||||
cb_info[btn->count[0]].cb(btn, cb_info[btn->count[0]].usr_data);
|
||||
btn->count[0]++;
|
||||
if (btn->count[0] >= btn->size[BUTTON_LONG_PRESS_START]) {
|
||||
break;
|
||||
}
|
||||
} while (time == cb_info[btn->count[0]].event_args.long_press.press_time);
|
||||
}
|
||||
}
|
||||
|
||||
/** Updating counter for BUTTON_LONG_PRESS_UP press_time */
|
||||
if (btn->cb_info[BUTTON_LONG_PRESS_UP]) {
|
||||
button_cb_info_t *cb_info = btn->cb_info[BUTTON_LONG_PRESS_UP];
|
||||
uint16_t time = cb_info[btn->count[1] + 1].event_data.long_press.press_time;
|
||||
if (btn->long_press_ticks * TICKS_INTERVAL > time) {
|
||||
for (int i = btn->count[1] + 1; i < btn->size[BUTTON_LONG_PRESS_UP]; i++) {
|
||||
time = cb_info[i].event_data.long_press.press_time;
|
||||
if (btn->long_press_ticks * TICKS_INTERVAL <= time) {
|
||||
btn->count[1] = i;
|
||||
break;
|
||||
}
|
||||
/** Updating counter for BUTTON_LONG_PRESS_UP press_time */
|
||||
if (btn->cb_info[BUTTON_LONG_PRESS_UP]) {
|
||||
button_cb_info_t *cb_info = btn->cb_info[BUTTON_LONG_PRESS_UP];
|
||||
uint16_t time = cb_info[btn->count[1] + 1].event_args.long_press.press_time;
|
||||
if (btn->long_press_ticks * TICKS_INTERVAL > time) {
|
||||
for (int i = btn->count[1] + 1; i < btn->size[BUTTON_LONG_PRESS_UP]; i++) {
|
||||
time = cb_info[i].event_args.long_press.press_time;
|
||||
if (btn->long_press_ticks * TICKS_INTERVAL <= time) {
|
||||
btn->count[1] = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (btn->count[1] + 1 < btn->size[BUTTON_LONG_PRESS_UP] && abs((int)ticks_time - (int)time) <= TOLERANCE) {
|
||||
do {
|
||||
btn->count[1]++;
|
||||
if (btn->count[1] + 1 >= btn->size[BUTTON_LONG_PRESS_UP]) {
|
||||
break;
|
||||
}
|
||||
} while (time == cb_info[btn->count[1] + 1].event_data.long_press.press_time);
|
||||
}
|
||||
}
|
||||
if (btn->count[1] + 1 < btn->size[BUTTON_LONG_PRESS_UP] && abs((int)pressed_time - (int)time) <= TOLERANCE) {
|
||||
do {
|
||||
btn->count[1]++;
|
||||
if (btn->count[1] + 1 >= btn->size[BUTTON_LONG_PRESS_UP]) {
|
||||
break;
|
||||
}
|
||||
} while (time == cb_info[btn->count[1] + 1].event_args.long_press.press_time);
|
||||
}
|
||||
}
|
||||
} else { //releasd
|
||||
|
|
@ -295,7 +289,7 @@ static void button_handler(button_dev_t *btn)
|
|||
break;
|
||||
}
|
||||
btn->count[1]--;
|
||||
} while (cb_info[btn->count[1]].event_data.long_press.press_time == cb_info[btn->count[1] + 1].event_data.long_press.press_time);
|
||||
} while (cb_info[btn->count[1]].event_args.long_press.press_time == cb_info[btn->count[1] + 1].event_args.long_press.press_time);
|
||||
|
||||
/** Reset the counter */
|
||||
btn->count[1] = -1;
|
||||
|
|
@ -307,7 +301,7 @@ static void button_handler(button_dev_t *btn)
|
|||
|
||||
btn->event = (uint8_t)BUTTON_PRESS_UP;
|
||||
CALL_EVENT_CB(BUTTON_PRESS_UP);
|
||||
btn->state = 0; //reset
|
||||
btn->state = PRESS_DOWN_CHECK; //reset
|
||||
btn->long_press_hold_cnt = 0;
|
||||
btn->event = (uint8_t)BUTTON_PRESS_END;
|
||||
CALL_EVENT_CB(BUTTON_PRESS_END);
|
||||
|
|
@ -320,18 +314,13 @@ static void button_cb(void *args)
|
|||
{
|
||||
button_dev_t *target;
|
||||
/*!< When all buttons enter the BUTTON_NONE_PRESS state, the system enters low-power mode */
|
||||
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||
bool enter_power_save_flag = true;
|
||||
#endif
|
||||
for (target = g_head_handle; target; target = target->next) {
|
||||
button_handler(target);
|
||||
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||
if (!(target->enable_power_save && target->debounce_cnt == 0 && target->event == BUTTON_NONE_PRESS)) {
|
||||
if (!(target->driver->enable_power_save && target->debounce_cnt == 0 && target->event == BUTTON_NONE_PRESS)) {
|
||||
enter_power_save_flag = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||
if (enter_power_save_flag) {
|
||||
/*!< Stop esp timer for power save */
|
||||
if (g_is_timer_running) {
|
||||
|
|
@ -339,9 +328,8 @@ static void button_cb(void *args)
|
|||
g_is_timer_running = false;
|
||||
}
|
||||
for (target = g_head_handle; target; target = target->next) {
|
||||
if (target->type == BUTTON_TYPE_GPIO && target->enable_power_save) {
|
||||
button_gpio_intr_control((int)(target->hardware_data), true);
|
||||
button_gpio_enable_gpio_wakeup((uint32_t)(target->hardware_data), target->active_level, true);
|
||||
if (target->driver->enable_power_save && target->driver->enter_power_save) {
|
||||
target->driver->enter_power_save(target->driver);
|
||||
}
|
||||
}
|
||||
/*!< Notify the user that the Button has entered power save mode by calling this callback function. */
|
||||
|
|
@ -349,212 +337,21 @@ static void button_cb(void *args)
|
|||
power_save_usr_cfg.enter_power_save_cb(power_save_usr_cfg.usr_data);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||
static void IRAM_ATTR button_power_save_isr_handler(void* arg)
|
||||
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_event_args_t *event_args, button_cb_t cb, void *usr_data)
|
||||
{
|
||||
if (!g_is_timer_running) {
|
||||
esp_timer_start_periodic(g_button_timer_handle, TICKS_INTERVAL * 1000U);
|
||||
g_is_timer_running = true;
|
||||
}
|
||||
button_gpio_intr_control((int)arg, false);
|
||||
/*!< disable gpio wakeup not need active level*/
|
||||
button_gpio_enable_gpio_wakeup((uint32_t)arg, 0, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
static button_dev_t *button_create_com(uint8_t active_level, uint8_t (*hal_get_key_state)(void *hardware_data), void *hardware_data, uint16_t long_press_ticks, uint16_t short_press_ticks)
|
||||
{
|
||||
BTN_CHECK(NULL != hal_get_key_state, "Function pointer is invalid", NULL);
|
||||
|
||||
button_dev_t *btn = (button_dev_t *) calloc(1, sizeof(button_dev_t));
|
||||
BTN_CHECK(NULL != btn, "Button memory alloc failed", NULL);
|
||||
btn->hardware_data = hardware_data;
|
||||
btn->event = BUTTON_NONE_PRESS;
|
||||
btn->active_level = active_level;
|
||||
btn->hal_button_Level = hal_get_key_state;
|
||||
btn->button_level = !active_level;
|
||||
btn->long_press_ticks = long_press_ticks;
|
||||
btn->short_press_ticks = short_press_ticks;
|
||||
|
||||
/** Add handle to list */
|
||||
btn->next = g_head_handle;
|
||||
g_head_handle = btn;
|
||||
|
||||
if (!g_button_timer_handle) {
|
||||
esp_timer_create_args_t button_timer = {0};
|
||||
button_timer.arg = NULL;
|
||||
button_timer.callback = button_cb;
|
||||
button_timer.dispatch_method = ESP_TIMER_TASK;
|
||||
button_timer.name = "button_timer";
|
||||
esp_timer_create(&button_timer, &g_button_timer_handle);
|
||||
}
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
static esp_err_t button_delete_com(button_dev_t *btn)
|
||||
{
|
||||
BTN_CHECK(NULL != btn, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||
|
||||
button_dev_t **curr;
|
||||
for (curr = &g_head_handle; *curr;) {
|
||||
button_dev_t *entry = *curr;
|
||||
if (entry == btn) {
|
||||
*curr = entry->next;
|
||||
free(entry);
|
||||
} else {
|
||||
curr = &entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* count button number */
|
||||
uint16_t number = 0;
|
||||
button_dev_t *target = g_head_handle;
|
||||
while (target) {
|
||||
target = target->next;
|
||||
number++;
|
||||
}
|
||||
ESP_LOGD(TAG, "remain btn number=%d", number);
|
||||
|
||||
if (0 == number && g_is_timer_running) { /**< if all button is deleted, stop the timer */
|
||||
esp_timer_stop(g_button_timer_handle);
|
||||
esp_timer_delete(g_button_timer_handle);
|
||||
g_button_timer_handle = NULL;
|
||||
g_is_timer_running = false;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
button_handle_t iot_button_create(const button_config_t *config)
|
||||
{
|
||||
ESP_LOGI(TAG, "IoT Button Version: %d.%d.%d", BUTTON_VER_MAJOR, BUTTON_VER_MINOR, BUTTON_VER_PATCH);
|
||||
BTN_CHECK(config, "Invalid button config", NULL);
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
button_dev_t *btn = NULL;
|
||||
uint16_t long_press_time = 0;
|
||||
uint16_t short_press_time = 0;
|
||||
long_press_time = TIME_TO_TICKS(config->long_press_time, LONG_TICKS);
|
||||
short_press_time = TIME_TO_TICKS(config->short_press_time, SHORT_TICKS);
|
||||
switch (config->type) {
|
||||
case BUTTON_TYPE_GPIO: {
|
||||
const button_gpio_config_t *cfg = &(config->gpio_button_config);
|
||||
ret = button_gpio_init(cfg);
|
||||
BTN_CHECK(ESP_OK == ret, "gpio button init failed", NULL);
|
||||
btn = button_create_com(cfg->active_level, button_gpio_get_key_level, (void *)cfg->gpio_num, long_press_time, short_press_time);
|
||||
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||
if (cfg->enable_power_save) {
|
||||
btn->enable_power_save = cfg->enable_power_save;
|
||||
button_gpio_set_intr(cfg->gpio_num, cfg->active_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL, button_power_save_isr_handler, (void *)cfg->gpio_num);
|
||||
}
|
||||
#endif
|
||||
} break;
|
||||
#if CONFIG_SOC_ADC_SUPPORTED
|
||||
case BUTTON_TYPE_ADC: {
|
||||
const button_adc_config_t *cfg = &(config->adc_button_config);
|
||||
ret = button_adc_init(cfg);
|
||||
BTN_CHECK(ESP_OK == ret, "adc button init failed", NULL);
|
||||
btn = button_create_com(1, button_adc_get_key_level, (void *)ADC_BUTTON_COMBINE(cfg->adc_channel, cfg->button_index), long_press_time, short_press_time);
|
||||
} break;
|
||||
#endif
|
||||
case BUTTON_TYPE_MATRIX: {
|
||||
const button_matrix_config_t *cfg = &(config->matrix_button_config);
|
||||
ret = button_matrix_init(cfg);
|
||||
BTN_CHECK(ESP_OK == ret, "matrix button init failed", NULL);
|
||||
btn = button_create_com(1, button_matrix_get_key_level, (void *)MATRIX_BUTTON_COMBINE(cfg->row_gpio_num, cfg->col_gpio_num), long_press_time, short_press_time);
|
||||
} break;
|
||||
case BUTTON_TYPE_CUSTOM: {
|
||||
if (config->custom_button_config.button_custom_init) {
|
||||
ret = config->custom_button_config.button_custom_init(config->custom_button_config.priv);
|
||||
BTN_CHECK(ESP_OK == ret, "custom button init failed", NULL);
|
||||
}
|
||||
|
||||
btn = button_create_com(config->custom_button_config.active_level,
|
||||
config->custom_button_config.button_custom_get_key_value,
|
||||
config->custom_button_config.priv,
|
||||
long_press_time, short_press_time);
|
||||
if (btn) {
|
||||
btn->hal_button_deinit = config->custom_button_config.button_custom_deinit;
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unsupported button type");
|
||||
break;
|
||||
}
|
||||
BTN_CHECK(NULL != btn, "button create failed", NULL);
|
||||
btn->type = config->type;
|
||||
if (!btn->enable_power_save && !g_is_timer_running) {
|
||||
esp_timer_start_periodic(g_button_timer_handle, TICKS_INTERVAL * 1000U);
|
||||
g_is_timer_running = true;
|
||||
}
|
||||
return (button_handle_t)btn;
|
||||
}
|
||||
|
||||
esp_err_t iot_button_delete(button_handle_t btn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||
button_dev_t *btn = (button_dev_t *)btn_handle;
|
||||
switch (btn->type) {
|
||||
case BUTTON_TYPE_GPIO:
|
||||
ret = button_gpio_deinit((int)(btn->hardware_data));
|
||||
break;
|
||||
#if CONFIG_SOC_ADC_SUPPORTED
|
||||
case BUTTON_TYPE_ADC:
|
||||
ret = button_adc_deinit(ADC_BUTTON_SPLIT_CHANNEL(btn->hardware_data), ADC_BUTTON_SPLIT_INDEX(btn->hardware_data));
|
||||
break;
|
||||
#endif
|
||||
case BUTTON_TYPE_MATRIX:
|
||||
ret = button_matrix_deinit(MATRIX_BUTTON_SPLIT_ROW(btn->hardware_data), MATRIX_BUTTON_SPLIT_COL(btn->hardware_data));
|
||||
break;
|
||||
case BUTTON_TYPE_CUSTOM:
|
||||
if (btn->hal_button_deinit) {
|
||||
ret = btn->hal_button_deinit(btn->hardware_data);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
BTN_CHECK(ESP_OK == ret, "button deinit failed", ESP_FAIL);
|
||||
for (int i = 0; i < BUTTON_EVENT_MAX; i++) {
|
||||
if (btn->cb_info[i]) {
|
||||
free(btn->cb_info[i]);
|
||||
}
|
||||
}
|
||||
button_delete_com(btn);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_cb_t cb, void *usr_data)
|
||||
{
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||
ESP_RETURN_ON_FALSE(NULL != btn_handle, ESP_ERR_INVALID_ARG, TAG, "Pointer of handle is invalid");
|
||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||
BTN_CHECK(event != BUTTON_MULTIPLE_CLICK, "event argument is invalid", ESP_ERR_INVALID_ARG);
|
||||
button_event_config_t event_cfg = {
|
||||
.event = event,
|
||||
};
|
||||
ESP_RETURN_ON_FALSE(event < BUTTON_EVENT_MAX, ESP_ERR_INVALID_ARG, TAG, "event is invalid");
|
||||
ESP_RETURN_ON_FALSE(NULL != cb, ESP_ERR_INVALID_ARG, TAG, "Pointer of cb is invalid");
|
||||
ESP_RETURN_ON_FALSE(event != BUTTON_MULTIPLE_CLICK || event_args, ESP_ERR_INVALID_ARG, TAG, "event is invalid");
|
||||
|
||||
if ((event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) && !event_cfg.event_data.long_press.press_time) {
|
||||
event_cfg.event_data.long_press.press_time = btn->long_press_ticks * TICKS_INTERVAL;
|
||||
if (event_args) {
|
||||
ESP_RETURN_ON_FALSE(!(event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) || event_args->long_press.press_time > btn->short_press_ticks * TICKS_INTERVAL, ESP_ERR_INVALID_ARG, TAG, "event_args is invalid");
|
||||
ESP_RETURN_ON_FALSE(event != BUTTON_MULTIPLE_CLICK || event_args->multiple_clicks.clicks, ESP_ERR_INVALID_ARG, TAG, "event_args is invalid");
|
||||
}
|
||||
|
||||
return iot_button_register_event_cb(btn_handle, event_cfg, cb, usr_data);
|
||||
}
|
||||
|
||||
esp_err_t iot_button_register_event_cb(button_handle_t btn_handle, button_event_config_t event_cfg, button_cb_t cb, void *usr_data)
|
||||
{
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||
button_event_t event = event_cfg.event;
|
||||
BTN_CHECK(event < BUTTON_EVENT_MAX, "event is invalid", ESP_ERR_INVALID_ARG);
|
||||
BTN_CHECK(!(event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) || event_cfg.event_data.long_press.press_time > btn->short_press_ticks * TICKS_INTERVAL, "event_data is invalid", ESP_ERR_INVALID_ARG);
|
||||
BTN_CHECK(event != BUTTON_MULTIPLE_CLICK || event_cfg.event_data.multiple_clicks.clicks, "event_data is invalid", ESP_ERR_INVALID_ARG);
|
||||
|
||||
if (!btn->cb_info[event]) {
|
||||
btn->cb_info[event] = calloc(1, sizeof(button_cb_info_t));
|
||||
BTN_CHECK(NULL != btn->cb_info[event], "calloc cb_info failed", ESP_ERR_NO_MEM);
|
||||
|
|
@ -573,27 +370,30 @@ esp_err_t iot_button_register_event_cb(button_handle_t btn_handle, button_event_
|
|||
btn->cb_info[event][btn->size[event]].usr_data = usr_data;
|
||||
btn->size[event]++;
|
||||
|
||||
/** Inserting the event_data in sorted manner */
|
||||
/** Inserting the event_args in sorted manner */
|
||||
if (event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) {
|
||||
uint16_t press_time = event_cfg.event_data.long_press.press_time;
|
||||
BTN_CHECK(press_time / TICKS_INTERVAL > btn->short_press_ticks, "press_time event_data is less than short_press_ticks", ESP_ERR_INVALID_ARG);
|
||||
uint16_t press_time = btn->long_press_ticks * TICKS_INTERVAL;
|
||||
if (event_args) {
|
||||
press_time = event_args->long_press.press_time;
|
||||
}
|
||||
BTN_CHECK(press_time / TICKS_INTERVAL > btn->short_press_ticks, "press_time event_args is less than short_press_ticks", ESP_ERR_INVALID_ARG);
|
||||
if (btn->size[event] >= 2) {
|
||||
for (int i = btn->size[event] - 2; i >= 0; i--) {
|
||||
if (btn->cb_info[event][i].event_data.long_press.press_time > press_time) {
|
||||
if (btn->cb_info[event][i].event_args.long_press.press_time > press_time) {
|
||||
btn->cb_info[event][i + 1] = btn->cb_info[event][i];
|
||||
|
||||
btn->cb_info[event][i].event_data.long_press.press_time = press_time;
|
||||
btn->cb_info[event][i].event_args.long_press.press_time = press_time;
|
||||
btn->cb_info[event][i].cb = cb;
|
||||
btn->cb_info[event][i].usr_data = usr_data;
|
||||
} else {
|
||||
btn->cb_info[event][i + 1].event_data.long_press.press_time = press_time;
|
||||
btn->cb_info[event][i + 1].event_args.long_press.press_time = press_time;
|
||||
btn->cb_info[event][i + 1].cb = cb;
|
||||
btn->cb_info[event][i + 1].usr_data = usr_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
btn->cb_info[event][btn->size[event] - 1].event_data.long_press.press_time = press_time;
|
||||
btn->cb_info[event][btn->size[event] - 1].event_args.long_press.press_time = press_time;
|
||||
}
|
||||
|
||||
int32_t press_ticks = press_time / TICKS_INTERVAL;
|
||||
|
|
@ -603,35 +403,52 @@ esp_err_t iot_button_register_event_cb(button_handle_t btn_handle, button_event_
|
|||
}
|
||||
|
||||
if (event == BUTTON_MULTIPLE_CLICK) {
|
||||
uint16_t clicks = btn->long_press_ticks * TICKS_INTERVAL;
|
||||
if (event_args) {
|
||||
clicks = event_args->multiple_clicks.clicks;
|
||||
}
|
||||
if (btn->size[event] >= 2) {
|
||||
for (int i = btn->size[event] - 2; i >= 0; i--) {
|
||||
if (btn->cb_info[event][i].event_data.multiple_clicks.clicks > event_cfg.event_data.multiple_clicks.clicks) {
|
||||
if (btn->cb_info[event][i].event_args.multiple_clicks.clicks > clicks) {
|
||||
btn->cb_info[event][i + 1] = btn->cb_info[event][i];
|
||||
|
||||
btn->cb_info[event][i].event_data.multiple_clicks.clicks = event_cfg.event_data.multiple_clicks.clicks;
|
||||
btn->cb_info[event][i].event_args.multiple_clicks.clicks = clicks;
|
||||
btn->cb_info[event][i].cb = cb;
|
||||
btn->cb_info[event][i].usr_data = usr_data;
|
||||
} else {
|
||||
btn->cb_info[event][i + 1].event_data.multiple_clicks.clicks = event_cfg.event_data.multiple_clicks.clicks;
|
||||
btn->cb_info[event][i + 1].event_args.multiple_clicks.clicks = clicks;
|
||||
btn->cb_info[event][i + 1].cb = cb;
|
||||
btn->cb_info[event][i + 1].usr_data = usr_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
btn->cb_info[event][btn->size[event] - 1].event_data.multiple_clicks.clicks = event_cfg.event_data.multiple_clicks.clicks;
|
||||
btn->cb_info[event][btn->size[event] - 1].event_args.multiple_clicks.clicks = clicks;
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t iot_button_unregister_cb(button_handle_t btn_handle, button_event_t event)
|
||||
esp_err_t iot_button_unregister_cb(button_handle_t btn_handle, button_event_t event, button_event_args_t *event_args)
|
||||
{
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||
BTN_CHECK(event < BUTTON_EVENT_MAX, "event is invalid", ESP_ERR_INVALID_ARG);
|
||||
ESP_RETURN_ON_FALSE(NULL != btn_handle, ESP_ERR_INVALID_ARG, TAG, "Pointer of handle is invalid");
|
||||
ESP_RETURN_ON_FALSE(event < BUTTON_EVENT_MAX, ESP_ERR_INVALID_ARG, TAG, "event is invalid");
|
||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||
BTN_CHECK(NULL != btn->cb_info[event], "No callbacks registered for the event", ESP_ERR_INVALID_STATE);
|
||||
ESP_RETURN_ON_FALSE(btn->cb_info[event], ESP_ERR_INVALID_STATE, TAG, "No callbacks registered for the event");
|
||||
|
||||
int check = -1;
|
||||
|
||||
if ((event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) && event_args) {
|
||||
if (event_args->long_press.press_time != 0) {
|
||||
goto unregister_event;
|
||||
}
|
||||
}
|
||||
|
||||
if (event == BUTTON_MULTIPLE_CLICK && event_args) {
|
||||
if (event_args->multiple_clicks.clicks != 0) {
|
||||
goto unregister_event;
|
||||
}
|
||||
}
|
||||
|
||||
if (btn->cb_info[event]) {
|
||||
free(btn->cb_info[event]);
|
||||
|
|
@ -648,52 +465,40 @@ esp_err_t iot_button_unregister_cb(button_handle_t btn_handle, button_event_t ev
|
|||
btn->cb_info[event] = NULL;
|
||||
btn->size[event] = 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t iot_button_unregister_event(button_handle_t btn_handle, button_event_config_t event_cfg, button_cb_t cb)
|
||||
{
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||
button_event_t event = event_cfg.event;
|
||||
BTN_CHECK(event < BUTTON_EVENT_MAX, "event is invalid", ESP_ERR_INVALID_ARG);
|
||||
BTN_CHECK(NULL != cb, "Pointer to function callback is invalid", ESP_ERR_INVALID_ARG);
|
||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||
|
||||
int check = -1;
|
||||
unregister_event:
|
||||
|
||||
for (int i = 0; i < btn->size[event]; i++) {
|
||||
if (cb == btn->cb_info[event][i].cb) {
|
||||
if ((event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) && event_cfg.event_data.long_press.press_time) {
|
||||
if (event_cfg.event_data.long_press.press_time != btn->cb_info[event][i].event_data.long_press.press_time) {
|
||||
continue;
|
||||
}
|
||||
if ((event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) && event_args->long_press.press_time) {
|
||||
if (event_args->long_press.press_time != btn->cb_info[event][i].event_args.long_press.press_time) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event == BUTTON_MULTIPLE_CLICK && event_cfg.event_data.multiple_clicks.clicks) {
|
||||
if (event_cfg.event_data.multiple_clicks.clicks != btn->cb_info[event][i].event_data.multiple_clicks.clicks) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
check = i;
|
||||
for (int j = i; j <= btn->size[event] - 1; j++) {
|
||||
btn->cb_info[event][j] = btn->cb_info[event][j + 1];
|
||||
}
|
||||
|
||||
if (btn->size[event] != 1) {
|
||||
button_cb_info_t *p = realloc(btn->cb_info[event], sizeof(button_cb_info_t) * (btn->size[event] - 1));
|
||||
BTN_CHECK(NULL != p, "realloc cb_info failed", ESP_ERR_NO_MEM);
|
||||
btn->cb_info[event] = p;
|
||||
btn->size[event]--;
|
||||
} else {
|
||||
free(btn->cb_info[event]);
|
||||
btn->cb_info[event] = NULL;
|
||||
btn->size[event] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (event == BUTTON_MULTIPLE_CLICK && event_args->multiple_clicks.clicks) {
|
||||
if (event_args->multiple_clicks.clicks != btn->cb_info[event][i].event_args.multiple_clicks.clicks) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
check = i;
|
||||
for (int j = i; j <= btn->size[event] - 1; j++) {
|
||||
btn->cb_info[event][j] = btn->cb_info[event][j + 1];
|
||||
}
|
||||
|
||||
if (btn->size[event] != 1) {
|
||||
button_cb_info_t *p = realloc(btn->cb_info[event], sizeof(button_cb_info_t) * (btn->size[event] - 1));
|
||||
BTN_CHECK(NULL != p, "realloc cb_info failed", ESP_ERR_NO_MEM);
|
||||
btn->cb_info[event] = p;
|
||||
btn->size[event]--;
|
||||
} else {
|
||||
free(btn->cb_info[event]);
|
||||
btn->cb_info[event] = NULL;
|
||||
btn->size[event] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
BTN_CHECK(check != -1, "No such callback registered for the event", ESP_ERR_INVALID_STATE);
|
||||
|
||||
ESP_RETURN_ON_FALSE(check != -1, ESP_ERR_NOT_FOUND, TAG, "No such callback registered for the event");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
|
@ -710,7 +515,7 @@ size_t iot_button_count_cb(button_handle_t btn_handle)
|
|||
return ret;
|
||||
}
|
||||
|
||||
size_t iot_button_count_event(button_handle_t btn_handle, button_event_t event)
|
||||
size_t iot_button_count_event_cb(button_handle_t btn_handle, button_event_t event)
|
||||
{
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
|
||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||
|
|
@ -745,13 +550,18 @@ uint8_t iot_button_get_repeat(button_handle_t btn_handle)
|
|||
return btn->repeat;
|
||||
}
|
||||
|
||||
uint32_t iot_button_get_ticks_time(button_handle_t btn_handle)
|
||||
uint32_t iot_button_get_pressed_time(button_handle_t btn_handle)
|
||||
{
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", 0);
|
||||
button_dev_t *btn = (button_dev_t *) btn_handle;
|
||||
return (btn->ticks * TICKS_INTERVAL);
|
||||
}
|
||||
|
||||
uint32_t iot_button_get_ticks_time(button_handle_t btn_handle)
|
||||
{
|
||||
return iot_button_get_pressed_time(btn_handle);
|
||||
}
|
||||
|
||||
uint16_t iot_button_get_long_press_hold_cnt(button_handle_t btn_handle)
|
||||
{
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", 0);
|
||||
|
|
@ -782,18 +592,19 @@ uint8_t iot_button_get_key_level(button_handle_t btn_handle)
|
|||
{
|
||||
BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", 0);
|
||||
button_dev_t *btn = (button_dev_t *)btn_handle;
|
||||
uint8_t level = btn->hal_button_Level(btn->hardware_data);
|
||||
return (level == btn->active_level) ? 1 : 0;
|
||||
uint8_t level = btn->driver->get_key_level(btn->driver);
|
||||
return level;
|
||||
}
|
||||
|
||||
esp_err_t iot_button_resume(void)
|
||||
{
|
||||
BTN_CHECK(g_button_timer_handle, "Button timer handle is invalid", ESP_ERR_INVALID_STATE);
|
||||
BTN_CHECK(!g_is_timer_running, "Button timer is already running", ESP_ERR_INVALID_STATE);
|
||||
|
||||
esp_err_t err = esp_timer_start_periodic(g_button_timer_handle, TICKS_INTERVAL * 1000U);
|
||||
BTN_CHECK(ESP_OK == err, "Button timer start failed", ESP_FAIL);
|
||||
g_is_timer_running = true;
|
||||
if (!g_button_timer_handle) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (!g_is_timer_running) {
|
||||
esp_timer_start_periodic(g_button_timer_handle, TICKS_INTERVAL * 1000U);
|
||||
g_is_timer_running = true;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
|
@ -808,7 +619,6 @@ esp_err_t iot_button_stop(void)
|
|||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_GPIO_BUTTON_SUPPORT_POWER_SAVE
|
||||
esp_err_t iot_button_register_power_save_cb(const button_power_save_config_t *config)
|
||||
{
|
||||
BTN_CHECK(g_head_handle, "No button registered", ESP_ERR_INVALID_STATE);
|
||||
|
|
@ -818,4 +628,83 @@ esp_err_t iot_button_register_power_save_cb(const button_power_save_config_t *co
|
|||
power_save_usr_cfg.usr_data = config->usr_data;
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t iot_button_create(const button_config_t *config, const button_driver_t *driver, button_handle_t *ret_button)
|
||||
{
|
||||
if (!g_head_handle) {
|
||||
ESP_LOGI(TAG, "IoT Button Version: %d.%d.%d", BUTTON_VER_MAJOR, BUTTON_VER_MINOR, BUTTON_VER_PATCH);
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(driver && config && ret_button, ESP_ERR_INVALID_ARG, TAG, "Invalid argument");
|
||||
button_dev_t *btn = (button_dev_t *) calloc(1, sizeof(button_dev_t));
|
||||
ESP_RETURN_ON_FALSE(btn, ESP_ERR_NO_MEM, TAG, "Button memory alloc failed");
|
||||
|
||||
btn->driver = (button_driver_t *)driver;
|
||||
btn->long_press_ticks = TIME_TO_TICKS(config->long_press_time, LONG_TICKS);
|
||||
btn->short_press_ticks = TIME_TO_TICKS(config->short_press_time, SHORT_TICKS);
|
||||
btn->event = BUTTON_NONE_PRESS;
|
||||
btn->button_level = BUTTON_INACTIVE;
|
||||
|
||||
btn->next = g_head_handle;
|
||||
g_head_handle = btn;
|
||||
|
||||
if (!g_button_timer_handle) {
|
||||
esp_timer_create_args_t button_timer = {0};
|
||||
button_timer.arg = NULL;
|
||||
button_timer.callback = button_cb;
|
||||
button_timer.dispatch_method = ESP_TIMER_TASK;
|
||||
button_timer.name = "button_timer";
|
||||
esp_timer_create(&button_timer, &g_button_timer_handle);
|
||||
}
|
||||
|
||||
if (!driver->enable_power_save && !g_is_timer_running) {
|
||||
esp_timer_start_periodic(g_button_timer_handle, TICKS_INTERVAL * 1000U);
|
||||
g_is_timer_running = true;
|
||||
}
|
||||
|
||||
*ret_button = (button_handle_t)btn;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t iot_button_delete(button_handle_t btn_handle)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_RETURN_ON_FALSE(NULL != btn_handle, ESP_ERR_INVALID_ARG, TAG, "Pointer of handle is invalid");
|
||||
button_dev_t *btn = (button_dev_t *)btn_handle;
|
||||
|
||||
for (int i = 0; i < BUTTON_EVENT_MAX; i++) {
|
||||
if (btn->cb_info[i]) {
|
||||
free(btn->cb_info[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ret = btn->driver->del(btn->driver);
|
||||
ESP_RETURN_ON_FALSE(ESP_OK == ret, ret, TAG, "Failed to delete button driver");
|
||||
|
||||
button_dev_t **curr;
|
||||
for (curr = &g_head_handle; *curr;) {
|
||||
button_dev_t *entry = *curr;
|
||||
if (entry == btn) {
|
||||
*curr = entry->next;
|
||||
free(entry);
|
||||
} else {
|
||||
curr = &entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* count button number */
|
||||
uint16_t number = 0;
|
||||
button_dev_t *target = g_head_handle;
|
||||
while (target) {
|
||||
target = target->next;
|
||||
number++;
|
||||
}
|
||||
ESP_LOGD(TAG, "remain btn number=%d", number);
|
||||
|
||||
if (0 == number && g_is_timer_running) { /**< if all button is deleted, stop the timer */
|
||||
esp_timer_stop(g_button_timer_handle);
|
||||
esp_timer_delete(g_button_timer_handle);
|
||||
g_button_timer_handle = NULL;
|
||||
g_is_timer_running = false;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue