multi_button.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. * @retval None
  15. */
  16. void button_init_Head(void)
  17. {
  18. head_handle = NULL;
  19. }
  20. void button_init(struct Button* handle, uint8_t(*pin_level)(), uint8_t active_level)
  21. {
  22. memset(handle, 0, sizeof(struct Button));
  23. handle->event = (uint8_t)NONE_PRESS;
  24. handle->hal_button_Level = pin_level;
  25. handle->button_level = handle->hal_button_Level();
  26. handle->active_level = active_level;
  27. }
  28. /**
  29. * @brief Attach the button event callback function.
  30. * @param handle: the button handle strcut.
  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 strcut.
  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 strcut.
  51. * @retval None
  52. */
  53. void button_handler(struct Button* handle)
  54. {
  55. uint8_t read_gpio_level = handle->hal_button_Level();
  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 { //leved 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_RRESS_START;
  89. EVENT_CB(LONG_RRESS_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. handle->repeat++;
  98. if(handle->repeat == 2) {
  99. EVENT_CB(DOUBLE_CLICK); // repeat hit
  100. }
  101. EVENT_CB(PRESS_REPEAT); // repeat hit
  102. handle->ticks = 0;
  103. handle->state = 3;
  104. } else if(handle->ticks > SHORT_TICKS) { //released timeout
  105. if(handle->repeat == 1) {
  106. handle->event = (uint8_t)SINGLE_CLICK;
  107. EVENT_CB(SINGLE_CLICK);
  108. } else if(handle->repeat == 2) {
  109. handle->event = (uint8_t)DOUBLE_CLICK;
  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. }
  125. break;
  126. case 5:
  127. if(handle->button_level == handle->active_level) {
  128. #ifndef LONG_TICKS_TRIG
  129. //continue hold trigger
  130. handle->event = (uint8_t)LONG_PRESS_HOLD;
  131. EVENT_CB(LONG_PRESS_HOLD);
  132. #else
  133. //长按后tick每周期触发
  134. //增加长按周期触发
  135. if(handle->ticks > (LONG_TICKS+LONG_TICKS_TRIG))
  136. {
  137. handle->ticks = LONG_TICKS;//重新启动
  138. handle->event = (uint8_t)LONG_PRESS_HOLD;
  139. EVENT_CB(LONG_PRESS_HOLD);
  140. }
  141. #endif
  142. } else { //releasd
  143. handle->event = (uint8_t)PRESS_UP;
  144. EVENT_CB(PRESS_UP);
  145. handle->state = 0; //reset
  146. }
  147. break;
  148. }
  149. }
  150. /**
  151. * @brief Start the button work, add the handle into work list.
  152. * @param handle: target handle strcut.
  153. * @retval 0: succeed. -1: already exist.
  154. */
  155. int button_start(struct Button* handle)
  156. {
  157. struct Button* target = head_handle;
  158. while(target) {
  159. if(target == handle) return -1; //already exist.
  160. target = target->next;
  161. }
  162. handle->next = head_handle;
  163. head_handle = handle;
  164. return 0;
  165. }
  166. /**
  167. * @brief Stop the button work, remove the handle off work list.
  168. * @param handle: target handle strcut.
  169. * @retval None
  170. */
  171. void button_stop(struct Button* handle)
  172. {
  173. struct Button** curr;
  174. for(curr = &head_handle; *curr; ) {
  175. struct Button* entry = *curr;
  176. if (entry == handle) {
  177. *curr = entry->next;
  178. // free(entry);
  179. } else {
  180. curr = &entry->next;
  181. }
  182. }
  183. }
  184. /**
  185. * @brief background ticks, timer repeat invoking interval 5ms.
  186. * @param None.
  187. * @retval None
  188. */
  189. void button_ticks()
  190. {
  191. struct Button* target;
  192. for(target=head_handle; target; target=target->next) {
  193. button_handler(target);
  194. }
  195. }