WInterrupts.c
Go to the documentation of this file.
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 
35 static void nothing(void) {
36 }
37 
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 
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 
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 
void detachInterrupt(uint8_t interruptNum)
Definition: WInterrupts.c:187
void(* voidFuncPtr)(void)
#define EXTERNAL_INT_6
GLenum mode
#define IMPLEMENT_ISR(vect, interrupt)
Definition: WInterrupts.c:283
static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]
Definition: WInterrupts.c:38
#define EXTERNAL_INT_1
#define EXTERNAL_INT_5
#define EXTERNAL_INT_3
#define EXTERNAL_INT_2
static void nothing(void)
Definition: WInterrupts.c:35
#define EXTERNAL_INT_0
#define EXTERNAL_NUM_INTERRUPTS
void attachInterrupt(uint8_t interruptNum, void(*userFunc)(void), int mode)
Definition: WInterrupts.c:70
#define EXTERNAL_INT_7
#define EXTERNAL_INT_4


arduino_daq
Author(s):
autogenerated on Mon Jun 10 2019 12:46:03