ChibiOS-Contrib/os/various/devices_lib/sensors/hdc1000/hdc1000.c

256 lines
6.7 KiB
C
Raw Normal View History

2016-02-07 07:48:22 -08:00
/*
HDC1008 for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu
*/
/**
* @file HDC1000.c
* @brief HDC1000 interface module code.
*
* @addtogroup hdc1000
* @{
*/
#define I2C_HELPERS_AUTOMATIC_DRV TRUE
#include "hal.h"
#include "i2c_helpers.h"
#include "hdc1000.h"
/* DOC: http://www.ti.com/lit/ds/symlink/hdc1008.pdf
*/
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/* I2C Register */
#define HDC1000_REG_TEMP_HUMID 0x00
#define HDC1000_REG_TEMP 0x00
#define HDC1000_REG_HUMID 0x01
#define HDC1000_REG_CONFIG 0x02
#define HDC1000_REG_SERIAL 0xFB
#define HDC1000_REG_SERIAL_1 0xFB
#define HDC1000_REG_SERIAL_2 0xFC
#define HDC1000_REG_SERIAL_3 0xFD
#define HDC1000_REG_MANUF_ID 0xFE
#define HDC1000_REG_DEVICE_ID 0xFF
/* Configuration */
#define HDC1000_CONFIG_RST (1 << 15)
#define HDC1000_CONFIG_HEATER (1 << 13)
#define HDC1000_CONFIG_MODE_ONE (0 << 12)
#define HDC1000_CONFIG_MODE_BOTH (1 << 12)
#define HDC1000_CONFIG_BATT (1 << 11)
#define HDC1000_CONFIG_TRES_14 (0)
#define HDC1000_CONFIG_TRES_11 (1 << 10)
#define HDC1000_CONFIG_HRES_14 (0)
#define HDC1000_CONFIG_HRES_11 (1 << 8)
#define HDC1000_CONFIG_HRES_8 (1 << 9)
/* Value */
#define HDC1000_MANUF_ID 0x5449
#define HDC1000_DEVICE_ID 0x1000
/* Delay in micro seconds */
#define HDC1000_DELAY_ACQUIRE_SAFETY 1000
#define HDC1000_DELAY_ACQUIRE_TRES_14 6350
#define HDC1000_DELAY_ACQUIRE_TRES_11 3650
#define HDC1000_DELAY_ACQUIRE_HRES_14 6500
#define HDC1000_DELAY_ACQUIRE_HRES_11 3850
#define HDC1000_DELAY_ACQUIRE_HRES_8 2500
#define HDC1000_DELAY_STARTUP 15000
// Deefault config (high res)
#define HDC1000_CONFIG_RES (HDC1000_CONFIG_TRES_14 | \
HDC1000_CONFIG_HRES_14)
#define HDC1000_DELAY_ACQUIRE (HDC1000_DELAY_ACQUIRE_TRES_14 + \
HDC1000_DELAY_ACQUIRE_HRES_14)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
inline msg_t
_apply_config(HDC1000_drv *drv) {
struct __attribute__((packed)) {
uint8_t reg;
uint16_t conf;
} tx = { HDC1000_REG_CONFIG, cpu_to_be16(drv->cfg) };
return i2c_send((uint8_t*)&tx, sizeof(tx));
}
inline msg_t
_decode_measure(HDC1000_drv *drv,
uint32_t val, float *temperature, float *humidity) {
(void)drv;
/* Temperature */
if (temperature) {
float temp = (val >> 16);
temp /= 65536;
temp *= 165;
temp -= 40;
*temperature = temp;
}
/* Humidiy */
if (humidity) {
float hum = (val & 0xFFFF);
hum /= 65535;
hum *= 100;
*humidity = hum;
}
return MSG_OK;
}
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
void
HDC1000_init(HDC1000_drv *drv, HDC1000_config *config) {
drv->config = config;
drv->cfg = HDC1000_CONFIG_RST | HDC1000_CONFIG_MODE_BOTH |
HDC1000_CONFIG_RES;
drv->delay = (HDC1000_DELAY_ACQUIRE +
HDC1000_DELAY_ACQUIRE_SAFETY) / 1000;
drv->state = HDC1000_INIT;
}
msg_t
HDC1000_check(HDC1000_drv *drv) {
msg_t msg = -10;
uint16_t val;
if ((msg = i2c_reg_recv16_be(HDC1000_REG_MANUF_ID, &val)) < MSG_OK)
return msg;
if (val != HDC1000_MANUF_ID)
return -2;
if ((msg = i2c_reg_recv16_be(HDC1000_REG_DEVICE_ID, &val)) < MSG_OK)
return msg;
if (val != HDC1000_DEVICE_ID)
return -2;
return MSG_OK;
}
msg_t
HDC1000_start(HDC1000_drv *drv) {
osalDbgAssert((drv->state == HDC1000_INIT ) ||
(drv->state == HDC1000_ERROR ) ||
(drv->state == HDC1000_STOPPED),
"invalid state");
msg_t msg;
if ((msg = _apply_config(drv)) < MSG_OK) {
drv->state = HDC1000_ERROR;
return msg;
}
drv->state = HDC1000_STARTED;
return MSG_OK;
}
msg_t
HDC1000_stop(HDC1000_drv *drv) {
drv->state = HDC1000_STOPPED;
return MSG_OK;
}
msg_t
HDC1000_setHeater(HDC1000_drv *drv, bool on) {
if (on) { drv->cfg |= HDC1000_CONFIG_HEATER; }
else { drv->cfg &= ~HDC1000_CONFIG_HEATER; }
msg_t msg;
if ((msg = _apply_config(drv)) < MSG_OK) {
drv->state = HDC1000_ERROR;
return msg;
}
return MSG_OK;
}
msg_t
HDC1000_startMeasure(HDC1000_drv *drv) {
msg_t msg;
osalDbgAssert(drv->state == HDC1000_STARTED, "invalid state");
if ((msg = i2c_reg(HDC1000_REG_TEMP_HUMID)) < MSG_OK)
return msg;
drv->state = HDC1000_MEASURING;
return MSG_OK;
}
msg_t
HDC1000_readSerial(HDC1000_drv *drv, uint8_t *serial) {
msg_t msg;
osalDbgAssert(drv->state == HDC1000_STARTED, "invalid state");
if (((msg = i2c_reg_recv16(HDC1000_REG_SERIAL_1,
(uint16_t*)&serial[0])) < MSG_OK) ||
((msg = i2c_reg_recv16(HDC1000_REG_SERIAL_2,
(uint16_t*)&serial[2])) < MSG_OK) ||
((msg = i2c_reg_recv8 (HDC1000_REG_SERIAL_3,
(uint8_t*) &serial[4])) < MSG_OK))
return msg;
return MSG_OK;
}
msg_t
HDC1000_readMeasure(HDC1000_drv *drv,
float *temperature, float *humidity) {
msg_t msg;
uint32_t val;
osalDbgAssert((drv->state == HDC1000_MEASURING) ||
(drv->state == HDC1000_READY ),
"invalid state");
if ((msg = i2c_recv32_be(&val)) < MSG_OK) {
drv->state = HDC1000_ERROR;
return msg;
}
drv->state = HDC1000_STARTED;
return _decode_measure(drv, val, temperature, humidity);
}
msg_t
HDC1000_readTemperatureHumidity(HDC1000_drv *drv,
float *temperature, float *humidity) {
msg_t msg;
uint32_t val;
osalDbgAssert(drv->state == HDC1000_STARTED, "invalid state");
/* Request value */
if ((msg = i2c_reg(HDC1000_REG_TEMP_HUMID)) < MSG_OK)
return msg;
/* Wait */
osalThreadSleepMilliseconds(drv->delay);
/* Get value */
if ((msg = i2c_recv32_be(&val)) < MSG_OK) {
drv->state = HDC1000_ERROR;
return msg;
}
return _decode_measure(drv, val, temperature, humidity);
}
/** @} */