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 "lib/sensors.h"
00034 #include "dev/irq.h"
00035 #include "dev/lpm.h"
00036 #include <io.h>
00037 #include <signal.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 interrupt(PORT1_VECTOR)
00047      irq_p1(void)
00048 {
00049   int i;
00050   ENERGEST_ON(ENERGEST_TYPE_IRQ);
00051   for(i = 0; i < 8; i++) {
00052     if((P1IFG & (1 << i)) && port1_irq[i] != NULL) {
00053       if((port1_irq[i])()) {
00054         LPM4_EXIT;
00055       }
00056     }
00057   }
00058   P1IFG = 0x00;
00059   ENERGEST_OFF(ENERGEST_TYPE_IRQ);
00060 }
00061 /*---------------------------------------------------------------------------*/
00062 interrupt (ADC_VECTOR)
00063      irq_adc(void)
00064 {
00065   int i;
00066   ENERGEST_ON(ENERGEST_TYPE_IRQ);
00067   for(i = 0; i < 8; i++) {
00068     if(adc12_irq[i] != NULL) {
00069       if((adc12_irq[i])()) {
00070         LPM4_EXIT;
00071       }
00072     }
00073   }
00074   ENERGEST_OFF(ENERGEST_TYPE_IRQ);
00075 }
00076 /*---------------------------------------------------------------------------*/
00077 void
00078 irq_init(void)
00079 {
00080   int i;
00081   adcflags = 0;
00082   for(i = 0; i < 8; i++) {
00083     adc12_irq[i] = NULL;
00084     port1_irq[i] = NULL;
00085   }
00086   /* Setup ADC12, ref., sampling time */
00087   ADC12CTL0 = REF2_5V | SHT0_10 | SHT1_10 | MSC;
00088 
00089   /* Use sampling timer, repeat-sequence-of-channels */
00090 /*   ADC12CTL1 = SHP | CONSEQ_3 | ADC12DIV_3; */
00091   ADC12CTL1 = SHP | CONSEQ_3 | ADC12DIV_7;
00092 }
00093 /*---------------------------------------------------------------------------*/
00094 void
00095 irq_port1_activate(unsigned char irqno, int (* irq)(void))
00096 {
00097   if(irqno < 8) {
00098     port1_irq[irqno] = irq;
00099   }
00100 }
00101 /*---------------------------------------------------------------------------*/
00102 void
00103 irq_port1_deactivate(unsigned char irqno)
00104 {
00105   if(irqno < 8) {
00106     port1_irq[irqno] = NULL;
00107   }
00108 }
00109 /*---------------------------------------------------------------------------*/
00110 /* Set lowest ADC to be start in sequence and highest to be interrupt
00111    enabled and set end-of-sequence on the highest active ADC */
00112 static void
00113 sethilo(void)
00114 {
00115   int c;
00116 
00117   /* Clear start of sequence */
00118   ADC12CTL1 &= ~(CSTARTADD_15);
00119 
00120   /* Set new start of sequence to lowest active memory holder */
00121   for(c = 0; c < 8; c++) {
00122     if(adcflags & (1 << c)) {
00123       ADC12CTL1 |= (c * CSTARTADD_1);
00124       break;
00125     }
00126   }
00127 
00128   /* Clear all interrupts and end-of-sequences */
00129   ADC12IE = 0;
00130   for(c = 0; c < 8; c++) {
00131     ADC12MCTL_NO(c) &= ~EOS;
00132   }
00133 
00134   /* Set highest interrupt and end-of-sequence. This will generate one
00135      interrupt for each sequence of conversions. */
00136   for(c = 0; c < 8; c++) {
00137     if(adcflags & (128 >> c)) {
00138       ADC12IE |= 128 >> c;
00139       ADC12MCTL_NO(7 - c) |= EOS;
00140       break;
00141     }
00142   }
00143 }
00144 /*---------------------------------------------------------------------------*/
00145 void
00146 irq_adc12_activate(unsigned char adcno, unsigned char config,
00147                    int (* irq)(void))
00148 {
00149   if(adcno >= 8) {
00150     return;
00151   }
00152   /* stop converting */
00153   ADC12CTL0 &= ~ENC;
00154   /* wait for conversion to stop */
00155   while(ADC12CTL0 & ADC12BUSY);
00156   ADC12CTL0 &= ~(ADC12ON | REFON);
00157   ADC12IE = 0;
00158 
00159   /* clear any pending interrupts */
00160   ADC12IFG = 0;
00161 
00162   adcflags |= (1 << adcno);
00163 
00164   ADC12MCTL_NO(adcno) = config;
00165 
00166   sethilo();
00167 
00168   ADC12CTL0 |= ADC12ON | REFON;
00169 
00170   adc12_irq[adcno] = irq;
00171 
00172   /* Delay */
00173   clock_delay(20000);
00174 
00175   ADC12CTL0 |= ENC | ADC12SC;
00176 }
00177 /*---------------------------------------------------------------------------*/
00178 void
00179 irq_adc12_deactivate(unsigned char adcno)
00180 {
00181   if(adcno >= 8) {
00182     return;
00183   }
00184   /* stop converting */
00185   ADC12CTL0 &= ~ENC;
00186   /* wait for conversion to stop */
00187   while(ADC12CTL0 & ADC12BUSY);
00188   ADC12CTL0 &= ~(ADC12ON | REFON);
00189   ADC12IE = 0;
00190 
00191   /* clear any pending interrupts */
00192   ADC12IFG = 0;
00193 
00194   adcflags &= ~(1 << adcno);
00195 
00196   ADC12MCTL_NO(adcno) = 0;
00197 
00198   sethilo();
00199 
00200   adc12_irq[adcno] = NULL;
00201 
00202   if(adcflags) {
00203     /* Turn on the ADC12 */
00204     ADC12CTL0 |= (ADC12ON | REFON);
00205 
00206     /* Delay */
00207     clock_delay(20000);
00208 
00209     /* Still active. Turn on the conversion. */
00210     ADC12CTL0 |= ENC | ADC12SC;
00211   }
00212 }
00213 /*---------------------------------------------------------------------------*/
00214 int
00215 irq_adc12_active(unsigned char adcno)
00216 {
00217   return adcflags & (1 << adcno) ? 1 : 0;
00218 }
00219 /*---------------------------------------------------------------------------*/

Generated on Mon Apr 11 14:23:43 2011 for Contiki 2.5 by  doxygen 1.6.1