From 9d262d06987a58d4fd127f2cd66425017185a969 Mon Sep 17 00:00:00 2001 From: Corey Wharton Date: Thu, 6 Feb 2025 22:31:10 -0800 Subject: [PATCH] drivers: sensor: lsm6dsv16x: support setting and getting wake attributes Adds support for the SENSOR_ATTR_SLOPE_TH and SENSOR_ATTR_SLOPE_DUR attributes These set the sensitivity for the SENSOR_TRIG_DELTA trigger which uses the sensor's wakeup feature. Signed-off-by: Corey Wharton --- drivers/sensor/st/lsm6dsv16x/lsm6dsv16x.c | 100 +++++++++++++++++++++- 1 file changed, 96 insertions(+), 4 deletions(-) diff --git a/drivers/sensor/st/lsm6dsv16x/lsm6dsv16x.c b/drivers/sensor/st/lsm6dsv16x/lsm6dsv16x.c index 8172bfab337..4dadcebeff7 100644 --- a/drivers/sensor/st/lsm6dsv16x/lsm6dsv16x.c +++ b/drivers/sensor/st/lsm6dsv16x/lsm6dsv16x.c @@ -234,6 +234,55 @@ static int lsm6dsv16x_accel_range_set(const struct device *dev, int32_t range) return 0; } +#define LSM6DSV16X_WU_INACT_THS_W_MAX 5 +#define LSM6DSV16X_WAKE_UP_THS_MAX 0x3FU +static const float wu_inact_ths_w_lsb[] = {7.8125f, 15.625f, 31.25f, 62.5f, 125.0f, 250.0f}; + +static int lsm6dsv16x_accel_wake_threshold_set(const struct device *dev, + const struct sensor_value *val) +{ + const struct lsm6dsv16x_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lsm6dsv16x_act_thresholds_t thresholds; + + if (lsm6dsv16x_act_thresholds_get(ctx, &thresholds) < 0) { + LOG_DBG("failed to get thresholds"); + return -EIO; + } + + float val_mg = sensor_ms2_to_ug(val) / 1000.0f; + + thresholds.inactivity_cfg.wu_inact_ths_w = LSM6DSV16X_WU_INACT_THS_W_MAX; + thresholds.threshold = LSM6DSV16X_WAKE_UP_THS_MAX; + + for (uint8_t i = 0; i <= LSM6DSV16X_WU_INACT_THS_W_MAX; i++) { + if (val_mg < (wu_inact_ths_w_lsb[i] * (float)LSM6DSV16X_WAKE_UP_THS_MAX)) { + thresholds.inactivity_cfg.wu_inact_ths_w = i; + thresholds.threshold = (uint8_t)(val_mg / wu_inact_ths_w_lsb[i]); + break; + } + } + + return lsm6dsv16x_act_thresholds_set(ctx, &thresholds); +} + +static int lsm6dsv16x_accel_wake_duration_set(const struct device *dev, + const struct sensor_value *val) +{ + const struct lsm6dsv16x_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lsm6dsv16x_act_thresholds_t thresholds; + + if (lsm6dsv16x_act_thresholds_get(ctx, &thresholds) < 0) { + LOG_DBG("failed to get thresholds"); + return -EIO; + } + + thresholds.duration = MIN(val->val1, 3); + + return lsm6dsv16x_act_thresholds_set(ctx, &thresholds); +} + static int lsm6dsv16x_accel_config(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, @@ -248,6 +297,10 @@ static int lsm6dsv16x_accel_config(const struct device *dev, return lsm6dsv16x_accel_range_set(dev, sensor_ms2_to_g(val)); case SENSOR_ATTR_SAMPLING_FREQUENCY: return lsm6dsv16x_accel_odr_set(dev, val->val1); + case SENSOR_ATTR_SLOPE_TH: + return lsm6dsv16x_accel_wake_threshold_set(dev, val); + case SENSOR_ATTR_SLOPE_DUR: + return lsm6dsv16x_accel_wake_duration_set(dev, val); case SENSOR_ATTR_CONFIGURATION: switch (val->val1) { case 0: /* High Performance */ @@ -402,6 +455,43 @@ static int lsm6dsv16x_attr_set(const struct device *dev, return 0; } +static int lsm6dsv16x_accel_wake_threshold_get(const struct device *dev, struct sensor_value *val) +{ + const struct lsm6dsv16x_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lsm6dsv16x_act_thresholds_t thresholds; + float val_mg; + + if (lsm6dsv16x_act_thresholds_get(ctx, &thresholds) < 0) { + LOG_DBG("failed to get thresholds"); + return -EIO; + } + + val_mg = wu_inact_ths_w_lsb[thresholds.inactivity_cfg.wu_inact_ths_w]; + val_mg *= (float)thresholds.threshold; + + sensor_ug_to_ms2(1000.0f * val_mg, val); + + return 0; +} + +static int lsm6dsv16x_accel_wake_duration_get(const struct device *dev, struct sensor_value *val) +{ + const struct lsm6dsv16x_config *cfg = dev->config; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lsm6dsv16x_act_thresholds_t thresholds; + + if (lsm6dsv16x_act_thresholds_get(ctx, &thresholds) < 0) { + LOG_DBG("failed to get thresholds"); + return -EIO; + } + + val->val1 = thresholds.duration; + val->val2 = 0; + + return 0; +} + static int lsm6dsv16x_accel_get_config(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, @@ -429,6 +519,10 @@ static int lsm6dsv16x_accel_get_config(const struct device *dev, val->val2 = 0; break; } + case SENSOR_ATTR_SLOPE_TH: + return lsm6dsv16x_accel_wake_threshold_get(dev, val); + case SENSOR_ATTR_SLOPE_DUR: + return lsm6dsv16x_accel_wake_duration_get(dev, val); case SENSOR_ATTR_CONFIGURATION: { lsm6dsv16x_xl_mode_t mode; @@ -529,10 +623,8 @@ static int lsm6dsv16x_gyro_get_config(const struct device *dev, return 0; } -static int lsm6dsv16x_attr_get(const struct device *dev, - enum sensor_channel chan, - enum sensor_attribute attr, - struct sensor_value *val) +static int lsm6dsv16x_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) { if (!lsm6dsv16x_is_active(dev)) { return -EBUSY;