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
36volatile static voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS];
37// volatile static voidFuncPtr twiIntFunc;
38
39void 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
119void 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/*
182void attachInterruptTwi(void (*userFunc)(void) ) {
183  twiIntFunc = userFunc;
184}
185*/
186
187#if defined(EICRA) && defined(EICRB)
188
189SIGNAL(INT0_vect) {
190  if(intFunc[EXTERNAL_INT_2])
191    intFunc[EXTERNAL_INT_2]();
192}
193
194SIGNAL(INT1_vect) {
195  if(intFunc[EXTERNAL_INT_3])
196    intFunc[EXTERNAL_INT_3]();
197}
198
199SIGNAL(INT2_vect) {
200  if(intFunc[EXTERNAL_INT_4])
201    intFunc[EXTERNAL_INT_4]();
202}
203
204SIGNAL(INT3_vect) {
205  if(intFunc[EXTERNAL_INT_5])
206    intFunc[EXTERNAL_INT_5]();
207}
208
209SIGNAL(INT4_vect) {
210  if(intFunc[EXTERNAL_INT_0])
211    intFunc[EXTERNAL_INT_0]();
212}
213
214SIGNAL(INT5_vect) {
215  if(intFunc[EXTERNAL_INT_1])
216    intFunc[EXTERNAL_INT_1]();
217}
218
219SIGNAL(INT6_vect) {
220  if(intFunc[EXTERNAL_INT_6])
221    intFunc[EXTERNAL_INT_6]();
222}
223
224SIGNAL(INT7_vect) {
225  if(intFunc[EXTERNAL_INT_7])
226    intFunc[EXTERNAL_INT_7]();
227}
228
229#else
230
231SIGNAL(INT0_vect) {
232  if(intFunc[EXTERNAL_INT_0])
233    intFunc[EXTERNAL_INT_0]();
234}
235
236SIGNAL(INT1_vect) {
237  if(intFunc[EXTERNAL_INT_1])
238    intFunc[EXTERNAL_INT_1]();
239}
240
241#endif
242
243/*
244SIGNAL(SIG_2WIRE_SERIAL) {
245  if(twiIntFunc)
246    twiIntFunc();
247}
248*/
249
250