multi_button.c 5.1 KB

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