Home | History | Annotate | Download | only in arduino
      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