diff options
| author | Stephane D'Alu <sdalu@sdalu.com> | 2016-02-07 16:48:22 +0100 | 
|---|---|---|
| committer | Stephane D'Alu <sdalu@sdalu.com> | 2016-02-07 16:48:22 +0100 | 
| commit | ee5bea89c258d29dd628e366940569dd9795b1a9 (patch) | |
| tree | 3f92899ee45f73fddf472458c72b560e5ffc7ca3 | |
| parent | 5af8452153646009731c11dd92a8634695b60d55 (diff) | |
| download | ChibiOS-Contrib-ee5bea89c258d29dd628e366940569dd9795b1a9.tar.gz ChibiOS-Contrib-ee5bea89c258d29dd628e366940569dd9795b1a9.tar.bz2 ChibiOS-Contrib-ee5bea89c258d29dd628e366940569dd9795b1a9.zip  | |
hdc1008 sensor
| -rw-r--r-- | os/various/bswap.h | 138 | ||||
| -rw-r--r-- | os/various/devices_lib/sensors/hdc1000/bswap.h | 138 | ||||
| -rw-r--r-- | os/various/devices_lib/sensors/hdc1000/hdc1000.c | 255 | ||||
| -rw-r--r-- | os/various/devices_lib/sensors/hdc1000/hdc1000.h | 233 | ||||
| -rw-r--r-- | os/various/i2c_helpers.h | 267 | 
5 files changed, 1031 insertions, 0 deletions
diff --git a/os/various/bswap.h b/os/various/bswap.h new file mode 100644 index 0000000..624e4ba --- /dev/null +++ b/os/various/bswap.h @@ -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 + + diff --git a/os/various/devices_lib/sensors/hdc1000/bswap.h b/os/various/devices_lib/sensors/hdc1000/bswap.h new file mode 100644 index 0000000..624e4ba --- /dev/null +++ b/os/various/devices_lib/sensors/hdc1000/bswap.h @@ -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 + + diff --git a/os/various/devices_lib/sensors/hdc1000/hdc1000.c b/os/various/devices_lib/sensors/hdc1000/hdc1000.c new file mode 100644 index 0000000..ac8160c --- /dev/null +++ b/os/various/devices_lib/sensors/hdc1000/hdc1000.c @@ -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); +} + + +/** @} */ diff --git a/os/various/devices_lib/sensors/hdc1000/hdc1000.h b/os/various/devices_lib/sensors/hdc1000/hdc1000.h new file mode 100644 index 0000000..43090d9 --- /dev/null +++ b/os/various/devices_lib/sensors/hdc1000/hdc1000.h @@ -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 + diff --git a/os/various/i2c_helpers.h b/os/various/i2c_helpers.h new file mode 100644 index 0000000..56f9be6 --- /dev/null +++ b/os/various/i2c_helpers.h @@ -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  | 
