Contiki-NG
tmp-007-sensor.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/
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 copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 /*---------------------------------------------------------------------------*/
31 /**
32  * \addtogroup sensortag-cc26xx-tmp-sensor
33  * @{
34  *
35  * \file
36  * Driver for the Sensortag TI TMP007 infrared thermophile sensor
37  */
38 /*---------------------------------------------------------------------------*/
39 #include "contiki.h"
40 #include "lib/sensors.h"
41 #include "tmp-007-sensor.h"
42 #include "sys/ctimer.h"
43 #include "board-i2c.h"
44 #include "sensor-common.h"
45 #include "ti-lib.h"
46 
47 #include <stdint.h>
48 #include <string.h>
49 #include <stdio.h>
50 #include <math.h>
51 /*---------------------------------------------------------------------------*/
52 #define DEBUG 0
53 #if DEBUG
54 #define PRINTF(...) printf(__VA_ARGS__)
55 #else
56 #define PRINTF(...)
57 #endif
58 /*---------------------------------------------------------------------------*/
59 /* Slave address */
60 #define SENSOR_I2C_ADDRESS 0x44
61 /*---------------------------------------------------------------------------*/
62 /* TMP007 register addresses */
63 #define TMP007_REG_ADDR_VOLTAGE 0x00
64 #define TMP007_REG_ADDR_LOCAL_TEMP 0x01
65 #define TMP007_REG_ADDR_CONFIG 0x02
66 #define TMP007_REG_ADDR_OBJ_TEMP 0x03
67 #define TMP007_REG_ADDR_STATUS 0x04
68 #define TMP007_REG_PROD_ID 0x1F
69 /*---------------------------------------------------------------------------*/
70 /* TMP007 register values */
71 #define TMP007_VAL_CONFIG_ON 0x1000 /* Sensor on state */
72 #define TMP007_VAL_CONFIG_OFF 0x0000 /* Sensor off state */
73 #define TMP007_VAL_CONFIG_RESET 0x8000
74 #define TMP007_VAL_PROD_ID 0x0078 /* Product ID */
75 /*---------------------------------------------------------------------------*/
76 /* Conversion ready (status register) bit values */
77 #define CONV_RDY_BIT 0x4000
78 /*---------------------------------------------------------------------------*/
79 /* Register length */
80 #define REGISTER_LENGTH 2
81 /*---------------------------------------------------------------------------*/
82 /* Sensor data size */
83 #define DATA_SIZE 4
84 /*---------------------------------------------------------------------------*/
85 /* Byte swap of 16-bit register value */
86 #define HI_UINT16(a) (((a) >> 8) & 0xFF)
87 #define LO_UINT16(a) ((a) & 0xFF)
88 
89 #define SWAP(v) ((LO_UINT16(v) << 8) | HI_UINT16(v))
90 /*---------------------------------------------------------------------------*/
91 #define SELECT() board_i2c_select(BOARD_I2C_INTERFACE_0, SENSOR_I2C_ADDRESS)
92 /*---------------------------------------------------------------------------*/
93 static uint8_t buf[DATA_SIZE];
94 static uint16_t val;
95 /*---------------------------------------------------------------------------*/
96 #define SENSOR_STATUS_DISABLED 0
97 #define SENSOR_STATUS_INITIALISED 1
98 #define SENSOR_STATUS_NOT_READY 2
99 #define SENSOR_STATUS_READY 3
100 
101 static int enabled = SENSOR_STATUS_DISABLED;
102 /*---------------------------------------------------------------------------*/
103 /* Wait SENSOR_STARTUP_DELAY clock ticks for the sensor to be ready - 275ms */
104 #define SENSOR_STARTUP_DELAY 36
105 
106 static struct ctimer startup_timer;
107 /*---------------------------------------------------------------------------*/
108 /* Latched values */
109 static int obj_temp_latched;
110 static int amb_temp_latched;
111 /*---------------------------------------------------------------------------*/
112 static void
113 notify_ready(void *not_used)
114 {
115  enabled = SENSOR_STATUS_READY;
116  sensors_changed(&tmp_007_sensor);
117 }
118 /*---------------------------------------------------------------------------*/
119 /**
120  * \brief Turn the sensor on/off
121  */
122 static bool
123 enable_sensor(bool enable)
124 {
125  bool success;
126 
127  SELECT();
128 
129  if(enable) {
130  val = TMP007_VAL_CONFIG_ON;
131  } else {
132  val = TMP007_VAL_CONFIG_OFF;
133  }
134  val = SWAP(val);
135 
136  success = sensor_common_write_reg(TMP007_REG_ADDR_CONFIG, (uint8_t *)&val,
137  REGISTER_LENGTH);
138 
139  return success;
140 }
141 /*---------------------------------------------------------------------------*/
142 /**
143  * \brief Read the sensor value registers
144  * \param raw_temp Temperature in 16 bit format
145  * \param raw_obj_temp object temperature in 16 bit format
146  * \return TRUE if valid data could be retrieved
147  */
148 static bool
149 read_data(uint16_t *raw_temp, uint16_t *raw_obj_temp)
150 {
151  bool success;
152 
153  SELECT();
154 
155  success = sensor_common_read_reg(TMP007_REG_ADDR_STATUS, (uint8_t *)&val,
156  REGISTER_LENGTH);
157 
158  if(success) {
159  val = SWAP(val);
160  success = val & CONV_RDY_BIT;
161  }
162 
163  if(success) {
164  success = sensor_common_read_reg(TMP007_REG_ADDR_LOCAL_TEMP, &buf[0],
165  REGISTER_LENGTH);
166  if(success) {
167  success = sensor_common_read_reg(TMP007_REG_ADDR_OBJ_TEMP, &buf[2],
168  REGISTER_LENGTH);
169  }
170  }
171 
172  if(!success) {
174  }
175 
176  /* Swap byte order */
177  *raw_temp = buf[0] << 8 | buf[1];
178  *raw_obj_temp = buf[2] << 8 | buf[3];
179 
180  return success;
181 }
182 /*---------------------------------------------------------------------------*/
183 /**
184  * \brief Convert raw data to values in degrees C
185  * \param raw_temp raw ambient temperature from sensor
186  * \param raw_obj_temp raw object temperature from sensor
187  * \param obj converted object temperature
188  * \param amb converted ambient temperature
189  */
190 static void
191 convert(uint16_t raw_temp, uint16_t raw_obj_temp, float *obj, float *amb)
192 {
193  const float SCALE_LSB = 0.03125;
194  float t;
195  int it;
196 
197  it = (int)((raw_obj_temp) >> 2);
198  t = ((float)(it)) * SCALE_LSB;
199  *obj = t;
200 
201  it = (int)((raw_temp) >> 2);
202  t = (float)it;
203  *amb = t * SCALE_LSB;
204 }
205 /*---------------------------------------------------------------------------*/
206 /**
207  * \brief Returns a reading from the sensor
208  * \param type TMP_007_SENSOR_TYPE_OBJECT or TMP_007_SENSOR_TYPE_AMBIENT
209  * \return Object or Ambient temperature in milli degrees C
210  */
211 static int
212 value(int type)
213 {
214  int rv;
215  uint16_t raw_temp;
216  uint16_t raw_obj_temp;
217  float obj_temp;
218  float amb_temp;
219 
220  if(enabled != SENSOR_STATUS_READY) {
221  PRINTF("Sensor disabled or starting up (%d)\n", enabled);
222  return CC26XX_SENSOR_READING_ERROR;
223  }
224 
225  if((type & TMP_007_SENSOR_TYPE_ALL) == 0) {
226  PRINTF("Invalid type\n");
227  return CC26XX_SENSOR_READING_ERROR;
228  }
229 
230  rv = CC26XX_SENSOR_READING_ERROR;
231 
232  if(type == TMP_007_SENSOR_TYPE_ALL) {
233  rv = read_data(&raw_temp, &raw_obj_temp);
234 
235  if(rv == 0) {
236  return CC26XX_SENSOR_READING_ERROR;
237  }
238 
239  convert(raw_temp, raw_obj_temp, &obj_temp, &amb_temp);
240  PRINTF("TMP: %04X %04X o=%d a=%d\n", raw_temp, raw_obj_temp,
241  (int)(obj_temp * 1000), (int)(amb_temp * 1000));
242 
243  obj_temp_latched = (int)(obj_temp * 1000);
244  amb_temp_latched = (int)(amb_temp * 1000);
245  rv = 1;
246  } else if(type == TMP_007_SENSOR_TYPE_OBJECT) {
247  rv = obj_temp_latched;
248  } else if(type == TMP_007_SENSOR_TYPE_AMBIENT) {
249  rv = amb_temp_latched;
250  }
251 
252  return rv;
253 }
254 /*---------------------------------------------------------------------------*/
255 /**
256  * \brief Configuration function for the TMP007 sensor.
257  *
258  * \param type Activate, enable or disable the sensor. See below
259  * \param enable
260  *
261  * When type == SENSORS_HW_INIT we turn on the hardware
262  * When type == SENSORS_ACTIVE and enable==1 we enable the sensor
263  * When type == SENSORS_ACTIVE and enable==0 we disable the sensor
264  */
265 static int
266 configure(int type, int enable)
267 {
268  switch(type) {
269  case SENSORS_HW_INIT:
270  ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_TMP_RDY);
271  ti_lib_ioc_io_port_pull_set(BOARD_IOID_TMP_RDY, IOC_IOPULL_UP);
272  ti_lib_ioc_io_hyst_set(BOARD_IOID_TMP_RDY, IOC_HYST_ENABLE);
273 
274  enable_sensor(false);
275  enabled = SENSOR_STATUS_INITIALISED;
276  break;
277  case SENSORS_ACTIVE:
278  /* Must be initialised first */
279  if(enabled == SENSOR_STATUS_DISABLED) {
280  return SENSOR_STATUS_DISABLED;
281  }
282  if(enable) {
283  enable_sensor(true);
284  ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL);
285  enabled = SENSOR_STATUS_NOT_READY;
286  } else {
287  ctimer_stop(&startup_timer);
288  enable_sensor(false);
289  enabled = SENSOR_STATUS_INITIALISED;
290  }
291  break;
292  default:
293  break;
294  }
295  return enabled;
296 }
297 /*---------------------------------------------------------------------------*/
298 /**
299  * \brief Returns the status of the sensor
300  * \param type SENSORS_ACTIVE or SENSORS_READY
301  * \return 1 if the sensor is enabled
302  */
303 static int
304 status(int type)
305 {
306  switch(type) {
307  case SENSORS_ACTIVE:
308  case SENSORS_READY:
309  return enabled;
310  break;
311  default:
312  break;
313  }
314  return SENSOR_STATUS_DISABLED;
315 }
316 /*---------------------------------------------------------------------------*/
317 SENSORS_SENSOR(tmp_007_sensor, "TMP007", value, configure, status);
318 /*---------------------------------------------------------------------------*/
319 /** @} */
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149
Header file with macros which rename TI CC26xxware functions.
Header file for the Sensortag I2C Driver.
static bool enable_sensor(bool enable)
Turn the sensor on/off.
void sensor_common_set_error_data(uint8_t *buf, uint8_t len)
Fill a result buffer with dummy error data.
Definition: sensor-common.c:71
bool sensor_common_read_reg(uint8_t addr, uint8_t *buf, uint8_t len)
Reads a sensor&#39;s register over I2C.
Definition: sensor-common.c:48
Header file for the callback timer
Header file for the Sensortag Common sensor utilities.
static int status(int type)
Returns the status of the sensor.
static int configure(int type, int enable)
Configuration function for the TMP007 sensor.
static void convert(uint16_t raw_temp, uint16_t raw_obj_temp, float *obj, float *amb)
Convert raw data to values in degrees C.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
#define BOARD_IOID_TMP_RDY
TMP Sensor.
Definition: board.h:200
bool sensor_common_write_reg(uint8_t addr, uint8_t *buf, uint8_t len)
Write to a sensor&#39;s register over I2C.
Definition: sensor-common.c:54
static void notify_ready(void *unused)
Callback when sensor is ready to read data from.
Header file for the Sensortag TI TMP007 infrared thermophile sensor.
static int value(int type)
Returns a reading from the sensor.
static bool read_data(uint16_t *raw_temp, uint16_t *raw_obj_temp)
Read the sensor value registers.