diff --git a/drivers/sensor/st/lis2dw12/Kconfig b/drivers/sensor/st/lis2dw12/Kconfig index 2241505902f..d2ccde49fed 100644 --- a/drivers/sensor/st/lis2dw12/Kconfig +++ b/drivers/sensor/st/lis2dw12/Kconfig @@ -63,10 +63,15 @@ config LIS2DW12_TAP endif # LIS2DW12_TRIGGER -config LIS2DW12_THRESHOLD - bool "Wakeup threshold trigger (via interrupt)" +config LIS2DW12_SLEEP + bool "Sleep mode" help - Enable the wakeup threshold trigger feature. + Enable sleep (inactivity) mode with ODR change when detected + +config LIS2DW12_WAKEUP + bool "Wakeup detection (via interrupt)" + help + Enable the wakeup detection feature. The wake-up interrupt signal is generated if a certain number of consecutive data exceed the configured threshold (config in DT). The threshold is applied to both positive and negative data: for diff --git a/drivers/sensor/st/lis2dw12/lis2dw12.c b/drivers/sensor/st/lis2dw12/lis2dw12.c index 005238ca87d..3f1e7580780 100644 --- a/drivers/sensor/st/lis2dw12/lis2dw12.c +++ b/drivers/sensor/st/lis2dw12/lis2dw12.c @@ -187,7 +187,7 @@ static inline int32_t sensor_ms2_to_mg(const struct sensor_value *ms2) } } -#if CONFIG_LIS2DW12_THRESHOLD +#if (CONFIG_LIS2DW12_SLEEP || CONFIG_LIS2DW12_WAKEUP) /* Converts a lis2dw12_fs_t range to its value in milli-g * Range can be 2/4/8/16G @@ -290,27 +290,50 @@ static int lis2dw12_attr_set_ff_dur(const struct device *dev, } #endif +#ifdef CONFIG_LIS2DW12_SLEEP +static int lis2dw12_attr_set_act_mode(const struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + const struct lis2dw12_device_config *cfg = dev->config; + struct lis2dw12_data *lis2dw12 = dev->data; + stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx; + lis2dw12_sleep_on_t sleep_val = val->val1 & 0x03U; + + /* can only be set for all directions at once */ + if (chan != SENSOR_CHAN_ACCEL_XYZ) { + return -EINVAL; + } + + return lis2dw12_act_mode_set(ctx, sleep_val); +} +#endif + static int lis2dw12_attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, const struct sensor_value *val) { -#if CONFIG_LIS2DW12_THRESHOLD switch (attr) { +#if (CONFIG_LIS2DW12_SLEEP || CONFIG_LIS2DW12_WAKEUP) case SENSOR_ATTR_UPPER_THRESH: case SENSOR_ATTR_LOWER_THRESH: return lis2dw12_attr_set_thresh(dev, chan, attr, val); +#endif +#ifdef CONFIG_LIS2DW12_FREEFALL + case SENSOR_ATTR_FF_DUR: + return lis2dw12_attr_set_ff_dur(dev, chan, attr, val); +#endif +#ifdef CONFIG_LIS2DW12_SLEEP + case SENSOR_ATTR_FEATURE_MASK: + return lis2dw12_attr_set_act_mode(dev, chan, attr, val); +#endif default: /* Do nothing */ break; } -#endif -#ifdef CONFIG_LIS2DW12_FREEFALL - if (attr == SENSOR_ATTR_FF_DUR) { - return lis2dw12_attr_set_ff_dur(dev, chan, attr, val); - } -#endif switch (chan) { case SENSOR_CHAN_ACCEL_X: @@ -527,13 +550,20 @@ static int lis2dw12_init(const struct device *dev) return ret; } -#ifdef CONFIG_LIS2DW12_THRESHOLD +#ifdef CONFIG_LIS2DW12_WAKEUP ret = lis2dw12_wkup_dur_set(ctx, cfg->wakeup_duration); if (ret < 0) { LOG_ERR("wakeup duration config error %d", ret); return ret; } -#endif /* CONFIG_LIS2DW12_THRESHOLD */ +#endif /* CONFIG_LIS2DW12_WAKEUP */ +#ifdef CONFIG_LIS2DW12_SLEEP + ret = lis2dw12_act_sleep_dur_set(ctx, cfg->sleep_duration); + if (ret < 0) { + LOG_ERR("sleep duration config error %d", ret); + return ret; + } +#endif /* CONFIG_LIS2DW12_SLEEP */ return 0; } @@ -580,11 +610,18 @@ static int lis2dw12_init(const struct device *dev) #define LIS2DW12_CONFIG_FREEFALL(inst) #endif /* CONFIG_LIS2DW12_FREEFALL */ -#ifdef CONFIG_LIS2DW12_THRESHOLD -#define LIS2DW12_CONFIG_THRESHOLD(inst) \ +#ifdef CONFIG_LIS2DW12_WAKEUP +#define LIS2DW12_CONFIG_WAKEUP(inst) \ .wakeup_duration = DT_INST_PROP(inst, wakeup_duration), #else -#define LIS2DW12_CONFIG_THRESHOLD(inst) +#define LIS2DW12_CONFIG_WAKEUP(inst) +#endif + +#ifdef CONFIG_LIS2DW12_SLEEP +#define LIS2DW12_CONFIG_SLEEP(inst) \ + .sleep_duration = DT_INST_PROP(inst, sleep_duration), +#else +#define LIS2DW12_CONFIG_SLEEP(inst) #endif #ifdef CONFIG_LIS2DW12_TRIGGER @@ -606,7 +643,8 @@ static int lis2dw12_init(const struct device *dev) .drdy_pulsed = DT_INST_PROP(inst, drdy_pulsed), \ LIS2DW12_CONFIG_TAP(inst) \ LIS2DW12_CONFIG_FREEFALL(inst) \ - LIS2DW12_CONFIG_THRESHOLD(inst) \ + LIS2DW12_CONFIG_WAKEUP(inst) \ + LIS2DW12_CONFIG_SLEEP(inst) \ COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, irq_gpios), \ (LIS2DW12_CFG_IRQ(inst)), ()) diff --git a/drivers/sensor/st/lis2dw12/lis2dw12.h b/drivers/sensor/st/lis2dw12/lis2dw12.h index 266f13bf789..b0a16660f64 100644 --- a/drivers/sensor/st/lis2dw12/lis2dw12.h +++ b/drivers/sensor/st/lis2dw12/lis2dw12.h @@ -97,13 +97,16 @@ struct lis2dw12_device_config { uint8_t tap_latency; uint8_t tap_quiet; #endif /* CONFIG_LIS2DW12_TAP */ +#ifdef CONFIG_LIS2DW12_SLEEP + uint8_t sleep_duration; +#endif #ifdef CONFIG_LIS2DW12_FREEFALL uint8_t freefall_duration; uint8_t freefall_threshold; #endif /* CONFIG_LIS2DW12_FREEFALL */ -#ifdef CONFIG_LIS2DW12_THRESHOLD +#ifdef CONFIG_LIS2DW12_WAKEUP uint8_t wakeup_duration; -#endif /* CONFIG_LIS2DW12_THRESHOLD */ +#endif /* CONFIG_LIS2DW12_WAKEUP */ #endif /* CONFIG_LIS2DW12_TRIGGER */ }; @@ -131,10 +134,14 @@ struct lis2dw12_data { sensor_trigger_handler_t double_tap_handler; const struct sensor_trigger *double_tap_trig; #endif /* CONFIG_LIS2DW12_TAP */ -#ifdef CONFIG_LIS2DW12_THRESHOLD - sensor_trigger_handler_t threshold_handler; - const struct sensor_trigger *threshold_trig; -#endif /* CONFIG_LIS2DW12_THRESHOLD */ +#ifdef CONFIG_LIS2DW12_WAKEUP + sensor_trigger_handler_t motion_handler; + const struct sensor_trigger *motion_trig; +#endif /* CONFIG_LIS2DW12_WAKEUP */ +#ifdef CONFIG_LIS2DW12_SLEEP + sensor_trigger_handler_t stationary_handler; + const struct sensor_trigger *stationary_trig; +#endif #ifdef CONFIG_LIS2DW12_FREEFALL sensor_trigger_handler_t freefall_handler; const struct sensor_trigger *freefall_trig; diff --git a/drivers/sensor/st/lis2dw12/lis2dw12_trigger.c b/drivers/sensor/st/lis2dw12/lis2dw12_trigger.c index e30d6d4c167..0f300d157b6 100644 --- a/drivers/sensor/st/lis2dw12/lis2dw12_trigger.c +++ b/drivers/sensor/st/lis2dw12/lis2dw12_trigger.c @@ -67,14 +67,14 @@ static int lis2dw12_enable_int(const struct device *dev, return lis2dw12_pin_int1_route_set(ctx, &int_route.ctrl4_int1_pad_ctrl); #endif /* CONFIG_LIS2DW12_TAP */ -#ifdef CONFIG_LIS2DW12_THRESHOLD +#ifdef CONFIG_LIS2DW12_WAKEUP /** * Trigger fires when channel reading transitions configured * thresholds. The thresholds are configured via the @ref * SENSOR_ATTR_LOWER_THRESH and @ref SENSOR_ATTR_UPPER_THRESH * attributes. */ - case SENSOR_TRIG_THRESHOLD: + case SENSOR_TRIG_MOTION: LOG_DBG("Setting int1_wu: %d\n", enable); lis2dw12_pin_int1_route_get(ctx, &int_route.ctrl4_int1_pad_ctrl); @@ -82,6 +82,21 @@ static int lis2dw12_enable_int(const struct device *dev, return lis2dw12_pin_int1_route_set(ctx, &int_route.ctrl4_int1_pad_ctrl); #endif +#ifdef CONFIG_LIS2DW12_SLEEP + /** + * Trigger fires when channel reading transitions configured + * thresholds for a certain time. The thresholds are configured + * via the @ref SENSOR_ATTR_LOWER_THRESH and @ref SENSOR_ATTR_UPPER_THRESH + * attributes. + */ + case SENSOR_TRIG_STATIONARY: + LOG_DBG("Setting int2_sleep_chg: %d\n", enable); + lis2dw12_pin_int2_route_get(ctx, + &int_route.ctrl5_int2_pad_ctrl); + int_route.ctrl5_int2_pad_ctrl.int2_sleep_chg = enable; + return lis2dw12_pin_int2_route_set(ctx, + &int_route.ctrl5_int2_pad_ctrl); +#endif #ifdef CONFIG_LIS2DW12_FREEFALL /** * Trigger fires when the readings does not include Earth's @@ -154,13 +169,22 @@ int lis2dw12_trigger_set(const struct device *dev, lis2dw12->double_tap_trig = trig; return lis2dw12_enable_int(dev, SENSOR_TRIG_DOUBLE_TAP, state); #endif /* CONFIG_LIS2DW12_TAP */ -#ifdef CONFIG_LIS2DW12_THRESHOLD - case SENSOR_TRIG_THRESHOLD: +#ifdef CONFIG_LIS2DW12_WAKEUP + case SENSOR_TRIG_MOTION: { LOG_DBG("Set trigger %d (handler: %p)\n", trig->type, handler); - lis2dw12->threshold_handler = handler; - lis2dw12->threshold_trig = trig; - return lis2dw12_enable_int(dev, SENSOR_TRIG_THRESHOLD, state); + lis2dw12->motion_handler = handler; + lis2dw12->motion_trig = trig; + return lis2dw12_enable_int(dev, SENSOR_TRIG_MOTION, state); + } +#endif +#ifdef CONFIG_LIS2DW12_SLEEP + case SENSOR_TRIG_STATIONARY: + { + LOG_DBG("Set trigger %d (handler: %p)\n", trig->type, handler); + lis2dw12->stationary_handler = handler; + lis2dw12->stationary_trig = trig; + return lis2dw12_enable_int(dev, SENSOR_TRIG_STATIONARY, state); } #endif #ifdef CONFIG_LIS2DW12_FREEFALL @@ -214,14 +238,28 @@ static int lis2dw12_handle_double_tap_int(const struct device *dev) } #endif /* CONFIG_LIS2DW12_TAP */ -#ifdef CONFIG_LIS2DW12_THRESHOLD +#ifdef CONFIG_LIS2DW12_WAKEUP static int lis2dw12_handle_wu_ia_int(const struct device *dev) { struct lis2dw12_data *lis2dw12 = dev->data; - sensor_trigger_handler_t handler = lis2dw12->threshold_handler; + sensor_trigger_handler_t handler = lis2dw12->motion_handler; if (handler) { - handler(dev, lis2dw12->threshold_trig); + handler(dev, lis2dw12->motion_trig); + } + + return 0; +} +#endif + +#ifdef CONFIG_LIS2DW12_SLEEP +static int lis2dw12_handle_sleep_change_int(const struct device *dev) +{ + struct lis2dw12_data *lis2dw12 = dev->data; + sensor_trigger_handler_t handler = lis2dw12->stationary_handler; + + if (handler) { + handler(dev, lis2dw12->stationary_trig); } return 0; @@ -265,11 +303,16 @@ static void lis2dw12_handle_interrupt(const struct device *dev) lis2dw12_handle_double_tap_int(dev); } #endif /* CONFIG_LIS2DW12_TAP */ -#ifdef CONFIG_LIS2DW12_THRESHOLD +#ifdef CONFIG_LIS2DW12_WAKEUP if (sources.all_int_src.wu_ia) { lis2dw12_handle_wu_ia_int(dev); } #endif +#ifdef CONFIG_LIS2DW12_SLEEP + if (sources.all_int_src.sleep_change_ia) { + lis2dw12_handle_sleep_change_int(dev); + } +#endif #ifdef CONFIG_LIS2DW12_FREEFALL if (sources.all_int_src.ff_ia) { lis2dw12_handle_ff_ia_int(dev); diff --git a/dts/bindings/sensor/st,lis2dw12-common.yaml b/dts/bindings/sensor/st,lis2dw12-common.yaml index c95a97da398..85baed2109c 100644 --- a/dts/bindings/sensor/st,lis2dw12-common.yaml +++ b/dts/bindings/sensor/st,lis2dw12-common.yaml @@ -247,3 +247,21 @@ properties: - 3 # LIS2DW12_DT_WAKEUP_4_ODR enum: [0, 1, 2, 3] + + sleep-duration: + type: int + default: 0 + description: | + The sleep duration. Default value is the register reset value (0000 -> 16*1/ODR). + If the accelerometer readings of the all axes are lower + than the wakeup threshold value for the sleep duration long, + then a sleep trigger occurs or the device goes in sleep mode. This value is 4 bits long in the + register and 1 LSB = 512 * 1/ODR. + + Value goes from 0 to 15 + + - 0 # LIS2DW12_DT_SLEEP_0_ODR + ... + - 15 # LIS2DW12_DT_SLEEP_15_ODR + + enum: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] diff --git a/include/zephyr/dt-bindings/sensor/lis2dw12.h b/include/zephyr/dt-bindings/sensor/lis2dw12.h index 9e5892ec0a5..e5d2e0482d5 100644 --- a/include/zephyr/dt-bindings/sensor/lis2dw12.h +++ b/include/zephyr/dt-bindings/sensor/lis2dw12.h @@ -39,4 +39,22 @@ #define LIS2DW12_DT_WAKEUP_3_ODR 2 #define LIS2DW12_DT_WAKEUP_4_ODR 3 +/* sleep duration */ +#define LIS2DW12_DT_SLEEP_0_ODR 0 +#define LIS2DW12_DT_SLEEP_1_ODR 1 +#define LIS2DW12_DT_SLEEP_2_ODR 2 +#define LIS2DW12_DT_SLEEP_3_ODR 3 +#define LIS2DW12_DT_SLEEP_4_ODR 4 +#define LIS2DW12_DT_SLEEP_5_ODR 5 +#define LIS2DW12_DT_SLEEP_6_ODR 6 +#define LIS2DW12_DT_SLEEP_7_ODR 7 +#define LIS2DW12_DT_SLEEP_8_ODR 8 +#define LIS2DW12_DT_SLEEP_9_ODR 9 +#define LIS2DW12_DT_SLEEP_10_ODR 10 +#define LIS2DW12_DT_SLEEP_11_ODR 11 +#define LIS2DW12_DT_SLEEP_12_ODR 12 +#define LIS2DW12_DT_SLEEP_13_ODR 13 +#define LIS2DW12_DT_SLEEP_14_ODR 14 +#define LIS2DW12_DT_SLEEP_15_ODR 15 + #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ST_LIS2DW12_H_ */