iot_button.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. /* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
  2. *
  3. * SPDX-License-Identifier: Apache-2.0
  4. */
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include "freertos/FreeRTOS.h"
  9. #include "freertos/task.h"
  10. #include "freertos/timers.h"
  11. #include "esp_log.h"
  12. #include "driver/gpio.h"
  13. #include "iot_button.h"
  14. #include "esp_timer.h"
  15. #include "sdkconfig.h"
  16. static const char *TAG = "button";
  17. static portMUX_TYPE s_button_lock = portMUX_INITIALIZER_UNLOCKED;
  18. #define BUTTON_ENTER_CRITICAL() portENTER_CRITICAL(&s_button_lock)
  19. #define BUTTON_EXIT_CRITICAL() portEXIT_CRITICAL(&s_button_lock)
  20. #define BTN_CHECK(a, str, ret_val) \
  21. if (!(a)) { \
  22. ESP_LOGE(TAG, "%s(%d): %s", __FUNCTION__, __LINE__, str); \
  23. return (ret_val); \
  24. }
  25. /**
  26. * @brief Structs to store callback info
  27. *
  28. */
  29. typedef struct {
  30. button_cb_t cb;
  31. void *usr_data;
  32. button_event_data_t event_data;
  33. } button_cb_info_t;
  34. /**
  35. * @brief Structs to record individual key parameters
  36. *
  37. */
  38. typedef struct Button {
  39. uint16_t ticks;
  40. uint16_t long_press_ticks; /*! Trigger ticks for long press*/
  41. uint16_t short_press_ticks; /*! Trigger ticks for repeat press*/
  42. uint16_t long_press_hold_cnt; /*! Record long press hold count*/
  43. uint16_t long_press_ticks_default;
  44. uint8_t repeat;
  45. uint8_t state: 3;
  46. uint8_t debounce_cnt: 3;
  47. uint8_t active_level: 1;
  48. uint8_t button_level: 1;
  49. button_event_t event;
  50. uint8_t (*hal_button_Level)(void *hardware_data);
  51. esp_err_t (*hal_button_deinit)(void *hardware_data);
  52. void *hardware_data;
  53. button_type_t type;
  54. button_cb_info_t *cb_info[BUTTON_EVENT_MAX];
  55. size_t size[BUTTON_EVENT_MAX];
  56. int count[2];
  57. struct Button *next;
  58. } button_dev_t;
  59. //button handle list head.
  60. static button_dev_t *g_head_handle = NULL;
  61. static esp_timer_handle_t g_button_timer_handle = NULL;
  62. static bool g_is_timer_running = false;
  63. #define TICKS_INTERVAL CONFIG_BUTTON_PERIOD_TIME_MS
  64. #define DEBOUNCE_TICKS CONFIG_BUTTON_DEBOUNCE_TICKS //MAX 8
  65. #define SHORT_TICKS (CONFIG_BUTTON_SHORT_PRESS_TIME_MS /TICKS_INTERVAL)
  66. #define LONG_TICKS (CONFIG_BUTTON_LONG_PRESS_TIME_MS /TICKS_INTERVAL)
  67. #define SERIAL_TICKS (CONFIG_BUTTON_SERIAL_TIME_MS /TICKS_INTERVAL)
  68. #define TOLERANCE CONFIG_BUTTON_LONG_PRESS_TOLERANCE_MS
  69. #define CALL_EVENT_CB(ev) \
  70. if (btn->cb_info[ev]) { \
  71. for (int i = 0; i < btn->size[ev]; i++) { \
  72. btn->cb_info[ev][i].cb(btn, btn->cb_info[ev][i].usr_data); \
  73. } \
  74. } \
  75. #define TIME_TO_TICKS(time, congfig_time) (0 == (time))?congfig_time:(((time) / TICKS_INTERVAL))?((time) / TICKS_INTERVAL):1
  76. /**
  77. * @brief Button driver core function, driver state machine.
  78. */
  79. static void button_handler(button_dev_t *btn)
  80. {
  81. uint8_t read_gpio_level = btn->hal_button_Level(btn->hardware_data);
  82. /** ticks counter working.. */
  83. if ((btn->state) > 0) {
  84. btn->ticks++;
  85. }
  86. /**< button debounce handle */
  87. if (read_gpio_level != btn->button_level) {
  88. if (++(btn->debounce_cnt) >= DEBOUNCE_TICKS) {
  89. btn->button_level = read_gpio_level;
  90. btn->debounce_cnt = 0;
  91. }
  92. } else {
  93. btn->debounce_cnt = 0;
  94. }
  95. /** State machine */
  96. switch (btn->state) {
  97. case 0:
  98. if (btn->button_level == btn->active_level) {
  99. btn->event = (uint8_t)BUTTON_PRESS_DOWN;
  100. CALL_EVENT_CB(BUTTON_PRESS_DOWN);
  101. btn->ticks = 0;
  102. btn->repeat = 1;
  103. btn->state = 1;
  104. } else {
  105. btn->event = (uint8_t)BUTTON_NONE_PRESS;
  106. }
  107. break;
  108. case 1:
  109. if (btn->button_level != btn->active_level) {
  110. btn->event = (uint8_t)BUTTON_PRESS_UP;
  111. CALL_EVENT_CB(BUTTON_PRESS_UP);
  112. btn->ticks = 0;
  113. btn->state = 2;
  114. } else if (btn->ticks > btn->long_press_ticks) {
  115. btn->event = (uint8_t)BUTTON_LONG_PRESS_START;
  116. btn->state = 4;
  117. /** Calling callbacks for BUTTON_LONG_PRESS_START */
  118. uint16_t ticks_time = iot_button_get_ticks_time(btn);
  119. if (btn->cb_info[btn->event] && btn->count[0] == 0) {
  120. if (abs(ticks_time - (btn->long_press_ticks * TICKS_INTERVAL)) <= TOLERANCE && btn->cb_info[btn->event][btn->count[0]].event_data.long_press.press_time == (btn->long_press_ticks * TICKS_INTERVAL)) {
  121. do {
  122. btn->cb_info[btn->event][btn->count[0]].cb(btn, btn->cb_info[btn->event][btn->count[0]].usr_data);
  123. btn->count[0]++;
  124. if (btn->count[0] >= btn->size[btn->event])
  125. break;
  126. } while (btn->cb_info[btn->event][btn->count[0]].event_data.long_press.press_time == btn->long_press_ticks * TICKS_INTERVAL);
  127. }
  128. }
  129. }
  130. break;
  131. case 2:
  132. if (btn->button_level == btn->active_level) {
  133. btn->event = (uint8_t)BUTTON_PRESS_DOWN;
  134. CALL_EVENT_CB(BUTTON_PRESS_DOWN);
  135. btn->event = (uint8_t)BUTTON_PRESS_REPEAT;
  136. btn->repeat++;
  137. CALL_EVENT_CB(BUTTON_PRESS_REPEAT); // repeat hit
  138. btn->ticks = 0;
  139. btn->state = 3;
  140. } else if (btn->ticks > btn->short_press_ticks) {
  141. if (btn->repeat == 1) {
  142. btn->event = (uint8_t)BUTTON_SINGLE_CLICK;
  143. CALL_EVENT_CB(BUTTON_SINGLE_CLICK);
  144. } else if (btn->repeat == 2) {
  145. btn->event = (uint8_t)BUTTON_DOUBLE_CLICK;
  146. CALL_EVENT_CB(BUTTON_DOUBLE_CLICK); // repeat hit
  147. }
  148. btn->event = (uint8_t)BUTTON_MULTIPLE_CLICK;
  149. /** Calling the callbacks for MULTIPLE BUTTON CLICKS */
  150. for (int i = 0; i < btn->size[btn->event]; i++) {
  151. if (btn->repeat == btn->cb_info[btn->event][i].event_data.multiple_clicks.clicks) {
  152. do {
  153. btn->cb_info[btn->event][i].cb(btn, btn->cb_info[btn->event][i].usr_data);
  154. i++;
  155. if (i >= btn->size[btn->event])
  156. break;
  157. } while (btn->cb_info[btn->event][i].event_data.multiple_clicks.clicks == btn->repeat);
  158. }
  159. }
  160. btn->event = (uint8_t)BUTTON_PRESS_REPEAT_DONE;
  161. CALL_EVENT_CB(BUTTON_PRESS_REPEAT_DONE); // repeat hit
  162. btn->repeat = 0;
  163. btn->state = 0;
  164. }
  165. break;
  166. case 3:
  167. if (btn->button_level != btn->active_level) {
  168. btn->event = (uint8_t)BUTTON_PRESS_UP;
  169. CALL_EVENT_CB(BUTTON_PRESS_UP);
  170. if (btn->ticks < SHORT_TICKS) {
  171. btn->ticks = 0;
  172. btn->state = 2; //repeat press
  173. } else {
  174. btn->state = 0;
  175. }
  176. }
  177. break;
  178. case 4:
  179. if (btn->button_level == btn->active_level) {
  180. //continue hold trigger
  181. if (btn->ticks >= (btn->long_press_hold_cnt + 1) * SERIAL_TICKS + btn->long_press_ticks) {
  182. btn->event = (uint8_t)BUTTON_LONG_PRESS_HOLD;
  183. btn->long_press_hold_cnt++;
  184. CALL_EVENT_CB(BUTTON_LONG_PRESS_HOLD);
  185. /** Calling callbacks for BUTTON_LONG_PRESS_START based on press_time */
  186. uint16_t ticks_time = iot_button_get_ticks_time(btn);
  187. if (btn->cb_info[BUTTON_LONG_PRESS_START]) {
  188. button_cb_info_t *cb_info = btn->cb_info[BUTTON_LONG_PRESS_START];
  189. uint16_t time = cb_info[btn->count[0]].event_data.long_press.press_time;
  190. if (btn->long_press_ticks * TICKS_INTERVAL > time) {
  191. for (int i = btn->count[0] + 1; i < btn->size[BUTTON_LONG_PRESS_START]; i++) {
  192. time = cb_info[i].event_data.long_press.press_time;
  193. if (btn->long_press_ticks * TICKS_INTERVAL <= time) {
  194. btn->count[0] = i;
  195. break;
  196. }
  197. }
  198. }
  199. if (btn->count[0] < btn->size[BUTTON_LONG_PRESS_START] && abs(ticks_time - time) <= TOLERANCE) {
  200. do {
  201. cb_info[btn->count[0]].cb(btn, cb_info[btn->count[0]].usr_data);
  202. btn->count[0]++;
  203. if (btn->count[0] >= btn->size[BUTTON_LONG_PRESS_START])
  204. break;
  205. } while (time == cb_info[btn->count[0]].event_data.long_press.press_time);
  206. }
  207. }
  208. /** Updating counter for BUTTON_LONG_PRESS_UP press_time */
  209. if (btn->cb_info[BUTTON_LONG_PRESS_UP]) {
  210. button_cb_info_t *cb_info = btn->cb_info[BUTTON_LONG_PRESS_UP];
  211. uint16_t time = cb_info[btn->count[1] + 1].event_data.long_press.press_time;
  212. if (btn->long_press_ticks * TICKS_INTERVAL > time) {
  213. for (int i = btn->count[1] + 1; i < btn->size[BUTTON_LONG_PRESS_UP]; i++) {
  214. time = cb_info[i].event_data.long_press.press_time;
  215. if (btn->long_press_ticks * TICKS_INTERVAL <= time) {
  216. btn->count[1] = i;
  217. break;
  218. }
  219. }
  220. }
  221. if(btn->count[1] + 1 < btn->size[BUTTON_LONG_PRESS_UP] && abs(ticks_time - time) <= TOLERANCE) {
  222. do {
  223. btn->count[1]++;
  224. if (btn->count[1] + 1 >= btn->size[BUTTON_LONG_PRESS_UP])
  225. break;
  226. } while (time == cb_info[btn->count[1] + 1].event_data.long_press.press_time);
  227. }
  228. }
  229. }
  230. } else { //releasd
  231. btn->event = BUTTON_LONG_PRESS_UP;
  232. /** calling callbacks for BUTTON_LONG_PRESS_UP press_time */
  233. if (btn->cb_info[btn->event] && btn->count[1] >= 0) {
  234. button_cb_info_t *cb_info = btn->cb_info[btn->event];
  235. do {
  236. cb_info[btn->count[1]].cb(btn, cb_info[btn->count[1]].usr_data);
  237. if (!btn->count[1])
  238. break;
  239. btn->count[1]--;
  240. } while (cb_info[btn->count[1]].event_data.long_press.press_time == cb_info[btn->count[1] + 1].event_data.long_press.press_time);
  241. /** Reset the counter */
  242. btn->count[1] = -1;
  243. }
  244. /** Reset counter */
  245. if (btn->cb_info[BUTTON_LONG_PRESS_START]) {
  246. btn->count[0] = 0;
  247. }
  248. btn->event = (uint8_t)BUTTON_PRESS_UP;
  249. CALL_EVENT_CB(BUTTON_PRESS_UP);
  250. btn->state = 0; //reset
  251. btn->long_press_hold_cnt = 0;
  252. }
  253. break;
  254. }
  255. }
  256. static void button_cb(void *args)
  257. {
  258. button_dev_t *target;
  259. for (target = g_head_handle; target; target = target->next) {
  260. button_handler(target);
  261. }
  262. }
  263. 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)
  264. {
  265. BTN_CHECK(NULL != hal_get_key_state, "Function pointer is invalid", NULL);
  266. button_dev_t *btn = (button_dev_t *) calloc(1, sizeof(button_dev_t));
  267. BTN_CHECK(NULL != btn, "Button memory alloc failed", NULL);
  268. btn->hardware_data = hardware_data;
  269. btn->event = BUTTON_NONE_PRESS;
  270. btn->active_level = active_level;
  271. btn->hal_button_Level = hal_get_key_state;
  272. btn->button_level = !active_level;
  273. btn->long_press_ticks = long_press_ticks;
  274. btn->long_press_ticks_default = btn->long_press_ticks;
  275. btn->short_press_ticks = short_press_ticks;
  276. /** Add handle to list */
  277. btn->next = g_head_handle;
  278. g_head_handle = btn;
  279. if (false == g_is_timer_running) {
  280. esp_timer_create_args_t button_timer;
  281. button_timer.arg = NULL;
  282. button_timer.callback = button_cb;
  283. button_timer.dispatch_method = ESP_TIMER_TASK;
  284. button_timer.name = "button_timer";
  285. esp_timer_create(&button_timer, &g_button_timer_handle);
  286. esp_timer_start_periodic(g_button_timer_handle, TICKS_INTERVAL * 1000U);
  287. g_is_timer_running = true;
  288. }
  289. return btn;
  290. }
  291. static esp_err_t button_delete_com(button_dev_t *btn)
  292. {
  293. BTN_CHECK(NULL != btn, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
  294. button_dev_t **curr;
  295. for (curr = &g_head_handle; *curr; ) {
  296. button_dev_t *entry = *curr;
  297. if (entry == btn) {
  298. *curr = entry->next;
  299. free(entry);
  300. } else {
  301. curr = &entry->next;
  302. }
  303. }
  304. /* count button number */
  305. uint16_t number = 0;
  306. button_dev_t *target = g_head_handle;
  307. while (target) {
  308. target = target->next;
  309. number++;
  310. }
  311. ESP_LOGD(TAG, "remain btn number=%d", number);
  312. if (0 == number && g_is_timer_running) { /**< if all button is deleted, stop the timer */
  313. esp_timer_stop(g_button_timer_handle);
  314. esp_timer_delete(g_button_timer_handle);
  315. g_is_timer_running = false;
  316. }
  317. return ESP_OK;
  318. }
  319. button_handle_t iot_button_create(const button_config_t *config)
  320. {
  321. //ESP_LOGI(TAG, "IoT Button Version: %d.%d.%d", BUTTON_VER_MAJOR, BUTTON_VER_MINOR, BUTTON_VER_PATCH);
  322. BTN_CHECK(config, "Invalid button config", NULL);
  323. esp_err_t ret = ESP_OK;
  324. button_dev_t *btn = NULL;
  325. uint16_t long_press_time = 0;
  326. uint16_t short_press_time = 0;
  327. long_press_time = TIME_TO_TICKS(config->long_press_time, LONG_TICKS);
  328. short_press_time = TIME_TO_TICKS(config->short_press_time, SHORT_TICKS);
  329. switch (config->type) {
  330. case BUTTON_TYPE_GPIO: {
  331. const button_gpio_config_t *cfg = &(config->gpio_button_config);
  332. ret = button_gpio_init(cfg);
  333. BTN_CHECK(ESP_OK == ret, "gpio button init failed", NULL);
  334. btn = button_create_com(cfg->active_level, button_gpio_get_key_level, (void *)cfg->gpio_num, long_press_time, short_press_time);
  335. } break;
  336. case BUTTON_TYPE_ADC: {
  337. const button_adc_config_t *cfg = &(config->adc_button_config);
  338. ret = button_adc_init(cfg);
  339. if (ret != ESP_OK)
  340. {
  341. printf("adc button init failed\r\n");
  342. }
  343. BTN_CHECK(ESP_OK == ret, "adc button init failed", NULL);
  344. 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);
  345. } break;
  346. case BUTTON_TYPE_MATRIX: {
  347. const button_matrix_config_t *cfg = &(config->matrix_button_config);
  348. ret = button_matrix_init(cfg);
  349. BTN_CHECK(ESP_OK == ret, "matrix button init failed", NULL);
  350. 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);
  351. } break;
  352. case BUTTON_TYPE_CUSTOM: {
  353. if (config->custom_button_config.button_custom_init) {
  354. ret = config->custom_button_config.button_custom_init(config->custom_button_config.priv);
  355. BTN_CHECK(ESP_OK == ret, "custom button init failed", NULL);
  356. }
  357. btn = button_create_com(config->custom_button_config.active_level,
  358. config->custom_button_config.button_custom_get_key_value,
  359. config->custom_button_config.priv,
  360. long_press_time, short_press_time);
  361. if (btn) {
  362. btn->hal_button_deinit = config->custom_button_config.button_custom_deinit;
  363. }
  364. } break;
  365. default:
  366. ESP_LOGE(TAG, "Unsupported button type");
  367. break;
  368. }
  369. BTN_CHECK(NULL != btn, "button create failed", NULL);
  370. btn->type = config->type;
  371. return (button_handle_t)btn;
  372. }
  373. esp_err_t iot_button_delete(button_handle_t btn_handle)
  374. {
  375. esp_err_t ret = ESP_OK;
  376. BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
  377. button_dev_t *btn = (button_dev_t *)btn_handle;
  378. switch (btn->type) {
  379. case BUTTON_TYPE_GPIO:
  380. ret = button_gpio_deinit((int)(btn->hardware_data));
  381. break;
  382. case BUTTON_TYPE_ADC:
  383. ret = button_adc_deinit(ADC_BUTTON_SPLIT_CHANNEL(btn->hardware_data), ADC_BUTTON_SPLIT_INDEX(btn->hardware_data));
  384. break;
  385. case BUTTON_TYPE_MATRIX:
  386. ret = button_matrix_deinit(MATRIX_BUTTON_SPLIT_ROW(btn->hardware_data), MATRIX_BUTTON_SPLIT_COL(btn->hardware_data));
  387. break;
  388. case BUTTON_TYPE_CUSTOM:
  389. if (btn->hal_button_deinit) {
  390. ret = btn->hal_button_deinit(btn->hardware_data);
  391. }
  392. break;
  393. default:
  394. break;
  395. }
  396. BTN_CHECK(ESP_OK == ret, "button deinit failed", ESP_FAIL);
  397. for (int i = 0; i < BUTTON_EVENT_MAX; i++) {
  398. if (btn->cb_info[i]) {
  399. free(btn->cb_info[i]);
  400. }
  401. }
  402. button_delete_com(btn);
  403. return ESP_OK;
  404. }
  405. esp_err_t iot_button_register_cb(button_handle_t btn_handle, button_event_t event, button_cb_t cb, void *usr_data)
  406. {
  407. BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
  408. button_dev_t *btn = (button_dev_t *) btn_handle;
  409. BTN_CHECK(event != BUTTON_MULTIPLE_CLICK, "event argument is invalid", ESP_ERR_INVALID_ARG);
  410. button_event_config_t event_cfg = {
  411. .event = event,
  412. };
  413. if ((event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) && !event_cfg.event_data.long_press.press_time) {
  414. event_cfg.event_data.long_press.press_time = btn->long_press_ticks_default * TICKS_INTERVAL;
  415. }
  416. return iot_button_register_event_cb(btn_handle, event_cfg, cb, usr_data);
  417. }
  418. 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)
  419. {
  420. BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
  421. button_dev_t *btn = (button_dev_t *) btn_handle;
  422. button_event_t event = event_cfg.event;
  423. BTN_CHECK(event < BUTTON_EVENT_MAX, "event is invalid", ESP_ERR_INVALID_ARG);
  424. 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);
  425. BTN_CHECK(event != BUTTON_MULTIPLE_CLICK || event_cfg.event_data.multiple_clicks.clicks, "event_data is invalid", ESP_ERR_INVALID_ARG);
  426. if (!btn->cb_info[event]) {
  427. btn->cb_info[event] = calloc(1, sizeof(button_cb_info_t));
  428. BTN_CHECK(NULL != btn->cb_info[event], "calloc cb_info failed", ESP_ERR_NO_MEM);
  429. if (event == BUTTON_LONG_PRESS_START) {
  430. btn->count[0] = 0;
  431. } else if (event == BUTTON_LONG_PRESS_UP) {
  432. btn->count[1] = -1;
  433. }
  434. }
  435. else {
  436. button_cb_info_t *p = realloc(btn->cb_info[event], sizeof(button_cb_info_t) * (btn->size[event] + 1));
  437. BTN_CHECK(NULL != p, "realloc cb_info failed", ESP_ERR_NO_MEM);
  438. btn->cb_info[event] = p;
  439. }
  440. btn->cb_info[event][btn->size[event]].cb = cb;
  441. btn->cb_info[event][btn->size[event]].usr_data = usr_data;
  442. btn->size[event]++;
  443. /** Inserting the event_data in sorted manner */
  444. if (event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) {
  445. uint16_t press_time = event_cfg.event_data.long_press.press_time;
  446. BTN_CHECK(press_time / TICKS_INTERVAL > btn->short_press_ticks, "press_time event_data is less than short_press_ticks", ESP_ERR_INVALID_ARG);
  447. if (btn->size[event] >= 2) {
  448. for (int i = btn->size[event] - 2; i >= 0; i--) {
  449. if (btn->cb_info[event][i].event_data.long_press.press_time > press_time) {
  450. btn->cb_info[event][i + 1] = btn->cb_info[event][i];
  451. btn->cb_info[event][i].event_data.long_press.press_time = press_time;
  452. btn->cb_info[event][i].cb = cb;
  453. btn->cb_info[event][i].usr_data = usr_data;
  454. } else {
  455. btn->cb_info[event][i + 1].event_data.long_press.press_time = press_time;
  456. btn->cb_info[event][i + 1].cb = cb;
  457. btn->cb_info[event][i + 1].usr_data = usr_data;
  458. break;
  459. }
  460. }
  461. } else {
  462. btn->cb_info[event][btn->size[event] - 1].event_data.long_press.press_time = press_time;
  463. }
  464. int32_t press_ticks = press_time / TICKS_INTERVAL;
  465. if (btn->short_press_ticks < press_ticks && press_ticks < btn->long_press_ticks) {
  466. iot_button_set_param(btn, BUTTON_LONG_PRESS_TIME_MS, (void*)(intptr_t)press_time);
  467. }
  468. }
  469. if (event == BUTTON_MULTIPLE_CLICK) {
  470. if (btn->size[event] >= 2) {
  471. for (int i = btn->size[event] - 2; i >= 0; i--) {
  472. if (btn->cb_info[event][i].event_data.multiple_clicks.clicks > event_cfg.event_data.multiple_clicks.clicks) {
  473. btn->cb_info[event][i + 1] = btn->cb_info[event][i];
  474. btn->cb_info[event][i].event_data.multiple_clicks.clicks = event_cfg.event_data.multiple_clicks.clicks;
  475. btn->cb_info[event][i].cb = cb;
  476. btn->cb_info[event][i].usr_data = usr_data;
  477. } else {
  478. btn->cb_info[event][i + 1].event_data.multiple_clicks.clicks = event_cfg.event_data.multiple_clicks.clicks;
  479. btn->cb_info[event][i + 1].cb = cb;
  480. btn->cb_info[event][i + 1].usr_data = usr_data;
  481. break;
  482. }
  483. }
  484. } else {
  485. btn->cb_info[event][btn->size[event] - 1].event_data.multiple_clicks.clicks = event_cfg.event_data.multiple_clicks.clicks;
  486. }
  487. }
  488. return ESP_OK;
  489. }
  490. esp_err_t iot_button_unregister_cb(button_handle_t btn_handle, button_event_t event)
  491. {
  492. BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
  493. BTN_CHECK(event < BUTTON_EVENT_MAX, "event is invalid", ESP_ERR_INVALID_ARG);
  494. button_dev_t *btn = (button_dev_t *) btn_handle;
  495. BTN_CHECK(NULL != btn->cb_info[event], "No callbacks registered for the event", ESP_ERR_INVALID_STATE);
  496. if (btn->cb_info[event]) {
  497. free(btn->cb_info[event]);
  498. /** Reset the counter */
  499. if (event == BUTTON_LONG_PRESS_START) {
  500. btn->count[0] = 0;
  501. } else if (event == BUTTON_LONG_PRESS_UP) {
  502. btn->count[1] = -1;
  503. }
  504. }
  505. btn->cb_info[event] = NULL;
  506. btn->size[event] = 0;
  507. return ESP_OK;
  508. }
  509. esp_err_t iot_button_unregister_event(button_handle_t btn_handle, button_event_config_t event_cfg, button_cb_t cb)
  510. {
  511. BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
  512. button_event_t event = event_cfg.event;
  513. BTN_CHECK(event < BUTTON_EVENT_MAX, "event is invalid", ESP_ERR_INVALID_ARG);
  514. BTN_CHECK(NULL != cb, "Pointer to function callback is invalid", ESP_ERR_INVALID_ARG);
  515. button_dev_t *btn = (button_dev_t *) btn_handle;
  516. int check = -1;
  517. for (int i = 0; i < btn->size[event]; i++) {
  518. if (cb == btn->cb_info[event][i].cb) {
  519. if ((event == BUTTON_LONG_PRESS_START || event == BUTTON_LONG_PRESS_UP) && event_cfg.event_data.long_press.press_time) {
  520. if (event_cfg.event_data.long_press.press_time != btn->cb_info[event][i].event_data.long_press.press_time) {
  521. continue;
  522. }
  523. }
  524. if (event == BUTTON_MULTIPLE_CLICK && event_cfg.event_data.multiple_clicks.clicks) {
  525. if (event_cfg.event_data.multiple_clicks.clicks != btn->cb_info[event][i].event_data.multiple_clicks.clicks) {
  526. continue;
  527. }
  528. }
  529. check = i;
  530. for (int j = i; j <= btn->size[event]-1; j++) {
  531. btn->cb_info[event][j] = btn->cb_info[event][j + 1];
  532. }
  533. if (btn->size[event] != 1) {
  534. button_cb_info_t *p = realloc(btn->cb_info[event], sizeof(button_cb_info_t) * (btn->size[event] - 1));
  535. BTN_CHECK(NULL != p, "realloc cb_info failed", ESP_ERR_NO_MEM);
  536. btn->cb_info[event] = p;
  537. btn->size[event]--;
  538. } else {
  539. free(btn->cb_info[event]);
  540. btn->cb_info[event] = NULL;
  541. btn->size[event] = 0;
  542. }
  543. break;
  544. }
  545. }
  546. BTN_CHECK(check != -1, "No such callback registered for the event", ESP_ERR_INVALID_STATE);
  547. return ESP_OK;
  548. }
  549. size_t iot_button_count_cb(button_handle_t btn_handle)
  550. {
  551. BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
  552. button_dev_t *btn = (button_dev_t *) btn_handle;
  553. size_t ret = 0;
  554. for (size_t i = 0; i < BUTTON_EVENT_MAX; i++) {
  555. if (btn->cb_info[i]) {
  556. ret+=btn->size[i];
  557. }
  558. }
  559. return ret;
  560. }
  561. size_t iot_button_count_event(button_handle_t btn_handle, button_event_t event)
  562. {
  563. BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
  564. button_dev_t *btn = (button_dev_t *) btn_handle;
  565. return btn->size[event];
  566. }
  567. button_event_t iot_button_get_event(button_handle_t btn_handle)
  568. {
  569. BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", BUTTON_NONE_PRESS);
  570. button_dev_t *btn = (button_dev_t *) btn_handle;
  571. return btn->event;
  572. }
  573. uint8_t iot_button_get_repeat(button_handle_t btn_handle)
  574. {
  575. BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", 0);
  576. button_dev_t *btn = (button_dev_t *) btn_handle;
  577. return btn->repeat;
  578. }
  579. uint16_t iot_button_get_ticks_time(button_handle_t btn_handle)
  580. {
  581. BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", 0);
  582. button_dev_t *btn = (button_dev_t *) btn_handle;
  583. return (btn->ticks * TICKS_INTERVAL);
  584. }
  585. uint16_t iot_button_get_long_press_hold_cnt(button_handle_t btn_handle)
  586. {
  587. BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", 0);
  588. button_dev_t *btn = (button_dev_t *) btn_handle;
  589. return btn->long_press_hold_cnt;
  590. }
  591. esp_err_t iot_button_set_param(button_handle_t btn_handle, button_param_t param, void *value)
  592. {
  593. BTN_CHECK(NULL != btn_handle, "Pointer of handle is invalid", ESP_ERR_INVALID_ARG);
  594. button_dev_t *btn = (button_dev_t *) btn_handle;
  595. BUTTON_ENTER_CRITICAL();
  596. switch (param) {
  597. case BUTTON_LONG_PRESS_TIME_MS:
  598. btn->long_press_ticks = (int32_t)value / TICKS_INTERVAL;
  599. break;
  600. case BUTTON_SHORT_PRESS_TIME_MS:
  601. btn->short_press_ticks = (int32_t)value / TICKS_INTERVAL;
  602. break;
  603. default:
  604. break;
  605. }
  606. BUTTON_EXIT_CRITICAL();
  607. return ESP_OK;
  608. }
  609. esp_err_t iot_button_resume(void)
  610. {
  611. BTN_CHECK(g_button_timer_handle, "Button timer handle is invalid", ESP_ERR_INVALID_STATE);
  612. if(g_is_timer_running){
  613. return ESP_ERR_INVALID_STATE;
  614. }
  615. BTN_CHECK(!g_is_timer_running, "Button timer is already running", ESP_ERR_INVALID_STATE);
  616. esp_err_t err = esp_timer_start_periodic(g_button_timer_handle, TICKS_INTERVAL * 1000U);
  617. BTN_CHECK(ESP_OK == err, "Button timer start failed", ESP_FAIL);
  618. g_is_timer_running = true;
  619. return ESP_OK;
  620. }
  621. esp_err_t iot_button_stop(void)
  622. {
  623. BTN_CHECK(g_button_timer_handle, "Button timer handle is invalid", ESP_ERR_INVALID_STATE);
  624. BTN_CHECK(g_is_timer_running, "Button timer is not running", ESP_ERR_INVALID_STATE);
  625. esp_err_t err = esp_timer_stop(g_button_timer_handle);
  626. BTN_CHECK(ESP_OK == err, "Button timer stop failed", ESP_FAIL);
  627. g_is_timer_running = false;
  628. return ESP_OK;
  629. }
  630. bool is_button_timer_active(void)//判断btn定时器是否活动
  631. {
  632. return g_is_timer_running;
  633. }