Contiki 3.x
adc-sensor.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, Loughborough University - 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 
32 /**
33  * \file
34  * ADC sensor module for sensinode devices.
35  *
36  * This file respects configuration in contiki-conf.h. It also turns
37  * off features which are not present in the model that we are
38  * building for.
39  *
40  * \author
41  * George Oikonomou - <oikonomou@users.sourceforge.net>
42  */
43 #include "dev/sensinode-sensors.h"
44 
45 #if ADC_SENSOR_ON
46 SENSORS_SENSOR(adc_sensor, ADC_SENSOR, value, configure, status);
47 
48 static uint8_t ready;
49 
50 /*---------------------------------------------------------------------------*/
51 static int
52 value(int type)
53 {
54  uint16_t reading;
55  /*
56  * For single-shot AD conversions, we may only write to ADCCON3[3:0] once
57  * (This write triggers the conversion). We thus use the variable 'command'
58  * to store intermediate steps (reference, decimation rate, input channel)
59  */
60  uint8_t command;
61 
62  ADCCFG = 0; /* Enables/Disables Input Channel */
63 
64  /* 1.25V ref, max decimation rate */
65  command = ADEDIV1 | ADEDIV0;
66 
67  /* Clear the Interrupt Flag */
68  TCON_ADCIF = 0;
69 
70  /* Depending on the desired reading, append the input bits to 'command' and
71  * enable the corresponding input channel in ADCCFG if necessary */
72  switch(type) {
73 #if TEMP_SENSOR_ON
74  case ADC_SENSOR_TYPE_TEMP:
75  command |= ADECH3 | ADECH2 | ADECH1;
76  break;
77 #endif
78 #if ACC_SENSOR_ON
79  case ADC_SENSOR_TYPE_ACC_X:
80  ADCCFG = ADC5EN;
81  command |= ADECH2 | ADECH0;
82  break;
83  case ADC_SENSOR_TYPE_ACC_Y:
84  ADCCFG = ADC6EN;
85  command |= ADECH2 | ADECH1;
86  break;
87  case ADC_SENSOR_TYPE_ACC_Z:
88  ADCCFG = ADC7EN;
89  command |= ADECH2 | ADECH1 | ADECH0;
90  break;
91 #endif
92 #if VDD_SENSOR_ON
93  case ADC_SENSOR_TYPE_VDD:
94  command |= ADECH3 | ADECH2 | ADECH1 | ADECH0;
95  break;
96 #endif
97 #if LIGHT_SENSOR_ON
98  case ADC_SENSOR_TYPE_LIGHT:
99  ADCCFG = ADC0EN;
100  break;
101 #endif
102 #if BATTERY_SENSOR_ON
103  case ADC_SENSOR_TYPE_BATTERY:
104  ADCCFG = ADC1EN;
105  command |= ADECH0 | ADEREF1; /* AVDD_SOC reference */
106  break;
107 #endif
108  default:
109  /* If the sensor is not present or disabled in conf, return -1 */
110  return -1;
111  }
112 
113  /* Writing in bits 3:0 of ADCCON3 will trigger a single conversion */
114  ADCCON3 = command;
115 
116  /*
117  * When the conversion is complete, the ADC interrupt flag is set. We don't
118  * use an ISR here, we just wait on the flag and clear it afterwards.
119  */
120  while(!TCON_ADCIF);
121 
122  /* Clear the Interrupt Flag */
123  TCON_ADCIF = 0;
124 
125  reading = 0;
126  reading = ADCL;
127  reading |= (((uint8_t) ADCH) << 8);
128  /* 12-bit decimation rate: 4 LS bits are noise */
129  reading >>= 4;
130 
131  return reading;
132 }
133 /*---------------------------------------------------------------------------*/
134 static int
135 status(int type)
136 {
137  return ready;
138 }
139 /*---------------------------------------------------------------------------*/
140 /*
141  * On N740 we can control Ill and Acc individually:
142  * ADC_VAL_OTHERS 0x01
143  * ADC_VAL_LIGHT_ON 0x04
144  * ADC_VAL_ACC_ON 0x08
145  * ADC_VAL_ACC_GSEL 0x10
146  *
147  * Return Value is always light | acc | acc_gsel
148  *
149  * SENSORS_ACTIVE:
150  * - 1: Activate everything, use default setting for ACC G-select
151  * - 0: Turn everything off
152  * - xyz: Mask with the defines above and act accordingly.
153  *
154  * SENSORS_READY:
155  * - Return Status (0: all off or a value based on the defines above)
156  */
157 static int
158 configure(int type, int value)
159 {
160 #ifdef MODEL_N740
161  /*
162  * Read current state of the ser-par, ignoring current sensor settings
163  * Those will be set all over depending on VALUE
164  */
165  uint8_t ser_par_val = n740_ser_par_get() & 0xF2;
166 #endif /* MODEL_N740 */
167 
168  /* 'Others' are either compiled in or not. Can't be turned on/off */
169  ready = ADC_VAL_ALL;
170 
171  switch(type) {
172  case SENSORS_HW_INIT:
173  case SENSORS_ACTIVE:
174 #ifdef MODEL_N740
175  if(value == ADC_VAL_ALL) {
176  value = ADC_VAL_ACC_ON | ADC_VAL_LIGHT_ON;
177 #if ACC_SENSOR_GSEL
178  value |= ADC_VAL_ACC_GSEL;
179 #endif /* ACC_SENSOR_GSEL */
180  }
181 #endif /* MODEL_N740 */
182 
183  /* OK, Now value definitely specifies our bits, start masking
184  * We will refuse to turn things on if they are specified OFF in conf. */
185 #ifdef MODEL_N740
186 #if ACC_SENSOR_ON
187  if(value & ADC_VAL_ACC_ON) {
188  P0SEL |= 0x80 | 0x40 | 0x20;
189  ser_par_val |= N740_SER_PAR_ACC;
190  ready |= ADC_VAL_ACC_ON;
191 #if ACC_SENSOR_GSEL
192  if(value & ADC_VAL_ACC_GSEL) {
193  ser_par_val |= N740_SER_PAR_ACC_GSEL;
194  ready |= ADC_VAL_ACC_GSEL;
195  }
196 #endif /*ACC_SENSOR_GSEL */
197  }
198 #endif /* ACC_SENSOR_ON */
199 
200 #if LIGHT_SENSOR_ON
201  if(value & ADC_VAL_LIGHT_ON) {
202  ser_par_val |= N740_SER_PAR_LIGHT;
203  ready |= ADC_VAL_LIGHT_ON;
204  }
205 #endif /* LIGHT_SENSOR_ON */
206  n740_ser_par_set(ser_par_val);
207 #endif /* MODEL_N740 */
208  }
209  return ready;
210 }
211 
212 #endif /* ADC_SENSOR_ON */
Defines for the sensors on the various Sensinode models.