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 "wiring_private.h"
34 
nothing(void)35 static void nothing(void) {
36 }
37 
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.
41     nothing,
42 #endif
43 #if EXTERNAL_NUM_INTERRUPTS > 7
44     nothing,
45 #endif
46 #if EXTERNAL_NUM_INTERRUPTS > 6
47     nothing,
48 #endif
49 #if EXTERNAL_NUM_INTERRUPTS > 5
50     nothing,
51 #endif
52 #if EXTERNAL_NUM_INTERRUPTS > 4
53     nothing,
54 #endif
55 #if EXTERNAL_NUM_INTERRUPTS > 3
56     nothing,
57 #endif
58 #if EXTERNAL_NUM_INTERRUPTS > 2
59     nothing,
60 #endif
61 #if EXTERNAL_NUM_INTERRUPTS > 1
62     nothing,
63 #endif
64 #if EXTERNAL_NUM_INTERRUPTS > 0
65     nothing,
66 #endif
67 };
68 // volatile static voidFuncPtr twiIntFunc;
69 
attachInterrupt(uint8_t interruptNum,void (* userFunc)(void),int mode)70 void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
71   if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
72     intFunc[interruptNum] = userFunc;
73 
74     // Configure the interrupt mode (trigger on low input, any change, rising
75     // edge, or falling edge).  The mode constants were chosen to correspond
76     // to the configuration bits in the hardware register, so we simply shift
77     // the mode into place.
78 
79     // Enable the interrupt.
80 
81     switch (interruptNum) {
82 #if defined(__AVR_ATmega32U4__)
83 	// I hate doing this, but the register assignment differs between the 1280/2560
84 	// and the 32U4.  Since avrlib defines registers PCMSK1 and PCMSK2 that aren't
85 	// even present on the 32U4 this is the only way to distinguish between them.
86     case 0:
87 	EICRA = (EICRA & ~((1<<ISC00) | (1<<ISC01))) | (mode << ISC00);
88 	EIMSK |= (1<<INT0);
89 	break;
90     case 1:
91 	EICRA = (EICRA & ~((1<<ISC10) | (1<<ISC11))) | (mode << ISC10);
92 	EIMSK |= (1<<INT1);
93 	break;
94     case 2:
95         EICRA = (EICRA & ~((1<<ISC20) | (1<<ISC21))) | (mode << ISC20);
96         EIMSK |= (1<<INT2);
97         break;
98     case 3:
99         EICRA = (EICRA & ~((1<<ISC30) | (1<<ISC31))) | (mode << ISC30);
100         EIMSK |= (1<<INT3);
101         break;
102     case 4:
103         EICRB = (EICRB & ~((1<<ISC60) | (1<<ISC61))) | (mode << ISC60);
104         EIMSK |= (1<<INT6);
105         break;
106 #elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
107     case 2:
108       EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
109       EIMSK |= (1 << INT0);
110       break;
111     case 3:
112       EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
113       EIMSK |= (1 << INT1);
114       break;
115     case 4:
116       EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
117       EIMSK |= (1 << INT2);
118       break;
119     case 5:
120       EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30);
121       EIMSK |= (1 << INT3);
122       break;
123     case 0:
124       EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40);
125       EIMSK |= (1 << INT4);
126       break;
127     case 1:
128       EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50);
129       EIMSK |= (1 << INT5);
130       break;
131     case 6:
132       EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60);
133       EIMSK |= (1 << INT6);
134       break;
135     case 7:
136       EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
137       EIMSK |= (1 << INT7);
138       break;
139 #else
140     case 0:
141     #if defined(EICRA) && defined(ISC00) && defined(EIMSK)
142       EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
143       EIMSK |= (1 << INT0);
144     #elif defined(MCUCR) && defined(ISC00) && defined(GICR)
145       MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
146       GICR |= (1 << INT0);
147     #elif defined(MCUCR) && defined(ISC00) && defined(GIMSK)
148       MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
149       GIMSK |= (1 << INT0);
150     #else
151       #error attachInterrupt not finished for this CPU (case 0)
152     #endif
153       break;
154 
155     case 1:
156     #if defined(EICRA) && defined(ISC10) && defined(ISC11) && defined(EIMSK)
157       EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
158       EIMSK |= (1 << INT1);
159     #elif defined(MCUCR) && defined(ISC10) && defined(ISC11) && defined(GICR)
160       MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
161       GICR |= (1 << INT1);
162     #elif defined(MCUCR) && defined(ISC10) && defined(GIMSK) && defined(GIMSK)
163       MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
164       GIMSK |= (1 << INT1);
165     #else
166       #warning attachInterrupt may need some more work for this cpu (case 1)
167     #endif
168       break;
169 
170     case 2:
171     #if defined(EICRA) && defined(ISC20) && defined(ISC21) && defined(EIMSK)
172       EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
173       EIMSK |= (1 << INT2);
174     #elif defined(MCUCR) && defined(ISC20) && defined(ISC21) && defined(GICR)
175       MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
176       GICR |= (1 << INT2);
177     #elif defined(MCUCR) && defined(ISC20) && defined(GIMSK) && defined(GIMSK)
178       MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
179       GIMSK |= (1 << INT2);
180     #endif
181       break;
182 #endif
183     }
184   }
185 }
186 
detachInterrupt(uint8_t interruptNum)187 void detachInterrupt(uint8_t interruptNum) {
188   if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
189     // Disable the interrupt.  (We can't assume that interruptNum is equal
190     // to the number of the EIMSK bit to clear, as this isn't true on the
191     // ATmega8.  There, INT0 is 6 and INT1 is 7.)
192     switch (interruptNum) {
193 #if defined(__AVR_ATmega32U4__)
194     case 0:
195         EIMSK &= ~(1<<INT0);
196         break;
197     case 1:
198         EIMSK &= ~(1<<INT1);
199         break;
200     case 2:
201         EIMSK &= ~(1<<INT2);
202         break;
203     case 3:
204         EIMSK &= ~(1<<INT3);
205         break;
206     case 4:
207         EIMSK &= ~(1<<INT6);
208         break;
209 #elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
210     case 2:
211       EIMSK &= ~(1 << INT0);
212       break;
213     case 3:
214       EIMSK &= ~(1 << INT1);
215       break;
216     case 4:
217       EIMSK &= ~(1 << INT2);
218       break;
219     case 5:
220       EIMSK &= ~(1 << INT3);
221       break;
222     case 0:
223       EIMSK &= ~(1 << INT4);
224       break;
225     case 1:
226       EIMSK &= ~(1 << INT5);
227       break;
228     case 6:
229       EIMSK &= ~(1 << INT6);
230       break;
231     case 7:
232       EIMSK &= ~(1 << INT7);
233       break;
234 #else
235     case 0:
236     #if defined(EIMSK) && defined(INT0)
237       EIMSK &= ~(1 << INT0);
238     #elif defined(GICR) && defined(ISC00)
239       GICR &= ~(1 << INT0); // atmega32
240     #elif defined(GIMSK) && defined(INT0)
241       GIMSK &= ~(1 << INT0);
242     #else
243       #error detachInterrupt not finished for this cpu
244     #endif
245       break;
246 
247     case 1:
248     #if defined(EIMSK) && defined(INT1)
249       EIMSK &= ~(1 << INT1);
250     #elif defined(GICR) && defined(INT1)
251       GICR &= ~(1 << INT1); // atmega32
252     #elif defined(GIMSK) && defined(INT1)
253       GIMSK &= ~(1 << INT1);
254     #else
255       #warning detachInterrupt may need some more work for this cpu (case 1)
256     #endif
257       break;
258 
259     case 2:
260     #if defined(EIMSK) && defined(INT2)
261       EIMSK &= ~(1 << INT2);
262     #elif defined(GICR) && defined(INT2)
263       GICR &= ~(1 << INT2); // atmega32
264     #elif defined(GIMSK) && defined(INT2)
265       GIMSK &= ~(1 << INT2);
266     #elif defined(INT2)
267       #warning detachInterrupt may need some more work for this cpu (case 2)
268     #endif
269       break;
270 #endif
271     }
272 
273     intFunc[interruptNum] = nothing;
274   }
275 }
276 
277 /*
278 void attachInterruptTwi(void (*userFunc)(void) ) {
279   twiIntFunc = userFunc;
280 }
281 */
282 
283 #define IMPLEMENT_ISR(vect, interrupt) \
284   ISR(vect) { \
285     intFunc[interrupt](); \
286   }
287 
288 #if defined(__AVR_ATmega32U4__)
289 
290 IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
291 IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
292 IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_2)
293 IMPLEMENT_ISR(INT3_vect, EXTERNAL_INT_3)
294 IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_4)
295 
296 #elif defined(EICRA) && defined(EICRB)
297 
298 IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_2)
299 IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_3)
300 IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_4)
301 IMPLEMENT_ISR(INT3_vect, EXTERNAL_INT_5)
302 IMPLEMENT_ISR(INT4_vect, EXTERNAL_INT_0)
303 IMPLEMENT_ISR(INT5_vect, EXTERNAL_INT_1)
304 IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_6)
305 IMPLEMENT_ISR(INT7_vect, EXTERNAL_INT_7)
306 
307 #else
308 
309 IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
310 IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
311 
312 #if defined(EICRA) && defined(ISC20)
313 IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_2)
314 #endif
315 
316 #endif
317 
318 /*
319 ISR(TWI_vect) {
320   if(twiIntFunc)
321     twiIntFunc();
322 }
323 */
324 
325