MHVLib  20111227
An efficiency oriented runtime library for AVR microcontrollers
A:/eclipse/mhvlib/MHV_PinChangeManager.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011, Make, Hack, Void Inc
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *  * Redistributions of source code must retain the above copyright
00008  *    notice, this list of conditions and the following disclaimer.
00009  *  * Redistributions in binary form must reproduce the above copyright
00010  *    notice, this list of conditions and the following disclaimer in the
00011  *    documentation and/or other materials provided with the distribution.
00012  *  * Neither the name of the Make, Hack, Void nor the
00013  *    names of its contributors may be used to endorse or promote products
00014  *    derived from this software without specific prior written permission.
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  * DISCLAIMED. IN NO EVENT SHALL MAKE, HACK, VOID BE LIABLE FOR ANY
00020  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  */
00027 #include <MHV_PinChangeManager.h>
00028 
00033 MHV_PinChangeManager::MHV_PinChangeManager() {
00034         for (uint8_t i = 0; i < MHV_PC_INT_COUNT; i++) {
00035                 _pins[i].port = NULL;
00036         }
00037 }
00038 
00042 void MHV_PinChangeManager::pinChange0() {
00043         pinChange(0);
00044 }
00045 
00046 #if MHV_PC_INT_COUNT > 7
00047 
00050 void MHV_PinChangeManager::pinChange1() {
00051         pinChange(8);
00052 }
00053 #endif
00054 
00055 #if MHV_PC_INT_COUNT > 15
00056 
00059 void MHV_PinChangeManager::pinChange2() {
00060         pinChange(16);
00061 }
00062 #endif
00063 
00068 void MHV_PinChangeManager::pinChange(uint8_t offset) {
00069         MHV_EVENT_PIN *pin = _pins + offset;
00070         MHV_EVENT_PIN *maxPin = pin + 8;
00071 
00072         for (; pin < maxPin; ++pin) {
00073                 if (NULL == pin->port) {
00074                         continue;
00075                 }
00076 
00077                 bool cur = *(pin->port) & pin->mask;
00078                 if (cur != pin->previous) {
00079                         // Pin has changed
00080                         pin->previous = cur;
00081                         pin->changed = 1;
00082                         pin->listener->pinChanged(pin - _pins, cur);
00083                 }
00084         }
00085 }
00086 
00092 void MHV_PinChangeManager::registerListener(MHV_DECLARE_PIN(pin), MHV_PinEventListener *listener) {
00093 
00094         mhv_setInput(MHV_PIN_PARMS(pin));
00095 
00096         _pins[pinPinchangeInterrupt].port = pinIn;
00097         _pins[pinPinchangeInterrupt].mask = _BV(pinPin);
00098         _pins[pinPinchangeInterrupt].listener = listener;
00099         _pins[pinPinchangeInterrupt].previous = mhv_pinRead(MHV_PIN_PARMS(pin));
00100         _pins[pinPinchangeInterrupt].changed = false;
00101 
00102         // Enable the interrupt
00103         uint8_t bit = pinPinchangeInterrupt;
00104 #if MHV_PC_INT_COUNT > 15
00105         if (pinPinchangeInterrupt > 15) {
00106                 bit -= 16;
00107                 PCMSK2 |= _BV(bit);
00108                 PCICR |= _BV(PCIE2);
00109         } else
00110 #endif
00111 #if MHV_PC_INT_COUNT > 7
00112         if (pinPinchangeInterrupt > 7) {
00113                 bit -= 8;
00114                 PCMSK1 |= _BV(bit);
00115                 PCICR |= _BV(PCIE1);
00116         } else
00117 #endif
00118 #ifdef PCMSK0
00119         {
00120                 PCMSK0 |= _BV(bit);
00121                 PCICR |= _BV(PCIE0);
00122         }
00123 #else
00124         {
00125                 PCMSK |= _BV(bit);
00126                 GIMSK |= _BV(PCIE);
00127         }
00128 #endif
00129 }
00130 
00135 void MHV_PinChangeManager::deregisterListener(MHV_DECLARE_PIN(pin)) {
00136 
00137         _pins[pinPinchangeInterrupt].listener = NULL;
00138         _pins[pinPinchangeInterrupt].changed = false;
00139 
00140 // Disable the interrupt
00141         uint8_t bit = pinPinchangeInterrupt;
00142 #if MHV_PC_INT_COUNT > 15
00143         if (pinPinchangeInterrupt > 15) {
00144                 bit -= 16;
00145                 PCMSK2 &= ~_BV(bit);
00146         } else
00147 #endif
00148 #if MHV_PC_INT_COUNT > 7
00149         if (pinPinchangeInterrupt > 7) {
00150                 bit -= 8;
00151                 PCMSK1 &= ~_BV(bit);
00152         } else
00153 #endif
00154 #ifdef PCMSK0
00155         {
00156                 PCMSK0 &= ~_BV(bit);
00157         }
00158 #else
00159         {
00160                 PCMSK &= ~_BV(bit);
00161         }
00162 #endif
00163 }
00164 
00168 void MHV_PinChangeManager::handleEvents() {
00169         uint8_t i;
00170 
00171         for (i = 0; i < MHV_PC_INT_COUNT; i++) {
00172                 if (_pins[i].changed) {
00173                         _pins[i].changed = 0;
00174                         _pins[i].listener->pinChanged(i, _pins[i].previous);
00175                 }
00176         }
00177 }