185 lines
4.3 KiB
C++
185 lines
4.3 KiB
C++
// Please read Bounce2.h for information about the liscence and authors
|
|
|
|
#if defined(ARDUINO) && ARDUINO >= 100
|
|
#include "Arduino.h"
|
|
#else
|
|
#include "WProgram.h"
|
|
#endif
|
|
#include "Bounce2.h"
|
|
|
|
#define DEBOUNCED_STATE 0
|
|
#define UNSTABLE_STATE 1
|
|
#define STATE_CHANGED 3
|
|
#define STATE_HELD_ON 4
|
|
#define FIRSTUPDATE 5
|
|
|
|
|
|
Bounce::Bounce(int pin, uint16_t interval_millis, uint16_t interval_retrigger, uint16_t interval_hold)
|
|
{
|
|
this->pin = pin;
|
|
interval(interval_millis);
|
|
holdinterval(interval_hold);
|
|
retriggerinterval(interval_retrigger);
|
|
previous_millis_state_changed = 0;
|
|
state = _BV(FIRSTUPDATE);
|
|
}
|
|
|
|
void Bounce::attach(int pin) {
|
|
this->pin = pin;
|
|
bool read = digitalRead(pin);
|
|
state = 0;
|
|
if (digitalRead(pin)) {
|
|
state = _BV(DEBOUNCED_STATE) | _BV(UNSTABLE_STATE);
|
|
}
|
|
#ifdef BOUNCE_LOCK_OUT
|
|
previous_millis = 0;
|
|
#else
|
|
previous_millis = millis();
|
|
#endif
|
|
}
|
|
|
|
void Bounce::attach(int pin, int mode){
|
|
pinMode(pin, mode);
|
|
|
|
this->attach(pin);
|
|
}
|
|
|
|
void Bounce::interval(uint16_t interval_millis)
|
|
{
|
|
this->interval_millis = interval_millis;
|
|
}
|
|
|
|
void Bounce::holdinterval(uint16_t interval_hold)
|
|
{
|
|
this->interval_hold = interval_hold;
|
|
}
|
|
|
|
void Bounce::retriggerinterval(uint16_t interval_retrigger)
|
|
{
|
|
this->interval_retrigger = interval_retrigger;
|
|
}
|
|
|
|
bool Bounce::update()
|
|
{
|
|
// Attaches the pin the first time update is called
|
|
if(state & _BV(FIRSTUPDATE))
|
|
{
|
|
attach(pin);
|
|
state &= ~_BV(FIRSTUPDATE);
|
|
}
|
|
else
|
|
{
|
|
#ifdef BOUNCE_LOCK_OUT
|
|
state &= ~_BV(STATE_CHANGED);
|
|
// Ignore everything if we are locked out
|
|
if (millis() - previous_millis >= interval_millis) {
|
|
bool currentState = digitalRead(pin);
|
|
if ((bool)(state & _BV(DEBOUNCED_STATE)) != currentState) {
|
|
previous_millis = millis();
|
|
state ^= _BV(DEBOUNCED_STATE);
|
|
state |= _BV(STATE_CHANGED);
|
|
}
|
|
}
|
|
return state & _BV(STATE_CHANGED);
|
|
#else
|
|
// Read the state of the switch in a temporary variable.
|
|
bool currentState = digitalRead(pin);
|
|
state &= ~_BV(STATE_CHANGED);
|
|
|
|
// If the reading is different from last reading, reset the debounce counter
|
|
if ( currentState != (bool)(state & _BV(UNSTABLE_STATE)) ) {
|
|
previous_millis = millis();
|
|
state ^= _BV(UNSTABLE_STATE);
|
|
} else
|
|
if ( millis() - previous_millis >= interval_millis ) {
|
|
// We have passed the threshold time, so the input is now stable
|
|
// If it is different from last state, set the STATE_CHANGED flag
|
|
if ((bool)(state & _BV(DEBOUNCED_STATE)) != currentState) {
|
|
previous_millis = millis();
|
|
state ^= _BV(DEBOUNCED_STATE);
|
|
state |= _BV(STATE_CHANGED);
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
//code for checking if state has been held on >= 500ms or interval_hold
|
|
|
|
// If state has changed and has not been held on previously
|
|
if(state & _BV(STATE_CHANGED) && !(state & _BV(STATE_HELD_ON)))
|
|
{
|
|
//If state has been changed before 500ms since last change, reset state change timer
|
|
if(millis() - previous_millis_state_changed < interval_hold)
|
|
{
|
|
previous_millis_state_changed = 0;
|
|
}
|
|
else
|
|
{
|
|
previous_millis_state_changed = millis();
|
|
}
|
|
}
|
|
// If state has changed and has been held on previously
|
|
else if(state & _BV(STATE_CHANGED) && (state & _BV(STATE_HELD_ON)))
|
|
{
|
|
// Immediately turn off held on state
|
|
state &= ~_BV(STATE_HELD_ON);
|
|
previous_millis_state_changed = 0;
|
|
}
|
|
else if(previous_millis_state_changed != 0)
|
|
{
|
|
//if button has been at a debounced state for >= 500ms
|
|
if(millis() - previous_millis_state_changed >= interval_hold)
|
|
{
|
|
state |= _BV(STATE_HELD_ON);
|
|
previous_millis_state_changed = 0;
|
|
}
|
|
}
|
|
return state & _BV(STATE_CHANGED);
|
|
}
|
|
}
|
|
|
|
bool Bounce::retrigger()
|
|
{
|
|
// if button is being held
|
|
if(this->held())
|
|
{
|
|
if(previous_millis_state_changed != 0)
|
|
{
|
|
// Checks if it has been longer that retrigger time
|
|
if (millis() - previous_millis_state_changed >= interval_retrigger)
|
|
{
|
|
previous_millis_state_changed = millis();
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// sets the millis when first going into function
|
|
previous_millis_state_changed = millis();
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool Bounce::read()
|
|
{
|
|
return state & _BV(DEBOUNCED_STATE);
|
|
}
|
|
|
|
bool Bounce::rose()
|
|
{
|
|
return ( state & _BV(DEBOUNCED_STATE) ) && ( state & _BV(STATE_CHANGED));
|
|
}
|
|
|
|
bool Bounce::fell()
|
|
{
|
|
return !( state & _BV(DEBOUNCED_STATE) ) && ( state & _BV(STATE_CHANGED));
|
|
}
|
|
|
|
bool Bounce::held()
|
|
{
|
|
return (state & _BV(STATE_HELD_ON));
|
|
}
|