drivers: sensor: Added driver for the Würth Elektronik WSEN-TIDS sensor
Added sample for the WSEN-TIDS temperature sensor. Signed-off-by: Matthias Hauser <Matthias.Hauser@we-online.de>
This commit is contained in:
parent
6ecc6c3cec
commit
d4e9e5f46c
@ -113,6 +113,7 @@ add_subdirectory_ifdef(CONFIG_TEMP_KINETIS nxp_kinetis_temp)
|
||||
add_subdirectory_ifdef(CONFIG_TACH_XEC mchp_tach_xec)
|
||||
add_subdirectory_ifdef(CONFIG_WSEN_HIDS wsen_hids)
|
||||
add_subdirectory_ifdef(CONFIG_ITDS wsen_itds)
|
||||
add_subdirectory_ifdef(CONFIG_WSEN_TIDS wsen_tids)
|
||||
add_subdirectory_ifdef(CONFIG_MCUX_ACMP mcux_acmp)
|
||||
add_subdirectory_ifdef(CONFIG_TACH_NPCX nuvoton_tach_npcx)
|
||||
add_subdirectory_ifdef(CONFIG_ADC_CMP_NPCX nuvoton_adc_cmp_npcx)
|
||||
|
||||
@ -265,6 +265,8 @@ source "drivers/sensor/wsen_hids/Kconfig"
|
||||
|
||||
source "drivers/sensor/wsen_itds/Kconfig"
|
||||
|
||||
source "drivers/sensor/wsen_tids/Kconfig"
|
||||
|
||||
source "drivers/sensor/mcux_acmp/Kconfig"
|
||||
|
||||
source "drivers/sensor/nuvoton_tach_npcx/Kconfig"
|
||||
|
||||
7
drivers/sensor/wsen_tids/CMakeLists.txt
Normal file
7
drivers/sensor/wsen_tids/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
# Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(wsen_tids.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_WSEN_TIDS_TRIGGER wsen_tids_trigger.c)
|
||||
53
drivers/sensor/wsen_tids/Kconfig
Normal file
53
drivers/sensor/wsen_tids/Kconfig
Normal file
@ -0,0 +1,53 @@
|
||||
# Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menuconfig WSEN_TIDS
|
||||
bool "WSEN-TIDS temperature sensor"
|
||||
default y
|
||||
depends on DT_HAS_WE_WSEN_TIDS_ENABLED
|
||||
select I2C if $(dt_compat_on_bus,$(DT_COMPAT_WE_WSEN_TIDS),i2c)
|
||||
select HAS_WESENSORS
|
||||
help
|
||||
Enable driver for the WSEN-TIDS I2C-based temperature sensor.
|
||||
|
||||
if WSEN_TIDS
|
||||
|
||||
choice WSEN_TIDS_TRIGGER_MODE
|
||||
prompt "Trigger mode"
|
||||
default WSEN_TIDS_TRIGGER_NONE
|
||||
help
|
||||
Specify the type of triggering to be used by the driver.
|
||||
|
||||
config WSEN_TIDS_TRIGGER_NONE
|
||||
bool "No trigger"
|
||||
|
||||
config WSEN_TIDS_TRIGGER_GLOBAL_THREAD
|
||||
bool "Use global thread"
|
||||
depends on GPIO
|
||||
select WSEN_TIDS_TRIGGER
|
||||
|
||||
config WSEN_TIDS_TRIGGER_OWN_THREAD
|
||||
bool "Use own thread"
|
||||
depends on GPIO
|
||||
select WSEN_TIDS_TRIGGER
|
||||
|
||||
endchoice # WSEN_TIDS_TRIGGER_MODE
|
||||
|
||||
config WSEN_TIDS_TRIGGER
|
||||
bool
|
||||
|
||||
config WSEN_TIDS_THREAD_PRIORITY
|
||||
int "Thread priority"
|
||||
depends on WSEN_TIDS_TRIGGER_OWN_THREAD
|
||||
default 10
|
||||
help
|
||||
Priority of thread used by the driver to handle interrupts.
|
||||
|
||||
config WSEN_TIDS_THREAD_STACK_SIZE
|
||||
int "Thread stack size"
|
||||
depends on WSEN_TIDS_TRIGGER_OWN_THREAD
|
||||
default 1024
|
||||
help
|
||||
Stack size of thread used by the driver to handle interrupts.
|
||||
|
||||
endif # WSEN_TIDS
|
||||
229
drivers/sensor/wsen_tids/wsen_tids.c
Normal file
229
drivers/sensor/wsen_tids/wsen_tids.c
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT we_wsen_tids
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <zephyr/sys/__assert.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "wsen_tids.h"
|
||||
|
||||
LOG_MODULE_REGISTER(WSEN_TIDS, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
/*
|
||||
* List of supported output data rates. Index into this list is used as
|
||||
* argument for TIDS_setOutputDataRate()
|
||||
*/
|
||||
static const int32_t tids_odr_list[] = {
|
||||
25,
|
||||
50,
|
||||
100,
|
||||
200,
|
||||
};
|
||||
|
||||
static int tids_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
struct tids_data *data = dev->data;
|
||||
int16_t raw_temperature;
|
||||
|
||||
if ((chan != SENSOR_CHAN_ALL) && (chan != SENSOR_CHAN_AMBIENT_TEMP)) {
|
||||
LOG_ERR("Fetching is not supported on channel %d.", chan);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (TIDS_getRawTemperature(&data->sensor_interface, &raw_temperature) != WE_SUCCESS) {
|
||||
LOG_ERR("Failed to fetch data sample");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
data->temperature = raw_temperature;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tids_channel_get(const struct device *dev, enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
struct tids_data *data = dev->data;
|
||||
|
||||
if (chan == SENSOR_CHAN_AMBIENT_TEMP) {
|
||||
/* Convert temperature from 0.01 degrees Celsius to degrees Celsius */
|
||||
val->val1 = data->temperature / 100;
|
||||
val->val2 = ((int32_t)data->temperature % 100) * (1000000 / 100);
|
||||
} else {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set output data rate. See tids_odr_list for allowed values. */
|
||||
static int tids_odr_set(const struct device *dev, const struct sensor_value *odr)
|
||||
{
|
||||
struct tids_data *data = dev->data;
|
||||
int odr_index;
|
||||
|
||||
for (odr_index = 0; odr_index < ARRAY_SIZE(tids_odr_list); odr_index++) {
|
||||
if (odr->val1 == tids_odr_list[odr_index] && odr->val2 == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (odr_index == ARRAY_SIZE(tids_odr_list)) {
|
||||
/* ODR not allowed (was not found in tids_odr_list) */
|
||||
LOG_ERR("Bad sampling frequency %d.%d", odr->val1, abs(odr->val2));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (TIDS_setOutputDataRate(&data->sensor_interface, (TIDS_outputDataRate_t)odr_index) !=
|
||||
WE_SUCCESS) {
|
||||
LOG_ERR("Failed to set output data rate");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tids_attr_set(const struct device *dev, enum sensor_channel chan,
|
||||
enum sensor_attribute attr, const struct sensor_value *val)
|
||||
{
|
||||
if (chan != SENSOR_CHAN_ALL) {
|
||||
LOG_WRN("attr_set() is not supported on channel %d.", chan);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
switch (attr) {
|
||||
case SENSOR_ATTR_SAMPLING_FREQUENCY:
|
||||
return tids_odr_set(dev, val);
|
||||
|
||||
#ifdef CONFIG_WSEN_TIDS_TRIGGER
|
||||
case SENSOR_ATTR_LOWER_THRESH:
|
||||
return tids_threshold_set(dev, val, false);
|
||||
|
||||
case SENSOR_ATTR_UPPER_THRESH:
|
||||
return tids_threshold_set(dev, val, true);
|
||||
#endif /* CONFIG_WSEN_TIDS_TRIGGER */
|
||||
|
||||
default:
|
||||
LOG_ERR("Operation not supported.");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api tids_driver_api = {
|
||||
.attr_set = tids_attr_set,
|
||||
#if CONFIG_WSEN_TIDS_TRIGGER
|
||||
.trigger_set = tids_trigger_set,
|
||||
#endif
|
||||
.sample_fetch = tids_sample_fetch,
|
||||
.channel_get = tids_channel_get,
|
||||
};
|
||||
|
||||
static int tids_init(const struct device *dev)
|
||||
{
|
||||
const struct tids_config *const config = dev->config;
|
||||
struct tids_data *data = dev->data;
|
||||
int status;
|
||||
uint8_t device_id;
|
||||
struct sensor_value odr;
|
||||
|
||||
/* Initialize WE sensor interface */
|
||||
TIDS_getDefaultInterface(&data->sensor_interface);
|
||||
data->sensor_interface.interfaceType = WE_i2c;
|
||||
data->sensor_interface.handle = (void *)&config->bus_cfg.i2c;
|
||||
|
||||
/* First communication test - check device ID */
|
||||
if (TIDS_getDeviceID(&data->sensor_interface, &device_id) != WE_SUCCESS) {
|
||||
LOG_ERR("Failed to read device ID.");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (device_id != TIDS_DEVICE_ID_VALUE) {
|
||||
LOG_ERR("Invalid device ID 0x%x.", device_id);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Reset the sensor with an arbitrary off time of 5 us */
|
||||
TIDS_softReset(&data->sensor_interface, TIDS_enable);
|
||||
k_sleep(K_USEC(5));
|
||||
TIDS_softReset(&data->sensor_interface, TIDS_disable);
|
||||
|
||||
odr.val1 = tids_odr_list[config->odr];
|
||||
odr.val2 = 0;
|
||||
status = tids_odr_set(dev, &odr);
|
||||
if (status < 0) {
|
||||
LOG_ERR("Failed to set output data rate.");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (TIDS_enableBlockDataUpdate(&data->sensor_interface, TIDS_enable) != WE_SUCCESS) {
|
||||
LOG_ERR("Failed to enable block data update.");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (TIDS_enableContinuousMode(&data->sensor_interface, TIDS_enable) != WE_SUCCESS) {
|
||||
LOG_ERR("Failed to enable continuous mode.");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WSEN_TIDS_TRIGGER
|
||||
status = tids_init_interrupt(dev);
|
||||
if (status < 0) {
|
||||
LOG_ERR("Failed to initialize threshold interrupt.");
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
|
||||
#warning "TIDS driver enabled without any devices"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Device creation macros
|
||||
*/
|
||||
|
||||
#define TIDS_DEVICE_INIT(inst) \
|
||||
SENSOR_DEVICE_DT_INST_DEFINE(inst, \
|
||||
tids_init, \
|
||||
NULL, \
|
||||
&tids_data_##inst, \
|
||||
&tids_config_##inst, \
|
||||
POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, \
|
||||
&tids_driver_api);
|
||||
|
||||
#ifdef CONFIG_WSEN_TIDS_TRIGGER
|
||||
#define TIDS_CFG_IRQ(inst) \
|
||||
.gpio_threshold = GPIO_DT_SPEC_INST_GET(inst, int_gpios), \
|
||||
.high_threshold = DT_INST_PROP(inst, temp_high_threshold), \
|
||||
.low_threshold = DT_INST_PROP(inst, temp_low_threshold)
|
||||
#else
|
||||
#define TIDS_CFG_IRQ(inst)
|
||||
#endif /* CONFIG_WSEN_TIDS_TRIGGER */
|
||||
|
||||
/*
|
||||
* Main instantiation macro.
|
||||
*/
|
||||
#define TIDS_DEFINE(inst) \
|
||||
static struct tids_data tids_data_##inst; \
|
||||
static const struct tids_config tids_config_##inst = \
|
||||
{ \
|
||||
.bus_cfg = { \
|
||||
.i2c = I2C_DT_SPEC_INST_GET(inst), \
|
||||
}, \
|
||||
.odr = (TIDS_outputDataRate_t)(DT_INST_ENUM_IDX(inst, odr)), \
|
||||
COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, int_gpios), \
|
||||
(TIDS_CFG_IRQ(inst)), ()) \
|
||||
}; \
|
||||
TIDS_DEVICE_INIT(inst)
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(TIDS_DEFINE)
|
||||
77
drivers/sensor/wsen_tids/wsen_tids.h
Normal file
77
drivers/sensor/wsen_tids/wsen_tids.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_TIDS_WSEN_TIDS_H_
|
||||
#define ZEPHYR_DRIVERS_SENSOR_WSEN_TIDS_WSEN_TIDS_H_
|
||||
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
|
||||
#include <weplatform.h>
|
||||
|
||||
#include "WSEN_TIDS_2521020222501.h"
|
||||
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
|
||||
struct tids_data {
|
||||
/* WE sensor interface configuration */
|
||||
WE_sensorInterface_t sensor_interface;
|
||||
|
||||
/* Last temperature sample */
|
||||
int16_t temperature;
|
||||
|
||||
#ifdef CONFIG_WSEN_TIDS_TRIGGER
|
||||
const struct device *dev;
|
||||
|
||||
/* Callback for high/low limit interrupts */
|
||||
struct gpio_callback threshold_cb;
|
||||
|
||||
struct sensor_trigger threshold_trigger;
|
||||
sensor_trigger_handler_t threshold_handler;
|
||||
|
||||
#if defined(CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD)
|
||||
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_WSEN_TIDS_THREAD_STACK_SIZE);
|
||||
struct k_thread thread;
|
||||
struct k_sem threshold_sem;
|
||||
#elif defined(CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD)
|
||||
struct k_work work;
|
||||
#endif
|
||||
#endif /* CONFIG_WSEN_TIDS_TRIGGER */
|
||||
};
|
||||
|
||||
struct tids_config {
|
||||
union {
|
||||
const struct i2c_dt_spec i2c;
|
||||
} bus_cfg;
|
||||
|
||||
/* Output data rate */
|
||||
const TIDS_outputDataRate_t odr;
|
||||
|
||||
#ifdef CONFIG_WSEN_TIDS_TRIGGER
|
||||
/* Interrupt pin used for high and low limit interrupt events */
|
||||
const struct gpio_dt_spec gpio_threshold;
|
||||
|
||||
/* High temperature interrupt threshold */
|
||||
const int high_threshold;
|
||||
|
||||
/* Low temperature interrupt threshold */
|
||||
const int low_threshold;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WSEN_TIDS_TRIGGER
|
||||
int tids_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler);
|
||||
|
||||
int tids_threshold_set(const struct device *dev, const struct sensor_value *thresh_value,
|
||||
bool upper);
|
||||
|
||||
int tids_init_interrupt(const struct device *dev);
|
||||
#endif
|
||||
|
||||
int tids_i2c_init(const struct device *dev);
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_TIDS_WSEN_TIDS_H_ */
|
||||
238
drivers/sensor/wsen_tids/wsen_tids_trigger.c
Normal file
238
drivers/sensor/wsen_tids/wsen_tids_trigger.c
Normal file
@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT we_wsen_tids
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "wsen_tids.h"
|
||||
|
||||
LOG_MODULE_DECLARE(WSEN_TIDS, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
#define THRESHOLD_TEMPERATURE2REGISTER_OFFSET (double)63.
|
||||
#define THRESHOLD_TEMPERATURE2REGISTER_STEP (double)0.64
|
||||
|
||||
/* Enable/disable threshold interrupt handling */
|
||||
static inline void tids_setup_threshold_interrupt(const struct device *dev, bool enable)
|
||||
{
|
||||
const struct tids_config *cfg = dev->config;
|
||||
unsigned int flags = enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE;
|
||||
|
||||
gpio_pin_interrupt_configure_dt(&cfg->gpio_threshold, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is called when a "threshold exceeded" interrupt occurred. Triggers
|
||||
* asynchronous processing of the interrupt in tids_process_threshold_interrupt().
|
||||
*/
|
||||
static void tids_handle_threshold_interrupt(const struct device *dev)
|
||||
{
|
||||
struct tids_data *data = dev->data;
|
||||
|
||||
/* Disable interrupt handling until the interrupt has been processed */
|
||||
tids_setup_threshold_interrupt(dev, false);
|
||||
|
||||
#if defined(CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD)
|
||||
k_sem_give(&data->threshold_sem);
|
||||
#elif defined(CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD)
|
||||
k_work_submit(&data->work);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Is called after a "threshold exceeded" interrupt occurred.
|
||||
* Checks the sensor's status register for the limit exceeded flags and
|
||||
* calls the trigger handler if one of the flags is set.
|
||||
*/
|
||||
static void tids_process_threshold_interrupt(const struct device *dev)
|
||||
{
|
||||
struct tids_data *data = dev->data;
|
||||
TIDS_status_t status;
|
||||
|
||||
/*
|
||||
* Read the sensor's status register - this also causes the interrupt pin
|
||||
* to be de-asserted
|
||||
*/
|
||||
if (TIDS_getStatusRegister(&data->sensor_interface, &status) != WE_SUCCESS) {
|
||||
LOG_ERR("Failed to read status register");
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->threshold_handler != NULL &&
|
||||
(status.upperLimitExceeded != 0 || status.lowerLimitExceeded != 0)) {
|
||||
data->threshold_handler(dev, &data->threshold_trigger);
|
||||
}
|
||||
|
||||
if (data->threshold_handler != NULL) {
|
||||
tids_setup_threshold_interrupt(dev, true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enables/disables processing of the "threshold exceeded" interrupt. */
|
||||
int tids_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler)
|
||||
{
|
||||
struct tids_data *data = dev->data;
|
||||
const struct tids_config *cfg = dev->config;
|
||||
|
||||
if (trig->type != SENSOR_TRIG_THRESHOLD) {
|
||||
LOG_ERR("Unsupported sensor trigger");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
tids_setup_threshold_interrupt(dev, false);
|
||||
|
||||
data->threshold_handler = handler;
|
||||
if (handler == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
data->threshold_trigger = *trig;
|
||||
|
||||
tids_setup_threshold_interrupt(dev, true);
|
||||
|
||||
/*
|
||||
* If threshold interrupt is active we probably won't get the rising edge, so
|
||||
* invoke the callback manually.
|
||||
*/
|
||||
if (gpio_pin_get_dt(&cfg->gpio_threshold) > 0) {
|
||||
tids_handle_threshold_interrupt(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tids_threshold_callback(const struct device *dev, struct gpio_callback *cb,
|
||||
uint32_t pins)
|
||||
{
|
||||
struct tids_data *data = CONTAINER_OF(cb, struct tids_data, threshold_cb);
|
||||
|
||||
ARG_UNUSED(pins);
|
||||
|
||||
tids_handle_threshold_interrupt(data->dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD
|
||||
static void tids_thread(struct tids_data *tids)
|
||||
{
|
||||
while (true) {
|
||||
k_sem_take(&tids->threshold_sem, K_FOREVER);
|
||||
tids_process_threshold_interrupt(tids->dev);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD */
|
||||
|
||||
#ifdef CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD
|
||||
static void tids_work_cb(struct k_work *work)
|
||||
{
|
||||
struct tids_data *tids = CONTAINER_OF(work, struct tids_data, work);
|
||||
|
||||
tids_process_threshold_interrupt(tids->dev);
|
||||
}
|
||||
#endif /* CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD */
|
||||
|
||||
int tids_threshold_set(const struct device *dev, const struct sensor_value *thresh_value,
|
||||
bool upper)
|
||||
{
|
||||
struct tids_data *data = dev->data;
|
||||
double thresh = (sensor_value_to_double(thresh_value) / THRESHOLD_TEMPERATURE2REGISTER_STEP)
|
||||
+ THRESHOLD_TEMPERATURE2REGISTER_OFFSET;
|
||||
|
||||
if (thresh < 0) {
|
||||
thresh = 0;
|
||||
} else if (thresh > 255) {
|
||||
thresh = 255;
|
||||
}
|
||||
|
||||
if (upper) {
|
||||
if (TIDS_setTempHighLimit(&data->sensor_interface, (uint8_t)thresh) != WE_SUCCESS) {
|
||||
LOG_ERR("Failed to set high temperature threshold to %d.%d (%d).",
|
||||
thresh_value->val1, abs(thresh_value->val2), (uint8_t)thresh);
|
||||
return -EIO;
|
||||
}
|
||||
} else {
|
||||
if (TIDS_setTempLowLimit(&data->sensor_interface, (uint8_t)thresh) != WE_SUCCESS) {
|
||||
LOG_ERR("Failed to set low temperature threshold to %d.%d (%d).",
|
||||
thresh_value->val1, abs(thresh_value->val2), (uint8_t)thresh);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tids_init_interrupt(const struct device *dev)
|
||||
{
|
||||
struct tids_data *data = dev->data;
|
||||
const struct tids_config *cfg = dev->config;
|
||||
int status;
|
||||
struct sensor_value upper_limit;
|
||||
struct sensor_value lower_limit;
|
||||
|
||||
if (cfg->gpio_threshold.port == NULL) {
|
||||
LOG_ERR("int-gpios is not defined in the device tree.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!device_is_ready(cfg->gpio_threshold.port)) {
|
||||
LOG_ERR("Device %s is not ready", cfg->gpio_threshold.port->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data->dev = dev;
|
||||
|
||||
/* Setup threshold gpio interrupt */
|
||||
status = gpio_pin_configure_dt(&cfg->gpio_threshold, GPIO_INPUT);
|
||||
if (status < 0) {
|
||||
LOG_ERR("Failed to configure %s.%02u", cfg->gpio_threshold.port->name,
|
||||
cfg->gpio_threshold.pin);
|
||||
return status;
|
||||
}
|
||||
|
||||
gpio_init_callback(&data->threshold_cb, tids_threshold_callback,
|
||||
BIT(cfg->gpio_threshold.pin));
|
||||
|
||||
status = gpio_add_callback(cfg->gpio_threshold.port, &data->threshold_cb);
|
||||
if (status < 0) {
|
||||
LOG_ERR("Failed to set gpio callback.");
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable interrupt on high/low temperature (interrupt generation is enabled if at
|
||||
* least one threshold is non-zero)
|
||||
*/
|
||||
upper_limit.val1 = cfg->high_threshold;
|
||||
upper_limit.val2 = 0;
|
||||
lower_limit.val1 = cfg->low_threshold;
|
||||
lower_limit.val2 = 0;
|
||||
|
||||
status = tids_threshold_set(dev, &upper_limit, true);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = tids_threshold_set(dev, &lower_limit, false);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD)
|
||||
k_sem_init(&data->threshold_sem, 0, K_SEM_MAX_LIMIT);
|
||||
|
||||
k_thread_create(&data->thread, data->thread_stack, CONFIG_WSEN_TIDS_THREAD_STACK_SIZE,
|
||||
(k_thread_entry_t)tids_thread, data, NULL, NULL,
|
||||
K_PRIO_COOP(CONFIG_WSEN_TIDS_THREAD_PRIORITY), 0, K_NO_WAIT);
|
||||
#elif defined(CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD)
|
||||
data->work.handler = tids_work_cb;
|
||||
#endif
|
||||
|
||||
tids_setup_threshold_interrupt(dev, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
37
dts/bindings/sensor/we,wsen-tids.yaml
Normal file
37
dts/bindings/sensor/we,wsen-tids.yaml
Normal file
@ -0,0 +1,37 @@
|
||||
# Copyright (c) 2022 Würth Elektronik eiSos GmbH & Co. KG
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
Würth Elektronik WSEN-TIDS temperature sensor
|
||||
|
||||
compatible: "we,wsen-tids"
|
||||
|
||||
include: [sensor-device.yaml, i2c-device.yaml]
|
||||
|
||||
properties:
|
||||
int-gpios:
|
||||
type: phandle-array
|
||||
description: Threshold interrupt pin.
|
||||
Interrupt is active low by default.
|
||||
|
||||
odr:
|
||||
type: int
|
||||
required: true
|
||||
enum:
|
||||
- 25
|
||||
- 50
|
||||
- 100
|
||||
- 200
|
||||
description: |
|
||||
Sensor output data rate expressed in samples per second.
|
||||
Data rates supported by the chip are 25, 50, 100 and 200.
|
||||
|
||||
temp-high-threshold:
|
||||
type: int
|
||||
description: |
|
||||
Threshold for temperature high limit interrupt event.
|
||||
|
||||
temp-low-threshold:
|
||||
type: int
|
||||
description: |
|
||||
Threshold for temperature low limit interrupt event.
|
||||
@ -657,3 +657,10 @@ test_i2c_akm09918c: akm09918c@66 {
|
||||
compatible = "asahi-kasei,akm09918c";
|
||||
reg = <0x66>;
|
||||
};
|
||||
|
||||
test_i2c_wsen_tids: wsen_tids@67 {
|
||||
compatible = "we,wsen-tids";
|
||||
reg = <0x67>;
|
||||
int-gpios = <&test_gpio 0 0>;
|
||||
odr = <25>;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user