123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- /*
- Switch.cpp
- Copyright (C) 2012 Albert van Dalen http://www.avdweb.nl
- This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at http://www.gnu.org/licenses .
- AUTHOR: Albert van Dalen
- WEBSITE: http://www.avdweb.nl/arduino/hardware-interfacing/simple-switch-debouncer.html
- HISTORY:
- 1.0.0 20-04-2013 _debouncePeriod=50
- 1.0.1 22-05-2013 Added longPress, doubleClick
- 1.0.2 01-12-2015 added process(input)
- 1.0.3 15-01-2016 added deglitching
- 1.0.5 25-01-2017 file renamed to avdweb_Switch
- 1.1.0 28-07-2018 added callbacks (code by Sean Lanigan, added by Martin Laclaustra)
- 1.2.0-rc 28-07-2017 added singleclick. Reorganize, keeping variables for each event in one function
- ..........................................DEGLITCHING..............................
- ________________ _
- on | | | | _
- | | | | | |
- | |_| |___| |__
- analog off_____|_____________________________|____________________________
- ________________ _ _
- input _____| |_| |___| |_______________________________
- poll ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
- equal 0 1 1 0 1 1 1 1 1 1 1 1 0 0 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
- deglitchPeriod <--------><-- <-- <- <--------><--------><--------
- ___________________________
- deglitched _________________| |__________________
- deglitchTime ^ ^ ^ ^ ^ ^ ^
- ..........................................DEBOUNCING.............................
- debouncePeriod <-------------------------------->
- _________________________________
- debounced _________________| |____________
- _ _
- _switched _________________| |_______________________________| |__________
- switchedTime ^ ^
- **********************************************************************************
- ........................................DOUBLE CLICK..............................
- __________ ______
- debounced ________| |_______| |_____________________________
- poll ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
- _ _
- pushed _________| |________________| |__________________________________
- pushedTime ^ ^
- _ _
- released ____________________| |____________| |___________________________
- releasedTime ^ ^
- doubleClickPeriod <------------------------------------->
- _
- _doubleClick ___________________________| |__________________________________
- ........................................LONG PRESS................................
- ___________________________
- debounced ________| |___________________________
- poll ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
- longPressPeriod <--------------->
- _ _
- _switched _________| |_________________________| |________________________
- __________
- longPressDisable ___________________________| |_________________________
- _
- _longPress ___________________________| |__________________________________
- ........................................SINGLE CLICK..............................
- __________ ______
- debounced ________| |_______________________________| |_____
- poll ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
- longPressPeriod <--------------->
- doubleClickPeriod <------------------------------------->
- _ _ _ _
- _switched _________| |_______| |_____________________________| |____| |___
- _____
- singleClickDisable______________________________________________| |__________
- _
- _singleClick _______________________________________________| |______________
- */
- #include "Arduino.h"
- #include "avdweb_Switch.h"
- Switch::Switch(byte _pin, byte PinMode, bool polarity, int debouncePeriod, int longPressPeriod, int doubleClickPeriod, int deglitchPeriod):
- pin(_pin), polarity(polarity), deglitchPeriod(deglitchPeriod), debouncePeriod(debouncePeriod), longPressPeriod(longPressPeriod), doubleClickPeriod(doubleClickPeriod)
- { pinMode(pin, PinMode);
- switchedTime = millis();
- debounced = digitalRead(pin);
- singleClickDisable = true;
- }
- bool Switch::poll()
- { input = digitalRead(pin);
- ms = millis();
- return process();
- }
- bool Switch::process()
- { deglitch();
- debounce();
- calcSingleClick();
- calcDoubleClick();
- calcLongPress();
- if(switched())
- { switchedTime = ms; //stores last times for future rounds
- if(pushed())
- { pushedTime = ms;
- } else { releasedTime = ms;
- }
- }
- triggerCallbacks();
- return _switched;
- }
- void inline Switch::deglitch()
- {
- if(input == lastInput) equal = 1;
- else
- { equal = 0;
- deglitchTime = ms;
- }
- if(equal && ((ms - deglitchTime) > deglitchPeriod)) // max 50ms, disable deglitch: 0ms
- { deglitched = input;
- deglitchTime = ms;
- }
- lastInput = input;
- }
- void inline Switch::debounce()
- {
- _switched = 0;
- if((deglitched != debounced) && ((ms - switchedTime) > debouncePeriod))
- { debounced = deglitched;
- _switched = 1;
- }
- }
- void inline Switch::calcSingleClick()
- { _singleClick = false;
- if(pushed())
- { if((ms - pushedTime) >= doubleClickPeriod)
- { singleClickDisable = false; //resets when pushed not in second click of doubleclick
- } else { singleClickDisable = true; //silence single click in second cl. doublecl.
- }
- }
- if(!singleClickDisable)
- { _singleClick = !switched() && !on() && ((releasedTime - pushedTime) <= longPressPeriod) && ((ms - pushedTime) >= doubleClickPeriod); // true just one time between polls
- singleClickDisable = _singleClick; // will be reset at next push
- }
- }
- void inline Switch::calcDoubleClick()
- { _doubleClick = pushed() && ((ms - pushedTime) < doubleClickPeriod);
- }
- void inline Switch::calcLongPress()
- { _longPress = false;
- if(released()) longPressDisable = false; //resets when released
- if(!longPressDisable)
- { _longPress = !switched() && on() && ((ms - pushedTime) > longPressPeriod); // true just one time between polls
- longPressDisable = _longPress; // will be reset at next release
- }
- }
- bool Switch::switched()
- { return _switched;
- }
- bool Switch::on()
- { return !(debounced^polarity);
- }
- bool Switch::pushed()
- { return _switched && !(debounced^polarity);
- }
- bool Switch::released()
- { return _switched && (debounced^polarity);
- }
- bool Switch::longPress()
- { return _longPress;
- }
- bool Switch::doubleClick()
- { return _doubleClick;
- }
- bool Switch::singleClick()
- { return _singleClick;
- }
- void Switch::triggerCallbacks()
- {
- if(_pushedCallback && pushed())
- { _pushedCallback(_pushedCallbackParam);
- }
- else if(_releasedCallback && released())
- { _releasedCallback(_releasedCallbackParam);
- }
- if(_longPressCallback && longPress())
- { _longPressCallback(_longPressCallbackParam);
- }
- if(_doubleClickCallback && doubleClick())
- { _doubleClickCallback(_doubleClickCallbackParam);
- }
- if(_singleClickCallback && singleClick())
- { _singleClickCallback(_singleClickCallbackParam);
- }
- }
- void Switch::setPushedCallback(switchCallback_t cb, void* param)
- { /// Store the "pushed" callback function
- _pushedCallback = cb;
- _pushedCallbackParam = param;
- }
- void Switch::setReleasedCallback(switchCallback_t cb, void* param)
- { /// Store the "released" callback function
- _releasedCallback = cb;
- _releasedCallbackParam = param;
- }
- void Switch::setLongPressCallback(switchCallback_t cb, void* param)
- { /// Store the "long press" callback function
- _longPressCallback = cb;
- _longPressCallbackParam = param;
- }
- void Switch::setDoubleClickCallback(switchCallback_t cb, void* param)
- { /// Store the "double click" callback function
- _doubleClickCallback = cb;
- _doubleClickCallbackParam = param;
- }
- void Switch::setSingleClickCallback(switchCallback_t cb, void* param)
- { /// Store the "double click" callback function
- _singleClickCallback = cb;
- _singleClickCallbackParam = param;
- }
|