/* ✔ */ #pragma once #include #include BEGIN_AH_NAMESPACE /** * @brief A class for reading and debouncing buttons and switches. * * @ingroup AH_HardwareUtils */ class Button { public: /** * @brief Construct a new Button object. * * **This constructor should not be used.** * It is just a way to easily create arrays of buttons, and initializing * them later. */ Button() : pin(NO_PIN) {} /** * @brief Construct a new Button object. * * @param pin * The digital pin to read from. The internal pull-up resistor * will be enabled when `begin` is called. */ Button(pin_t pin); /// @copydoc Button(pin_t) Button(ArduinoPin_t pin) : Button(pin_t(pin)) {} /// @brief Initialize (enable the internal pull-up resistor). void begin(); /** * @brief Invert the input state of this button * (button pressed is `HIGH` instead of `LOW`). */ void invert(); /// @brief An enumeration of the different states a button can be in. enum State { Pressed = 0b00, ///< Input went from low to low (0,0) Released = 0b11, ///< Input went from high to high (1,1) Falling = 0b10, ///< Input went from high to low (1,0) Rising = 0b01 ///< Input went from low to high (0,1) }; /** * @brief Read the button and return its new state. * * The button is debounced, the debounce time can be set in * Settings.hpp: #BUTTON_DEBOUNCE_TIME. * * ``` * Debounce time: ├────┤ * * Raw input: * HIGH ──────┐ ┌──────┐ ┌─┐ ┌─┐ ┌──────┐ ┌──────── * LOW └──────┘ └─┘ └──────┘ └─┘ └─┘ * ├────┤ ├────┤ ├─┼─┼────┤ ├─┼─┼────┤ ├─┼────┤ * * Debounced output: * HIGH ──────┐ ┌──────┐ ┌──────────┐ ┌─── * LOW └──────┘ └──────────┘ └──────┘ * * States: * HIGH ────────────────┐ ┌───────────────── * LOW └──────────────────┘ * Released Falling Pressed Rising * ``` * * @return The state of the button, either Button::Pressed, * Button::Released, Button::Falling or Button::Rising. */ State update(); /** * @brief Get the state of the button, without updating it. * Returns the same value as the last call to @ref update. * * @return The state of the button, either Button::Pressed, * Button::Released, Button::Falling or Button::Rising. */ State getState() const; /// @brief Return the name of the state as a string. static FlashString_t getName(State state); /// Return the time point (in milliseconds) when the button last bounced. unsigned long previousBounceTime() const; /// Return the time (in milliseconds) that the button has been stable for, /// compared to the given time point. unsigned long stableTime(unsigned long now) const; /// Return the time (in milliseconds) that the button has been stable for. unsigned long stableTime() const; /** * @brief Set the debounce time for all Button%s. * * @note This function affects **all** Button objects. * * @param debounceTime * The new debounce time in milliseconds. */ static void setDebounceTime(unsigned long debounceTime = BUTTON_DEBOUNCE_TIME); /** * @brief Get the debounce time. * @return The debounce time in milliseconds. * @see setDebounceTime */ static unsigned long getDebounceTime(); private: pin_t pin; struct InternalState { InternalState() : debounced(0b11), bouncing(true), prevInput(HIGH), invert(false), prevBounceTime(0) {} uint8_t debounced : 2; bool bouncing : 1; bool prevInput : 1; bool invert : 1; unsigned long prevBounceTime; } state; /// Edit this in Settings.hpp /// @see BUTTON_DEBOUNCE_TIME static unsigned long debounceTime; }; END_AH_NAMESPACE