Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions drivers/sensor/lis2dw12/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ config LIS2DW12_THREAD_STACK_SIZE
help
Stack size of thread used by the driver to handle interrupts.

config LIS2DW12_TAP
bool "Single/Double Tap recognition"
help
Enable Single/Double Tap recognition

choice
prompt "Sensor INT pin number"
default LIS2DW12_INT_PIN_1
Expand Down
14 changes: 12 additions & 2 deletions drivers/sensor/lis2dw12/lis2dw12.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ static int lis2dw12_set_range(struct device *dev, u16_t range)
lis2dw12->gain =
LIS2DW12_FS_TO_GAIN(LIS2DW12_FS_TO_REG(range),
shift_gain);
#ifdef CONFIG_LIS2DW12_TAP
lis2dw12->tap_ths =
LIS2DW12_FS_TO_TAP_THS(LIS2DW12_FS_TO_REG(range));
#endif /* CONFIG_LIS2DW12_TAP */
}

return err;
Expand All @@ -63,6 +67,7 @@ static int lis2dw12_set_range(struct device *dev, u16_t range)
static int lis2dw12_set_odr(struct device *dev, u16_t odr)
{
struct lis2dw12_data *lis2dw12 = dev->driver_data;
const struct lis2dw12_device_config *cfg = dev->config->config_info;

/* check if power off */
if (odr == 0) {
Expand All @@ -72,7 +77,8 @@ static int lis2dw12_set_odr(struct device *dev, u16_t odr)
LIS2DW12_ODR_POWER_OFF_VAL);
}

if (odr > LIS2DW12_MAX_ODR) {
if (odr > LIS2DW12_MAX_ODR ||
(odr > 200 && cfg->pm != LIS2DW12_HIGH_PERF)) {
LOG_ERR("ODR too high");
return -ENOTSUP;
}
Expand Down Expand Up @@ -194,7 +200,7 @@ static int lis2dw12_sample_fetch(struct device *dev, enum sensor_channel chan)
return -EIO;
}

if (!(tmp & LIS2DW12_STS_XLDA_UP)) {
if (!(tmp & LIS2DW12_STS_DRDY)) {
return -EAGAIN;
}

Expand Down Expand Up @@ -335,6 +341,10 @@ static int lis2dw12_init(struct device *dev)
cfg->pm == LIS2DW12_LOW_POWER_M1 ?
LIS2DW12_SHFT_GAIN_NOLP1 : 0);

#ifdef CONFIG_LIS2DW12_TAP
lis2dw12->tap_ths = LIS2DW12_FS_TO_TAP_THS(LIS2DW12_ACC_FS);
#endif /* CONFIG_LIS2DW12_TAP */

#ifdef CONFIG_LIS2DW12_TRIGGER
if (lis2dw12_init_interrupt(dev) < 0) {
LOG_ERR("Failed to initialize interrupts");
Expand Down
46 changes: 44 additions & 2 deletions drivers/sensor/lis2dw12/lis2dw12.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,16 @@ enum lis2dh_odr {
#define LIS2DW12_LIR_MASK BIT(4)

#define LIS2DW12_CTRL4_ADDR 0x23
#define LIS2DW12_INT1_STAP BIT(6)
#define LIS2DW12_INT1_DTAP BIT(3)
#define LIS2DW12_INT1_DRDY BIT(0)

#define LIS2DW12_CTRL5_ADDR 0x24
#define LIS2DW12_INT2_DRDY BIT(0)

#define LIS2DW12_CTRL6_ADDR 0x25
#define LIS2DW12_FS_MASK 0x30
#define LIS2DW12_FS_MASK (BIT(5) | BIT(4))
#define LIS2DW12_LOW_NOISE_MASK BIT(2)

enum lis2dh_fs {
LIS2DW12_FS_2G_VAL,
Expand All @@ -126,7 +129,9 @@ enum lis2dh_fs {
#define LIS2DW12_OUT_T_REG 0x26

#define LIS2DW12_STATUS_REG 0x27
#define LIS2DW12_STS_XLDA_UP 0x01
#define LIS2DW12_STS_DTAP BIT(4)
#define LIS2DW12_STS_STAP BIT(3)
#define LIS2DW12_STS_DRDY BIT(0)

#define LIS2DW12_OUT_X_L_ADDR 0x28

Expand All @@ -145,6 +150,37 @@ enum lis2dh_fs {
#define LIS2DW12_SHIFT_PM1 4
#define LIS2DW12_SHIFT_PMOTHER 2

#define LIS2DW12_TAP_THS_X 0x30
#define LIS2DW12_TAP_THS_Y 0x31
#define LIS2DW12_TAP_THS_Z 0x32
/* in TAP_THS_Y register */
#define LIS2DW12_TAP_PRI_MASK (BIT(7) | BIT(6) | BIT(5))
/* in TAP_THS_Z register */
#define LIS2DW12_TAP_EN_MASK (BIT(7) | BIT(6) | BIT(5))
/* in TAP_THS_X/Y/Z registers */
#define LIS2DW12_TAP_THS_MASK (BIT(4) | BIT(3) | BIT(2) | \
BIT(1) | BIT(0))

#define LIS2DW12_FS_2G_THS 9
#define LIS2DW12_FS_TO_TAP_THS(_fs) (LIS2DW12_FS_2G_THS >> ((_fs)))

#define LIS2DW12_INT_DUR 0x33
#define LIS2DW12_LATENCY_MASK (BIT(7) | BIT(6) | \
BIT(5) | BIT(4))
#define LIS2DW12_LATENCY_SHIFT 4
#define LIS2DW12_QUIET_MASK (BIT(3) | BIT(2))
#define LIS2DW12_QUIET_SHIFT 2
#define LIS2DW12_SHOCK_MASK (BIT(1) | BIT(0))
#define LIS2DW12_SHOCK_SHIFT 0

#define LIS2DW12_WAKE_UP_THS 0x34
#define LIS2DW12_DTAP_MASK BIT(7)

#define LIS2DW12_TAP_SRC 0x39

#define LIS2DW12_CTRL7_ADDR 0x3F
#define LIS2DW12_INTS_ENABLED BIT(5)

/**
* struct lis2dw12_device_config - lis2dw12 hw configuration
* @bus_name: Pointer to bus master identifier.
Expand Down Expand Up @@ -193,6 +229,7 @@ struct lis2dw12_data {
struct device *gpio;
struct gpio_callback gpio_cb;
sensor_trigger_handler_t handler_drdy;
sensor_trigger_handler_t handler_tap;

#if defined(CONFIG_LIS2DW12_TRIGGER_OWN_THREAD)
K_THREAD_STACK_MEMBER(thread_stack, CONFIG_LIS2DW12_THREAD_STACK_SIZE);
Expand All @@ -202,6 +239,11 @@ struct lis2dw12_data {
struct k_work work;
struct device *dev;
#endif /* CONFIG_LIS2DW12_TRIGGER_GLOBAL_THREAD */

#ifdef CONFIG_LIS2DW12_TAP
u8_t tap_ths;
#endif /* CONFIG_LIS2DW12_TAP */

#endif /* CONFIG_LIS2DW12_TRIGGER */
#if defined(DT_ST_LIS2DW12_0_CS_GPIO_CONTROLLER)
struct spi_cs_control cs_ctrl;
Expand Down
135 changes: 123 additions & 12 deletions drivers/sensor/lis2dw12/lis2dw12_trigger.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
LOG_MODULE_DECLARE(LIS2DW12);

/**
* lis2dw12_enable_int - enable selected int pin to generate interrupt
* lis2dw12_enable_drdy - enable selected int pin to generate DRDY interrupt
*/
static int lis2dw12_enable_int(struct device *dev, int enable)
static int lis2dw12_enable_drdy(struct device *dev, int enable)
{
const struct lis2dw12_device_config *cfg = dev->config->config_info;
struct lis2dw12_data *lis2dw12 = dev->driver_data;
Expand All @@ -39,6 +39,85 @@ static int lis2dw12_enable_int(struct device *dev, int enable)
enable);
}

#ifdef CONFIG_LIS2DW12_TAP
/*
* lis2dw12_enable_tap - enable single or double tap event
* (odr >= 400Hz)
*/
static int lis2dw12_enable_tap(struct device *dev, u8_t dtap, u8_t enable)
{
u8_t tmp;
u8_t int_dur, tap_int;
struct lis2dw12_data *lis2dw12 = dev->driver_data;

if (dtap) {
int_dur = 0x7f; /* latency = 7, shock = 3, quiet = 3 */
tap_int = LIS2DW12_INT1_DTAP;
} else {
int_dur = 0x06; /* latency = 0, shock = 2, quiet = 1 */
tap_int = LIS2DW12_INT1_STAP;
}

/* enable LOW noise */
if (lis2dw12->hw_tf->update_reg(lis2dw12, LIS2DW12_CTRL6_ADDR,
LIS2DW12_LOW_NOISE_MASK, 1)) {
LOG_ERR("enable low noise error");
return -EIO;
}

/* Set tap threshold for X axis. */
if (lis2dw12->hw_tf->update_reg(lis2dw12, LIS2DW12_TAP_THS_X,
LIS2DW12_TAP_THS_MASK,
lis2dw12->tap_ths)) {
LOG_ERR("set x-threshold error");
return -EIO;
}

/* Set tap threshold for Y axis and TAP priority Z-Y-X. */
tmp = (0xE0 | ((lis2dw12->tap_ths) & (LIS2DW12_TAP_THS_MASK)));
if (lis2dw12->hw_tf->write_reg(lis2dw12, LIS2DW12_TAP_THS_Y, tmp)) {
LOG_ERR("set y-threshold error");
return -EIO;
}

/* Set tap threshold for Z axis and tap detection on X, Y, Z-axis */
tmp = (0xE0 | ((lis2dw12->tap_ths) & (LIS2DW12_TAP_THS_MASK)));
if (lis2dw12->hw_tf->write_reg(lis2dw12, LIS2DW12_TAP_THS_Z, tmp)) {
LOG_ERR("set z-threshold error");
return -EIO;
}

/* Set interrupt duration params (latency/quiet/shock time windows */
if (lis2dw12->hw_tf->write_reg(lis2dw12, LIS2DW12_INT_DUR, int_dur)) {
LOG_ERR("set int duration error");
return -EIO;
}

/* Enable single-tap or double-tap event */
if (lis2dw12->hw_tf->update_reg(lis2dw12, LIS2DW12_WAKE_UP_THS,
LIS2DW12_DTAP_MASK, dtap)) {
LOG_ERR("enable single/double tap event error");
return -EIO;
}

/* Enable single-tap or double-tap interrupt */
if (lis2dw12->hw_tf->update_reg(lis2dw12, LIS2DW12_CTRL4_ADDR,
tap_int, enable)) {
LOG_ERR("enable single/double tap int error");
return -EIO;
}

/* Enable algo interrupts */
if (lis2dw12->hw_tf->update_reg(lis2dw12, LIS2DW12_CTRL7_ADDR,
LIS2DW12_INTS_ENABLED, enable)) {
LOG_ERR("enable algo int error");
return -EIO;
}

return 0;
}
#endif /* CONFIG_LIS2DW12_TAP */

/**
* lis2dw12_trigger_set - link external trigger to event data ready
*/
Expand All @@ -49,18 +128,29 @@ int lis2dw12_trigger_set(struct device *dev,
struct lis2dw12_data *lis2dw12 = dev->driver_data;
u8_t raw[6];

if (trig->chan == SENSOR_CHAN_ACCEL_XYZ) {
if (trig->type == SENSOR_TRIG_DATA_READY) {
lis2dw12->handler_drdy = handler;
if (handler) {
/* dummy read: re-trigger interrupt */
lis2dw12->hw_tf->read_data(lis2dw12,
LIS2DW12_OUT_X_L_ADDR, raw,
sizeof(raw));
return lis2dw12_enable_int(dev, LIS2DW12_EN_BIT);
return lis2dw12_enable_drdy(dev, LIS2DW12_EN_BIT);
} else {
return lis2dw12_enable_int(dev, LIS2DW12_DIS_BIT);
return lis2dw12_enable_drdy(dev, LIS2DW12_DIS_BIT);
}
}
#ifdef CONFIG_LIS2DW12_TAP
else if (trig->type == SENSOR_TRIG_TAP) {
lis2dw12->handler_tap = handler;

return lis2dw12_enable_tap(dev, 0, (handler) ? 1 : 0);
} else if (trig->type == SENSOR_TRIG_DOUBLE_TAP) {
lis2dw12->handler_tap = handler;

return lis2dw12_enable_tap(dev, 1, (handler) ? 1 : 0);
}
#endif /* CONFIG_LIS2DW12_TAP */

return -ENOTSUP;
}
Expand All @@ -71,15 +161,36 @@ int lis2dw12_trigger_set(struct device *dev,
*/
static void lis2dw12_handle_interrupt(void *arg)
{
u8_t status;
struct device *dev = 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;
struct sensor_trigger trigger;

if (lis2dw12->hw_tf->read_reg(lis2dw12,
LIS2DW12_STATUS_REG,
&status) < 0) {
LOG_ERR("status reading error");
}

if ((status & LIS2DW12_STS_DRDY) &&
(lis2dw12->handler_drdy != NULL)) {
trigger.type = SENSOR_TRIG_DATA_READY;
lis2dw12->handler_drdy(dev, &trigger);
}

if ((status & LIS2DW12_STS_STAP) &&
(lis2dw12->handler_tap != NULL)) {
trigger.type = SENSOR_TRIG_TAP;
lis2dw12->hw_tf->read_reg(lis2dw12, LIS2DW12_TAP_SRC, &status);
lis2dw12->handler_tap(dev, &trigger);
}

if (lis2dw12->handler_drdy != NULL) {
lis2dw12->handler_drdy(dev, &drdy_trigger);
if ((status & LIS2DW12_STS_DTAP) &&
(lis2dw12->handler_tap != NULL)) {
trigger.type = SENSOR_TRIG_DOUBLE_TAP;
lis2dw12->hw_tf->read_reg(lis2dw12, LIS2DW12_TAP_SRC, &status);
lis2dw12->handler_tap(dev, &trigger);
}

gpio_pin_enable_callback(lis2dw12->gpio, cfg->int_gpio_pin);
Expand Down Expand Up @@ -172,9 +283,9 @@ int lis2dw12_init_interrupt(struct device *dev)
return -EIO;
}

/* enable interrupt on int1/int2 in pulse mode */
/* enable interrupt on int1/int2 in lir mode */
if (lis2dw12->hw_tf->update_reg(lis2dw12, LIS2DW12_CTRL3_ADDR,
LIS2DW12_LIR_MASK, LIS2DW12_DIS_BIT)) {
LIS2DW12_LIR_MASK, 1)) {
return -EIO;
}

Expand Down