Commit 70de35d9 authored by Andrew Sonzogni's avatar Andrew Sonzogni Committed by Fabio Baltieri
Browse files

drivers: sensor: lis2dw12: add inactivity detection



Add inactivity mode or stationary detection

Signed-off-by: default avatarAndrew Sonzogni <andrew@safehear.fr>
parent c74dd3ee
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -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
+52 −14
Original line number Diff line number Diff line
@@ -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)), ())

+13 −6
Original line number Diff line number Diff line
@@ -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;
+54 −11
Original line number Diff line number Diff line
@@ -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->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->threshold_handler = handler;
		lis2dw12->threshold_trig = trig;
		return lis2dw12_enable_int(dev, SENSOR_TRIG_THRESHOLD, state);
		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);
+18 −0
Original line number Diff line number Diff line
@@ -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]
Loading