Contiki-NG
hdc-1000-sensor.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018, 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  * \addtogroup sensortag-hdc-sensor
32  * @{
33  *
34  * \file
35  * Driver for the Sensortag HDC1000 sensor.
36  * \author
37  * Edvard Pettersen <e.pettersen@ti.com>
38  */
39 /*---------------------------------------------------------------------------*/
40 #include "contiki.h"
41 #include "sys/ctimer.h"
42 #include "lib/sensors.h"
43 #include "dev/i2c-arch.h"
44 /*---------------------------------------------------------------------------*/
45 #include "board-conf.h"
46 #include "hdc-1000-sensor.h"
47 /*---------------------------------------------------------------------------*/
48 #include <Board.h>
49 
50 #include <ti/drivers/I2C.h>
51 /*---------------------------------------------------------------------------*/
52 #include <stdint.h>
53 #include <string.h>
54 #include <stdbool.h>
55 #include <stdio.h>
56 /*---------------------------------------------------------------------------*/
57 #define DEBUG 0
58 #if DEBUG
59 #define PRINTF(...) printf(__VA_ARGS__)
60 #else
61 #define PRINTF(...)
62 #endif
63 /*---------------------------------------------------------------------------*/
64 /*
65  * Disable the entire file if sensors are disabled, as it could potentially
66  * create compile errors with missing defines from either the Board file or
67  * configuration defines.
68  */
69 #if BOARD_SENSORS_ENABLE
70 /*---------------------------------------------------------------------------*/
71 #ifndef Board_HDC1000_ADDR
72 #error "Board file doesn't define the I2C address Board_HDC1000_ADDR"
73 #endif
74 /* Sensor I2C address */
75 #define HDC1000_I2C_ADDRESS Board_HDC1000_ADDR
76 /*---------------------------------------------------------------------------*/
77 /* Registers */
78 #define HDC1000_REG_TEMP 0x00 /* Temperature */
79 #define HDC1000_REG_HUM 0x01 /* Humidity */
80 #define HDC1000_REG_CONFIG 0x02 /* Configuration */
81 
82 #if CONTIKI_BOARD_SENSORTAG_CC1352R1
83 #define HDC2080_REG_CONFIG 0x0e /* Configuration for HDC 2080 */
84 #define HDC2080_MEA_CONFIG 0x0f /* Measure Configuration for HDC 2080 */
85 #endif
86 
87 #define HDC1000_REG_SERID_H 0xFB /* Serial ID high */
88 #define HDC1000_REG_SERID_M 0xFC /* Serial ID middle */
89 #define HDC1000_REG_SERID_L 0xFD /* Serial ID low */
90 #define HDC1000_REG_MANF_ID 0xFE /* Manufacturer ID */
91 #define HDC1000_REG_DEV_ID 0xFF /* Device ID */
92 /*---------------------------------------------------------------------------*/
93 /* Fixed values */
94 #define HDC1000_VAL_MANF_ID 0x5449
95 #define HDC1000_VAL_DEV_ID 0x1000
96 #define HDC1000_VAL_CONFIG 0x1000 /* 14 bit, acquired in sequence */
97 /*---------------------------------------------------------------------------*/
98 /* Byte swap of 16-bit register value */
99 #define HI_UINT16(a) (((a) >> 8) & 0xFF)
100 #define LO_UINT16(a) ((a) & 0xFF)
101 
102 #define SWAP16(v) ((LO_UINT16(v) << 8) | HI_UINT16(v))
103 
104 #define LSB16(v) (HI_UINT16(v)), (LO_UINT16(v))
105 /*---------------------------------------------------------------------------*/
106 static I2C_Handle i2c_handle;
107 /*---------------------------------------------------------------------------*/
108 /* Raw data as returned from the sensor (Big Endian) */
109 #if CONTIKI_BOARD_SENSORTAG_CC1352R1
110 typedef struct {
111  uint8_t temp_low;
112  uint8_t temp_high;
113  uint8_t hum_low;
114  uint8_t hum_high;
115 } HDC_1000_SensorData;
116 #else
117 typedef struct {
118  uint16_t temp;
119  uint16_t hum;
120 } HDC_1000_SensorData;
121 #endif
122 
123 static HDC_1000_SensorData sensor_data;
124 /*---------------------------------------------------------------------------*/
125 static volatile HDC_1000_SENSOR_STATUS sensor_status = HDC_1000_SENSOR_STATUS_DISABLED;
126 /*---------------------------------------------------------------------------*/
127 /*
128  * Maximum measurement durations in clock ticks. We use 14bit resolution, thus:
129  * - Tmp: 6.35ms
130  * - RH: 6.5ms
131  */
132 #define MEASUREMENT_DURATION 2
133 
134 /*
135  * Wait SENSOR_STARTUP_DELAY clock ticks between activation and triggering a
136  * reading (max 15ms)
137  */
138 #define SENSOR_STARTUP_DELAY 3
139 
140 static struct ctimer startup_timer;
141 /*---------------------------------------------------------------------------*/
142 /**
143  * \brief Initialize the HDC-1000 sensor driver.
144  * \return true if I2C operation successful; else, return false.
145  */
146 static bool
148 {
149  bool rv;
150 
151  i2c_handle = i2c_arch_acquire(Board_I2C0);
152 
153  if(!i2c_handle) {
154  return false;
155  }
156 
157  /* Enable reading data in one operation */
158 #if CONTIKI_BOARD_SENSORTAG_CC1352R1
159  /* From TI HDC 2080 Programming PDF */
160  uint8_t config_data[] = { HDC2080_REG_CONFIG, 0x00 };
161 #else
162  uint8_t config_data[] = { HDC1000_REG_CONFIG, LSB16(HDC1000_VAL_CONFIG) };
163 #endif
164 
165  rv = i2c_arch_write(i2c_handle, HDC1000_I2C_ADDRESS, config_data,
166  sizeof(config_data));
167 
168  i2c_arch_release(i2c_handle);
169 
170  return rv;
171 }
172 /*---------------------------------------------------------------------------*/
173 /**
174  * \brief Start measurement.
175  * \return true if I2C operation successful; else, return false.
176  */
177 static bool
178 start(void)
179 {
180  bool rv;
181 #if CONTIKI_BOARD_SENSORTAG_CC1352R1
182  uint8_t temp_reg[] = { HDC2080_MEA_CONFIG, 0x01 };
183 #else
184  uint8_t temp_reg[] = { HDC1000_REG_TEMP };
185 #endif
186 
187  i2c_handle = i2c_arch_acquire(Board_I2C0);
188 
189  if(!i2c_handle) {
190  return false;
191  }
192 
193  rv = i2c_arch_write(i2c_handle, HDC1000_I2C_ADDRESS, temp_reg,
194  sizeof(temp_reg));
195 
196  i2c_arch_release(i2c_handle);
197 
198  return rv;
199 }
200 /*---------------------------------------------------------------------------*/
201 /**
202  * \brief Convert raw data to temperature and humidity.
203  * \param temp Output variable to store converted temperature.
204  * \param hum Output variable to store converted humidity.
205  */
206 static void
207 convert(int32_t *temp, int32_t *hum)
208 {
209 #if CONTIKI_BOARD_SENSORTAG_CC1352R1
210  int32_t raw_temp = sensor_data.temp_high * 256 + sensor_data.temp_low;
211  int32_t raw_hum = sensor_data.hum_high * 256 + sensor_data.hum_low;
212 #else
213  int32_t raw_temp = SWAP16(sensor_data.temp);
214  int32_t raw_hum = SWAP16(sensor_data.hum);
215 #endif
216 
217  /* Convert temperature to degrees C */
218  *temp = (raw_temp * 100 * 165) / 65536 - 4000;
219  /* Convert relative humidity to a %RH value */
220  *hum = (raw_hum * 100 * 100) / 65536;
221 }
222 /*---------------------------------------------------------------------------*/
223 /**
224  * \brief Callback when sensor is ready to read data from.
225  */
226 static void
227 notify_ready(void *unused)
228 {
229  /* Unused args */
230  (void)unused;
231 
232  i2c_handle = i2c_arch_acquire(Board_I2C0);
233 
234  if(!i2c_handle) {
235  return;
236  }
237 
238  /* Latch readings */
239 #if CONTIKI_BOARD_SENSORTAG_CC1352R1
240  uint8_t temp_reg[] = { HDC1000_REG_TEMP };
241  if(i2c_arch_write_read(i2c_handle, HDC1000_I2C_ADDRESS, temp_reg,
242  sizeof(temp_reg), &sensor_data, sizeof(sensor_data))) {
243 #else
244  if(i2c_arch_read(i2c_handle, HDC1000_I2C_ADDRESS, &sensor_data,
245  sizeof(sensor_data))) {
246 #endif
248  } else {
249  sensor_status = HDC_1000_SENSOR_STATUS_I2C_ERROR;
250  }
251 
252  i2c_arch_release(i2c_handle);
253 
254  sensors_changed(&hdc_1000_sensor);
255 }
256 /*---------------------------------------------------------------------------*/
257 /**
258  * \brief Returns a reading from the sensor.
259  * \param type HDC_1000_SENSOR_TYPE_TEMP or HDC_1000_SENSOR_TYPE_HUMID.
260  * \return Temperature (centi degrees C) or Humidity (centi %RH).
261  */
262 static int
263 value(int type)
264 {
265  int32_t temp = 0;
266  int32_t hum = 0;
267 
268  if(sensor_status != HDC_1000_SENSOR_STATUS_READINGS_READY) {
269  PRINTF("Sensor disabled or starting up (%d)\n", sensor_status);
270  return HDC_1000_READING_ERROR;
271  }
272 
273  switch(type) {
274  case HDC_1000_SENSOR_TYPE_TEMP:
275  case HDC_1000_SENSOR_TYPE_HUMID:
276  convert(&temp, &hum);
277  PRINTF("HDC: t=%d h=%d\n", (int)temp, (int)hum);
278 
279  if(type == HDC_1000_SENSOR_TYPE_TEMP) {
280  return (int)temp;
281  } else if(type == HDC_1000_SENSOR_TYPE_HUMID) {
282  return (int)hum;
283  } else {
284  return HDC_1000_READING_ERROR;
285  }
286 
287  default:
288  PRINTF("Invalid type\n");
289  return HDC_1000_READING_ERROR;
290  }
291 }
292 /*---------------------------------------------------------------------------*/
293 /**
294  * \brief Configuration function for the HDC1000 sensor.
295  * \param type Activate, enable or disable the sensor. See below.
296  * \param enable Either enable or disable the sensor.
297  * When type == SENSORS_HW_INIT we turn on the hardware.
298  * When type == SENSORS_ACTIVE and enable==1 we enable the sensor.
299  * When type == SENSORS_ACTIVE and enable==0 we disable the sensor.
300  */
301 static int
302 configure(int type, int enable)
303 {
304  switch(type) {
305  case SENSORS_HW_INIT:
306  memset(&sensor_data, 0, sizeof(sensor_data));
307 
308  if(sensor_init()) {
309  sensor_status = HDC_1000_SENSOR_STATUS_INITIALISED;
310  } else {
311  sensor_status = HDC_1000_SENSOR_STATUS_I2C_ERROR;
312  }
313  break;
314 
315  case SENSORS_ACTIVE:
316  /* Must be initialised first */
317  if(sensor_status == HDC_1000_SENSOR_STATUS_DISABLED) {
318  break;
319  }
320 
321  if(enable) {
322  if(!start()) {
323  sensor_status = HDC_1000_SENSOR_STATUS_I2C_ERROR;
324  break;
325  }
326  ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL);
328  } else {
329  ctimer_stop(&startup_timer);
330  sensor_status = HDC_1000_SENSOR_STATUS_INITIALISED;
331  }
332  break;
333 
334  default:
335  break;
336  }
337  return sensor_status;
338 }
339 /*---------------------------------------------------------------------------*/
340 /**
341  * \brief Returns the status of the sensor.
342  * \param type SENSORS_ACTIVE or SENSORS_READY.
343  * \return One of the SENSOR_STATUS_xyz defines.
344  */
345 static int
346 status(int type)
347 {
348  switch(type) {
349  case SENSORS_ACTIVE:
350  case SENSORS_READY:
351  return sensor_status;
352 
353  default:
355  }
356 }
357 /*---------------------------------------------------------------------------*/
358 SENSORS_SENSOR(hdc_1000_sensor, "HDC1000", value, configure, status);
359 /*---------------------------------------------------------------------------*/
360 #endif /* BOARD_SENSORS_ENABLE */
361 /*---------------------------------------------------------------------------*/
362 /** @} */
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149
static bool start(void)
Start measurement.
static int configure(int type, int enable)
Configuration function for the HDC1000 sensor.
Implementation of the I2C HAL driver for CC13xx/CC26xx.
bool i2c_arch_write_read(I2C_Handle i2c_handle, uint_least8_t slave_addr, void *wbuf, size_t wcount, void *rbuf, size_t rcount)
Setup and peform an I2C transaction.
Definition: i2c-arch.c:53
static bool i2c_arch_write(I2C_Handle i2c_handle, uint_least8_t slave_addr, void *wbuf, size_t wcount)
Perform a write-only I2C transaction.
Definition: i2c-arch.h:128
static int status(int type)
Returns the status of the sensor.
Header file for the callback timer
void i2c_arch_release(I2C_Handle i2c_handle)
Release the I2C Peripheral for other modules to use.
Definition: i2c-arch.c:74
static void convert(int32_t *temp, int32_t *hum)
Convert raw data to temperature and humidity.
I2C_Handle i2c_arch_acquire(uint_least8_t index)
Open and lock the I2C Peripheral for use.
Definition: i2c-arch.c:84
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
I2C transaction failed.
static int value(int type)
Returns a reading from the sensor.
static bool i2c_arch_read(I2C_Handle i2c_handle, uint_least8_t slave_addr, void *rbuf, size_t rcount)
Perform a read-only I2C transaction.
Definition: i2c-arch.h:144
static bool sensor_init(void)
Initialize the HDC-1000 sensor driver.
static void notify_ready(void *unused)
Callback when sensor is ready to read data from.
Header file with definitions related to the sensors on the Sensortags.
HDC_1000_SENSOR_STATUS