MHVLib
20111011
An efficiency oriented runtime library for AVR microcontrollers
|
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 }