MHVLib
20111011
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 00096 void MHV_PinChangeManager::registerListener(volatile uint8_t *pinDir, volatile uint8_t *pinOut, 00097 volatile uint8_t *pinIn, uint8_t pinBit, int8_t pinChangeInterrupt, 00098 MHV_PinEventListener *listener) { 00099 00100 mhv_setInput(pinDir, pinOut, pinIn, pinBit, pinChangeInterrupt); 00101 00102 _pins[pinChangeInterrupt].port = pinIn; 00103 _pins[pinChangeInterrupt].mask = _BV(pinBit); 00104 _pins[pinChangeInterrupt].listener = listener; 00105 _pins[pinChangeInterrupt].previous = mhv_pinRead(pinDir, pinOut, pinIn, pinBit, pinChangeInterrupt); 00106 _pins[pinChangeInterrupt].changed = false; 00107 00108 // Enable the interrupt 00109 uint8_t bit = pinChangeInterrupt; 00110 #if MHV_PC_INT_COUNT > 15 00111 if (pinChangeInterrupt > 15) { 00112 bit -= 16; 00113 PCMSK2 |= _BV(bit); 00114 PCICR |= _BV(PCIE2); 00115 } else 00116 #endif 00117 #if MHV_PC_INT_COUNT > 7 00118 if (pinChangeInterrupt > 7) { 00119 bit -= 8; 00120 PCMSK1 |= _BV(bit); 00121 PCICR |= _BV(PCIE1); 00122 } else 00123 #endif 00124 #ifdef PCMSK0 00125 { 00126 PCMSK0 |= _BV(bit); 00127 PCICR |= _BV(PCIE0); 00128 } 00129 #else 00130 { 00131 PCMSK |= _BV(bit); 00132 GIMSK |= _BV(PCIE); 00133 } 00134 #endif 00135 } 00136 00145 void MHV_PinChangeManager::deregisterListener(volatile uint8_t *pinDir, volatile uint8_t *pinOut, 00146 volatile uint8_t *pinIn, uint8_t pinBit, int8_t pinChangeInterrupt) { 00147 00148 _pins[pinChangeInterrupt].listener = NULL; 00149 _pins[pinChangeInterrupt].changed = false; 00150 00151 // Disable the interrupt 00152 uint8_t bit = pinChangeInterrupt; 00153 #if MHV_PC_INT_COUNT > 15 00154 if (pinChangeInterrupt > 15) { 00155 bit -= 16; 00156 PCMSK2 &= ~_BV(bit); 00157 } else 00158 #endif 00159 #if MHV_PC_INT_COUNT > 7 00160 if (pinChangeInterrupt > 7) { 00161 bit -= 8; 00162 PCMSK1 &= ~_BV(bit); 00163 } else 00164 #endif 00165 #ifdef PCMSK0 00166 { 00167 PCMSK0 &= ~_BV(bit); 00168 } 00169 #else 00170 { 00171 PCMSK &= ~_BV(bit); 00172 } 00173 #endif 00174 } 00175 00179 void MHV_PinChangeManager::handleEvents() { 00180 uint8_t i; 00181 00182 for (i = 0; i < MHV_PC_INT_COUNT; i++) { 00183 if (_pins[i].changed) { 00184 _pins[i].changed = 0; 00185 _pins[i].listener->pinChanged(i, _pins[i].previous); 00186 } 00187 } 00188 }