sensor: add driver for SHT3xD sensors
Add device driver for the SHT3xD temperature and humidity sensors. Datasheets: https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/Humidity_Sensors/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/Humidity_Sensors/Sensirion_Humidity_Sensors_SHT3x_Application_Note_Alert_Mode_DIS_V1.pdf Origin: Original Change-Id: I9cda2f1bc7172e93ce34fde63c6febf0b8b28289 Signed-off-by: Bogdan Davidoaia <bogdan.m.davidoaia@intel.com>
This commit is contained in:
parent
babb62a0ed
commit
653874c73f
6 changed files with 756 additions and 0 deletions
|
@ -50,4 +50,6 @@ source "drivers/sensor/Kconfig.isl29035"
|
||||||
|
|
||||||
source "drivers/sensor/Kconfig.mcp9808"
|
source "drivers/sensor/Kconfig.mcp9808"
|
||||||
|
|
||||||
|
source "drivers/sensor/Kconfig.sht3xd"
|
||||||
|
|
||||||
source "drivers/sensor/Kconfig.sx9500"
|
source "drivers/sensor/Kconfig.sx9500"
|
||||||
|
|
186
drivers/sensor/Kconfig.sht3xd
Normal file
186
drivers/sensor/Kconfig.sht3xd
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
# Kconfig.sht3xd - SHT3xD temperature and humidity sensor configuration options
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 Intel Corporation
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
menuconfig SHT3XD
|
||||||
|
bool
|
||||||
|
prompt "SHT3xD Temperature and Humidity Sensor"
|
||||||
|
depends on SENSOR && I2C
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable driver for SHT3xD temperature and humidity sensors.
|
||||||
|
|
||||||
|
config SHT3XD_NAME
|
||||||
|
string
|
||||||
|
prompt "Driver name"
|
||||||
|
default "SHT3XD"
|
||||||
|
depends on SHT3XD
|
||||||
|
help
|
||||||
|
Device name with which the SHT3xD sensor is identified.
|
||||||
|
|
||||||
|
config SHT3XD_INIT_PRIORITY
|
||||||
|
int
|
||||||
|
prompt "Init priority"
|
||||||
|
depends on SHT3XD
|
||||||
|
default 70
|
||||||
|
help
|
||||||
|
Device driver initialization priority.
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "I2C address"
|
||||||
|
depends on SHT3XD
|
||||||
|
default SHT3XD_I2C_ADDR_A
|
||||||
|
help
|
||||||
|
I2C address of the SHT3xD sensor.
|
||||||
|
|
||||||
|
config SHT3XD_I2C_ADDR_A
|
||||||
|
bool
|
||||||
|
prompt "0x44"
|
||||||
|
help
|
||||||
|
Choose this option if the ADDR pin is connected to VSS.
|
||||||
|
|
||||||
|
config SHT3XD_I2C_ADDR_B
|
||||||
|
bool
|
||||||
|
prompt "0x45"
|
||||||
|
help
|
||||||
|
Choose this option if the ADDR pin is connected to VDD.
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config SHT3XD_I2C_MASTER_DEV_NAME
|
||||||
|
string
|
||||||
|
prompt "I2C master where SHT3xD is connected"
|
||||||
|
depends on SHT3XD
|
||||||
|
default "I2C0"
|
||||||
|
help
|
||||||
|
Specify the device name of the I2C master device to which the
|
||||||
|
SHT3xD chip is connected.
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Trigger mode"
|
||||||
|
depends on SHT3XD
|
||||||
|
default SHT3XD_TRIGGER_NONE
|
||||||
|
help
|
||||||
|
Specify the type of triggering to be used by the driver.
|
||||||
|
|
||||||
|
config SHT3XD_TRIGGER_NONE
|
||||||
|
bool
|
||||||
|
prompt "No trigger"
|
||||||
|
|
||||||
|
config SHT3XD_TRIGGER_GLOBAL_FIBER
|
||||||
|
bool
|
||||||
|
prompt "Use global fiber"
|
||||||
|
depends on GPIO
|
||||||
|
select SHT3XD_TRIGGER
|
||||||
|
select SENSOR_DELAYED_WORK
|
||||||
|
|
||||||
|
config SHT3XD_TRIGGER_OWN_FIBER
|
||||||
|
bool
|
||||||
|
prompt "Use own fiber"
|
||||||
|
depends on GPIO
|
||||||
|
select SHT3XD_TRIGGER
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config SHT3XD_TRIGGER
|
||||||
|
bool
|
||||||
|
depends on SHT3XD
|
||||||
|
|
||||||
|
config SHT3XD_GPIO_DEV_NAME
|
||||||
|
string
|
||||||
|
prompt "GPIO device"
|
||||||
|
default "GPIO_0"
|
||||||
|
depends on SHT3XD && SHT3XD_TRIGGER
|
||||||
|
help
|
||||||
|
The device name of the GPIO device to which the SHT3xD interrupt
|
||||||
|
pins are connected.
|
||||||
|
|
||||||
|
config SHT3XD_GPIO_PIN_NUM
|
||||||
|
int
|
||||||
|
prompt "Interrupt GPIO pin number"
|
||||||
|
default 0
|
||||||
|
depends on SHT3XD && SHT3XD_TRIGGER
|
||||||
|
help
|
||||||
|
The number of the GPIO on which the interrupt signal from the
|
||||||
|
SHT3xD chip will be received.
|
||||||
|
|
||||||
|
config SHT3XD_FIBER_PRIORITY
|
||||||
|
int
|
||||||
|
prompt "Fiber priority"
|
||||||
|
depends on SHT3XD && SHT3XD_TRIGGER_OWN_FIBER
|
||||||
|
default 10
|
||||||
|
help
|
||||||
|
Priority of fiber used by the driver to handle interrupts.
|
||||||
|
|
||||||
|
config SHT3XD_FIBER_STACK_SIZE
|
||||||
|
int
|
||||||
|
prompt "Fiber stack size"
|
||||||
|
depends on SHT3XD && SHT3XD_TRIGGER_OWN_FIBER
|
||||||
|
default 1024
|
||||||
|
help
|
||||||
|
Stack size of fiber used by the driver to handle interrupts.
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Measurement repeatability"
|
||||||
|
depends on SHT3XD
|
||||||
|
default SHT3XD_REPEATABILITY_HIGH
|
||||||
|
help
|
||||||
|
Repeatability modes differ with respect to measurement duration,
|
||||||
|
noise level and energy consumption.
|
||||||
|
|
||||||
|
config SHT3XD_REPEATABILITY_LOW
|
||||||
|
bool
|
||||||
|
prompt "low"
|
||||||
|
|
||||||
|
config SHT3XD_REPEATABILITY_MEDIUM
|
||||||
|
bool
|
||||||
|
prompt "medium"
|
||||||
|
|
||||||
|
config SHT3XD_REPEATABILITY_HIGH
|
||||||
|
bool
|
||||||
|
prompt "high"
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Measurements per second"
|
||||||
|
depends on SHT3XD
|
||||||
|
default SHT3XD_MPS_1
|
||||||
|
help
|
||||||
|
Number of measurements per second.
|
||||||
|
|
||||||
|
config SHT3XD_MPS_05
|
||||||
|
bool
|
||||||
|
prompt "0.5"
|
||||||
|
|
||||||
|
config SHT3XD_MPS_1
|
||||||
|
bool
|
||||||
|
prompt "1"
|
||||||
|
|
||||||
|
config SHT3XD_MPS_2
|
||||||
|
bool
|
||||||
|
prompt "2"
|
||||||
|
|
||||||
|
config SHT3XD_MPS_4
|
||||||
|
bool
|
||||||
|
prompt "4"
|
||||||
|
|
||||||
|
config SHT3XD_MPS_10
|
||||||
|
bool
|
||||||
|
prompt "10"
|
||||||
|
|
||||||
|
endchoice
|
|
@ -8,5 +8,7 @@ obj-$(CONFIG_ISL29035) += sensor_isl29035.o
|
||||||
obj-$(CONFIG_ISL29035_TRIGGER) += sensor_isl29035_trigger.o
|
obj-$(CONFIG_ISL29035_TRIGGER) += sensor_isl29035_trigger.o
|
||||||
obj-$(CONFIG_MCP9808) += sensor_mcp9808.o
|
obj-$(CONFIG_MCP9808) += sensor_mcp9808.o
|
||||||
obj-$(CONFIG_MCP9808_TRIGGER) += sensor_mcp9808_trigger.o
|
obj-$(CONFIG_MCP9808_TRIGGER) += sensor_mcp9808_trigger.o
|
||||||
|
obj-$(CONFIG_SHT3XD) += sensor_sht3xd.o
|
||||||
|
obj-$(CONFIG_SHT3XD_TRIGGER) += sensor_sht3xd_trigger.o
|
||||||
obj-$(CONFIG_SX9500) += sensor_sx9500.o
|
obj-$(CONFIG_SX9500) += sensor_sx9500.o
|
||||||
obj-$(CONFIG_SX9500_TRIGGER) += sensor_sx9500_trigger.o
|
obj-$(CONFIG_SX9500_TRIGGER) += sensor_sx9500_trigger.o
|
||||||
|
|
207
drivers/sensor/sensor_sht3xd.c
Normal file
207
drivers/sensor/sensor_sht3xd.c
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <i2c.h>
|
||||||
|
#include <nanokernel.h>
|
||||||
|
#include <sensor.h>
|
||||||
|
|
||||||
|
#include "sensor_sht3xd.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CRC algorithm parameters were taken from the
|
||||||
|
* "Checksum Calculation" section of the datasheet.
|
||||||
|
*/
|
||||||
|
static uint8_t sht3xd_compute_crc(uint16_t value)
|
||||||
|
{
|
||||||
|
uint8_t buf[2] = {value >> 8, value & 0xFF};
|
||||||
|
uint8_t crc = 0xFF;
|
||||||
|
uint8_t polynom = 0x31;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < 2; ++i) {
|
||||||
|
crc = crc ^ buf[i];
|
||||||
|
for (j = 0; j < 8; ++j) {
|
||||||
|
if (crc & 0x80) {
|
||||||
|
crc = (crc << 1) ^ polynom;
|
||||||
|
} else {
|
||||||
|
crc = crc << 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sht3xd_write_command(struct sht3xd_data *drv_data, uint16_t cmd)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf[2] = {cmd >> 8, cmd & 0xFF};
|
||||||
|
|
||||||
|
return i2c_write(drv_data->i2c, tx_buf, sizeof(tx_buf),
|
||||||
|
SHT3XD_I2C_ADDRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sht3xd_write_reg(struct sht3xd_data *drv_data, uint16_t cmd,
|
||||||
|
uint16_t val)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf[5];
|
||||||
|
|
||||||
|
tx_buf[0] = cmd >> 8;
|
||||||
|
tx_buf[1] = cmd & 0xFF;
|
||||||
|
tx_buf[2] = val >> 8;
|
||||||
|
tx_buf[3] = val & 0xFF;
|
||||||
|
tx_buf[4] = sht3xd_compute_crc(val);
|
||||||
|
|
||||||
|
return i2c_write(drv_data->i2c, tx_buf, sizeof(tx_buf),
|
||||||
|
SHT3XD_I2C_ADDRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sht3xd_sample_fetch(struct device *dev)
|
||||||
|
{
|
||||||
|
struct sht3xd_data *drv_data = dev->driver_data;
|
||||||
|
uint8_t rx_buf[6];
|
||||||
|
uint16_t t_sample, rh_sample;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
uint8_t tx_buf[2] = {
|
||||||
|
SHT3XD_CMD_FETCH >> 8,
|
||||||
|
SHT3XD_CMD_FETCH & 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
struct i2c_msg msgs[2] = {
|
||||||
|
{
|
||||||
|
.buf = tx_buf,
|
||||||
|
.len = sizeof(tx_buf),
|
||||||
|
.flags = I2C_MSG_WRITE | I2C_MSG_RESTART,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.buf = rx_buf,
|
||||||
|
.len = sizeof(rx_buf),
|
||||||
|
.flags = I2C_MSG_READ | I2C_MSG_STOP,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
rc = i2c_transfer(drv_data->i2c, msgs, 2, SHT3XD_I2C_ADDRESS);
|
||||||
|
if (rc != DEV_OK) {
|
||||||
|
DBG("Failed to read data sample!\n");
|
||||||
|
return DEV_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_sample = (rx_buf[0] << 8) | rx_buf[1];
|
||||||
|
if (sht3xd_compute_crc(t_sample) != rx_buf[2]) {
|
||||||
|
DBG("Received invalid temperature CRC!\n");
|
||||||
|
return DEV_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rh_sample = (rx_buf[3] << 8) | rx_buf[4];
|
||||||
|
if (sht3xd_compute_crc(rh_sample) != rx_buf[5]) {
|
||||||
|
DBG("Received invalid relative humidity CRC!\n");
|
||||||
|
return DEV_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
drv_data->t_sample = t_sample;
|
||||||
|
drv_data->rh_sample = rh_sample;
|
||||||
|
|
||||||
|
return DEV_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sht3xd_channel_get(struct device *dev,
|
||||||
|
enum sensor_channel chan,
|
||||||
|
struct sensor_value *val)
|
||||||
|
{
|
||||||
|
struct sht3xd_data *drv_data = dev->driver_data;
|
||||||
|
uint64_t tmp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See datasheet "Conversion of Signal Output" section
|
||||||
|
* for more details on processing sample data.
|
||||||
|
*/
|
||||||
|
if (chan == SENSOR_CHAN_TEMP) {
|
||||||
|
/* val = -45 + 175 * sample / (2^16 -1) */
|
||||||
|
tmp = 175 * (uint64_t)drv_data->t_sample;
|
||||||
|
val->type = SENSOR_TYPE_INT_PLUS_MICRO;
|
||||||
|
val->val1 = (int32_t)(tmp / 0xFFFF) - 45;
|
||||||
|
val->val2 = (1000000 * (tmp % 0xFFFF)) / 0xFFFF;
|
||||||
|
} else if (chan == SENSOR_CHAN_HUMIDITY) {
|
||||||
|
/* val = 100000 * sample / (2^16 -1) */
|
||||||
|
tmp = 100000 * (uint64_t)drv_data->rh_sample;
|
||||||
|
val->type = SENSOR_TYPE_INT_PLUS_MICRO;
|
||||||
|
val->val1 = tmp / 0xFFFF;
|
||||||
|
val->val2 = (1000000 * (tmp % 0xFFFF)) / 0xFFFF;
|
||||||
|
} else {
|
||||||
|
return DEV_INVALID_OP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEV_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sensor_driver_api sht3xd_driver_api = {
|
||||||
|
#ifdef CONFIG_SHT3XD_TRIGGER
|
||||||
|
.attr_set = sht3xd_attr_set,
|
||||||
|
.trigger_set = sht3xd_trigger_set,
|
||||||
|
#endif
|
||||||
|
.sample_fetch = sht3xd_sample_fetch,
|
||||||
|
.channel_get = sht3xd_channel_get,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int sht3xd_init(struct device *dev)
|
||||||
|
{
|
||||||
|
struct sht3xd_data *drv_data = dev->driver_data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
dev->driver_api = &sht3xd_driver_api;
|
||||||
|
|
||||||
|
drv_data->i2c = device_get_binding(CONFIG_SHT3XD_I2C_MASTER_DEV_NAME);
|
||||||
|
if (drv_data->i2c == NULL) {
|
||||||
|
DBG("Failed to get pointer to %s device!\n",
|
||||||
|
CONFIG_SHT3XD_I2C_MASTER_DEV_NAME);
|
||||||
|
return DEV_INVALID_CONF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear status register */
|
||||||
|
rc = sht3xd_write_command(drv_data, SHT3XD_CMD_CLEAR_STATUS);
|
||||||
|
if (rc != DEV_OK) {
|
||||||
|
DBG("Failed to clear status register!\n");
|
||||||
|
return DEV_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_thread_busy_wait(SHT3XD_CLEAR_STATUS_WAIT_USEC);
|
||||||
|
|
||||||
|
/* set periodic measurement mode */
|
||||||
|
rc = sht3xd_write_command(drv_data,
|
||||||
|
sht3xd_measure_cmd[SHT3XD_MPS_IDX][SHT3XD_REPEATABILITY_IDX]);
|
||||||
|
if (rc != DEV_OK) {
|
||||||
|
DBG("Failed to set measurement mode!\n");
|
||||||
|
return DEV_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_thread_busy_wait(sht3xd_measure_wait[SHT3XD_REPEATABILITY_IDX]);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SHT3XD_TRIGGER
|
||||||
|
rc = sht3xd_init_interrupt(dev);
|
||||||
|
if (rc != DEV_OK) {
|
||||||
|
DBG("Failed to initialize interrupt\n");
|
||||||
|
return DEV_FAIL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return DEV_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sht3xd_data sht3xd_driver;
|
||||||
|
|
||||||
|
DEVICE_INIT(sht3xd, CONFIG_SHT3XD_NAME, sht3xd_init, &sht3xd_driver,
|
||||||
|
NULL, SECONDARY, CONFIG_SHT3XD_INIT_PRIORITY);
|
124
drivers/sensor/sensor_sht3xd.h
Normal file
124
drivers/sensor/sensor_sht3xd.h
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SENSOR_SHT3XD_
|
||||||
|
#define _SENSOR_SHT3XD_
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <nanokernel.h>
|
||||||
|
|
||||||
|
#ifndef CONFIG_SENSOR_DEBUG
|
||||||
|
#define DBG(...) { ; }
|
||||||
|
#else
|
||||||
|
#include <misc/printk.h>
|
||||||
|
#define DBG printk
|
||||||
|
#endif /* CONFIG_SENSOR_DEBUG */
|
||||||
|
|
||||||
|
#if CONFIG_SHT3XD_I2C_ADDR_A
|
||||||
|
#define SHT3XD_I2C_ADDRESS 0x44
|
||||||
|
#elif CONFIG_SHT3XD_I2C_ADDR_B
|
||||||
|
#define SHT3XD_I2C_ADDRESS 0x45
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SHT3XD_CMD_FETCH 0xE000
|
||||||
|
#define SHT3XD_CMD_ART 0x2B32
|
||||||
|
#define SHT3XD_CMD_READ_STATUS 0xF32D
|
||||||
|
#define SHT3XD_CMD_CLEAR_STATUS 0x3041
|
||||||
|
|
||||||
|
#define SHT3XD_CMD_WRITE_TH_HIGH_SET 0x611D
|
||||||
|
#define SHT3XD_CMD_WRITE_TH_HIGH_CLEAR 0x6116
|
||||||
|
#define SHT3XD_CMD_WRITE_TH_LOW_SET 0x610B
|
||||||
|
#define SHT3XD_CMD_WRITE_TH_LOW_CLEAR 0x6100
|
||||||
|
|
||||||
|
#if CONFIG_SHT3XD_REPEATABILITY_LOW
|
||||||
|
#define SHT3XD_REPEATABILITY_IDX 0
|
||||||
|
#elif CONFIG_SHT3XD_REPEATABILITY_MEDIUM
|
||||||
|
#define SHT3XD_REPEATABILITY_IDX 1
|
||||||
|
#elif CONFIG_SHT3XD_REPEATABILITY_HIGH
|
||||||
|
#define SHT3XD_REPEATABILITY_IDX 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_SHT3XD_MPS_05
|
||||||
|
#define SHT3XD_MPS_IDX 0
|
||||||
|
#elif CONFIG_SHT3XD_MPS_1
|
||||||
|
#define SHT3XD_MPS_IDX 1
|
||||||
|
#elif CONFIG_SHT3XD_MPS_2
|
||||||
|
#define SHT3XD_MPS_IDX 2
|
||||||
|
#elif CONFIG_SHT3XD_MPS_4
|
||||||
|
#define SHT3XD_MPS_IDX 3
|
||||||
|
#elif CONFIG_SHT3XD_MPS_10
|
||||||
|
#define SHT3XD_MPS_IDX 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SHT3XD_CLEAR_STATUS_WAIT_USEC 1000
|
||||||
|
|
||||||
|
static const uint16_t sht3xd_measure_cmd[5][3] = {
|
||||||
|
{0x202F, 0x2024, 0x2032},
|
||||||
|
{0x212D, 0x2126, 0x2130},
|
||||||
|
{0x222B, 0x2220, 0x2236},
|
||||||
|
{0x2329, 0x2322, 0x2334},
|
||||||
|
{0x272A, 0x2721, 0x2737}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int sht3xd_measure_wait[3] = {
|
||||||
|
4000, 6000, 15000
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sht3xd_data {
|
||||||
|
struct device *i2c;
|
||||||
|
uint16_t t_sample;
|
||||||
|
uint16_t rh_sample;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SHT3XD_TRIGGER
|
||||||
|
struct device *gpio;
|
||||||
|
|
||||||
|
uint16_t t_low;
|
||||||
|
uint16_t t_high;
|
||||||
|
uint16_t rh_low;
|
||||||
|
uint16_t rh_high;
|
||||||
|
|
||||||
|
sensor_trigger_handler_t handler;
|
||||||
|
struct sensor_trigger trigger;
|
||||||
|
|
||||||
|
#if defined(CONFIG_SHT3XD_TRIGGER_OWN_FIBER)
|
||||||
|
char __stack fiber_stack[CONFIG_SHT3XD_FIBER_STACK_SIZE];
|
||||||
|
struct nano_sem gpio_sem;
|
||||||
|
#elif defined(CONFIG_SHT3XD_TRIGGER_GLOBAL_FIBER)
|
||||||
|
struct sensor_work work;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONFIG_SHT3XD_TRIGGER */
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_SHT3XD_TRIGGER
|
||||||
|
int sht3xd_write_command(struct sht3xd_data *drv_data, uint16_t cmd);
|
||||||
|
|
||||||
|
int sht3xd_write_reg(struct sht3xd_data *drv_data, uint16_t cmd,
|
||||||
|
uint16_t val);
|
||||||
|
|
||||||
|
int sht3xd_attr_set(struct device *dev,
|
||||||
|
enum sensor_channel chan,
|
||||||
|
enum sensor_attribute attr,
|
||||||
|
const struct sensor_value *val);
|
||||||
|
|
||||||
|
int sht3xd_trigger_set(struct device *dev,
|
||||||
|
const struct sensor_trigger *trig,
|
||||||
|
sensor_trigger_handler_t handler);
|
||||||
|
|
||||||
|
int sht3xd_init_interrupt(struct device *dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _SENSOR_SHT3XD_ */
|
235
drivers/sensor/sensor_sht3xd_trigger.c
Normal file
235
drivers/sensor/sensor_sht3xd_trigger.c
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <gpio.h>
|
||||||
|
#include <misc/util.h>
|
||||||
|
#include <nanokernel.h>
|
||||||
|
#include <sensor.h>
|
||||||
|
|
||||||
|
#include "sensor_sht3xd.h"
|
||||||
|
|
||||||
|
extern struct sht3xd_data sht3xd_driver;
|
||||||
|
|
||||||
|
static uint16_t sht3xd_temp_processed_to_raw(const struct sensor_value *val)
|
||||||
|
{
|
||||||
|
uint32_t val2;
|
||||||
|
uint64_t uval;
|
||||||
|
|
||||||
|
if (val->type == SENSOR_TYPE_INT) {
|
||||||
|
val2 = 0;
|
||||||
|
} else {
|
||||||
|
val2 = val->val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ret = (val + 45) * (2^16 - 1) / 175 */
|
||||||
|
uval = (uint64_t)(val->val1 + 45) * 1000000 + val2;
|
||||||
|
return ((uval * 0xFFFF) / 175) / 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sht3xd_rh_processed_to_raw(const struct sensor_value *val)
|
||||||
|
{
|
||||||
|
uint32_t val2;
|
||||||
|
uint64_t uval;
|
||||||
|
|
||||||
|
if (val->type == SENSOR_TYPE_INT) {
|
||||||
|
val2 = 0;
|
||||||
|
} else {
|
||||||
|
val2 = val->val2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ret = val * (2^16 -1) / 100000 */
|
||||||
|
uval = (uint64_t)val->val1 * 1000000 + val2;
|
||||||
|
return ((uval * 0xFFFF) / 100000) / 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sht3xd_attr_set(struct device *dev,
|
||||||
|
enum sensor_channel chan,
|
||||||
|
enum sensor_attribute attr,
|
||||||
|
const struct sensor_value *val)
|
||||||
|
{
|
||||||
|
struct sht3xd_data *drv_data = dev->driver_data;
|
||||||
|
uint16_t set_cmd, clear_cmd, reg_val, temp, rh;
|
||||||
|
|
||||||
|
if (val->type != SENSOR_TYPE_INT &&
|
||||||
|
val->type != SENSOR_TYPE_INT_PLUS_MICRO) {
|
||||||
|
return DEV_INVALID_OP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attr == SENSOR_ATTR_LOWER_THRESH) {
|
||||||
|
if (chan == SENSOR_CHAN_TEMP) {
|
||||||
|
drv_data->t_low = sht3xd_temp_processed_to_raw(val);
|
||||||
|
} else if (chan == SENSOR_CHAN_HUMIDITY) {
|
||||||
|
drv_data->rh_low = sht3xd_rh_processed_to_raw(val);
|
||||||
|
} else {
|
||||||
|
return DEV_INVALID_OP;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_cmd = SHT3XD_CMD_WRITE_TH_LOW_SET;
|
||||||
|
clear_cmd = SHT3XD_CMD_WRITE_TH_LOW_CLEAR;
|
||||||
|
temp = drv_data->t_low;
|
||||||
|
rh = drv_data->rh_low;
|
||||||
|
} else if (attr == SENSOR_ATTR_UPPER_THRESH) {
|
||||||
|
if (chan == SENSOR_CHAN_TEMP) {
|
||||||
|
drv_data->t_high = sht3xd_temp_processed_to_raw(val);
|
||||||
|
} else if (chan == SENSOR_CHAN_HUMIDITY) {
|
||||||
|
drv_data->rh_high = sht3xd_rh_processed_to_raw(val);
|
||||||
|
} else {
|
||||||
|
return DEV_INVALID_OP;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_cmd = SHT3XD_CMD_WRITE_TH_HIGH_SET;
|
||||||
|
clear_cmd = SHT3XD_CMD_WRITE_TH_HIGH_CLEAR;
|
||||||
|
temp = drv_data->t_high;
|
||||||
|
rh = drv_data->rh_high;
|
||||||
|
} else {
|
||||||
|
return DEV_INVALID_OP;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_val = (rh & 0xFE00) | ((temp & 0xFF80) >> 7);
|
||||||
|
|
||||||
|
if (sht3xd_write_reg(drv_data, set_cmd, reg_val) != DEV_OK ||
|
||||||
|
sht3xd_write_reg(drv_data, clear_cmd, reg_val) != DEV_OK) {
|
||||||
|
DBG("Failed to write threshold value!\n");
|
||||||
|
return DEV_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEV_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sht3xd_gpio_callback(struct device *dev, uint32_t pin)
|
||||||
|
{
|
||||||
|
gpio_pin_disable_callback(dev, pin);
|
||||||
|
|
||||||
|
#if defined(CONFIG_SHT3XD_TRIGGER_OWN_FIBER)
|
||||||
|
nano_sem_give(&sht3xd_driver.gpio_sem);
|
||||||
|
#elif defined(CONFIG_SHT3XD_TRIGGER_GLOBAL_FIBER)
|
||||||
|
nano_isr_fifo_put(sensor_get_work_fifo(), &sht3xd_driver.work);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sht3xd_fiber_cb(void *arg)
|
||||||
|
{
|
||||||
|
struct device *dev = arg;
|
||||||
|
struct sht3xd_data *drv_data = dev->driver_data;
|
||||||
|
|
||||||
|
if (drv_data->handler != NULL) {
|
||||||
|
drv_data->handler(dev, &drv_data->trigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_pin_enable_callback(drv_data->gpio, CONFIG_SHT3XD_GPIO_PIN_NUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SHT3XD_TRIGGER_OWN_FIBER
|
||||||
|
static void sht3xd_fiber(int dev_ptr, int unused)
|
||||||
|
{
|
||||||
|
struct device *dev = INT_TO_POINTER(dev_ptr);
|
||||||
|
struct sht3xd_data *drv_data = dev->driver_data;
|
||||||
|
|
||||||
|
ARG_UNUSED(unused);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
nano_fiber_sem_take(&drv_data->gpio_sem, TICKS_UNLIMITED);
|
||||||
|
sht3xd_fiber_cb(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int sht3xd_trigger_set(struct device *dev,
|
||||||
|
const struct sensor_trigger *trig,
|
||||||
|
sensor_trigger_handler_t handler)
|
||||||
|
{
|
||||||
|
struct sht3xd_data *drv_data = dev->driver_data;
|
||||||
|
|
||||||
|
if (trig->type != SENSOR_TRIG_THRESHOLD) {
|
||||||
|
return DEV_INVALID_OP;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_pin_disable_callback(drv_data->gpio, CONFIG_SHT3XD_GPIO_PIN_NUM);
|
||||||
|
drv_data->handler = handler;
|
||||||
|
drv_data->trigger = *trig;
|
||||||
|
gpio_pin_enable_callback(drv_data->gpio, CONFIG_SHT3XD_GPIO_PIN_NUM);
|
||||||
|
|
||||||
|
return DEV_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sht3xd_init_interrupt(struct device *dev)
|
||||||
|
{
|
||||||
|
struct sht3xd_data *drv_data = dev->driver_data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
drv_data->t_low = 0;
|
||||||
|
drv_data->rh_low = 0;
|
||||||
|
drv_data->t_high = 0xFFFF;
|
||||||
|
drv_data->rh_high = 0xFFFF;
|
||||||
|
|
||||||
|
/* set alert thresholds to match reamsurement ranges */
|
||||||
|
rc = sht3xd_write_reg(drv_data, SHT3XD_CMD_WRITE_TH_HIGH_SET, 0xFFFF);
|
||||||
|
if (rc != DEV_OK) {
|
||||||
|
DBG("Failed to write threshold high set value!\n");
|
||||||
|
return DEV_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sht3xd_write_reg(drv_data, SHT3XD_CMD_WRITE_TH_HIGH_CLEAR,
|
||||||
|
0xFFFF);
|
||||||
|
if (rc != DEV_OK) {
|
||||||
|
DBG("Failed to write threshold high clear value!\n");
|
||||||
|
return DEV_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sht3xd_write_reg(drv_data, SHT3XD_CMD_WRITE_TH_LOW_SET, 0);
|
||||||
|
if (rc != DEV_OK) {
|
||||||
|
DBG("Failed to write threshold low set value!\n");
|
||||||
|
return DEV_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sht3xd_write_reg(drv_data, SHT3XD_CMD_WRITE_TH_LOW_SET, 0);
|
||||||
|
if (rc != DEV_OK) {
|
||||||
|
DBG("Failed to write threshold low clear value!\n");
|
||||||
|
return DEV_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup gpio interrupt */
|
||||||
|
drv_data->gpio = device_get_binding(CONFIG_SHT3XD_GPIO_DEV_NAME);
|
||||||
|
if (drv_data->gpio == NULL) {
|
||||||
|
DBG("Failed to get pointer to %s device!\n",
|
||||||
|
CONFIG_SHT3XD_GPIO_DEV_NAME);
|
||||||
|
return DEV_INVALID_CONF;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_pin_configure(drv_data->gpio, CONFIG_SHT3XD_GPIO_PIN_NUM,
|
||||||
|
GPIO_DIR_IN | GPIO_INT | GPIO_INT_LEVEL |
|
||||||
|
GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE);
|
||||||
|
|
||||||
|
rc = gpio_set_callback(drv_data->gpio, sht3xd_gpio_callback);
|
||||||
|
if (rc != DEV_OK) {
|
||||||
|
DBG("Failed to set gpio callback!\n");
|
||||||
|
return DEV_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_SHT3XD_TRIGGER_OWN_FIBER)
|
||||||
|
nano_sem_init(&drv_data->gpio_sem);
|
||||||
|
|
||||||
|
fiber_start(drv_data->fiber_stack, CONFIG_SHT3XD_FIBER_STACK_SIZE,
|
||||||
|
(nano_fiber_entry_t)sht3xd_fiber, POINTER_TO_INT(dev),
|
||||||
|
0, CONFIG_SHT3XD_FIBER_PRIORITY, 0);
|
||||||
|
#elif defined(CONFIG_SHT3XD_TRIGGER_GLOBAL_FIBER)
|
||||||
|
drv_data->work.handler = sht3xd_fiber_cb;
|
||||||
|
drv_data->work.arg = dev;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return DEV_OK;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue