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