|
| 1 | +/* |
| 2 | + * SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: MIT |
| 5 | + */ |
| 6 | +/*! |
| 7 | + @file button_status.hpp |
| 8 | + @brief Button status management |
| 9 | + */ |
| 10 | +#ifndef M5_UTILITY_BUTTON_STATUS_HPP |
| 11 | +#define M5_UTILITY_BUTTON_STATUS_HPP |
| 12 | + |
| 13 | +#include <cstdint> |
| 14 | + |
| 15 | +namespace m5 { |
| 16 | +namespace utility { |
| 17 | +namespace button { |
| 18 | + |
| 19 | +/*! |
| 20 | + @class m5::utility::button::Status |
| 21 | + @brief Button status management |
| 22 | + @note Class compatible with Button_Class in M5Unified |
| 23 | + */ |
| 24 | +class Status { |
| 25 | +public: |
| 26 | + /*! |
| 27 | + @enum button_state_t |
| 28 | + @brief Button status |
| 29 | + */ |
| 30 | + enum class button_state_t : uint8_t { state_nochange, state_clicked, state_hold, state_decide_click_count }; |
| 31 | + |
| 32 | + /*! |
| 33 | + @brief Constructor |
| 34 | + @param hold_ms Time to be considered hold(ms) |
| 35 | + @param debounce_ms Debounce time(ms) |
| 36 | + */ |
| 37 | + Status(const uint16_t hold_ms = 500, const uint16_t debounce_ms = 10) |
| 38 | + : _msecHold{hold_ms}, _msecDebounce{debounce_ms} |
| 39 | + { |
| 40 | + } |
| 41 | + |
| 42 | + ///@name Settings |
| 43 | + ///@{ |
| 44 | + //! @brief Set debounce time(ms) |
| 45 | + inline void setDebounceThreshold(const uint32_t msec) |
| 46 | + { |
| 47 | + _msecDebounce = msec; |
| 48 | + } |
| 49 | + //! @brief Set time to be considered hold(ms) |
| 50 | + inline void setHoldThreshold(const uint32_t msec) |
| 51 | + { |
| 52 | + _msecHold = msec; |
| 53 | + } |
| 54 | + //! @brief Gets the debounce time(ms) |
| 55 | + inline uint32_t getDebounceThreshold(void) const |
| 56 | + { |
| 57 | + return _msecDebounce; |
| 58 | + } |
| 59 | + //! @brief Gets the time to be considered hold(ms) |
| 60 | + inline uint32_t getHoldThreshold(void) const |
| 61 | + { |
| 62 | + return _msecHold; |
| 63 | + } |
| 64 | + ///@} |
| 65 | + |
| 66 | + ///@name Button status |
| 67 | + ///@{ |
| 68 | + //! @brief Is pressed? |
| 69 | + bool isPressed(void) const |
| 70 | + { |
| 71 | + return _press; |
| 72 | + } |
| 73 | + //! @brief Is released? |
| 74 | + bool isReleased(void) const |
| 75 | + { |
| 76 | + return !_press; |
| 77 | + } |
| 78 | + //! @brief Returns true if the button is currently held pressed |
| 79 | + bool isHolding(void) const |
| 80 | + { |
| 81 | + return _press == 2; |
| 82 | + } |
| 83 | + //! @brief Returns true if button was pressed |
| 84 | + bool wasPressed(void) const |
| 85 | + { |
| 86 | + return !_oldPress && _press; |
| 87 | + } |
| 88 | + //! @brief Returns true if button was released |
| 89 | + bool wasReleased(void) const |
| 90 | + { |
| 91 | + return _oldPress && !_press; |
| 92 | + } |
| 93 | + //! @brief Returns true when the button is pressed briefly and released |
| 94 | + bool wasClicked(void) const |
| 95 | + { |
| 96 | + return _currentState == button_state_t::state_clicked; |
| 97 | + } |
| 98 | + //! @brief Returns true when the button has been held pressed for a while |
| 99 | + bool wasHold(void) const |
| 100 | + { |
| 101 | + return _currentState == button_state_t::state_hold; |
| 102 | + } |
| 103 | + //! @brief Returns true when some time has passed since the button was single clicked |
| 104 | + bool wasSingleClicked(void) const |
| 105 | + { |
| 106 | + return _currentState == button_state_t::state_decide_click_count && _clickCount == 1; |
| 107 | + } |
| 108 | + //! @brief Returns true when some time has passed since the button was double clicked |
| 109 | + bool wasDoubleClicked(void) const |
| 110 | + { |
| 111 | + return _currentState == button_state_t::state_decide_click_count && _clickCount == 2; |
| 112 | + } |
| 113 | + //! @brief Returns true when some time has passed since the button was multiple clicked |
| 114 | + bool wasDecideClickCount(void) const |
| 115 | + { |
| 116 | + return _currentState == button_state_t::state_decide_click_count; |
| 117 | + } |
| 118 | + //! @brief Gets the number of consecutive button clicks |
| 119 | + uint8_t getClickCount(void) const |
| 120 | + { |
| 121 | + return _clickCount; |
| 122 | + } |
| 123 | + //! @brief Has the button press state changed? |
| 124 | + bool wasChangePressed(void) const |
| 125 | + { |
| 126 | + return ((bool)_press) != ((bool)_oldPress); |
| 127 | + } |
| 128 | + //! @brief Pressed and released a button for more than the set hold time? |
| 129 | + bool wasReleasedAfterHold(void) const |
| 130 | + { |
| 131 | + return !_press && _oldPress == 2; |
| 132 | + } |
| 133 | + //! @brief Was it pressed for more than the specified time? |
| 134 | + bool wasReleaseFor(const uint32_t ms) const |
| 135 | + { |
| 136 | + return _oldPress && !_press && _lastHoldPeriod >= ms; |
| 137 | + } |
| 138 | + //! @brief Is pressed for more than the specified time? |
| 139 | + bool pressedFor(const uint32_t ms) const |
| 140 | + { |
| 141 | + return (_press && _lastMsec - _lastChange >= ms); |
| 142 | + } |
| 143 | + //! @brief Is released for more than the specified time? |
| 144 | + bool releasedFor(const uint32_t ms) const |
| 145 | + { |
| 146 | + return (!_press && _lastMsec - _lastChange >= ms); |
| 147 | + } |
| 148 | + ///@} |
| 149 | + |
| 150 | + ///@name Status |
| 151 | + ///@{ |
| 152 | + void setRawState(const uint32_t msec, const bool press); |
| 153 | + void setState(const uint32_t msec, const button_state_t state); |
| 154 | + inline button_state_t getState(void) const |
| 155 | + { |
| 156 | + return _currentState; |
| 157 | + } |
| 158 | + inline uint32_t lastChange(void) const |
| 159 | + { |
| 160 | + return _lastChange; |
| 161 | + } |
| 162 | + inline uint32_t getUpdateMsec(void) const |
| 163 | + { |
| 164 | + return _lastMsec; |
| 165 | + } |
| 166 | + ///@} |
| 167 | + |
| 168 | +private: |
| 169 | + uint16_t _msecHold{500}, _msecDebounce{10}; |
| 170 | + uint32_t _lastMsec{}, _lastChange{}, _lastRawChange{}, _lastClicked{}; |
| 171 | + uint16_t _lastHoldPeriod{}; |
| 172 | + button_state_t _currentState{button_state_t::state_nochange}; |
| 173 | + bool _raw_press{}; |
| 174 | + // 0:release 1:click 2:holding |
| 175 | + uint8_t _press{}, _oldPress{}, _clickCount{}; |
| 176 | +}; |
| 177 | + |
| 178 | +} // namespace button |
| 179 | +} // namespace utility |
| 180 | +} // namespace m5 |
| 181 | + |
| 182 | +#endif |
0 commit comments