Button.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #include "Button.h"
  2. Button::Button(uint8_t pin, bool activeState)
  3. : _pin(pin), _activeState(activeState), _isAnalog(false), _analogThreshold(20) {
  4. _currentState = false; // Initialize as not pressed
  5. _lastState = _currentState;
  6. }
  7. Button::Button(uint8_t pin, bool activeState, bool isAnalog, uint16_t analogThreshold)
  8. : _pin(pin), _activeState(activeState), _isAnalog(isAnalog), _analogThreshold(analogThreshold) {
  9. _currentState = false; // Initialize as not pressed
  10. _lastState = _currentState;
  11. }
  12. void Button::begin() {
  13. _currentState = readButton();
  14. _lastState = _currentState;
  15. }
  16. void Button::update() {
  17. uint32_t now = millis();
  18. // Read button at specified interval
  19. if (now - _lastReadTime < BUTTON_READ_INTERVAL_MS) {
  20. return;
  21. }
  22. _lastReadTime = now;
  23. bool newState = readButton();
  24. // Check if state has changed
  25. if (newState != _lastState) {
  26. _stateChangeTime = now;
  27. }
  28. // Debounce check
  29. if ((now - _stateChangeTime) > BUTTON_DEBOUNCE_TIME_MS) {
  30. if (newState != _currentState) {
  31. _currentState = newState;
  32. handleStateChange();
  33. }
  34. }
  35. _lastState = newState;
  36. // Handle multi-click timeout
  37. if (_state == WAITING_FOR_MULTI_CLICK && (now - _releaseTime) > BUTTON_CLICK_TIMEOUT_MS) {
  38. // Timeout reached, process the clicks
  39. if (_clickCount == 1) {
  40. triggerEvent(SHORT_PRESS);
  41. } else if (_clickCount == 2) {
  42. triggerEvent(DOUBLE_PRESS);
  43. } else if (_clickCount == 3) {
  44. triggerEvent(TRIPLE_PRESS);
  45. } else if (_clickCount >= 4) {
  46. triggerEvent(QUADRUPLE_PRESS);
  47. }
  48. _clickCount = 0;
  49. _state = IDLE;
  50. }
  51. // Handle long press while button is held
  52. if (_state == PRESSED && (now - _pressTime) > BUTTON_LONG_PRESS_TIME_MS) {
  53. triggerEvent(LONG_PRESS);
  54. _state = IDLE; // Prevent multiple press events
  55. _clickCount = 0;
  56. }
  57. }
  58. bool Button::readButton() {
  59. if (_isAnalog) {
  60. return (analogRead(_pin) < _analogThreshold);
  61. } else {
  62. return (digitalRead(_pin) == _activeState);
  63. }
  64. }
  65. void Button::handleStateChange() {
  66. uint32_t now = millis();
  67. if (_currentState) {
  68. // Button pressed
  69. _pressTime = now;
  70. _state = PRESSED;
  71. triggerEvent(ANY_PRESS);
  72. } else {
  73. // Button released
  74. if (_state == PRESSED) {
  75. uint32_t pressDuration = now - _pressTime;
  76. if (pressDuration < BUTTON_LONG_PRESS_TIME_MS) {
  77. // Short press detected
  78. _clickCount++;
  79. _releaseTime = now;
  80. _state = WAITING_FOR_MULTI_CLICK;
  81. } else {
  82. // Long press already handled in update()
  83. _state = IDLE;
  84. _clickCount = 0;
  85. }
  86. }
  87. }
  88. }
  89. void Button::triggerEvent(EventType event) {
  90. _lastEvent = event;
  91. switch (event) {
  92. case ANY_PRESS:
  93. if (_onAnyPress) _onAnyPress();
  94. break;
  95. case SHORT_PRESS:
  96. if (_onShortPress) _onShortPress();
  97. break;
  98. case DOUBLE_PRESS:
  99. if (_onDoublePress) _onDoublePress();
  100. break;
  101. case TRIPLE_PRESS:
  102. if (_onTriplePress) _onTriplePress();
  103. break;
  104. case QUADRUPLE_PRESS:
  105. if (_onQuadruplePress) _onQuadruplePress();
  106. break;
  107. case LONG_PRESS:
  108. if (_onLongPress) _onLongPress();
  109. break;
  110. default:
  111. break;
  112. }
  113. }