MultiButton.c 4.9 KB

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