Contiki 2.6
|
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 /*---------------------------------------------------------------------------*/