diff --git a/drivers/sensor/lis2dw12/Kconfig b/drivers/sensor/lis2dw12/Kconfig index 3d0d00a9e20..6d538877d6e 100644 --- a/drivers/sensor/lis2dw12/Kconfig +++ b/drivers/sensor/lis2dw12/Kconfig @@ -68,6 +68,94 @@ config LIS2DW12_INT_PIN_2 bool "int2" endchoice +menuconfig LIS2DW12_PULSE + bool "Pulse detection" + help + Enable pulse (single/double tap) detection + +if LIS2DW12_PULSE + +choice + prompt "Pulse interrupt source" + default LIS2DW12_ONLY_SINGLE + +config LIS2DW12_ONLY_SINGLE + bool "single" + +config LIS2DW12_SINGLE_DOUBLE + bool "single/double" + +endchoice + +config LIS2DW12_PULSE_THSX + hex "Pulse X-axis threshold" + range 0 0x1F + default 0x0E + help + Threshold to start the pulse-event detection procedure on the X-axis. + Threshold values for each axis are unsigned 5-bit corresponding + to an 2g acceleration full-scale range. + +config LIS2DW12_PULSE_THSY + hex "Pulse Y-axis threshold" + range 0 0x1F + default 0x0E + help + Threshold to start the pulse-event detection procedure on the Y-axis. + Threshold values for each axis are unsigned 5-bit corresponding + to an 2g acceleration full-scale range. + +config LIS2DW12_PULSE_THSZ + hex "Pulse Z-axis threshold" + range 0 0x1F + default 0x0E + help + Threshold to start the pulse-event detection procedure on the Z-axis. + Threshold values for each axis are unsigned 5-bit corresponding + to an 2g acceleration full-scale range. + +config LIS2DW12_PULSE_X + bool "Enable X axis for pulse" + default y + +config LIS2DW12_PULSE_Y + bool "Enable Y axis for pulse" + default y + +config LIS2DW12_PULSE_Z + bool "Enable Z axis for pulse" + default y + +config LIS2DW12_PULSE_SHOCK + hex "Shock value" + range 0 0x03 + default 0x00 + help + Maximum duration of over-threshold event: this register represents + the maximum time of an over-threshold signal detection to be + recognized as a tap event. Where 0 equals 4*1/ODR and 1LSB = 8*1/ODR. + +config LIS2DW12_PULSE_LTNCY + hex "Latency value" + range 0 0x0F + default 0x05 + help + When double-tap recognition is enabled, this register expresses + the maximum time between two successive detected taps to + determine a double-tap event. Where 0 equals 16*1/ODR and + 1LSB = 32*1/ODR. + +config LIS2DW12_PULSE_QUIET + hex "Quiet value" + range 0 0x03 + default 0x00 + help + Expected quiet time after a tap detection: this register represents + the time after the first detected tap in which there must not be + any overthreshold event. Where 0 equals 2*1/ODR and 1LSB = 4*1/ODR. + +endif # LIS2DW12_PULSE + endif # LIS2DW12_TRIGGER choice diff --git a/drivers/sensor/lis2dw12/lis2dw12.c b/drivers/sensor/lis2dw12/lis2dw12.c index 41a52f99efc..823fbdccc33 100644 --- a/drivers/sensor/lis2dw12/lis2dw12.c +++ b/drivers/sensor/lis2dw12/lis2dw12.c @@ -308,6 +308,64 @@ static int lis2dw12_init(struct device *dev) LOG_ERR("Failed to initialize interrupts"); return -EIO; } + +#ifdef CONFIG_LIS2DW12_PULSE + if (lis2dw12_tap_mode_set(lis2dw12->ctx, cfg->pulse_trigger) < 0) { + LOG_ERR("Failed to select pulse trigger mode"); + return -EIO; + } + + if (lis2dw12_tap_threshold_x_set(lis2dw12->ctx, + cfg->pulse_ths[0]) < 0) { + LOG_ERR("Failed to set tap X axis threshold"); + return -EIO; + } + + if (lis2dw12_tap_threshold_y_set(lis2dw12->ctx, + cfg->pulse_ths[1]) < 0) { + LOG_ERR("Failed to set tap Y axis threshold"); + return -EIO; + } + + if (lis2dw12_tap_threshold_z_set(lis2dw12->ctx, + cfg->pulse_ths[2]) < 0) { + LOG_ERR("Failed to set tap Z axis threshold"); + return -EIO; + } + + if (lis2dw12_tap_detection_on_x_set(lis2dw12->ctx, + CONFIG_LIS2DW12_PULSE_X) < 0) { + LOG_ERR("Failed to set tap detection on X axis"); + return -EIO; + } + + if (lis2dw12_tap_detection_on_y_set(lis2dw12->ctx, + CONFIG_LIS2DW12_PULSE_Y) < 0) { + LOG_ERR("Failed to set tap detection on Y axis"); + return -EIO; + } + + if (lis2dw12_tap_detection_on_z_set(lis2dw12->ctx, + CONFIG_LIS2DW12_PULSE_Z) < 0) { + LOG_ERR("Failed to set tap detection on Z axis"); + return -EIO; + } + + if (lis2dw12_tap_shock_set(lis2dw12->ctx, cfg->pulse_shock) < 0) { + LOG_ERR("Failed to set tap shock duration"); + return -EIO; + } + + if (lis2dw12_tap_dur_set(lis2dw12->ctx, cfg->pulse_ltncy) < 0) { + LOG_ERR("Failed to set tap latency"); + return -EIO; + } + + if (lis2dw12_tap_quiet_set(lis2dw12->ctx, cfg->pulse_quiet) < 0) { + LOG_ERR("Failed to set tap quiet time"); + return -EIO; + } +#endif /* CONFIG_LIS2DW12_PULSE */ #endif /* CONFIG_LIS2DW12_TRIGGER */ return 0; @@ -325,6 +383,19 @@ const struct lis2dw12_device_config lis2dw12_cfg = { .int_pin = 2, #endif /* CONFIG_LIS2DW12_INT_PIN */ +#ifdef CONFIG_LIS2DW12_PULSE +#if defined(CONFIG_LIS2DW12_ONLY_SINGLE) + .pulse_trigger = LIS2DW12_ONLY_SINGLE, +#elif defined(CONFIG_LIS2DW12_SINGLE_DOUBLE) + .pulse_trigger = LIS2DW12_BOTH_SINGLE_DOUBLE, +#endif + .pulse_ths[0] = CONFIG_LIS2DW12_PULSE_THSX, + .pulse_ths[1] = CONFIG_LIS2DW12_PULSE_THSY, + .pulse_ths[2] = CONFIG_LIS2DW12_PULSE_THSZ, + .pulse_shock = CONFIG_LIS2DW12_PULSE_SHOCK, + .pulse_ltncy = CONFIG_LIS2DW12_PULSE_LTNCY, + .pulse_quiet = CONFIG_LIS2DW12_PULSE_QUIET, +#endif /* CONFIG_LIS2DW12_PULSE */ #endif /* CONFIG_LIS2DW12_TRIGGER */ }; diff --git a/drivers/sensor/lis2dw12/lis2dw12.h b/drivers/sensor/lis2dw12/lis2dw12.h index 0895981eac2..5bbf811fbd7 100644 --- a/drivers/sensor/lis2dw12/lis2dw12.h +++ b/drivers/sensor/lis2dw12/lis2dw12.h @@ -88,6 +88,13 @@ struct lis2dw12_device_config { const char *int_gpio_port; u8_t int_gpio_pin; u8_t int_pin; +#ifdef CONFIG_LIS2DW12_PULSE + u8_t pulse_trigger; + u8_t pulse_ths[3]; + u8_t pulse_shock; + u8_t pulse_ltncy; + u8_t pulse_quiet; +#endif /* CONFIG_LIS2DW12_PULSE */ #endif /* CONFIG_LIS2DW12_TRIGGER */ }; @@ -106,8 +113,11 @@ struct lis2dw12_data { #ifdef CONFIG_LIS2DW12_TRIGGER struct device *gpio; struct gpio_callback gpio_cb; - sensor_trigger_handler_t handler_drdy; - + sensor_trigger_handler_t drdy_handler; +#ifdef CONFIG_LIS2DW12_PULSE + sensor_trigger_handler_t tap_handler; + sensor_trigger_handler_t double_tap_handler; +#endif /* CONFIG_LIS2DW12_PULSE */ #if defined(CONFIG_LIS2DW12_TRIGGER_OWN_THREAD) K_THREAD_STACK_MEMBER(thread_stack, CONFIG_LIS2DW12_THREAD_STACK_SIZE); struct k_thread thread; diff --git a/drivers/sensor/lis2dw12/lis2dw12_trigger.c b/drivers/sensor/lis2dw12/lis2dw12_trigger.c index 1d3267f4aab..ee2ec3a6f5d 100644 --- a/drivers/sensor/lis2dw12/lis2dw12_trigger.c +++ b/drivers/sensor/lis2dw12/lis2dw12_trigger.c @@ -21,26 +21,54 @@ LOG_MODULE_DECLARE(LIS2DW12); /** * lis2dw12_enable_int - enable selected int pin to generate interrupt */ -static int lis2dw12_enable_int(struct device *dev, int enable) +static int lis2dw12_enable_int(struct device *dev, + enum sensor_trigger_type type, int enable) { const struct lis2dw12_device_config *cfg = dev->config->config_info; struct lis2dw12_data *lis2dw12 = dev->driver_data; lis2dw12_reg_t int_route; - /* set interrupt */ if (cfg->int_pin == 1U) { + /* set interrupt for pin INT1 */ lis2dw12_pin_int1_route_get(lis2dw12->ctx, - &int_route.ctrl4_int1_pad_ctrl); - int_route.ctrl4_int1_pad_ctrl.int1_drdy = enable; - return lis2dw12_pin_int1_route_set(lis2dw12->ctx, - &int_route.ctrl4_int1_pad_ctrl); - } + &int_route.ctrl4_int1_pad_ctrl); - lis2dw12_pin_int2_route_get(lis2dw12->ctx, - &int_route.ctrl5_int2_pad_ctrl); - int_route.ctrl5_int2_pad_ctrl.int2_drdy = enable; - return lis2dw12_pin_int2_route_set(lis2dw12->ctx, - &int_route.ctrl5_int2_pad_ctrl); + switch (type) { + case SENSOR_TRIG_DATA_READY: + int_route.ctrl4_int1_pad_ctrl.int1_drdy = enable; + break; +#ifdef CONFIG_LIS2DW12_PULSE + case SENSOR_TRIG_TAP: + int_route.ctrl4_int1_pad_ctrl.int1_single_tap = enable; + break; + case SENSOR_TRIG_DOUBLE_TAP: + int_route.ctrl4_int1_pad_ctrl.int1_tap = enable; + break; +#endif /* CONFIG_LIS2DW12_PULSE */ + default: + LOG_ERR("Unsupported trigger interrupt route"); + return -ENOTSUP; + } + + return lis2dw12_pin_int1_route_set(lis2dw12->ctx, + &int_route.ctrl4_int1_pad_ctrl); + } else { + /* set interrupt for pin INT2 */ + lis2dw12_pin_int2_route_get(lis2dw12->ctx, + &int_route.ctrl5_int2_pad_ctrl); + + switch (type) { + case SENSOR_TRIG_DATA_READY: + int_route.ctrl5_int2_pad_ctrl.int2_drdy = enable; + break; + default: + LOG_ERR("Unsupported trigger interrupt route"); + return -ENOTSUP; + } + + return lis2dw12_pin_int2_route_set(lis2dw12->ctx, + &int_route.ctrl5_int2_pad_ctrl); + } } /** @@ -52,37 +80,109 @@ int lis2dw12_trigger_set(struct device *dev, { struct lis2dw12_data *lis2dw12 = dev->driver_data; axis3bit16_t raw; + int state = (handler != NULL) ? PROPERTY_ENABLE : PROPERTY_DISABLE; - if (trig->chan == SENSOR_CHAN_ACCEL_XYZ) { - lis2dw12->handler_drdy = handler; - if (handler) { + switch (trig->type) { + case SENSOR_TRIG_DATA_READY: + lis2dw12->drdy_handler = handler; + if (state) { /* dummy read: re-trigger interrupt */ lis2dw12_acceleration_raw_get(lis2dw12->ctx, raw.u8bit); - return lis2dw12_enable_int(dev, PROPERTY_ENABLE); - } else { - return lis2dw12_enable_int(dev, PROPERTY_DISABLE); } + return lis2dw12_enable_int(dev, SENSOR_TRIG_DATA_READY, state); + break; +#ifdef CONFIG_LIS2DW12_PULSE + case SENSOR_TRIG_TAP: + lis2dw12->tap_handler = handler; + return lis2dw12_enable_int(dev, SENSOR_TRIG_TAP, state); + break; + case SENSOR_TRIG_DOUBLE_TAP: + lis2dw12->double_tap_handler = handler; + return lis2dw12_enable_int(dev, SENSOR_TRIG_DOUBLE_TAP, state); + break; +#endif /* CONFIG_LIS2DW12_PULSE */ + default: + LOG_ERR("Unsupported sensor trigger"); + return -ENOTSUP; + } +} + +static int lis2dw12_handle_drdy_int(struct device *dev) +{ + struct lis2dw12_data *data = dev->driver_data; + + struct sensor_trigger drdy_trig = { + .type = SENSOR_TRIG_DATA_READY, + .chan = SENSOR_CHAN_ALL, + }; + + if (data->drdy_handler) { + data->drdy_handler(dev, &drdy_trig); } - return -ENOTSUP; + return 0; } +#ifdef CONFIG_LIS2DW12_PULSE +static int lis2dw12_handle_single_tap_int(struct device *dev) +{ + struct lis2dw12_data *data = dev->driver_data; + sensor_trigger_handler_t handler = data->tap_handler;; + + struct sensor_trigger pulse_trig = { + .type = SENSOR_TRIG_TAP, + .chan = SENSOR_CHAN_ALL, + }; + + if (handler) { + handler(dev, &pulse_trig); + } + + return 0; +} + +static int lis2dw12_handle_double_tap_int(struct device *dev) +{ + struct lis2dw12_data *data = dev->driver_data; + sensor_trigger_handler_t handler = data->double_tap_handler;; + + struct sensor_trigger pulse_trig = { + .type = SENSOR_TRIG_DOUBLE_TAP, + .chan = SENSOR_CHAN_ALL, + }; + + if (handler) { + handler(dev, &pulse_trig); + } + + return 0; +} +#endif /* CONFIG_LIS2DW12_PULSE */ + /** * lis2dw12_handle_interrupt - handle the drdy event * read data and call handler if registered any */ static void lis2dw12_handle_interrupt(void *arg) { - struct device *dev = arg; + struct device *dev = (struct device *)arg; struct lis2dw12_data *lis2dw12 = dev->driver_data; - struct sensor_trigger drdy_trigger = { - .type = SENSOR_TRIG_DATA_READY, - }; const struct lis2dw12_device_config *cfg = dev->config->config_info; + lis2dw12_all_sources_t sources; - if (lis2dw12->handler_drdy != NULL) { - lis2dw12->handler_drdy(dev, &drdy_trigger); + lis2dw12_all_sources_get(lis2dw12->ctx, &sources); + + if (sources.status_dup.drdy) { + lis2dw12_handle_drdy_int(dev); } +#ifdef CONFIG_LIS2DW12_PULSE + if (sources.status_dup.single_tap) { + lis2dw12_handle_single_tap_int(dev); + } + if (sources.status_dup.double_tap) { + lis2dw12_handle_double_tap_int(dev); + } +#endif /* CONFIG_LIS2DW12_PULSE */ gpio_pin_enable_callback(lis2dw12->gpio, cfg->int_gpio_pin); }