zephyr/drivers/sensor/th02/th02.c
Armando Visconti 87d6c50e47 sensors: Add separation between ambient and die temperature
Some device include a temperature sensor, usually used as a
companion for helping in drift compensation, that measure the
die temperature. This temperature IS NOT related to the the
ambient temperature, hence a clean separation between the two
is required.

This commit introduces a clean separation between the two
types of temperature leaving the old deprecated definition
still there.

The list of current drivers that read the die (and not the ambient)
temperature is the following:

 - adxl362
 - bma280
 - bmg160
 - bmi160
 - fxos8700
 - lis3mdl
 - lsm6ds0
 - lsm6dsl
 - lsm9ds0
 - mpu6050

Signed-off-by: Armando Visconti <armando.visconti@st.com>
2018-04-03 22:29:11 -04:00

143 lines
3.1 KiB
C

/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <kernel.h>
#include <device.h>
#include <i2c.h>
#include <misc/byteorder.h>
#include <misc/util.h>
#include <sensor.h>
#include <misc/__assert.h>
#include "th02.h"
static u8_t read8(struct device *dev, u8_t d)
{
u8_t buf;
if (i2c_reg_read_byte(dev, TH02_I2C_DEV_ID, d, &buf) < 0) {
SYS_LOG_ERR("Error reading register.");
}
return buf;
}
static int is_ready(struct device *dev)
{
u8_t status;
if (i2c_reg_read_byte(dev, TH02_I2C_DEV_ID,
TH02_REG_STATUS, &status) < 0) {
SYS_LOG_ERR("error reading status register");
}
if (status & TH02_STATUS_RDY_MASK) {
return 0;
} else {
return 1;
}
}
static u16_t get_humi(struct device *dev)
{
u16_t humidity = 0;
if (i2c_reg_write_byte(dev, TH02_I2C_DEV_ID,
TH02_REG_CONFIG, TH02_CMD_MEASURE_HUMI) < 0) {
SYS_LOG_ERR("Error writing register");
return 0;
}
while (!is_ready(dev)) {
}
;
humidity = read8(dev, TH02_REG_DATA_H) << 8;
humidity |= read8(dev, TH02_REG_DATA_L);
humidity >>= 4;
return humidity;
}
u16_t get_temp(struct device *dev)
{
u16_t temperature = 0;
if (i2c_reg_write_byte(dev, TH02_I2C_DEV_ID,
TH02_REG_CONFIG, TH02_CMD_MEASURE_TEMP) < 0) {
SYS_LOG_ERR("Error writing register");
return 0;
}
while (!is_ready(dev)) {
}
;
temperature = read8(dev, TH02_REG_DATA_H) << 8;
temperature |= read8(dev, TH02_REG_DATA_L);
temperature >>= 2;
return temperature;
}
static int th02_sample_fetch(struct device *dev, enum sensor_channel chan)
{
struct th02_data *drv_data = dev->driver_data;
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_AMBIENT_TEMP);
drv_data->t_sample = get_temp(drv_data->i2c);
SYS_LOG_INF("temp: %u", drv_data->t_sample);
drv_data->rh_sample = get_humi(drv_data->i2c);
SYS_LOG_INF("rh: %u", drv_data->rh_sample);
return 0;
}
static int th02_channel_get(struct device *dev, enum sensor_channel chan,
struct sensor_value *val)
{
struct th02_data *drv_data = dev->driver_data;
__ASSERT_NO_MSG(chan == SENSOR_CHAN_AMBIENT_TEMP ||
chan == SENSOR_CHAN_HUMIDITY);
if (chan == SENSOR_CHAN_AMBIENT_TEMP) {
/* val = sample / 32 - 50 */
val->val1 = drv_data->t_sample / 32 - 50;
val->val2 = (drv_data->t_sample % 32) * (1000000 / 32);
} else {
/* val = sample / 16 -24 */
val->val1 = drv_data->rh_sample / 16 - 24;
val->val2 = (drv_data->rh_sample % 16) * (1000000 / 16);
}
return 0;
}
static const struct sensor_driver_api th02_driver_api = {
.sample_fetch = th02_sample_fetch,
.channel_get = th02_channel_get,
};
static int th02_init(struct device *dev)
{
struct th02_data *drv_data = dev->driver_data;
drv_data->i2c = device_get_binding(CONFIG_TH02_I2C_MASTER_DEV_NAME);
if (drv_data->i2c == NULL) {
SYS_LOG_ERR("Failed to get pointer to %s device!",
CONFIG_TH02_I2C_MASTER_DEV_NAME);
return -EINVAL;
}
return 0;
}
static struct th02_data th02_driver;
DEVICE_AND_API_INIT(th02, CONFIG_TH02_NAME, th02_init, &th02_driver,
NULL, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
&th02_driver_api);