cs-midi/AH/Hardware/Button.hpp

143 lines
4.6 KiB
C++

/* ✔ */
#pragma once
#include <AH/Hardware/ExtendedInputOutput/ExtendedInputOutput.hpp>
#include <AH/Settings/SettingsWrapper.hpp>
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