mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-26 04:36:06 +00:00
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>
188 lines
4.7 KiB
C
188 lines
4.7 KiB
C
/* lps25hb.c - Driver for LPS25HB pressure and temperature sensor */
|
|
|
|
/*
|
|
* Copyright (c) 2016 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <sensor.h>
|
|
#include <kernel.h>
|
|
#include <device.h>
|
|
#include <init.h>
|
|
#include <misc/byteorder.h>
|
|
#include <misc/__assert.h>
|
|
|
|
#include "lps25hb.h"
|
|
|
|
static inline int lps25hb_power_ctrl(struct device *dev, u8_t value)
|
|
{
|
|
struct lps25hb_data *data = dev->driver_data;
|
|
const struct lps25hb_config *config = dev->config->config_info;
|
|
|
|
return i2c_reg_update_byte(data->i2c_master, config->i2c_slave_addr,
|
|
LPS25HB_REG_CTRL_REG1,
|
|
LPS25HB_MASK_CTRL_REG1_PD,
|
|
value << LPS25HB_SHIFT_CTRL_REG1_PD);
|
|
}
|
|
|
|
static inline int lps25hb_set_odr_raw(struct device *dev, u8_t odr)
|
|
{
|
|
struct lps25hb_data *data = dev->driver_data;
|
|
const struct lps25hb_config *config = dev->config->config_info;
|
|
|
|
return i2c_reg_update_byte(data->i2c_master, config->i2c_slave_addr,
|
|
LPS25HB_REG_CTRL_REG1,
|
|
LPS25HB_MASK_CTRL_REG1_ODR,
|
|
odr << LPS25HB_SHIFT_CTRL_REG1_ODR);
|
|
}
|
|
|
|
static int lps25hb_sample_fetch(struct device *dev,
|
|
enum sensor_channel chan)
|
|
{
|
|
struct lps25hb_data *data = dev->driver_data;
|
|
const struct lps25hb_config *config = dev->config->config_info;
|
|
u8_t out[5];
|
|
int offset;
|
|
|
|
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL);
|
|
|
|
for (offset = 0; offset < sizeof(out); ++offset) {
|
|
if (i2c_reg_read_byte(data->i2c_master, config->i2c_slave_addr,
|
|
LPS25HB_REG_PRESS_OUT_XL + offset,
|
|
out + offset) < 0) {
|
|
SYS_LOG_DBG("failed to read sample");
|
|
return -EIO;
|
|
}
|
|
}
|
|
|
|
data->sample_press = (s32_t)((u32_t)(out[0]) |
|
|
((u32_t)(out[1]) << 8) |
|
|
((u32_t)(out[2]) << 16));
|
|
data->sample_temp = (s16_t)((u16_t)(out[3]) |
|
|
((u16_t)(out[4]) << 8));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline void lps25hb_press_convert(struct sensor_value *val,
|
|
s32_t raw_val)
|
|
{
|
|
/* val = raw_val / 40960 */
|
|
val->val1 = raw_val / 40960;
|
|
val->val2 = ((s32_t)raw_val * 1000000 / 40960) % 1000000;
|
|
}
|
|
|
|
static inline void lps25hb_temp_convert(struct sensor_value *val,
|
|
s16_t raw_val)
|
|
{
|
|
s32_t uval;
|
|
|
|
/* val = raw_val / 480 + 42.5 */
|
|
uval = (s32_t)raw_val * 1000000 / 480 + 42500000;
|
|
val->val1 = (raw_val * 10 / 480 + 425) / 10;
|
|
val->val2 = uval % 1000000;
|
|
}
|
|
|
|
static int lps25hb_channel_get(struct device *dev,
|
|
enum sensor_channel chan,
|
|
struct sensor_value *val)
|
|
{
|
|
struct lps25hb_data *data = dev->driver_data;
|
|
|
|
if (chan == SENSOR_CHAN_PRESS) {
|
|
lps25hb_press_convert(val, data->sample_press);
|
|
} else if (chan == SENSOR_CHAN_AMBIENT_TEMP) {
|
|
lps25hb_temp_convert(val, data->sample_temp);
|
|
} else {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct sensor_driver_api lps25hb_api_funcs = {
|
|
.sample_fetch = lps25hb_sample_fetch,
|
|
.channel_get = lps25hb_channel_get,
|
|
};
|
|
|
|
static int lps25hb_init_chip(struct device *dev)
|
|
{
|
|
struct lps25hb_data *data = dev->driver_data;
|
|
const struct lps25hb_config *config = dev->config->config_info;
|
|
u8_t chip_id;
|
|
|
|
lps25hb_power_ctrl(dev, 0);
|
|
k_busy_wait(50 * USEC_PER_MSEC);
|
|
|
|
if (lps25hb_power_ctrl(dev, 1) < 0) {
|
|
SYS_LOG_DBG("failed to power on device");
|
|
return -EIO;
|
|
}
|
|
|
|
k_busy_wait(20 * USEC_PER_MSEC);
|
|
|
|
if (i2c_reg_read_byte(data->i2c_master, config->i2c_slave_addr,
|
|
LPS25HB_REG_WHO_AM_I, &chip_id) < 0) {
|
|
SYS_LOG_DBG("failed reading chip id");
|
|
goto err_poweroff;
|
|
}
|
|
if (chip_id != LPS25HB_VAL_WHO_AM_I) {
|
|
SYS_LOG_DBG("invalid chip id 0x%x", chip_id);
|
|
goto err_poweroff;
|
|
}
|
|
|
|
SYS_LOG_DBG("chip id 0x%x", chip_id);
|
|
|
|
if (lps25hb_set_odr_raw(dev, LPS25HB_DEFAULT_SAMPLING_RATE)
|
|
< 0) {
|
|
SYS_LOG_DBG("failed to set sampling rate");
|
|
goto err_poweroff;
|
|
}
|
|
|
|
if (i2c_reg_update_byte(data->i2c_master, config->i2c_slave_addr,
|
|
LPS25HB_REG_CTRL_REG1,
|
|
LPS25HB_MASK_CTRL_REG1_BDU,
|
|
(1 << LPS25HB_SHIFT_CTRL_REG1_BDU)) < 0) {
|
|
SYS_LOG_DBG("failed to set BDU");
|
|
goto err_poweroff;
|
|
}
|
|
|
|
return 0;
|
|
|
|
err_poweroff:
|
|
lps25hb_power_ctrl(dev, 0);
|
|
return -EIO;
|
|
}
|
|
|
|
static int lps25hb_init(struct device *dev)
|
|
{
|
|
const struct lps25hb_config * const config = dev->config->config_info;
|
|
struct lps25hb_data *data = dev->driver_data;
|
|
|
|
data->i2c_master = device_get_binding(config->i2c_master_dev_name);
|
|
if (!data->i2c_master) {
|
|
SYS_LOG_DBG("i2c master not found: %s",
|
|
config->i2c_master_dev_name);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (lps25hb_init_chip(dev) < 0) {
|
|
SYS_LOG_DBG("failed to initialize chip");
|
|
return -EIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct lps25hb_config lps25hb_config = {
|
|
.i2c_master_dev_name = CONFIG_LPS25HB_I2C_MASTER_DEV_NAME,
|
|
.i2c_slave_addr = CONFIG_LPS25HB_I2C_ADDR,
|
|
};
|
|
|
|
static struct lps25hb_data lps25hb_data;
|
|
|
|
DEVICE_AND_API_INIT(lps25hb, CONFIG_LPS25HB_DEV_NAME, lps25hb_init,
|
|
&lps25hb_data, &lps25hb_config, POST_KERNEL,
|
|
CONFIG_SENSOR_INIT_PRIORITY, &lps25hb_api_funcs);
|