MHVLib  20111011
An efficiency oriented runtime library for AVR microcontrollers
A:/eclipse/mhvlib/MHV_Debounce.cpp
Go to the documentation of this file.
00001 /* Copyright (c) 2011, Make, Hack, Void Inc
00002  * All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions are met:
00006  *  * Redistributions of source code must retain the above copyright
00007  *    notice, this list of conditions and the following disclaimer.
00008  *  * Redistributions in binary form must reproduce the above copyright
00009  *    notice, this list of conditions and the following disclaimer in the
00010  *    documentation and/or other materials provided with the distribution.
00011  *  * Neither the name of the Make, Hack, Void nor the
00012  *    names of its contributors may be used to endorse or promote products
00013  *    derived from this software without specific prior written permission.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00016  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00017  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00018  * DISCLAIMED. IN NO EVENT SHALL MAKE, HACK, VOID BE LIABLE FOR ANY
00019  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00020  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00021  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00022  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00023  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00024  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00025  */
00026 
00027 #include <MHV_Debounce.h>
00028 
00040 MHV_Debounce::MHV_Debounce(MHV_PinChangeManager *pinChangeManager, MHV_RTC *rtc,
00041                 uint16_t debounceTime, uint16_t heldTime, uint16_t repeatTime) {
00042         _pinChangeManager = pinChangeManager;
00043         _rtc = rtc;
00044         _debounceTime.timestamp = 0;
00045         _debounceTime.milliseconds = debounceTime;
00046 
00047         _heldTime.timestamp = 0;
00048         _heldTime.milliseconds = 0;
00049         mhv_timestampIncrement(&_heldTime, 0, heldTime);
00050 
00051         _repeatTime.timestamp = 0;
00052         _repeatTime.milliseconds = 0;
00053         mhv_timestampIncrement(&_repeatTime, 0, repeatTime);
00054 
00055         for (uint8_t i = 0; i < MHV_PC_INT_COUNT; ++i) {
00056                 initPin(i);
00057         }
00058 }
00059 
00060 void MHV_Debounce::initPin(uint8_t pinchangeInterrupt) {
00061         mhv_memClear(_pins + pinchangeInterrupt, sizeof(*_pins), 1);
00062 }
00063 
00068 void MHV_Debounce::checkHeld() {
00069         MHV_DEBOUNCE_PIN *pin = _pins;
00070         MHV_DEBOUNCE_PIN *maxPin = pin + MHV_PC_INT_COUNT;
00071 
00072         for (; pin < maxPin; ++pin) {
00073                 if (pin->timestamp.timestamp && !pin->previous) {
00074 // Pin is currently held down
00075                         MHV_TIMESTAMP heldFor;
00076                         _rtc->elapsed(&(pin->timestamp), &heldFor);
00077 
00078                         if (!pin->held && mhv_timestampGreaterThanOrEqual(&heldFor, &_heldTime)) {
00079                                 pin->held = true;
00080                                 pin->listener->heldDown(pin - _pins, &heldFor);
00081                                 _rtc->current(&(pin->timestamp));
00082                         } else if (pin->held && mhv_timestampGreaterThanOrEqual(&heldFor, &_repeatTime)) {
00083                                 pin->listener->heldDown(pin - _pins, &heldFor);
00084                                 _rtc->current(&(pin->timestamp));
00085                         }
00086                 }
00087         }
00088 }
00089 
00095 void MHV_Debounce::pinChanged(uint8_t pcInt, bool newState) {
00096         if (newState) {
00097 // Pin has been released
00098                 MHV_TIMESTAMP heldFor;
00099 
00100 /* Call the singlePress function if the time is greater than the debounce time,
00101  * and the button has not been held down
00102  */
00103                 _rtc->elapsed(&(_pins[pcInt].timestamp), &heldFor);
00104                 if (!_pins[pcInt].held && mhv_timestampGreaterThanOrEqual(&heldFor, &_debounceTime)) {
00105                         _pins[pcInt].listener->singlePress(pcInt, &heldFor);
00106                 }
00107 
00108                 _pins[pcInt].held = false;
00109                 _pins[pcInt].timestamp.timestamp = 0;
00110         } else {
00111 // Pin has been pressed
00112                 _rtc->current(&(_pins[pcInt].timestamp));
00113         }
00114 }
00115 
00116 
00126 void MHV_Debounce::assignKey(volatile uint8_t *dir, volatile uint8_t *out, volatile uint8_t *in,
00127                 uint8_t bit, int8_t pinchangeInterrupt, MHV_DebounceListener *listener) {
00128         _pins[pinchangeInterrupt].previous = *in & _BV(bit);
00129         _pins[pinchangeInterrupt].timestamp.milliseconds = 0;
00130         _pins[pinchangeInterrupt].timestamp.timestamp = 0;
00131         _pins[pinchangeInterrupt].listener = listener;
00132         _pins[pinchangeInterrupt].held = false;
00133 
00134         if (!_pins[pinchangeInterrupt].previous) {
00135 // Pin started off held down
00136                 _rtc->current(&(_pins[pinchangeInterrupt].timestamp));
00137         }
00138 
00139         _pinChangeManager->registerListener(dir, out, in, bit, pinchangeInterrupt, this);
00140 }
00141 
00150 void MHV_Debounce::deassignKey(volatile uint8_t *dir, volatile uint8_t *out, volatile uint8_t *in,
00151                 uint8_t bit, int8_t pinchangeInterrupt) {
00152         initPin(pinchangeInterrupt);
00153 }