Contiki 2.6

irq.c

00001 /*
00002  * Copyright (c) 2009, Swedish Institute of Computer Science
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * This file is part of the Contiki operating system.
00030  *
00031  * @(#)$Id: irq.c,v 1.4 2010/01/14 17:39:35 nifi Exp $
00032  */
00033 #include "contiki.h"
00034 #include "lib/sensors.h"
00035 #include "dev/irq.h"
00036 #include "dev/lpm.h"
00037 #include "isr_compat.h"
00038 
00039 #define ADC12MCTL_NO(adcno) ((unsigned char *) ADC12MCTL0_)[adcno]
00040 
00041 static int (* adc12_irq[8])(void);
00042 static int (* port1_irq[8])(void);
00043 static unsigned char adcflags;
00044 
00045 /*---------------------------------------------------------------------------*/
00046 ISR(PORT1, irq_p1)
00047 {
00048   int i;
00049   ENERGEST_ON(ENERGEST_TYPE_IRQ);
00050   for(i = 0; i < 8; i++) {
00051     if((P1IFG & (1 << i)) && port1_irq[i] != NULL) {
00052       if((port1_irq[i])()) {
00053         LPM4_EXIT;
00054       }
00055     }
00056   }
00057   P1IFG = 0x00;
00058   ENERGEST_OFF(ENERGEST_TYPE_IRQ);
00059 }
00060 /*---------------------------------------------------------------------------*/
00061 ISR(ADC, irq_adc)
00062 {
00063   int i;
00064   ENERGEST_ON(ENERGEST_TYPE_IRQ);
00065   for(i = 0; i < 8; i++) {
00066     if(adc12_irq[i] != NULL) {
00067       if((adc12_irq[i])()) {
00068         LPM4_EXIT;
00069       }
00070     }
00071   }
00072   ENERGEST_OFF(ENERGEST_TYPE_IRQ);
00073 }
00074 /*---------------------------------------------------------------------------*/
00075 void
00076 irq_init(void)
00077 {
00078   int i;
00079   adcflags = 0;
00080   for(i = 0; i < 8; i++) {
00081     adc12_irq[i] = NULL;
00082     port1_irq[i] = NULL;
00083   }
00084   /* Setup ADC12, ref., sampling time */
00085   ADC12CTL0 = REF2_5V | SHT0_10 | SHT1_10 | MSC;
00086 
00087   /* Use sampling timer, repeat-sequence-of-channels */
00088 /*   ADC12CTL1 = SHP | CONSEQ_3 | ADC12DIV_3; */
00089   ADC12CTL1 = SHP | CONSEQ_3 | ADC12DIV_7;
00090 }
00091 /*---------------------------------------------------------------------------*/
00092 void
00093 irq_port1_activate(unsigned char irqno, int (* irq)(void))
00094 {
00095   if(irqno < 8) {
00096     port1_irq[irqno] = irq;
00097   }
00098 }
00099 /*---------------------------------------------------------------------------*/
00100 void
00101 irq_port1_deactivate(unsigned char irqno)
00102 {
00103   if(irqno < 8) {
00104     port1_irq[irqno] = NULL;
00105   }
00106 }
00107 /*---------------------------------------------------------------------------*/
00108 /* Set lowest ADC to be start in sequence and highest to be interrupt
00109    enabled and set end-of-sequence on the highest active ADC */
00110 static void
00111 sethilo(void)
00112 {
00113   int c;
00114 
00115   /* Clear start of sequence */
00116   ADC12CTL1 &= ~(CSTARTADD_15);
00117 
00118   /* Set new start of sequence to lowest active memory holder */
00119   for(c = 0; c < 8; c++) {
00120     if(adcflags & (1 << c)) {
00121       ADC12CTL1 |= (c * CSTARTADD_1);
00122       break;
00123     }
00124   }
00125 
00126   /* Clear all interrupts and end-of-sequences */
00127   ADC12IE = 0;
00128   for(c = 0; c < 8; c++) {
00129     ADC12MCTL_NO(c) &= ~EOS;
00130   }
00131 
00132   /* Set highest interrupt and end-of-sequence. This will generate one
00133      interrupt for each sequence of conversions. */
00134   for(c = 0; c < 8; c++) {
00135     if(adcflags & (128 >> c)) {
00136       ADC12IE |= 128 >> c;
00137       ADC12MCTL_NO(7 - c) |= EOS;
00138       break;
00139     }
00140   }
00141 }
00142 /*---------------------------------------------------------------------------*/
00143 void
00144 irq_adc12_activate(unsigned char adcno, unsigned char config,
00145                    int (* irq)(void))
00146 {
00147   if(adcno >= 8) {
00148     return;
00149   }
00150   /* stop converting */
00151   ADC12CTL0 &= ~ENC;
00152   /* wait for conversion to stop */
00153   while(ADC12CTL0 & ADC12BUSY);
00154   ADC12CTL0 &= ~(ADC12ON | REFON);
00155   ADC12IE = 0;
00156 
00157   /* clear any pending interrupts */
00158   ADC12IFG = 0;
00159 
00160   adcflags |= (1 << adcno);
00161 
00162   ADC12MCTL_NO(adcno) = config;
00163 
00164   sethilo();
00165 
00166   ADC12CTL0 |= ADC12ON | REFON;
00167 
00168   adc12_irq[adcno] = irq;
00169 
00170   /* Delay */
00171   clock_delay(20000);
00172 
00173   ADC12CTL0 |= ENC | ADC12SC;
00174 }
00175 /*---------------------------------------------------------------------------*/
00176 void
00177 irq_adc12_deactivate(unsigned char adcno)
00178 {
00179   if(adcno >= 8) {
00180     return;
00181   }
00182   /* stop converting */
00183   ADC12CTL0 &= ~ENC;
00184   /* wait for conversion to stop */
00185   while(ADC12CTL0 & ADC12BUSY);
00186   ADC12CTL0 &= ~(ADC12ON | REFON);
00187   ADC12IE = 0;
00188 
00189   /* clear any pending interrupts */
00190   ADC12IFG = 0;
00191 
00192   adcflags &= ~(1 << adcno);
00193 
00194   ADC12MCTL_NO(adcno) = 0;
00195 
00196   sethilo();
00197 
00198   adc12_irq[adcno] = NULL;
00199 
00200   if(adcflags) {
00201     /* Turn on the ADC12 */
00202     ADC12CTL0 |= (ADC12ON | REFON);
00203 
00204     /* Delay */
00205     clock_delay(20000);
00206 
00207     /* Still active. Turn on the conversion. */
00208     ADC12CTL0 |= ENC | ADC12SC;
00209   }
00210 }
00211 /*---------------------------------------------------------------------------*/
00212 int
00213 irq_adc12_active(unsigned char adcno)
00214 {
00215   return adcflags & (1 << adcno) ? 1 : 0;
00216 }
00217 /*---------------------------------------------------------------------------*/