1 /* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
4 Part of the Wiring project - http://wiring.uniandes.edu.co
6 Copyright (c) 2004-05 Hernando Barragan
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.
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.
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
23 Modified 24 November 2006 by David A. Mellis
24 Modified 1 August 2010 by Mark Sproul
29 #include <avr/interrupt.h>
30 #include <avr/pgmspace.h>
33 #include "wiring_private.h"
35 static void nothing(void) {
38 static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] = {
39 #if EXTERNAL_NUM_INTERRUPTS > 8
40 #warning There are more than 8 external interrupts. Some callbacks may not be initialized.
43 #if EXTERNAL_NUM_INTERRUPTS > 7
46 #if EXTERNAL_NUM_INTERRUPTS > 6
49 #if EXTERNAL_NUM_INTERRUPTS > 5
52 #if EXTERNAL_NUM_INTERRUPTS > 4
55 #if EXTERNAL_NUM_INTERRUPTS > 3
58 #if EXTERNAL_NUM_INTERRUPTS > 2
61 #if EXTERNAL_NUM_INTERRUPTS > 1
64 #if EXTERNAL_NUM_INTERRUPTS > 0
69 void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
70 if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
71 intFunc[interruptNum] = userFunc;
73 // Configure the interrupt mode (trigger on low input, any change, rising
74 // edge, or falling edge). The mode constants were chosen to correspond
75 // to the configuration bits in the hardware register, so we simply shift
76 // the mode into place.
78 // Enable the interrupt.
80 switch (interruptNum) {
81 #if defined(__AVR_ATmega32U4__)
82 // I hate doing this, but the register assignment differs between the 1280/2560
83 // and the 32U4. Since avrlib defines registers PCMSK1 and PCMSK2 that aren't
84 // even present on the 32U4 this is the only way to distinguish between them.
86 EICRA = (EICRA & ~((1<<ISC00) | (1<<ISC01))) | (mode << ISC00);
90 EICRA = (EICRA & ~((1<<ISC10) | (1<<ISC11))) | (mode << ISC10);
94 EICRA = (EICRA & ~((1<<ISC20) | (1<<ISC21))) | (mode << ISC20);
98 EICRA = (EICRA & ~((1<<ISC30) | (1<<ISC31))) | (mode << ISC30);
102 EICRB = (EICRB & ~((1<<ISC60) | (1<<ISC61))) | (mode << ISC60);
105 #elif defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)
107 EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
108 EIMSK |= (1 << INT0);
111 EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
112 EIMSK |= (1 << INT1);
115 EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
116 EIMSK |= (1 << INT2);
119 EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30);
120 EIMSK |= (1 << INT3);
123 EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40);
124 EIMSK |= (1 << INT4);
127 EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50);
128 EIMSK |= (1 << INT5);
131 EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60);
132 EIMSK |= (1 << INT6);
135 EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
136 EIMSK |= (1 << INT7);
138 #elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
140 EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
141 EIMSK |= (1 << INT0);
144 EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
145 EIMSK |= (1 << INT1);
148 EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
149 EIMSK |= (1 << INT2);
152 EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30);
153 EIMSK |= (1 << INT3);
156 EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40);
157 EIMSK |= (1 << INT4);
160 EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50);
161 EIMSK |= (1 << INT5);
164 EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60);
165 EIMSK |= (1 << INT6);
168 EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
169 EIMSK |= (1 << INT7);
173 #if defined(EICRA) && defined(ISC00) && defined(EIMSK)
174 EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
175 EIMSK |= (1 << INT0);
176 #elif defined(MCUCR) && defined(ISC00) && defined(GICR)
177 MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
179 #elif defined(MCUCR) && defined(ISC00) && defined(GIMSK)
180 MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
181 GIMSK |= (1 << INT0);
183 #error attachInterrupt not finished for this CPU (case 0)
188 #if defined(EICRA) && defined(ISC10) && defined(ISC11) && defined(EIMSK)
189 EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
190 EIMSK |= (1 << INT1);
191 #elif defined(MCUCR) && defined(ISC10) && defined(ISC11) && defined(GICR)
192 MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
194 #elif defined(MCUCR) && defined(ISC10) && defined(GIMSK) && defined(GIMSK)
195 MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
196 GIMSK |= (1 << INT1);
198 #warning attachInterrupt may need some more work for this cpu (case 1)
203 #if defined(EICRA) && defined(ISC20) && defined(ISC21) && defined(EIMSK)
204 EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
205 EIMSK |= (1 << INT2);
206 #elif defined(MCUCR) && defined(ISC20) && defined(ISC21) && defined(GICR)
207 MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
209 #elif defined(MCUCR) && defined(ISC20) && defined(GIMSK) && defined(GIMSK)
210 MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
211 GIMSK |= (1 << INT2);
219 void detachInterrupt(uint8_t interruptNum) {
220 if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
221 // Disable the interrupt. (We can't assume that interruptNum is equal
222 // to the number of the EIMSK bit to clear, as this isn't true on the
223 // ATmega8. There, INT0 is 6 and INT1 is 7.)
224 switch (interruptNum) {
225 #if defined(__AVR_ATmega32U4__)
241 #elif defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)
243 EIMSK &= ~(1 << INT0);
246 EIMSK &= ~(1 << INT1);
249 EIMSK &= ~(1 << INT2);
252 EIMSK &= ~(1 << INT3);
255 EIMSK &= ~(1 << INT4);
258 EIMSK &= ~(1 << INT5);
261 EIMSK &= ~(1 << INT6);
264 EIMSK &= ~(1 << INT7);
266 #elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
268 EIMSK &= ~(1 << INT0);
271 EIMSK &= ~(1 << INT1);
274 EIMSK &= ~(1 << INT2);
277 EIMSK &= ~(1 << INT3);
280 EIMSK &= ~(1 << INT4);
283 EIMSK &= ~(1 << INT5);
286 EIMSK &= ~(1 << INT6);
289 EIMSK &= ~(1 << INT7);
293 #if defined(EIMSK) && defined(INT0)
294 EIMSK &= ~(1 << INT0);
295 #elif defined(GICR) && defined(ISC00)
296 GICR &= ~(1 << INT0); // atmega32
297 #elif defined(GIMSK) && defined(INT0)
298 GIMSK &= ~(1 << INT0);
300 #error detachInterrupt not finished for this cpu
305 #if defined(EIMSK) && defined(INT1)
306 EIMSK &= ~(1 << INT1);
307 #elif defined(GICR) && defined(INT1)
308 GICR &= ~(1 << INT1); // atmega32
309 #elif defined(GIMSK) && defined(INT1)
310 GIMSK &= ~(1 << INT1);
312 #warning detachInterrupt may need some more work for this cpu (case 1)
317 #if defined(EIMSK) && defined(INT2)
318 EIMSK &= ~(1 << INT2);
319 #elif defined(GICR) && defined(INT2)
320 GICR &= ~(1 << INT2); // atmega32
321 #elif defined(GIMSK) && defined(INT2)
322 GIMSK &= ~(1 << INT2);
324 #warning detachInterrupt may need some more work for this cpu (case 2)
330 intFunc[interruptNum] = nothing;
335 #define IMPLEMENT_ISR(vect, interrupt) \
337 intFunc[interrupt](); \
340 #if defined(__AVR_ATmega32U4__)
342 IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
343 IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
344 IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_2)
345 IMPLEMENT_ISR(INT3_vect, EXTERNAL_INT_3)
346 IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_4)
348 #elif defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)
350 IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
351 IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
352 IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_2)
353 IMPLEMENT_ISR(INT3_vect, EXTERNAL_INT_3)
354 IMPLEMENT_ISR(INT4_vect, EXTERNAL_INT_4)
355 IMPLEMENT_ISR(INT5_vect, EXTERNAL_INT_5)
356 IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_6)
357 IMPLEMENT_ISR(INT7_vect, EXTERNAL_INT_7)
359 #elif defined(EICRA) && defined(EICRB)
361 IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_2)
362 IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_3)
363 IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_4)
364 IMPLEMENT_ISR(INT3_vect, EXTERNAL_INT_5)
365 IMPLEMENT_ISR(INT4_vect, EXTERNAL_INT_0)
366 IMPLEMENT_ISR(INT5_vect, EXTERNAL_INT_1)
367 IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_6)
368 IMPLEMENT_ISR(INT7_vect, EXTERNAL_INT_7)
372 IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
373 IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
375 #if defined(EICRA) && defined(ISC20)
376 IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_2)