zephyr/drivers/sensor/tmp007/tmp007.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

139 lines
2.9 KiB
C

/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <device.h>
#include <i2c.h>
#include <gpio.h>
#include <misc/byteorder.h>
#include <misc/util.h>
#include <kernel.h>
#include <sensor.h>
#include <misc/__assert.h>
#include "tmp007.h"
int tmp007_reg_read(struct tmp007_data *drv_data, u8_t reg, u16_t *val)
{
struct i2c_msg msgs[2] = {
{
.buf = &reg,
.len = 1,
.flags = I2C_MSG_WRITE | I2C_MSG_RESTART,
},
{
.buf = (u8_t *)val,
.len = 2,
.flags = I2C_MSG_READ | I2C_MSG_STOP,
},
};
if (i2c_transfer(drv_data->i2c, msgs, 2, TMP007_I2C_ADDRESS) < 0) {
return -EIO;
}
*val = sys_be16_to_cpu(*val);
return 0;
}
int tmp007_reg_write(struct tmp007_data *drv_data, u8_t reg, u16_t val)
{
u8_t tx_buf[3] = {reg, val >> 8, val & 0xFF};
return i2c_write(drv_data->i2c, tx_buf, sizeof(tx_buf),
TMP007_I2C_ADDRESS);
}
int tmp007_reg_update(struct tmp007_data *drv_data, u8_t reg,
u16_t mask, u16_t val)
{
u16_t old_val = 0;
u16_t new_val;
if (tmp007_reg_read(drv_data, reg, &old_val) < 0) {
return -EIO;
}
new_val = old_val & ~mask;
new_val |= val & mask;
return tmp007_reg_write(drv_data, reg, new_val);
}
static int tmp007_sample_fetch(struct device *dev, enum sensor_channel chan)
{
struct tmp007_data *drv_data = dev->driver_data;
u16_t val;
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_AMBIENT_TEMP);
if (tmp007_reg_read(drv_data, TMP007_REG_TOBJ, &val) < 0) {
return -EIO;
}
if (val & TMP007_DATA_INVALID_BIT) {
return -EIO;
}
drv_data->sample = arithmetic_shift_right((s16_t)val, 2);
return 0;
}
static int tmp007_channel_get(struct device *dev,
enum sensor_channel chan,
struct sensor_value *val)
{
struct tmp007_data *drv_data = dev->driver_data;
s32_t uval;
if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
return -ENOTSUP;
}
uval = (s32_t)drv_data->sample * TMP007_TEMP_SCALE;
val->val1 = uval / 1000000;
val->val2 = uval % 1000000;
return 0;
}
static const struct sensor_driver_api tmp007_driver_api = {
#ifdef CONFIG_TMP007_TRIGGER
.attr_set = tmp007_attr_set,
.trigger_set = tmp007_trigger_set,
#endif
.sample_fetch = tmp007_sample_fetch,
.channel_get = tmp007_channel_get,
};
int tmp007_init(struct device *dev)
{
struct tmp007_data *drv_data = dev->driver_data;
drv_data->i2c = device_get_binding(CONFIG_TMP007_I2C_MASTER_DEV_NAME);
if (drv_data->i2c == NULL) {
SYS_LOG_DBG("Failed to get pointer to %s device!",
CONFIG_TMP007_I2C_MASTER_DEV_NAME);
return -EINVAL;
}
#ifdef CONFIG_TMP007_TRIGGER
if (tmp007_init_interrupt(dev) < 0) {
SYS_LOG_DBG("Failed to initialize interrupt!");
return -EIO;
}
#endif
return 0;
}
struct tmp007_data tmp007_driver;
DEVICE_AND_API_INIT(tmp007, CONFIG_TMP007_NAME, tmp007_init, &tmp007_driver,
NULL, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
&tmp007_driver_api);