Contiki 2.5
irq.c
1 /*
2  * Copyright (c) 2009, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * @(#)$Id: irq.c,v 1.4 2010/01/14 17:39:35 nifi Exp $
32  */
33 #include "contiki.h"
34 #include "lib/sensors.h"
35 #include "dev/irq.h"
36 #include "dev/lpm.h"
37 
38 #define ADC12MCTL_NO(adcno) ((unsigned char *) ADC12MCTL0_)[adcno]
39 
40 static int (* adc12_irq[8])(void);
41 static int (* port1_irq[8])(void);
42 static unsigned char adcflags;
43 
44 /*---------------------------------------------------------------------------*/
45 interrupt(PORT1_VECTOR)
46  irq_p1(void)
47 {
48  int i;
49  ENERGEST_ON(ENERGEST_TYPE_IRQ);
50  for(i = 0; i < 8; i++) {
51  if((P1IFG & (1 << i)) && port1_irq[i] != NULL) {
52  if((port1_irq[i])()) {
53  LPM4_EXIT;
54  }
55  }
56  }
57  P1IFG = 0x00;
58  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
59 }
60 /*---------------------------------------------------------------------------*/
61 interrupt (ADC_VECTOR)
62  irq_adc(void)
63 {
64  int i;
65  ENERGEST_ON(ENERGEST_TYPE_IRQ);
66  for(i = 0; i < 8; i++) {
67  if(adc12_irq[i] != NULL) {
68  if((adc12_irq[i])()) {
69  LPM4_EXIT;
70  }
71  }
72  }
73  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
74 }
75 /*---------------------------------------------------------------------------*/
76 void
77 irq_init(void)
78 {
79  int i;
80  adcflags = 0;
81  for(i = 0; i < 8; i++) {
82  adc12_irq[i] = NULL;
83  port1_irq[i] = NULL;
84  }
85  /* Setup ADC12, ref., sampling time */
86  ADC12CTL0 = REF2_5V | SHT0_10 | SHT1_10 | MSC;
87 
88  /* Use sampling timer, repeat-sequence-of-channels */
89 /* ADC12CTL1 = SHP | CONSEQ_3 | ADC12DIV_3; */
90  ADC12CTL1 = SHP | CONSEQ_3 | ADC12DIV_7;
91 }
92 /*---------------------------------------------------------------------------*/
93 void
94 irq_port1_activate(unsigned char irqno, int (* irq)(void))
95 {
96  if(irqno < 8) {
97  port1_irq[irqno] = irq;
98  }
99 }
100 /*---------------------------------------------------------------------------*/
101 void
102 irq_port1_deactivate(unsigned char irqno)
103 {
104  if(irqno < 8) {
105  port1_irq[irqno] = NULL;
106  }
107 }
108 /*---------------------------------------------------------------------------*/
109 /* Set lowest ADC to be start in sequence and highest to be interrupt
110  enabled and set end-of-sequence on the highest active ADC */
111 static void
112 sethilo(void)
113 {
114  int c;
115 
116  /* Clear start of sequence */
117  ADC12CTL1 &= ~(CSTARTADD_15);
118 
119  /* Set new start of sequence to lowest active memory holder */
120  for(c = 0; c < 8; c++) {
121  if(adcflags & (1 << c)) {
122  ADC12CTL1 |= (c * CSTARTADD_1);
123  break;
124  }
125  }
126 
127  /* Clear all interrupts and end-of-sequences */
128  ADC12IE = 0;
129  for(c = 0; c < 8; c++) {
130  ADC12MCTL_NO(c) &= ~EOS;
131  }
132 
133  /* Set highest interrupt and end-of-sequence. This will generate one
134  interrupt for each sequence of conversions. */
135  for(c = 0; c < 8; c++) {
136  if(adcflags & (128 >> c)) {
137  ADC12IE |= 128 >> c;
138  ADC12MCTL_NO(7 - c) |= EOS;
139  break;
140  }
141  }
142 }
143 /*---------------------------------------------------------------------------*/
144 void
145 irq_adc12_activate(unsigned char adcno, unsigned char config,
146  int (* irq)(void))
147 {
148  if(adcno >= 8) {
149  return;
150  }
151  /* stop converting */
152  ADC12CTL0 &= ~ENC;
153  /* wait for conversion to stop */
154  while(ADC12CTL0 & ADC12BUSY);
155  ADC12CTL0 &= ~(ADC12ON | REFON);
156  ADC12IE = 0;
157 
158  /* clear any pending interrupts */
159  ADC12IFG = 0;
160 
161  adcflags |= (1 << adcno);
162 
163  ADC12MCTL_NO(adcno) = config;
164 
165  sethilo();
166 
167  ADC12CTL0 |= ADC12ON | REFON;
168 
169  adc12_irq[adcno] = irq;
170 
171  /* Delay */
172  clock_delay(20000);
173 
174  ADC12CTL0 |= ENC | ADC12SC;
175 }
176 /*---------------------------------------------------------------------------*/
177 void
178 irq_adc12_deactivate(unsigned char adcno)
179 {
180  if(adcno >= 8) {
181  return;
182  }
183  /* stop converting */
184  ADC12CTL0 &= ~ENC;
185  /* wait for conversion to stop */
186  while(ADC12CTL0 & ADC12BUSY);
187  ADC12CTL0 &= ~(ADC12ON | REFON);
188  ADC12IE = 0;
189 
190  /* clear any pending interrupts */
191  ADC12IFG = 0;
192 
193  adcflags &= ~(1 << adcno);
194 
195  ADC12MCTL_NO(adcno) = 0;
196 
197  sethilo();
198 
199  adc12_irq[adcno] = NULL;
200 
201  if(adcflags) {
202  /* Turn on the ADC12 */
203  ADC12CTL0 |= (ADC12ON | REFON);
204 
205  /* Delay */
206  clock_delay(20000);
207 
208  /* Still active. Turn on the conversion. */
209  ADC12CTL0 |= ENC | ADC12SC;
210  }
211 }
212 /*---------------------------------------------------------------------------*/
213 int
214 irq_adc12_active(unsigned char adcno)
215 {
216  return adcflags & (1 << adcno) ? 1 : 0;
217 }
218 /*---------------------------------------------------------------------------*/