1 /* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 3 /* 4 Part of the Wiring project - http://wiring.uniandes.edu.co 5 6 Copyright (c) 2004-05 Hernando Barragan 7 8 This library is free software; you can redistribute it and/or 9 modify it under the terms of the GNU Lesser General Public 10 License as published by the Free Software Foundation; either 11 version 2.1 of the License, or (at your option) any later version. 12 13 This library is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 Lesser General Public License for more details. 17 18 You should have received a copy of the GNU Lesser General 19 Public License along with this library; if not, write to the 20 Free Software Foundation, Inc., 59 Temple Place, Suite 330, 21 Boston, MA 02111-1307 USA 22 23 Modified 24 November 2006 by David A. Mellis 24 Modified 1 August 2010 by Mark Sproul 25 */ 26 27 #include <inttypes.h> 28 #include <avr/io.h> 29 #include <avr/interrupt.h> 30 #include <avr/pgmspace.h> 31 #include <stdio.h> 32 33 #include "WConstants.h" 34 #include "wiring_private.h" 35 36 volatile static voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; 37 // volatile static voidFuncPtr twiIntFunc; 38 39 void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { 40 if(interruptNum < EXTERNAL_NUM_INTERRUPTS) { 41 intFunc[interruptNum] = userFunc; 42 43 // Configure the interrupt mode (trigger on low input, any change, rising 44 // edge, or falling edge). The mode constants were chosen to correspond 45 // to the configuration bits in the hardware register, so we simply shift 46 // the mode into place. 47 48 // Enable the interrupt. 49 50 switch (interruptNum) { 51 #if defined(EICRA) && defined(EICRB) && defined(EIMSK) 52 case 2: 53 EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); 54 EIMSK |= (1 << INT0); 55 break; 56 case 3: 57 EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); 58 EIMSK |= (1 << INT1); 59 break; 60 case 4: 61 EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20); 62 EIMSK |= (1 << INT2); 63 break; 64 case 5: 65 EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30); 66 EIMSK |= (1 << INT3); 67 break; 68 case 0: 69 EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40); 70 EIMSK |= (1 << INT4); 71 break; 72 case 1: 73 EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50); 74 EIMSK |= (1 << INT5); 75 break; 76 case 6: 77 EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60); 78 EIMSK |= (1 << INT6); 79 break; 80 case 7: 81 EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70); 82 EIMSK |= (1 << INT7); 83 break; 84 #else 85 case 0: 86 #if defined(EICRA) && defined(ISC00) && defined(EIMSK) 87 EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); 88 EIMSK |= (1 << INT0); 89 #elif defined(MCUCR) && defined(ISC00) && defined(GICR) 90 MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); 91 GICR |= (1 << INT0); 92 #elif defined(MCUCR) && defined(ISC00) && defined(GIMSK) 93 MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); 94 GIMSK |= (1 << INT0); 95 #else 96 #error attachInterrupt not finished for this CPU (case 0) 97 #endif 98 break; 99 100 case 1: 101 #if defined(EICRA) && defined(ISC10) && defined(ISC11) && defined(EIMSK) 102 EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); 103 EIMSK |= (1 << INT1); 104 #elif defined(MCUCR) && defined(ISC10) && defined(ISC11) && defined(GICR) 105 MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); 106 GICR |= (1 << INT1); 107 #elif defined(MCUCR) && defined(ISC10) && defined(GIMSK) && defined(GIMSK) 108 MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); 109 GIMSK |= (1 << INT1); 110 #else 111 #warning attachInterrupt may need some more work for this cpu (case 1) 112 #endif 113 break; 114 #endif 115 } 116 } 117 } 118 119 void detachInterrupt(uint8_t interruptNum) { 120 if(interruptNum < EXTERNAL_NUM_INTERRUPTS) { 121 // Disable the interrupt. (We can't assume that interruptNum is equal 122 // to the number of the EIMSK bit to clear, as this isn't true on the 123 // ATmega8. There, INT0 is 6 and INT1 is 7.) 124 switch (interruptNum) { 125 #if defined(EICRA) && defined(EICRB) && defined(EIMSK) 126 case 2: 127 EIMSK &= ~(1 << INT0); 128 break; 129 case 3: 130 EIMSK &= ~(1 << INT1); 131 break; 132 case 4: 133 EIMSK &= ~(1 << INT2); 134 break; 135 case 5: 136 EIMSK &= ~(1 << INT3); 137 break; 138 case 0: 139 EIMSK &= ~(1 << INT4); 140 break; 141 case 1: 142 EIMSK &= ~(1 << INT5); 143 break; 144 case 6: 145 EIMSK &= ~(1 << INT6); 146 break; 147 case 7: 148 EIMSK &= ~(1 << INT7); 149 break; 150 #else 151 case 0: 152 #if defined(EIMSK) && defined(INT0) 153 EIMSK &= ~(1 << INT0); 154 #elif defined(GICR) && defined(ISC00) 155 GICR &= ~(1 << INT0); // atmega32 156 #elif defined(GIMSK) && defined(INT0) 157 GIMSK &= ~(1 << INT0); 158 #else 159 #error detachInterrupt not finished for this cpu 160 #endif 161 break; 162 163 case 1: 164 #if defined(EIMSK) && defined(INT1) 165 EIMSK &= ~(1 << INT1); 166 #elif defined(GICR) && defined(INT1) 167 GICR &= ~(1 << INT1); // atmega32 168 #elif defined(GIMSK) && defined(INT1) 169 GIMSK &= ~(1 << INT1); 170 #else 171 #warning detachInterrupt may need some more work for this cpu (case 1) 172 #endif 173 break; 174 #endif 175 } 176 177 intFunc[interruptNum] = 0; 178 } 179 } 180 181 /* 182 void attachInterruptTwi(void (*userFunc)(void) ) { 183 twiIntFunc = userFunc; 184 } 185 */ 186 187 #if defined(EICRA) && defined(EICRB) 188 189 SIGNAL(INT0_vect) { 190 if(intFunc[EXTERNAL_INT_2]) 191 intFunc[EXTERNAL_INT_2](); 192 } 193 194 SIGNAL(INT1_vect) { 195 if(intFunc[EXTERNAL_INT_3]) 196 intFunc[EXTERNAL_INT_3](); 197 } 198 199 SIGNAL(INT2_vect) { 200 if(intFunc[EXTERNAL_INT_4]) 201 intFunc[EXTERNAL_INT_4](); 202 } 203 204 SIGNAL(INT3_vect) { 205 if(intFunc[EXTERNAL_INT_5]) 206 intFunc[EXTERNAL_INT_5](); 207 } 208 209 SIGNAL(INT4_vect) { 210 if(intFunc[EXTERNAL_INT_0]) 211 intFunc[EXTERNAL_INT_0](); 212 } 213 214 SIGNAL(INT5_vect) { 215 if(intFunc[EXTERNAL_INT_1]) 216 intFunc[EXTERNAL_INT_1](); 217 } 218 219 SIGNAL(INT6_vect) { 220 if(intFunc[EXTERNAL_INT_6]) 221 intFunc[EXTERNAL_INT_6](); 222 } 223 224 SIGNAL(INT7_vect) { 225 if(intFunc[EXTERNAL_INT_7]) 226 intFunc[EXTERNAL_INT_7](); 227 } 228 229 #else 230 231 SIGNAL(INT0_vect) { 232 if(intFunc[EXTERNAL_INT_0]) 233 intFunc[EXTERNAL_INT_0](); 234 } 235 236 SIGNAL(INT1_vect) { 237 if(intFunc[EXTERNAL_INT_1]) 238 intFunc[EXTERNAL_INT_1](); 239 } 240 241 #endif 242 243 /* 244 SIGNAL(SIG_2WIRE_SERIAL) { 245 if(twiIntFunc) 246 twiIntFunc(); 247 } 248 */ 249 250