Skip to content

Commit

Permalink
drivers: sensor: lis2dw12: add inactivity detection
Browse files Browse the repository at this point in the history
Add inactivity mode or stationary detection

Signed-off-by: Andrew Sonzogni <[email protected]>
  • Loading branch information
andy3469 authored and fabiobaltieri committed Oct 3, 2024
1 parent c74dd3e commit 70de35d
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 34 deletions.
11 changes: 8 additions & 3 deletions drivers/sensor/st/lis2dw12/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
66 changes: 52 additions & 14 deletions drivers/sensor/st/lis2dw12/lis2dw12.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand All @@ -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)), ())

Expand Down
19 changes: 13 additions & 6 deletions drivers/sensor/st/lis2dw12/lis2dw12.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
};

Expand Down Expand Up @@ -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;
Expand Down
65 changes: 54 additions & 11 deletions drivers/sensor/st/lis2dw12/lis2dw12_trigger.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,36 @@ 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);
int_route.ctrl4_int1_pad_ctrl.int1_wu = enable;
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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
18 changes: 18 additions & 0 deletions dts/bindings/sensor/st,lis2dw12-common.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
18 changes: 18 additions & 0 deletions include/zephyr/dt-bindings/sensor/lis2dw12.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */

0 comments on commit 70de35d

Please sign in to comment.