rotary_encoder.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * rotary_encoder.c
  3. *
  4. * Created on: Jan 12, 2021
  5. * Author: David Original work by Jose (PTDreamer), 2017
  6. */
  7. #include "rotary_encoder.h"
  8. #include "settings.h"
  9. volatile RE_State_t RE1_Data;
  10. /* Return with status macro */
  11. #define RETURN_WITH_STATUS(p, s) (p)->Rotation = s; return s
  12. void RE_Init(RE_State_t* data, GPIO_TypeDef* GPIO_A_Port, uint16_t GPIO_A_Pin, GPIO_TypeDef* GPIO_B_Port, uint16_t GPIO_B_Pin, GPIO_TypeDef* GPIO_BUTTON_Port, uint16_t GPIO_BUTTON_Pin) {
  13. /* Save parameters */
  14. data->GPIO_A = GPIO_A_Port;
  15. data->GPIO_B = GPIO_B_Port;
  16. data->GPIO_PIN_A = GPIO_A_Pin;
  17. data->GPIO_PIN_B = GPIO_B_Pin;
  18. data->GPIO_BUTTON = GPIO_BUTTON_Port;
  19. data->GPIO_PIN_BUTTON = GPIO_BUTTON_Pin;
  20. data->pv_click = RE_BT_HIDLE;
  21. /* Set default mode */
  22. data->Mode = systemSettings.settings.EncoderMode;
  23. /* Set default */
  24. data->RE_Count = 0;
  25. data->Diff = 0;
  26. data->Absolute = 0;
  27. data->LastA = 1;
  28. data->halfPointReached = 0;
  29. }
  30. RE_Rotation_t RE_Get(RE_State_t* data) {
  31. /* Calculate everything */
  32. data->Diff = data->RE_Count - data->Absolute;
  33. data->Absolute += data->Diff;
  34. /* Check */
  35. if(data->pv_click == RE_BT_CLICKED) {
  36. data->pv_click = RE_BT_UNRELEASED;
  37. RETURN_WITH_STATUS(data, Click);
  38. }
  39. else if(data->pv_click == RE_BT_LONG_CLICK) {
  40. data->pv_click = RE_BT_UNRELEASED;
  41. RETURN_WITH_STATUS(data, LongClick);
  42. }
  43. else if (data->Diff < 0) {
  44. if(data->pv_click == RE_BT_DRAG) {
  45. RETURN_WITH_STATUS(data, Rotate_Decrement_while_click);
  46. }
  47. RETURN_WITH_STATUS(data, Rotate_Decrement);
  48. } else if (data->Diff > 0) {
  49. if(data->pv_click == RE_BT_DRAG) {
  50. RETURN_WITH_STATUS(data, Rotate_Increment_while_click);
  51. }
  52. RETURN_WITH_STATUS(data, Rotate_Increment);
  53. }
  54. RETURN_WITH_STATUS(data, Rotate_Nothing);
  55. }
  56. void RE_SetMode(RE_State_t* data, RE_Mode_t mode) {
  57. /* Set mode */
  58. data->Mode = mode;
  59. }
  60. void RE_Process(RE_State_t* data) {
  61. static uint32_t push_time=0, halfPointReachedTime=0, debounce_time=0;
  62. static bool last_button_read=1, last_button_stable=1;
  63. uint32_t current_time = HAL_GetTick();
  64. uint32_t pressed_time = current_time - push_time;
  65. uint32_t stable_time = current_time - debounce_time;
  66. /* Read inputs */
  67. bool now_a = HAL_GPIO_ReadPin(data->GPIO_A, data->GPIO_PIN_A);
  68. bool now_b = HAL_GPIO_ReadPin(data->GPIO_B, data->GPIO_PIN_B);
  69. bool now_button = HAL_GPIO_ReadPin(data->GPIO_BUTTON, data->GPIO_PIN_BUTTON);
  70. if(last_button_read != now_button){ // If different than last reading
  71. last_button_read = now_button; // Update last reading value
  72. if(stable_time<20){ // If <debounce time
  73. debounce_time = current_time; // Reset debounce timer
  74. }
  75. }
  76. if(last_button_stable!=now_button){ // If button status different than stable status
  77. if(stable_time>20){ // If >debounce time
  78. last_button_stable = now_button; // Update last stable button value
  79. debounce_time = current_time; // Reset debounce timer
  80. }
  81. else{
  82. now_button = last_button_stable; // Ignore reading, use last stable button value
  83. }
  84. }
  85. if (now_a && now_b) {
  86. if(data->halfPointReached) {
  87. data->halfPointReached = 0;
  88. /* Check mode */
  89. if (data->Mode == RE_Mode_Zero) {
  90. if (data->direction) {
  91. data->RE_Count--;
  92. } else {
  93. data->RE_Count++;
  94. }
  95. }
  96. else {
  97. if (data->direction) {
  98. data->RE_Count++;
  99. } else {
  100. data->RE_Count--;
  101. }
  102. }
  103. }
  104. }
  105. else if(now_a == 0 && now_b == 0) {
  106. if(!data->halfPointReached){
  107. halfPointReachedTime = current_time;
  108. data->halfPointReached = 1;
  109. if(now_button == 0) {//button pressed
  110. data->pv_click = RE_BT_DRAG;
  111. }
  112. }
  113. else if((current_time-halfPointReachedTime)>500){
  114. if(now_button == 0 && data->pv_click == RE_BT_DRAG) {//button pressed
  115. data->pv_click = RE_BT_PRESSED;
  116. }
  117. }
  118. }
  119. else if(!data->halfPointReached) {
  120. if(now_a)
  121. data->direction = 1;
  122. else if (now_b)
  123. data->direction = 0;
  124. }
  125. if((data->pv_click == RE_BT_DRAG) && (now_button == 1))
  126. data->pv_click = RE_BT_HIDLE;
  127. else if(data->pv_click != RE_BT_DRAG) {
  128. if((data->pv_click == RE_BT_HIDLE) && (now_button == 0)) {
  129. data->pv_click = RE_BT_PRESSED;
  130. push_time = current_time;
  131. }
  132. else if(data->pv_click == RE_BT_PRESSED) {
  133. if((now_button == 0)&&(pressed_time > 500)){
  134. data->pv_click = RE_BT_LONG_CLICK;
  135. }
  136. else if((now_button == 1)&&(pressed_time > 50)){
  137. data->pv_click = RE_BT_CLICKED;
  138. }
  139. }
  140. if((data->pv_click == RE_BT_UNRELEASED) && (now_button == 1) ) {
  141. data->pv_click = RE_BT_HIDLE;
  142. }
  143. }
  144. }