multi_button.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. * Copyright (c) 2016 Zibin Zheng <znbin@qq.com>
  3. * All rights reserved
  4. */
  5. #include "multi_button.h"
  6. #define EVENT_CB(ev) if(handle->cb[ev])handle->cb[ev]((void*)handle)
  7. #define PRESS_REPEAT_MAX_NUM 15 /*!< The maximum value of the repeat counter */
  8. //button handle list head.
  9. static struct Button* head_handle = NULL;
  10. static void button_handler(struct Button* handle);
  11. /**
  12. * @brief Initializes the button struct handle.
  13. * @param handle: the button handle struct.
  14. * @param pin_level: read the HAL GPIO of the connected button level.
  15. * @param active_level: pressed GPIO level.
  16. * @param button_id: the button id.
  17. * @retval None
  18. */
  19. void button_init(struct Button* handle, uint8_t(*pin_level)(uint8_t), uint8_t active_level, uint8_t button_id)
  20. {
  21. memset(handle, 0, sizeof(struct Button));
  22. handle->event = (uint8_t)NONE_PRESS;
  23. handle->hal_button_Level = pin_level;
  24. handle->button_level = !active_level;
  25. handle->active_level = active_level;
  26. handle->button_id = button_id;
  27. }
  28. /**
  29. * @brief Attach the button event callback function.
  30. * @param handle: the button handle struct.
  31. * @param event: trigger event type.
  32. * @param cb: callback function.
  33. * @retval None
  34. */
  35. void button_attach(struct Button* handle, PressEvent event, BtnCallback cb)
  36. {
  37. handle->cb[event] = cb;
  38. }
  39. /**
  40. * @brief Inquire the button event happen.
  41. * @param handle: the button handle struct.
  42. * @retval button event.
  43. */
  44. PressEvent get_button_event(struct Button* handle)
  45. {
  46. return (PressEvent)(handle->event);
  47. }
  48. /**
  49. * @brief Button driver core function, driver state machine.
  50. * @param handle: the button handle struct.
  51. * @retval None
  52. */
  53. static void button_handler(struct Button* handle)
  54. {
  55. uint8_t read_gpio_level = handle->hal_button_Level(handle->button_id);
  56. //ticks counter working..
  57. if((handle->state) > 0) handle->ticks++;
  58. /*------------button debounce handle---------------*/
  59. if(read_gpio_level != handle->button_level) { //not equal to prev one
  60. //continue read 3 times same new level change
  61. if(++(handle->debounce_cnt) >= DEBOUNCE_TICKS) {
  62. handle->button_level = read_gpio_level;
  63. handle->debounce_cnt = 0;
  64. }
  65. } else { //level not change ,counter reset.
  66. handle->debounce_cnt = 0;
  67. }
  68. /*-----------------State machine-------------------*/
  69. switch (handle->state) {
  70. case 0:
  71. if(handle->button_level == handle->active_level) { //start press down
  72. handle->event = (uint8_t)PRESS_DOWN;
  73. EVENT_CB(PRESS_DOWN);
  74. handle->ticks = 0;
  75. handle->repeat = 1;
  76. handle->state = 1;
  77. } else {
  78. handle->event = (uint8_t)NONE_PRESS;
  79. }
  80. break;
  81. case 1:
  82. if(handle->button_level != handle->active_level) { //released press up
  83. handle->event = (uint8_t)PRESS_UP;
  84. EVENT_CB(PRESS_UP);
  85. handle->ticks = 0;
  86. handle->state = 2;
  87. } else if(handle->ticks > LONG_TICKS) {
  88. handle->event = (uint8_t)LONG_PRESS_START;
  89. EVENT_CB(LONG_PRESS_START);
  90. handle->state = 5;
  91. }
  92. break;
  93. case 2:
  94. if(handle->button_level == handle->active_level) { //press down again
  95. handle->event = (uint8_t)PRESS_DOWN;
  96. EVENT_CB(PRESS_DOWN);
  97. if(handle->repeat != PRESS_REPEAT_MAX_NUM) {
  98. handle->repeat++;
  99. }
  100. EVENT_CB(PRESS_REPEAT); // repeat hit
  101. handle->ticks = 0;
  102. handle->state = 3;
  103. } else if(handle->ticks > SHORT_TICKS) { //released timeout
  104. if(handle->repeat == 1) {
  105. handle->event = (uint8_t)SINGLE_CLICK;
  106. EVENT_CB(SINGLE_CLICK);
  107. } else if(handle->repeat == 2) {
  108. handle->event = (uint8_t)DOUBLE_CLICK;
  109. EVENT_CB(DOUBLE_CLICK); // repeat hit
  110. }
  111. handle->state = 0;
  112. }
  113. break;
  114. case 3:
  115. if(handle->button_level != handle->active_level) { //released press up
  116. handle->event = (uint8_t)PRESS_UP;
  117. EVENT_CB(PRESS_UP);
  118. if(handle->ticks < SHORT_TICKS) {
  119. handle->ticks = 0;
  120. handle->state = 2; //repeat press
  121. } else {
  122. handle->state = 0;
  123. }
  124. } else if(handle->ticks > SHORT_TICKS) { // SHORT_TICKS < press down hold time < LONG_TICKS
  125. handle->state = 1;
  126. }
  127. break;
  128. case 5:
  129. if(handle->button_level == handle->active_level) {
  130. //continue hold trigger
  131. handle->event = (uint8_t)LONG_PRESS_HOLD;
  132. EVENT_CB(LONG_PRESS_HOLD);
  133. } else { //released
  134. handle->event = (uint8_t)PRESS_UP;
  135. EVENT_CB(PRESS_UP);
  136. handle->state = 0; //reset
  137. }
  138. break;
  139. default:
  140. handle->state = 0; //reset
  141. break;
  142. }
  143. }
  144. /**
  145. * @brief Start the button work, add the handle into work list.
  146. * @param handle: target handle struct.
  147. * @retval 0: succeed. -1: already exist.
  148. */
  149. int button_start(struct Button* handle)
  150. {
  151. struct Button* target = head_handle;
  152. while(target) {
  153. if(target == handle) return -1; //already exist.
  154. target = target->next;
  155. }
  156. handle->next = head_handle;
  157. head_handle = handle;
  158. return 0;
  159. }
  160. /**
  161. * @brief Stop the button work, remove the handle off work list.
  162. * @param handle: target handle struct.
  163. * @retval None
  164. */
  165. void button_stop(struct Button* handle)
  166. {
  167. struct Button** curr;
  168. for(curr = &head_handle; *curr; ) {
  169. struct Button* entry = *curr;
  170. if(entry == handle) {
  171. *curr = entry->next;
  172. // free(entry);
  173. return;//glacier add 2021-8-18
  174. } else {
  175. curr = &entry->next;
  176. }
  177. }
  178. }
  179. /**
  180. * @brief background ticks, timer repeat invoking interval 5ms.
  181. * @param None.
  182. * @retval None
  183. */
  184. void button_ticks(void)
  185. {
  186. struct Button* target;
  187. for(target=head_handle; target; target=target->next) {
  188. button_handler(target);
  189. }
  190. }