hdc1008 sensor
This commit is contained in:
parent
5af8452153
commit
ee5bea89c2
|
@ -0,0 +1,138 @@
|
|||
#ifndef BSWAP_H
|
||||
#define BSWAP_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !(defined(ARCH_BIG_ENDIAN) || defined(ARCH_LITTLE_ENDIAN))
|
||||
#if YOTTA_CFG_CONFIG_ARCH_LITTLE_ENDIAN
|
||||
#define ARCH_LITTLE_ENDIAN
|
||||
#endif
|
||||
#if YOTTA_CFG_CONFIG_ARCH_BIG_ENDIAN
|
||||
#define ARCH_BIG_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !(defined(ARCH_BIG_ENDIAN) || defined(ARCH_LITTLE_ENDIAN))
|
||||
#error "ARCH_BIG_ENDIAN or ARCH_LITTLE_ENDIAN not set."
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_BIG_ENDIAN) && defined(ARCH_LITTLE_ENDIAN)
|
||||
#error "ARCH_BIG_ENDIAN and ARCH_LITTLE_ENDIAN are both set."
|
||||
#endif
|
||||
|
||||
|
||||
#define BSWAP_16(x) \
|
||||
(uint16_t)((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8))
|
||||
#define BSWAP_32(x) \
|
||||
(uint32_t)((((x) & 0xFF000000UL) >> 24UL) | \
|
||||
(((x) & 0x00FF0000UL) >> 8UL) | \
|
||||
(((x) & 0x0000FF00UL) << 8UL) | \
|
||||
(((x) & 0x000000FFUL) << 24UL))
|
||||
|
||||
|
||||
#if defined(ARCH_BIG_ENDIAN)
|
||||
#define le16_to_cpu(x) bswap_16(x)
|
||||
#define le32_to_cpu(x) bswap_32(x)
|
||||
#define be16_to_cpu(x) (x)
|
||||
#define be32_to_cpu(x) (x)
|
||||
#define cpu_to_le16(x) bswap_16(x)
|
||||
#define cpu_to_le32(x) bswap_32(x)
|
||||
#define cpu_to_be16(x) (x)
|
||||
#define cpu_to_be32(x) (x)
|
||||
#define LE16_TO_CPU(x) BSWAP_16(x)
|
||||
#define LE32_TO_CPU(x) BSWAP_32(x)
|
||||
#define BE16_TO_CPU(x) (x)
|
||||
#define BE32_TO_CPU(x) (x)
|
||||
#define CPU_TO_LE16(x) BSWAP_16(x)
|
||||
#define CPU_TO_LE32(x) BSWAP_32(x)
|
||||
#define CPU_TO_BE16(x) (x)
|
||||
#define CPU_TO_BE32(x) (x)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(ARCH_LITTLE_ENDIAN)
|
||||
#define le16_to_cpu(x) (x)
|
||||
#define le32_to_cpu(x) (x)
|
||||
#define be16_to_cpu(x) bswap_16(x)
|
||||
#define be32_to_cpu(x) bswap_32(x)
|
||||
#define cpu_to_le16(x) (x)
|
||||
#define cpu_to_le32(x) (x)
|
||||
#define cpu_to_be16(x) bswap_16(x)
|
||||
#define cpu_to_be32(x) bswap_32(x)
|
||||
#define LE16_TO_CPU(x) (x)
|
||||
#define LE32_TO_CPU(x) (x)
|
||||
#define BE16_TO_CPU(x) BSWAP_16(x)
|
||||
#define BE32_TO_CPU(x) BSWAP_32(x)
|
||||
#define CPU_TO_LE16(x) (x)
|
||||
#define CPU_TO_LE32(x) (x)
|
||||
#define CPU_TO_BE16(x) BSWAP_16(x)
|
||||
#define CPU_TO_BE32(x) BSWAP_32(x)
|
||||
#endif
|
||||
|
||||
|
||||
static inline uint16_t bswap_16(const uint16_t x)
|
||||
__attribute__ ((warn_unused_result))
|
||||
__attribute__ ((const))
|
||||
__attribute__ ((always_inline));
|
||||
|
||||
static inline uint16_t bswap_16(const uint16_t x) {
|
||||
if (__builtin_constant_p(x))
|
||||
return BSWAP_16(x);
|
||||
|
||||
uint8_t tmp;
|
||||
union { uint16_t x; uint8_t b[2]; } data;
|
||||
|
||||
data.x = x;
|
||||
tmp = data.b[0];
|
||||
data.b[0] = data.b[1];
|
||||
data.b[1] = tmp;
|
||||
|
||||
return data.x;
|
||||
}
|
||||
|
||||
static inline uint32_t bswap_32(const uint32_t x)
|
||||
__attribute__ ((warn_unused_result))
|
||||
__attribute__ ((const))
|
||||
__attribute__ ((always_inline));
|
||||
|
||||
|
||||
static inline uint32_t bswap_32(const uint32_t x) {
|
||||
if (__builtin_constant_p(x))
|
||||
return BSWAP_32(x);
|
||||
|
||||
uint8_t tmp;
|
||||
union { uint32_t x; uint8_t b[4]; } data;
|
||||
|
||||
data.x = x;
|
||||
tmp = data.b[0];
|
||||
data.b[0] = data.b[3];
|
||||
data.b[3] = tmp;
|
||||
tmp = data.b[1];
|
||||
data.b[1] = data.b[2];
|
||||
data.b[2] = tmp;
|
||||
|
||||
return data.x;
|
||||
}
|
||||
|
||||
static inline void bswap_n(void* const data, uint8_t len)
|
||||
__attribute__ ((nonnull (1)));
|
||||
|
||||
static inline void bswap_n(void* const data, uint8_t len) {
|
||||
uint8_t* ptr = (uint8_t*)data;
|
||||
|
||||
for ( ; len > 1 ; ptr++, len -= 2 ) {
|
||||
uint8_t tmp = *ptr;
|
||||
*ptr = *(ptr + len - 1);
|
||||
*(ptr + len - 1) = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
#ifndef BSWAP_H
|
||||
#define BSWAP_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !(defined(ARCH_BIG_ENDIAN) || defined(ARCH_LITTLE_ENDIAN))
|
||||
#if YOTTA_CFG_CONFIG_ARCH_LITTLE_ENDIAN
|
||||
#define ARCH_LITTLE_ENDIAN
|
||||
#endif
|
||||
#if YOTTA_CFG_CONFIG_ARCH_BIG_ENDIAN
|
||||
#define ARCH_BIG_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !(defined(ARCH_BIG_ENDIAN) || defined(ARCH_LITTLE_ENDIAN))
|
||||
#error "ARCH_BIG_ENDIAN or ARCH_LITTLE_ENDIAN not set."
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_BIG_ENDIAN) && defined(ARCH_LITTLE_ENDIAN)
|
||||
#error "ARCH_BIG_ENDIAN and ARCH_LITTLE_ENDIAN are both set."
|
||||
#endif
|
||||
|
||||
|
||||
#define BSWAP_16(x) \
|
||||
(uint16_t)((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8))
|
||||
#define BSWAP_32(x) \
|
||||
(uint32_t)((((x) & 0xFF000000UL) >> 24UL) | \
|
||||
(((x) & 0x00FF0000UL) >> 8UL) | \
|
||||
(((x) & 0x0000FF00UL) << 8UL) | \
|
||||
(((x) & 0x000000FFUL) << 24UL))
|
||||
|
||||
|
||||
#if defined(ARCH_BIG_ENDIAN)
|
||||
#define le16_to_cpu(x) bswap_16(x)
|
||||
#define le32_to_cpu(x) bswap_32(x)
|
||||
#define be16_to_cpu(x) (x)
|
||||
#define be32_to_cpu(x) (x)
|
||||
#define cpu_to_le16(x) bswap_16(x)
|
||||
#define cpu_to_le32(x) bswap_32(x)
|
||||
#define cpu_to_be16(x) (x)
|
||||
#define cpu_to_be32(x) (x)
|
||||
#define LE16_TO_CPU(x) BSWAP_16(x)
|
||||
#define LE32_TO_CPU(x) BSWAP_32(x)
|
||||
#define BE16_TO_CPU(x) (x)
|
||||
#define BE32_TO_CPU(x) (x)
|
||||
#define CPU_TO_LE16(x) BSWAP_16(x)
|
||||
#define CPU_TO_LE32(x) BSWAP_32(x)
|
||||
#define CPU_TO_BE16(x) (x)
|
||||
#define CPU_TO_BE32(x) (x)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(ARCH_LITTLE_ENDIAN)
|
||||
#define le16_to_cpu(x) (x)
|
||||
#define le32_to_cpu(x) (x)
|
||||
#define be16_to_cpu(x) bswap_16(x)
|
||||
#define be32_to_cpu(x) bswap_32(x)
|
||||
#define cpu_to_le16(x) (x)
|
||||
#define cpu_to_le32(x) (x)
|
||||
#define cpu_to_be16(x) bswap_16(x)
|
||||
#define cpu_to_be32(x) bswap_32(x)
|
||||
#define LE16_TO_CPU(x) (x)
|
||||
#define LE32_TO_CPU(x) (x)
|
||||
#define BE16_TO_CPU(x) BSWAP_16(x)
|
||||
#define BE32_TO_CPU(x) BSWAP_32(x)
|
||||
#define CPU_TO_LE16(x) (x)
|
||||
#define CPU_TO_LE32(x) (x)
|
||||
#define CPU_TO_BE16(x) BSWAP_16(x)
|
||||
#define CPU_TO_BE32(x) BSWAP_32(x)
|
||||
#endif
|
||||
|
||||
|
||||
static inline uint16_t bswap_16(const uint16_t x)
|
||||
__attribute__ ((warn_unused_result))
|
||||
__attribute__ ((const))
|
||||
__attribute__ ((always_inline));
|
||||
|
||||
static inline uint16_t bswap_16(const uint16_t x) {
|
||||
if (__builtin_constant_p(x))
|
||||
return BSWAP_16(x);
|
||||
|
||||
uint8_t tmp;
|
||||
union { uint16_t x; uint8_t b[2]; } data;
|
||||
|
||||
data.x = x;
|
||||
tmp = data.b[0];
|
||||
data.b[0] = data.b[1];
|
||||
data.b[1] = tmp;
|
||||
|
||||
return data.x;
|
||||
}
|
||||
|
||||
static inline uint32_t bswap_32(const uint32_t x)
|
||||
__attribute__ ((warn_unused_result))
|
||||
__attribute__ ((const))
|
||||
__attribute__ ((always_inline));
|
||||
|
||||
|
||||
static inline uint32_t bswap_32(const uint32_t x) {
|
||||
if (__builtin_constant_p(x))
|
||||
return BSWAP_32(x);
|
||||
|
||||
uint8_t tmp;
|
||||
union { uint32_t x; uint8_t b[4]; } data;
|
||||
|
||||
data.x = x;
|
||||
tmp = data.b[0];
|
||||
data.b[0] = data.b[3];
|
||||
data.b[3] = tmp;
|
||||
tmp = data.b[1];
|
||||
data.b[1] = data.b[2];
|
||||
data.b[2] = tmp;
|
||||
|
||||
return data.x;
|
||||
}
|
||||
|
||||
static inline void bswap_n(void* const data, uint8_t len)
|
||||
__attribute__ ((nonnull (1)));
|
||||
|
||||
static inline void bswap_n(void* const data, uint8_t len) {
|
||||
uint8_t* ptr = (uint8_t*)data;
|
||||
|
||||
for ( ; len > 1 ; ptr++, len -= 2 ) {
|
||||
uint8_t tmp = *ptr;
|
||||
*ptr = *(ptr + len - 1);
|
||||
*(ptr + len - 1) = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
HDC1000 for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hdc1000.h
|
||||
* @brief HDC1000 Temperature/Humidiry sensor interface module header.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _SENSOR_HDC1000_H_
|
||||
#define _SENSOR_HDC1000_H_
|
||||
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include "i2c_helpers.h"
|
||||
|
||||
// I2C address
|
||||
#define HDC1000_I2CADDR_1 0x40
|
||||
#define HDC1000_I2CADDR_2 0x41
|
||||
#define HDC1000_I2CADDR_3 0x42
|
||||
#define HDC1000_I2CADDR_4 0x43
|
||||
|
||||
#ifndef HDC1000_I2CADDR
|
||||
#define HDC1000_I2CADDR HDC1000_I2CADDR_1
|
||||
#endif
|
||||
|
||||
// Size of serial (40 bits)
|
||||
#define HDC1000_SERIAL_SIZE 5
|
||||
|
||||
#define HDC1000_CONTINUOUS_ACQUISITION_SUPPORTED FALSE
|
||||
|
||||
|
||||
/**
|
||||
* When changing sensor settings, you generally need to wait
|
||||
* for 2 * getAquisitionTime(), as usually the first acquisition
|
||||
* will be corrupted by the change of settings.
|
||||
*
|
||||
* No locking is done.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief HDC1000 configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
I2CHelper i2c; /* keep it first */
|
||||
} HDC1000_config;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Driver state machine possible states.
|
||||
*/
|
||||
typedef enum __attribute__ ((__packed__)) {
|
||||
HDC1000_UNINIT = 0, /**< Not initialized. */
|
||||
HDC1000_INIT = 1, /**< Initialized. */
|
||||
HDC1000_STARTED = 2, /**< Started. */
|
||||
HDC1000_MEASURING = 4, /**< Measuring. */
|
||||
HDC1000_READY = 3, /**< Ready. */
|
||||
HDC1000_STOPPED = 5, /**< Stopped. */
|
||||
HDC1000_ERROR = 6, /**< Error. */
|
||||
} HDC1000_state_t;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief HDC1000 configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
HDC1000_config *config;
|
||||
HDC1000_state_t state;
|
||||
unsigned int delay;
|
||||
uint16_t cfg;
|
||||
} HDC1000_drv;
|
||||
|
||||
/**
|
||||
* @brief Initialize the sensor driver
|
||||
*/
|
||||
void
|
||||
HDC1000_init(HDC1000_drv *drv,
|
||||
HDC1000_config *config);
|
||||
|
||||
/**
|
||||
* @brief Start the sensor
|
||||
*/
|
||||
msg_t
|
||||
HDC1000_start(HDC1000_drv *drv);
|
||||
|
||||
/**
|
||||
* @brief Stop the sensor
|
||||
*
|
||||
* @details If the sensor support it, it will be put in low energy mode.
|
||||
*/
|
||||
msg_t
|
||||
HDC1000_stop(HDC1000_drv *drv);
|
||||
|
||||
/**
|
||||
* @brief Check that the sensor is really present
|
||||
*/
|
||||
msg_t
|
||||
HDC1000_check(HDC1000_drv *drv);
|
||||
|
||||
|
||||
msg_t
|
||||
HDC1000_readSerial(HDC1000_drv *drv, uint8_t *serial);
|
||||
|
||||
/**
|
||||
* @brief Control the HD1000 heater.
|
||||
*/
|
||||
msg_t
|
||||
HDC1000_setHeater(HDC1000_drv *drv,
|
||||
bool on);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Time necessary for the sensor to boot
|
||||
*
|
||||
* @returns
|
||||
* unsigned int time in millis-seconds
|
||||
*/
|
||||
|
||||
static inline unsigned int
|
||||
HDC1000_getBootupTime(HDC1000_drv *drv) {
|
||||
(void)drv;
|
||||
return 15;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Time necessary the sensor to for starting
|
||||
*
|
||||
* @returns
|
||||
* unsigned int time in millis-seconds
|
||||
*/
|
||||
static inline unsigned int
|
||||
HDC1000_getStartupTime(HDC1000_drv *drv) {
|
||||
(void)drv;
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Time in milli-seconds necessary for acquiring a naw measure
|
||||
*
|
||||
* @returns
|
||||
* unsigned int time in millis-seconds
|
||||
*/
|
||||
static inline unsigned int
|
||||
HDC1000_getAcquisitionTime(HDC1000_drv *drv) {
|
||||
return drv->delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Trigger a mesure acquisition
|
||||
*/
|
||||
msg_t
|
||||
HDC1000_startMeasure(HDC1000_drv *drv);
|
||||
|
||||
/**
|
||||
* @brief Read the newly acquiered measure
|
||||
*
|
||||
* @note According the the sensor design the measure read
|
||||
* can be any value acquired after the acquisition time
|
||||
* and the call to readMeasure.
|
||||
*/
|
||||
msg_t
|
||||
HDC1000_readMeasure(HDC1000_drv *drv,
|
||||
float *temperature, float *humidity);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read temperature and humidity
|
||||
*
|
||||
* @details According to the sensor specification/configuration
|
||||
* (see #HDC1000_CONTINUOUS_ACQUISITION_SUPPORTED),
|
||||
* if the sensor is doing continuous measurement
|
||||
* it's value will be requested and returned immediately.
|
||||
* Otherwise a measure is started, the necessary amount of
|
||||
* time for acquiring the value is spend sleeping (not spinning),
|
||||
* and finally the measure is read.
|
||||
*
|
||||
* @note In continuous measurement mode, if you just started
|
||||
* the sensor, you will need to wait getAcquisitionTime()
|
||||
* in addition to the usual getStartupTime()
|
||||
|
||||
* @note If using several sensors, it is better to start all the
|
||||
* measure together, wait for the sensor having the longuest
|
||||
* aquisition time, and finally read all the values
|
||||
*/
|
||||
msg_t
|
||||
HDC1000_readTemperatureHumidity(HDC1000_drv *drv,
|
||||
float *temperature, float *humidity);
|
||||
|
||||
/**
|
||||
* @brief Return the humidity value in percent.
|
||||
*
|
||||
* @details Use readTemperatureHumidity() for returning the humidity value.
|
||||
*
|
||||
* @note Prefere readTemperatureHumidity(), if you need both temperature
|
||||
* and humidity, or if you need better error handling.
|
||||
*
|
||||
* @returns
|
||||
* float humidity percent
|
||||
* NAN on failure
|
||||
*/
|
||||
static inline float
|
||||
HDC1000_getHumidity(HDC1000_drv *drv) {
|
||||
float humidity = NAN;
|
||||
HDC1000_readTemperatureHumidity(drv, NULL, &humidity);
|
||||
return humidity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the temperature value in °C.
|
||||
*
|
||||
* @details Use readTemperatureHumidity() for returning the humidity value.
|
||||
*
|
||||
* @note Prefere readTemperatureHumidity(), if you need both temperature
|
||||
* and humidity, or if you need better error handling.
|
||||
*
|
||||
* @returns
|
||||
* float humidity percent
|
||||
* NAN on failure
|
||||
*/
|
||||
static inline float
|
||||
HDC1000_getTemperature(HDC1000_drv *drv) {
|
||||
float temperature = NAN;
|
||||
HDC1000_readTemperatureHumidity(drv, &temperature, NULL);
|
||||
return temperature;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
#ifndef I2C_HELPERS_H
|
||||
#define I2C_HELPERS_H
|
||||
|
||||
#include "hal.h"
|
||||
#include "bswap.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Pointer to the I2C driver.
|
||||
*/
|
||||
I2CDriver *driver;
|
||||
/**
|
||||
* @brief I2C address.
|
||||
*/
|
||||
i2caddr_t addr;
|
||||
} I2CHelper;
|
||||
|
||||
|
||||
|
||||
#if !defined(I2C_HELPERS_AUTOMATIC_DRV) || (I2C_HELPERS_AUTOMATIC_DRV == FALSE)
|
||||
|
||||
#define i2c_send(i2c, txbuf, txbytes) \
|
||||
_i2c_send(i2c, txbuf, txbytes)
|
||||
#define i2c_transmit(i2c, txbuf, txbytes, rxbuf, rxbytes) \
|
||||
_i2c_transmit(i2c, txbuf, txbytes, rxbuf, rxbytes)
|
||||
#define i2c_receive(i2, rxbuf, rxbytes) \
|
||||
_i2c_receive(i2c, rxbuf, rxbytes)
|
||||
|
||||
#define i2c_send_timeout(i2c, txbuf, txbytes) \
|
||||
_i2c_send(i2c, txbuf, txbytes)
|
||||
#define i2c_transmit_timeout(i2c, txbuf, txbytes, rxbuf, rxbytes) \
|
||||
_i2c_transmit(i2c, txbuf, txbytes, rxbuf, rxbytes)
|
||||
#define i2c_receive_timeout(i2, rxbuf, rxbytes) \
|
||||
_i2c_receive(i2c, rxbuf, rxbytes)
|
||||
|
||||
#define i2c_reg(i2c, reg) \
|
||||
_i2c_reg(i2c, reg)
|
||||
|
||||
#define i2c_reg_recv8(i2c, reg, val) \
|
||||
_i2c_reg_recv8(i2c, reg, val)
|
||||
#define i2c_reg_recv16(i2c, reg, val) \
|
||||
_i2c_reg_recv16(i2c, reg, val)
|
||||
#define i2c_reg_recv16_le(i2c, reg, val) \
|
||||
_i2c_reg_recv16_le(i2c, reg, val)
|
||||
#define i2c_reg_recv16_be(i2c, reg, val) \
|
||||
_i2c_reg_recv16_be(i2c, reg, val)
|
||||
#define i2c_reg_recv32(i2c, reg, val) \
|
||||
_i2c_reg_recv32(i2c, reg, val)
|
||||
#define i2c_reg_recv32_le(i2c, reg, val) \
|
||||
_i2c_reg_recv32_le(i2c, reg, val)
|
||||
#define i2c_reg_recv32_be(i2c, reg, val) \
|
||||
_i2c_reg_recv32_be(i2c, reg, val)
|
||||
|
||||
#define i2c_recv8(i2c, val) \
|
||||
_i2c_recv8(i2c, val)
|
||||
#define i2c_recv16(i2c, val) \
|
||||
_i2c_recv16(i2c, val)
|
||||
#define i2c_recv16_le(i2c, val) \
|
||||
_i2c_recv16_le(i2c, val)
|
||||
#define i2c_recv16_be(i2c, val) \
|
||||
_i2c_recv16_be(i2c, val)
|
||||
#define i2c_recv32(i2c, val) \
|
||||
_i2c_recv32(i2c, val)
|
||||
#define i2c_recv32_le(i2c, val) \
|
||||
_i2c_recv32_le(i2c, val)
|
||||
#define i2c_recv32_be(i2c, val) \
|
||||
_i2c_recv32_be(i2c, val)
|
||||
|
||||
#else
|
||||
|
||||
#define i2c_send(txbuf, txbytes) \
|
||||
_i2c_send(&drv->config->i2c, txbuf, txbytes)
|
||||
#define i2c_transmit(txbuf, txbytes, rxbuf, rxbytes) \
|
||||
_i2c_transmit(&drv->config->i2c, txbuf, txbytes, rxbuf, rxbytes)
|
||||
#define i2c_receive(rxbuf, rxbytes) \
|
||||
_i2c_receive(&drv->config->i2c, rxbuf, rxbytes)
|
||||
|
||||
#define i2c_send_timeout(txbuf, txbytes) \
|
||||
_i2c_send(&drv->config->i2c, txbuf, txbytes)
|
||||
#define i2c_transmit_timeout(txbuf, txbytes, rxbuf, rxbytes) \
|
||||
_i2c_transmit(&drv->config->i2c, txbuf, txbytes, rxbuf, rxbytes)
|
||||
#define i2c_receive_timeout(rxbuf, rxbytes) \
|
||||
_i2c_receive(&drv->config->i2c, rxbuf, rxbytes)
|
||||
|
||||
|
||||
#define i2c_reg(reg) \
|
||||
_i2c_reg(&drv->config->i2c, reg)
|
||||
|
||||
#define i2c_reg_recv8(reg, val) \
|
||||
_i2c_reg_recv8(&drv->config->i2c, reg, val)
|
||||
#define i2c_reg_recv16(reg, val) \
|
||||
_i2c_reg_recv16(&drv->config->i2c, reg, val)
|
||||
#define i2c_reg_recv16_le(reg, val) \
|
||||
_i2c_reg_recv16_le(&drv->config->i2c, reg, val)
|
||||
#define i2c_reg_recv16_be(reg, val) \
|
||||
_i2c_reg_recv16_be(&drv->config->i2c, reg, val)
|
||||
#define i2c_reg_recv32(reg, val) \
|
||||
_i2c_reg_recv32(&drv->config->i2c, reg, val)
|
||||
#define i2c_reg_recv32_le(reg, val) \
|
||||
_i2c_reg_recv32_le(&drv->config->i2c, reg, val)
|
||||
#define i2c_reg_recv32_be(reg, val) \
|
||||
_i2c_reg_recv32_be(&drv->config->i2c, reg, val)
|
||||
|
||||
#define i2c_recv8(val) \
|
||||
_i2c_recv8(&drv->config->i2c, val)
|
||||
#define i2c_recv16(val) \
|
||||
_i2c_recv16(&drv->config->i2c, val)
|
||||
#define i2c_recv16_le(val) \
|
||||
_i2c_recv16_le(&drv->config->i2c, val)
|
||||
#define i2c_recv16_be(val) \
|
||||
_i2c_recv16_be(&drv->config->i2c, val)
|
||||
#define i2c_recv32(val) \
|
||||
_i2c_recv32(&drv->config->i2c, val)
|
||||
#define i2c_recv32_le(val) \
|
||||
_i2c_recv32_le(&drv->config->i2c, val)
|
||||
#define i2c_recv32_be(val) \
|
||||
_i2c_recv32_be(&drv->config->i2c, val)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static inline msg_t
|
||||
_i2c_send(I2CHelper *i2c, const uint8_t *txbuf, size_t txbytes) {
|
||||
return i2cMasterTransmitTimeout(i2c->driver, i2c->addr,
|
||||
txbuf, txbytes, NULL, 0, TIME_INFINITE);
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_transmit(I2CHelper *i2c, const uint8_t *txbuf, size_t txbytes,
|
||||
uint8_t *rxbuf, size_t rxbytes) {
|
||||
return i2cMasterTransmitTimeout(i2c->driver, i2c->addr,
|
||||
txbuf, txbytes, rxbuf, rxbytes, TIME_INFINITE);
|
||||
}
|
||||
|
||||
static inline msg_t
|
||||
_i2c_receive(I2CHelper *i2c, uint8_t *rxbuf, size_t rxbytes) {
|
||||
return i2cMasterReceiveTimeout(i2c->driver, i2c->addr,
|
||||
rxbuf, rxbytes, TIME_INFINITE);
|
||||
};
|
||||
|
||||
|
||||
|
||||
static inline msg_t
|
||||
_i2c_send_timeout(I2CHelper *i2c, const uint8_t *txbuf, size_t txbytes,
|
||||
systime_t timeout) {
|
||||
return i2cMasterTransmitTimeout(i2c->driver, i2c->addr,
|
||||
txbuf, txbytes, NULL, 0, timeout);
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_transmit_timeout(I2CHelper *i2c, const uint8_t *txbuf, size_t txbytes,
|
||||
uint8_t *rxbuf, size_t rxbytes, systime_t timeout) {
|
||||
return i2cMasterTransmitTimeout(i2c->driver, i2c->addr,
|
||||
txbuf, txbytes, rxbuf, rxbytes, timeout);
|
||||
}
|
||||
|
||||
static inline msg_t
|
||||
_i2c_receive_timeout(I2CHelper *i2c, uint8_t *rxbuf, size_t rxbytes, systime_t timeout) {
|
||||
return i2cMasterReceiveTimeout(i2c->driver, i2c->addr,
|
||||
rxbuf, rxbytes, timeout);
|
||||
};
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
|
||||
|
||||
static inline msg_t
|
||||
_i2c_reg(I2CHelper *i2c, uint8_t reg) {
|
||||
return _i2c_transmit(i2c, ®, sizeof(reg), NULL, 0);
|
||||
};
|
||||
|
||||
/*======================================================================*/
|
||||
|
||||
static inline msg_t
|
||||
_i2c_reg_recv8(I2CHelper *i2c, uint8_t reg, uint8_t *val) {
|
||||
return _i2c_transmit(i2c, ®, sizeof(reg), (uint8_t*)val, sizeof(val));
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_reg_recv16(I2CHelper *i2c, uint8_t reg, uint16_t *val) {
|
||||
return _i2c_transmit(i2c, ®, sizeof(reg), (uint8_t*)val, sizeof(val));
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_reg_recv16_le(I2CHelper *i2c, uint8_t reg, uint16_t *val) {
|
||||
int msg = _i2c_reg_recv16(i2c, reg, val);
|
||||
if (msg >= 0) *val = le16_to_cpu(*val);
|
||||
return msg;
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_reg_recv16_be(I2CHelper *i2c, uint8_t reg, uint16_t *val) {
|
||||
int msg = _i2c_reg_recv16(i2c, reg, val);
|
||||
if (msg >= 0) *val = be16_to_cpu(*val);
|
||||
return msg;
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_reg_recv32(I2CHelper *i2c, uint8_t reg, uint32_t *val) {
|
||||
return _i2c_transmit(i2c, ®, sizeof(reg), (uint8_t*)val, sizeof(val));
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_reg_recv32_le(I2CHelper *i2c, uint8_t reg, uint32_t *val) {
|
||||
int msg = _i2c_reg_recv32(i2c, reg, val);
|
||||
if (msg >= 0) *val = le32_to_cpu(*val);
|
||||
return msg;
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_reg_recv32_be(I2CHelper *i2c, uint8_t reg, uint32_t *val) {
|
||||
int msg = _i2c_reg_recv32(i2c, reg, val);
|
||||
if (msg >= 0) *val = be32_to_cpu(*val);
|
||||
return msg;
|
||||
};
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
|
||||
static inline msg_t
|
||||
_i2c_recv8(I2CHelper *i2c, uint8_t *val) {
|
||||
return _i2c_receive(i2c, (uint8_t*)val, sizeof(val));
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_recv16(I2CHelper *i2c, uint16_t *val) {
|
||||
return _i2c_receive(i2c, (uint8_t*)val, sizeof(val));
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_recv16_le(I2CHelper *i2c, uint16_t *val) {
|
||||
int msg = _i2c_recv16(i2c, val);
|
||||
if (msg >= 0) *val = le16_to_cpu(*val);
|
||||
return msg;
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_recv16_be(I2CHelper *i2c, uint16_t *val) {
|
||||
int msg = _i2c_recv16(i2c, val);
|
||||
if (msg >= 0) *val = be16_to_cpu(*val);
|
||||
return msg;
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_recv32(I2CHelper *i2c, uint32_t *val) {
|
||||
return _i2c_receive(i2c, (uint8_t*)val, sizeof(val));
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_recv32_le(I2CHelper *i2c, uint32_t *val) {
|
||||
int msg = _i2c_recv32(i2c, val);
|
||||
if (msg >= 0) *val = le32_to_cpu(*val);
|
||||
return msg;
|
||||
};
|
||||
|
||||
static inline msg_t
|
||||
_i2c_recv32_be(I2CHelper *i2c, uint32_t *val) {
|
||||
int msg = _i2c_recv32(i2c, val);
|
||||
if (msg >= 0) *val = be32_to_cpu(*val);
|
||||
return msg;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue