multi_button.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*
  2. * @File: multi_button.c
  3. * @Author: Zibin Zheng
  4. * @Date: 2018-01-23 20:36:01
  5. *
  6. * @LICENSE: Copyright (c) 2016 Zibin Zheng <znbin@qq.com>
  7. * All rights reserved.
  8. *
  9. * @NOTE: The original author of MultiButton is Zibin Zheng.
  10. * Please contact the original author for authorization
  11. * before use.I(liu2guang) only adapt the library to
  12. * rt-thread and fix some bugs. I(liu2guang) am not
  13. * responsible for the authorization of the library.
  14. *
  15. * Change Logs:
  16. * Date Author Notes
  17. * 2018-01-23 liu2guang Adapter rtthread and Fix the bug.
  18. */
  19. #include "multi_button.h"
  20. #define EVENT_CB(ev) if(handle->cb[ev]) handle->cb[ev]((void*)handle)
  21. #define PRESS_REPEAT_MAX_NUM 15 /*!< The maximum value of the repeat counter */
  22. static struct button* head_handle = NULL;
  23. /**
  24. * @brief Initializes the button struct handle.
  25. * @param handle: the button handle struct.
  26. * @param pin_level: read the pin of the connected button level.
  27. * @param active_level: pin pressed level.
  28. * @retval None
  29. */
  30. void button_init(struct button* handle, uint8_t(*pin_level)(void), uint8_t active_level)
  31. {
  32. memset(handle, 0, sizeof(struct button));
  33. handle->event = (uint8_t)NONE_PRESS;
  34. handle->hal_button_Level = pin_level;
  35. handle->button_level = handle->hal_button_Level();
  36. handle->active_level = active_level;
  37. }
  38. /**
  39. * @brief Attach the button event callback function.
  40. * @param handle: the button handle struct.
  41. * @param event: trigger event type.
  42. * @param cb: callback function.
  43. * @retval None
  44. */
  45. void button_attach(struct button* handle, PressEvent event, BtnCallback cb)
  46. {
  47. handle->cb[event] = cb;
  48. }
  49. /**
  50. * @brief Inquire the button event happen.
  51. * @param handle: the button handle struct.
  52. * @retval button event.
  53. */
  54. PressEvent get_button_event(struct button* handle)
  55. {
  56. return (PressEvent)(handle->event);
  57. }
  58. /**
  59. * @brief button driver core function, driver state machine.
  60. * @param handle: the button handle struct.
  61. * @retval None
  62. */
  63. static void button_handler(struct button* handle)
  64. {
  65. uint8_t read_gpio_level = handle->hal_button_Level();
  66. //ticks counter working..
  67. if((handle->state) > 0)
  68. {
  69. handle->ticks++;
  70. }
  71. /*------------button debounce handle---------------*/
  72. if(read_gpio_level != handle->button_level)
  73. {
  74. //not equal to prev one
  75. //continue read 3 times same new level change
  76. if(++(handle->debounce_cnt) >= DEBOUNCE_TICKS)
  77. {
  78. handle->button_level = read_gpio_level;
  79. handle->debounce_cnt = 0;
  80. }
  81. }
  82. else
  83. {
  84. // level not change ,counter reset.
  85. handle->debounce_cnt = 0;
  86. }
  87. /*-----------------State machine-------------------*/
  88. switch (handle->state)
  89. {
  90. case 0:
  91. if(handle->button_level == handle->active_level)
  92. {
  93. handle->event = (uint8_t)PRESS_DOWN;
  94. EVENT_CB(PRESS_DOWN);
  95. handle->ticks = 0;
  96. handle->repeat = 1;
  97. handle->state = 1;
  98. }
  99. else
  100. {
  101. handle->event = (uint8_t)NONE_PRESS;
  102. }
  103. break;
  104. case 1:
  105. if(handle->button_level != handle->active_level)
  106. {
  107. handle->event = (uint8_t)PRESS_UP;
  108. EVENT_CB(PRESS_UP);
  109. handle->ticks = 0;
  110. handle->state = 2;
  111. }
  112. else if(handle->ticks > LONG_TICKS)
  113. {
  114. handle->event = (uint8_t)LONG_PRESS_START;
  115. EVENT_CB(LONG_PRESS_START);
  116. handle->state = 5;
  117. }
  118. break;
  119. case 2:
  120. if(handle->button_level == handle->active_level)
  121. {
  122. handle->event = (uint8_t)PRESS_DOWN;
  123. EVENT_CB(PRESS_DOWN);
  124. if(handle->repeat != PRESS_REPEAT_MAX_NUM)
  125. {
  126. handle->repeat++;
  127. }
  128. EVENT_CB(PRESS_REPEAT);
  129. handle->ticks = 0;
  130. handle->state = 3;
  131. }
  132. else if(handle->ticks > SHORT_TICKS)
  133. {
  134. if(handle->repeat == 1)
  135. {
  136. handle->event = (uint8_t)SINGLE_CLICK;
  137. EVENT_CB(SINGLE_CLICK);
  138. }
  139. else if(handle->repeat == 2)
  140. {
  141. handle->event = (uint8_t)DOUBLE_CLICK;
  142. EVENT_CB(DOUBLE_CLICK);
  143. }
  144. handle->state = 0;
  145. }
  146. break;
  147. case 3:
  148. if(handle->button_level != handle->active_level)
  149. {
  150. handle->event = (uint8_t)PRESS_UP;
  151. EVENT_CB(PRESS_UP);
  152. if(handle->ticks < SHORT_TICKS)
  153. {
  154. handle->ticks = 0;
  155. handle->state = 2;
  156. }
  157. else
  158. {
  159. handle->state = 0;
  160. }
  161. }
  162. else if(handle->ticks > SHORT_TICKS) // SHORT_TICKS < press down hold time < LONG_TICKS
  163. {
  164. handle->state = 1;
  165. }
  166. break;
  167. case 5:
  168. if(handle->button_level == handle->active_level)
  169. {
  170. handle->event = (uint8_t)LONG_PRESS_HOLD;
  171. if (handle->ticks % LONG_HOLD_CYC == 0)
  172. {
  173. EVENT_CB(LONG_PRESS_HOLD);
  174. }
  175. }
  176. else
  177. {
  178. handle->event = (uint8_t)PRESS_UP;
  179. EVENT_CB(PRESS_UP);
  180. handle->state = 0;
  181. }
  182. break;
  183. default:
  184. handle->state = 0; /* reset */
  185. break;
  186. }
  187. }
  188. /**
  189. * @brief Start the button work, add the handle into work list.
  190. * @param handle: target handle struct.
  191. * @retval 0: succeed. -1: already exist.
  192. */
  193. int button_start(struct button* handle)
  194. {
  195. struct button* target = head_handle;
  196. while(target)
  197. {
  198. if(target == handle)
  199. {
  200. return -1; //already exist.
  201. }
  202. target = target->next;
  203. }
  204. handle->next = head_handle;
  205. head_handle = handle;
  206. return 0;
  207. }
  208. /**
  209. * @brief Stop the button work, remove the handle off work list.
  210. * @param handle: target handle struct.
  211. * @retval None
  212. */
  213. void button_stop(struct button* handle)
  214. {
  215. struct button** curr;
  216. for(curr = &head_handle; *curr;)
  217. {
  218. struct button* entry = *curr;
  219. if (entry == handle)
  220. {
  221. *curr = entry->next;
  222. return;
  223. }
  224. else
  225. {
  226. curr = &entry->next;
  227. }
  228. }
  229. }
  230. /**
  231. * @brief background ticks, timer repeat invoking interval 5ms.
  232. * @param None.
  233. * @retval None
  234. */
  235. void button_ticks(void)
  236. {
  237. struct button* target;
  238. for(target = head_handle; target != NULL; target = target->next)
  239. {
  240. button_handler(target);
  241. }
  242. }