You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2018/11/15 00:59:19 UTC

[GitHub] vrahane closed pull request #1520: Lis2dh12 driver

vrahane closed pull request #1520: Lis2dh12 driver
URL: https://github.com/apache/mynewt-core/pull/1520
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/hw/drivers/sensors/lis2dh12/include/lis2dh12/lis2dh12.h b/hw/drivers/sensors/lis2dh12/include/lis2dh12/lis2dh12.h
index 7e13fcb9fd..ab4b807148 100644
--- a/hw/drivers/sensors/lis2dh12/include/lis2dh12/lis2dh12.h
+++ b/hw/drivers/sensors/lis2dh12/include/lis2dh12/lis2dh12.h
@@ -77,18 +77,191 @@ extern "C" {
 #define LIS2DH12_FS_8G                          0x20
 #define LIS2DH12_FS_16G                         0x30
 
+#define LIS2DH12_CLICK_SRC_IA               (1 << 6)
+#define LIS2DH12_CLICK_SRC_DCLICK           (1 << 5)
+#define LIS2DH12_CLICK_SRC_SCLICK           (1 << 4)
+#define LIS2DH12_CLICK_SRC_SIGN             (1 << 3)
+#define LIS2DH12_CLICK_SRC_Z                (1 << 2)
+#define LIS2DH12_CLICK_SRC_Y                (1 << 1)
+#define LIS2DH12_CLICK_SRC_X                (1 << 0)
+
+#define LIS2DH12_CTRL_REG6_I2_CLICK         (1 << 7)
+#define LIS2DH12_CTRL_REG6_I2_IA1           (1 << 6)
+#define LIS2DH12_CTRL_REG6_I2_IA2           (1 << 5)
+#define LIS2DH12_CTRL_REG6_I2_BOOT          (1 << 4)
+#define LIS2DH12_CTRL_REG6_I2_ACT           (1 << 3)
+#define LIS2DH12_CTRL_REG6_INT_POLARITY     (1 << 1)
+
+/* int1_src */
+#define LIS2DH12_INT1_IA                    (1 << 6)
+#define LIS2DH12_INT1_ZH                    (1 << 5)
+#define LIS2DH12_INT1_ZL                    (1 << 4)
+#define LIS2DH12_INT1_YH                    (1 << 3)
+#define LIS2DH12_INT1_YL                    (1 << 2)
+#define LIS2DH12_INT1_XH                    (1 << 1)
+#define LIS2DH12_INT1_XL                    (1 << 0)
+
+/* int2_src */
+#define LIS2DH12_INT2_IA                    (1 << 6)
+#define LIS2DH12_INT2_ZH                    (1 << 5)
+#define LIS2DH12_INT2_ZL                    (1 << 4)
+#define LIS2DH12_INT2_YH                    (1 << 3)
+#define LIS2DH12_INT2_YL                    (1 << 2)
+#define LIS2DH12_INT2_XH                    (1 << 1)
+#define LIS2DH12_INT2_XL                    (1 << 0)
+
+/* int_src */
+#define LIS2DH12_NOTIF_SRC_INT1_IA          (LIS2DH12_INT1_IA)
+#define LIS2DH12_NOTIF_SRC_INT1_ZH          (LIS2DH12_INT1_ZH)
+#define LIS2DH12_NOTIF_SRC_INT1_ZL          (LIS2DH12_INT1_ZL)
+#define LIS2DH12_NOTIF_SRC_INT1_YH          (LIS2DH12_INT1_YH)
+#define LIS2DH12_NOTIF_SRC_INT1_YL          (LIS2DH12_INT1_YL)
+#define LIS2DH12_NOTIF_SRC_INT1_XH          (LIS2DH12_INT1_XH)
+#define LIS2DH12_NOTIF_SRC_INT1_XL          (LIS2DH12_INT1_XL)
+#define LIS2DH12_NOTIF_SRC_INT2_IA          (LIS2DH12_INT2_IA << 8)
+#define LIS2DH12_NOTIF_SRC_INT2_ZH          (LIS2DH12_INT2_ZH << 8)
+#define LIS2DH12_NOTIF_SRC_INT2_ZL          (LIS2DH12_INT2_ZL << 8)
+#define LIS2DH12_NOTIF_SRC_INT2_YH          (LIS2DH12_INT2_YH << 8)
+#define LIS2DH12_NOTIF_SRC_INT2_YL          (LIS2DH12_INT2_YL << 8)
+#define LIS2DH12_NOTIF_SRC_INT2_XH          (LIS2DH12_INT2_XH << 8)
+#define LIS2DH12_NOTIF_SRC_INT2_XL          (LIS2DH12_INT2_XL << 8)
+
+/* int1 pin config - generate either data ready or in */
+#define LIS2DH12_CTRL_REG3_I1_CLICK         (1 << 7)
+#define LIS2DH12_CTRL_REG3_I1_IA1           (1 << 6)
+#define LIS2DH12_CTRL_REG3_I1_IA2           (1 << 5)
+#define LIS2DH12_CTRL_REG3_I1_ZYXDA         (1 << 4)
+#define LIS2DH12_CTRL_REG3_I1_WTM           (1 << 2)
+#define LIS2DH12_CTRL_REG3_I1_OVERRUN       (1 << 1)
+
+enum lis2dh12_read_mode {
+    LIS2DH12_READ_M_POLL = 0,
+    LIS2DH12_READ_M_STREAM = 1,
+};
+
+struct lis2dh12_notif_cfg {
+    sensor_event_type_t event;
+    uint8_t int_num;
+    uint16_t notif_src;
+    uint8_t int_cfg;
+};
+
+struct lis2dh12_tap_settings {
+    uint8_t en_xs  : 1; // Interrupt on X single tap
+    uint8_t en_ys  : 1; // Interrupt on Y single tap
+    uint8_t en_zs  : 1; // Interrupt on Z single tap
+    uint8_t en_xd  : 1; // Interrupt on X double tap
+    uint8_t en_yd  : 1; // Interrupt on Y double tap
+    uint8_t en_zd  : 1; // Interrupt on Z double tap
+    uint8_t hpf    : 1; // High pass filter enable
+
+    /* ths data is 7 bits, fs = +-2g */
+    int8_t click_ths;
+    /* shock is maximum time data can be over threshold to register as tap
+       LSB = 1/ODR */
+    int8_t time_limit;
+
+    /* latency is time between taps in double tap, LSB = 1/ODR */
+    uint8_t time_latency;
+    /* quiet is time after tap data is just below threshold
+       LSB = 1/ODR */
+    uint8_t time_window;
+};
+
+struct lis2dh12_int_cfg {
+    uint8_t cfg;
+    uint8_t ths;
+    uint8_t dur;
+};
+
+/* Read mode configuration */
+struct lis2dh12_read_mode_cfg {
+    enum lis2dh12_read_mode mode;
+    uint8_t int_num:1;
+    uint8_t int_cfg;
+};
+
 struct lis2dh12_cfg {
     uint8_t lc_rate;
     uint8_t lc_fs;
+
+    uint8_t reference;
+    /* Tap config */
+    struct lis2dh12_tap_settings tap;
+
+    /* Read mode config */
+    struct lis2dh12_read_mode_cfg read_mode;
+
+    /* Notif config */
+    struct lis2dh12_notif_cfg *notif_cfg;
+    uint8_t max_num_notif;
+
+    struct lis2dh12_int_cfg int_cfg[2];
+
+    uint8_t xen           : 1;
+    uint8_t yen           : 1;
+    uint8_t zen           : 1;
+    uint8_t hp_mode       : 2;
+    uint8_t hp_cut_off    : 2;
+    uint8_t hp_fds        : 1;
+    uint8_t hp_click      : 1;
+    uint8_t hp_ia1        : 1;
+    uint8_t hp_ia2        : 1;
+    uint8_t bdu           : 1;
+    uint8_t latch_int1    : 1;
+    uint8_t latch_int2    : 1;
+    uint8_t d4d_int1      : 1;
+    uint8_t d4d_int2      : 1;
+    uint8_t int_pp_od     : 1;
+
+    /* Power mode */
+    uint8_t power_mode;
+
+    /* Fifo config */
+    uint8_t fifo_mode;
+    uint8_t fifo_watermark;
+
+    /* Sleep/wakeup settings */
+    uint8_t act_ths;
+    uint8_t act_dur;
+
     uint8_t lc_pull_up_disc;
     sensor_type_t lc_s_mask;
 };
 
+/* Used to track interrupt state to wake any present waiters */
+struct lis2dh12_int {
+    /* Synchronize access to this structure */
+    os_sr_t lock;
+    /* Sleep waiting for an interrupt to occur */
+    struct os_sem wait;
+    /* Is the interrupt currently active */
+    bool active;
+    /* Is there a waiter currently sleeping */
+    bool asleep;
+    /* Configured interrupts */
+    struct sensor_int *ints;
+};
+
+/* Private per driver data */
+struct lis2dh12_pdd {
+    /* Notification event context */
+    struct sensor_notify_ev_ctx notify_ctx;
+    /* Inetrrupt state */
+    struct lis2dh12_int *interrupt;
+    /* Interrupt enabled on INT1 and INT2 pin (CTRL_REG3 and CTRL_REG6) */
+    uint8_t int_enable[2];
+    /* State of pin for sleep/wake up handling */
+    uint8_t int2_pin_state;
+};
+
 struct lis2dh12 {
     struct os_dev dev;
     struct sensor sensor;
     struct lis2dh12_cfg cfg;
+    struct lis2dh12_int intr;
     os_time_t last_read_time;
+    struct lis2dh12_pdd pdd;
 };
 
 /**
@@ -199,6 +372,17 @@ lis2dh12_pull_up_disc(struct sensor_itf *itf, uint8_t disconnect);
 int
 lis2dh12_reset(struct sensor_itf *itf);
 
+/**
+ * Set reference threshold
+ *
+ * @param the sensor interface
+ * @param threshold
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dh12_set_ref_thresh(struct sensor_itf *itf, uint8_t ths);
+
 /**
  * Enable interrupt 2
  *
@@ -206,7 +390,7 @@ lis2dh12_reset(struct sensor_itf *itf);
  * @param events to enable int for
  */
 int
-lis2dh12_enable_int2(struct sensor_itf *itf, uint8_t *reg);
+lis2dh12_enable_int2(struct sensor_itf *itf, uint8_t reg);
 
 /**
  * Enable interrupt 1
@@ -215,7 +399,7 @@ lis2dh12_enable_int2(struct sensor_itf *itf, uint8_t *reg);
  * @param events to enable int for
  */
 int
-lis2dh12_enable_int1(struct sensor_itf *itf, uint8_t *reg);
+lis2dh12_enable_int1(struct sensor_itf *itf, uint8_t reg);
 
 /**
  * Set interrupt threshold for int 1
@@ -243,17 +427,23 @@ lis2dh12_set_int2_thresh(struct sensor_itf *itf, uint8_t ths);
  * Clear interrupt 1
  *
  * @param the sensor interface
+ * @param src pointer to return interrupt source in
+ *
+ * @return 0 on success, non-zero on failure
  */
 int
-lis2dh12_clear_int1(struct sensor_itf *itf);
+lis2dh12_clear_int1(struct sensor_itf *itf, uint8_t *src);
 
 /**
  * Clear interrupt 2
  *
  * @param the sensor interface
+ * @param src pointer to return interrupt source in
+ *
+ * @return 0 on success, non-zero on failure
  */
 int
-lis2dh12_clear_int2(struct sensor_itf *itf);
+lis2dh12_clear_int2(struct sensor_itf *itf, uint8_t *src);
 
 /**
  * Set interrupt pin configuration for interrupt 1
@@ -321,6 +511,124 @@ lis2dh12_disable_int2(struct sensor_itf *itf);
 int
 lis2dh12_hpf_cfg(struct sensor_itf *itf, uint8_t reg);
 
+/**
+ * Set operating mode
+ *
+ * @param the sensor interface
+ * @param mode CTRL_REG1[3:0]:CTRL_REG4[3:0]
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dh12_set_op_mode(struct sensor_itf *itf, uint8_t mode);
+
+/**
+ * Clear click interrupt
+ *
+ * @param the sensor interface
+ * @param src pointer for active interrupts
+ */
+int
+lis2dh12_clear_click(struct sensor_itf *itf, uint8_t *src);
+
+/**
+ * Set click configuration register
+ *
+ * @param the sensor interface
+ * @param value to put in CLICK_CFG register
+ */
+int
+lis2dh12_set_click_cfg(struct sensor_itf *itf, uint8_t cfg);
+
+/**
+ * Set click threshold value
+ *
+ * @param the sensor interface
+ * @param value click threshold value
+ */
+int
+lis2dh12_set_click_threshold(struct sensor_itf *itf, uint8_t cfg);
+
+/**
+ * Set click time limit register
+ *
+ * This sets maximum time interval that can elapse between the start of
+ * the click-detection procedure and when the acceleration falls below
+ * thhreshold. 1 LSB = 1/ODR
+ *
+ * @param the sensor interface
+ * @param value to put in TIME_LIMIT register
+ */
+int
+lis2dh12_set_click_time_limit(struct sensor_itf *itf, uint8_t limit);
+
+/**
+ * Set click time latency register
+ *
+ * This function sets time interval that starts after the first click detection
+ * where the click-detection procedure is disabled. This is relevant for
+ * double click detection only.
+ *
+ * 1 LSB = 1/ODR
+ *
+ * @param the sensor interface
+ * @param value to put in TIME_LATENCY register
+ */
+int
+lis2dh12_set_click_time_latency(struct sensor_itf *itf, uint8_t latency);
+
+/**
+ * Set click time window register
+ *
+ * This function sets the maximum interval of time that can elapse after end of
+ * the latency interval in which click-detection procedure can start.
+ * This is relevant for double click detection only.
+ *
+ * 1 LSB = 1/ODR
+ *
+ * @param the sensor interface
+ * @param value to put in TIME_WINDOW register
+ */
+int
+lis2dh12_set_click_time_window(struct sensor_itf *itf, uint8_t window);
+
+/**
+ * Set activity threshold
+ *
+ * @param the sensor interface
+ * @param threshold 0..127 threshold value for activity/sleep detection
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dh12_set_activity_threshold(struct sensor_itf *itf, uint8_t threshold);
+
+/**
+ * Set activity duration
+ *
+ * @param the sensor interface
+ * @param duration Sleep-to-wake, return-to-sleep duration.
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dh12_set_activity_duration(struct sensor_itf *itf, uint8_t duration);
+
+/**
+ * Get number of samples in FIFO
+ *
+ * @param the sensor interface
+ * @param Pointer to return number of samples
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dh12_get_fifo_samples(struct sensor_itf *itf, uint8_t *samples);
+
+#if MYNEWT_VAL(LIS2DH12_CLI)
+int lis2dh12_shell_init(void);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hw/drivers/sensors/lis2dh12/src/lis2dh12.c b/hw/drivers/sensors/lis2dh12/src/lis2dh12.c
index fcb961e0f3..fcc272ab73 100644
--- a/hw/drivers/sensors/lis2dh12/src/lis2dh12.c
+++ b/hw/drivers/sensors/lis2dh12/src/lis2dh12.c
@@ -34,6 +34,100 @@
 #include "modlog/modlog.h"
 #include "stats/stats.h"
 #include <syscfg/syscfg.h>
+#include <sensor/sensor.h>
+#if LIS2DH12_PRINT_INTR
+#include "console/console.h"
+#endif
+
+#ifndef LIS2DH12_PRINT_INTR
+#define LIS2DH12_PRINT_INTR     (0)
+#endif
+
+/*
+ * Max time to wait for interrupt.
+ */
+#define LIS2DH12_MAX_INT_WAIT (4 * OS_TICKS_PER_SEC)
+
+static const struct lis2dh12_notif_cfg dflt_notif_cfg[] = {
+    {
+      .event     = SENSOR_EVENT_TYPE_SINGLE_TAP,
+      .int_num   = 0, // Should be 0, unless inactivity interrupt is not used
+      .notif_src = LIS2DH12_CLICK_SRC_SCLICK,
+      .int_cfg   = LIS2DH12_CTRL_REG3_I1_CLICK
+    },
+    {
+      .event     = SENSOR_EVENT_TYPE_DOUBLE_TAP,
+      .int_num   = 0, // Should be 0, unless inactivity interrupt is not used
+      .notif_src = LIS2DH12_CLICK_SRC_DCLICK,
+      .int_cfg   = LIS2DH12_CTRL_REG3_I1_CLICK
+    },
+    {
+      .event     = SENSOR_EVENT_TYPE_SLEEP,
+      .int_num   = 1, // Must be 1
+      .notif_src = 0, // Not used host pin is read for state
+      .int_cfg   = LIS2DH12_CTRL_REG6_I2_ACT
+    },
+    {
+      .event     = SENSOR_EVENT_TYPE_FREE_FALL,
+      .int_num   = 0, // Should be 0, unless inactivity interrupt is not used
+      .notif_src = LIS2DH12_NOTIF_SRC_INT2_IA,
+      .int_cfg   = LIS2DH12_CTRL_REG3_I1_IA2
+    },
+    {
+      .event     = SENSOR_EVENT_TYPE_WAKEUP,
+      .int_num   = 1, // Must be 1
+      .notif_src = 0, // Not used host pin is read for state
+      .int_cfg   = LIS2DH12_CTRL_REG6_I2_ACT
+    },
+    {
+      .event     = SENSOR_EVENT_TYPE_SLEEP_CHANGE,
+      .int_num   = 1, // Must be 1
+      .notif_src = 0, // Not used host pin is read for state
+      .int_cfg   = LIS2DH12_CTRL_REG6_I2_ACT
+    },
+    {
+      .event     = SENSOR_EVENT_TYPE_ORIENT_CHANGE,
+      .int_num   = 0, // Should be 0, unless inactivity interrupt is not used
+      .notif_src = LIS2DH12_NOTIF_SRC_INT1_IA,
+      .int_cfg   = LIS2DH12_CTRL_REG3_I1_IA1
+    },
+    {
+      .event     = SENSOR_EVENT_TYPE_ORIENT_X_L_CHANGE,
+      .int_num   = 0, // Should be 0, unless inactivity interrupt is not used
+      .notif_src = LIS2DH12_NOTIF_SRC_INT1_XL,
+      .int_cfg   = LIS2DH12_CTRL_REG3_I1_IA1
+    },
+    {
+      .event     = SENSOR_EVENT_TYPE_ORIENT_X_H_CHANGE,
+      .int_num   = 0, // Should be 0, unless inactivity interrupt is not used
+      .notif_src = LIS2DH12_NOTIF_SRC_INT1_XH,
+      .int_cfg   = LIS2DH12_CTRL_REG3_I1_IA1
+    },
+    {
+      .event     = SENSOR_EVENT_TYPE_ORIENT_Y_L_CHANGE,
+      .int_num   = 0, // Should be 0, unless inactivity interrupt is not used
+      .notif_src = LIS2DH12_NOTIF_SRC_INT1_YL,
+      .int_cfg   = LIS2DH12_CTRL_REG3_I1_IA1
+    },
+    {
+      .event     = SENSOR_EVENT_TYPE_ORIENT_Y_H_CHANGE,
+      .int_num   = 0, // Should be 0, unless inactivity interrupt is not used
+      .notif_src = LIS2DH12_NOTIF_SRC_INT1_YH,
+      .int_cfg   = LIS2DH12_CTRL_REG3_I1_IA1
+    },
+    {
+      .event     = SENSOR_EVENT_TYPE_ORIENT_Z_L_CHANGE,
+      .int_num   = 0, // Should be 0, unless inactivity interrupt is not used
+      .notif_src = LIS2DH12_NOTIF_SRC_INT1_ZL,
+      .int_cfg   = LIS2DH12_CTRL_REG3_I1_IA1
+    },
+    {
+      .event     = SENSOR_EVENT_TYPE_ORIENT_Z_H_CHANGE,
+      .int_num   = 0, // Should be 0, unless inactivity interrupt is not used
+      .notif_src = LIS2DH12_NOTIF_SRC_INT1_ZH,
+      .int_cfg   = LIS2DH12_CTRL_REG3_I1_IA1
+    }
+};
 
 static struct hal_spi_settings spi_lis2dh12_settings = {
     .data_order = HAL_SPI_MSB_FIRST,
@@ -46,12 +140,36 @@ static struct hal_spi_settings spi_lis2dh12_settings = {
 STATS_SECT_START(lis2dh12_stat_section)
     STATS_SECT_ENTRY(write_errors)
     STATS_SECT_ENTRY(read_errors)
+#if MYNEWT_VAL(LIS2DH12_NOTIF_STATS)
+    STATS_SECT_ENTRY(single_tap_notify)
+    STATS_SECT_ENTRY(double_tap_notify)
+    STATS_SECT_ENTRY(free_fall_notify)
+    STATS_SECT_ENTRY(sleep_notify)
+    STATS_SECT_ENTRY(wakeup_notify)
+    STATS_SECT_ENTRY(sleep_chg_notify)
+    STATS_SECT_ENTRY(orient_chg_notify)
+    STATS_SECT_ENTRY(orient_chg_x_notify)
+    STATS_SECT_ENTRY(orient_chg_y_notify)
+    STATS_SECT_ENTRY(orient_chg_z_notify)
+#endif
 STATS_SECT_END
 
 /* Define stat names for querying */
 STATS_NAME_START(lis2dh12_stat_section)
     STATS_NAME(lis2dh12_stat_section, write_errors)
     STATS_NAME(lis2dh12_stat_section, read_errors)
+#if MYNEWT_VAL(LIS2DH12_NOTIF_STATS)
+    STATS_NAME(lis2dh12_stat_section, single_tap_notify)
+    STATS_NAME(lis2dh12_stat_section, double_tap_notify)
+    STATS_NAME(lis2dh12_stat_section, free_fall_notify)
+    STATS_NAME(lis2dh12_stat_section, sleep_notify)
+    STATS_NAME(lis2dh12_stat_section, wakeup_notify)
+    STATS_NAME(lis2dh12_stat_section, sleep_chg_notify)
+    STATS_NAME(lis2dh12_stat_section, orient_chg_notify)
+    STATS_NAME(lis2dh12_stat_section, orient_chg_x_notify)
+    STATS_NAME(lis2dh12_stat_section, orient_chg_y_notify)
+    STATS_NAME(lis2dh12_stat_section, orient_chg_z_notify)
+#endif
 STATS_NAME_END(lis2dh12_stat_section)
 
 /* Global variable used to hold stats data */
@@ -65,6 +183,7 @@ static int lis2dh12_sensor_read(struct sensor *, sensor_type_t,
         sensor_data_func_t, void *, uint32_t);
 static int lis2dh12_sensor_get_config(struct sensor *, sensor_type_t,
         struct sensor_cfg *);
+static int lis2dh12_sensor_set_config(struct sensor *, void *);
 static int
 lis2dh12_sensor_set_trigger_thresh(struct sensor *, sensor_type_t,
                                    struct sensor_type_traits *);
@@ -74,13 +193,23 @@ lis2dh12_sensor_clear_low_thresh(struct sensor *, sensor_type_t);
 static int
 lis2dh12_sensor_clear_high_thresh(struct sensor *, sensor_type_t);
 
+static int lis2dh12_sensor_set_notification(struct sensor *,
+                                            sensor_event_type_t);
+static int lis2dh12_sensor_unset_notification(struct sensor *,
+                                              sensor_event_type_t);
+static int lis2dh12_sensor_handle_interrupt(struct sensor *);
+
 static const struct sensor_driver g_lis2dh12_sensor_driver = {
     .sd_read = lis2dh12_sensor_read,
+    .sd_set_config = lis2dh12_sensor_set_config,
     .sd_get_config = lis2dh12_sensor_get_config,
     /* Setting trigger threshold is optional */
     .sd_set_trigger_thresh = lis2dh12_sensor_set_trigger_thresh,
     .sd_clear_low_trigger_thresh = lis2dh12_sensor_clear_low_thresh,
-    .sd_clear_high_trigger_thresh = lis2dh12_sensor_clear_high_thresh
+    .sd_clear_high_trigger_thresh = lis2dh12_sensor_clear_high_thresh,
+    .sd_set_notification   = lis2dh12_sensor_set_notification,
+    .sd_unset_notification = lis2dh12_sensor_unset_notification,
+    .sd_handle_interrupt   = lis2dh12_sensor_handle_interrupt
 };
 
 /**
@@ -98,6 +227,11 @@ lis2dh12_i2c_readlen(struct sensor_itf *itf, uint8_t addr, uint8_t *buffer,
                      uint8_t len)
 {
     int rc;
+    if (len > 1)
+    {
+        addr |= 0x80;
+    }
+
     uint8_t payload[20] = { addr, 0, 0, 0, 0, 0, 0, 0,
                               0, 0, 0, 0, 0, 0, 0, 0,
                               0, 0, 0, 0};
@@ -379,6 +513,66 @@ lis2dh12_readlen(struct sensor_itf *itf, uint8_t addr, uint8_t *payload,
     return rc;
 }
 
+/**
+ * Write byte to sensor over different interfaces
+ *
+ * @param The sensor interface
+ * @param The register address to write to
+ * @param The value to write
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dh12_write8(struct sensor_itf *itf, uint8_t reg, uint8_t value)
+{
+    int rc;
+
+    rc = sensor_itf_lock(itf, MYNEWT_VAL(LIS2DH12_ITF_LOCK_TMO));
+    if (rc) {
+        return rc;
+    }
+
+    if (itf->si_type == SENSOR_ITF_I2C) {
+        rc = lis2dh12_i2c_writelen(itf, reg, &value, 1);
+    } else {
+        rc = lis2dh12_spi_writelen(itf, reg, &value, 1);
+    }
+
+    sensor_itf_unlock(itf);
+
+    return rc;
+}
+
+/**
+ * Read single register from LIS2DH12 sensor over different interfaces
+ *
+ * @param interface to use
+ * @param register address
+ * @param pinter to register data
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dh12_read8(struct sensor_itf *itf, uint8_t addr, uint8_t *reg)
+{
+    int rc;
+
+    rc = sensor_itf_lock(itf, MYNEWT_VAL(LIS2DH12_ITF_LOCK_TMO));
+    if (rc) {
+        return rc;
+    }
+
+    if (itf->si_type == SENSOR_ITF_I2C) {
+        rc = lis2dh12_i2c_readlen(itf, addr, reg, 1);
+    } else {
+        rc = lis2dh12_spi_readlen(itf, addr, reg, 1);
+    }
+
+    sensor_itf_unlock(itf);
+
+    return rc;
+}
+
 /**
  * Reset lis2dh12
  *
@@ -676,7 +870,8 @@ lis2dh12_set_fifo_mode(struct sensor_itf *itf, uint8_t mode)
         goto err;
     }
 
-    reg |= mode;
+    reg &= 0x3f;
+    reg |= mode << 6;
 
     rc = lis2dh12_writelen(itf, LIS2DH12_REG_FIFO_CTRL_REG, &reg, 1);
     if (rc) {
@@ -698,6 +893,27 @@ lis2dh12_set_fifo_mode(struct sensor_itf *itf, uint8_t mode)
     return rc;
 }
 
+/**
+ * Get Number of Samples in FIFO
+ *
+ * @param the sensor interface
+ * @param Pointer to return number of samples in
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dh12_get_fifo_samples(struct sensor_itf *itf, uint8_t *samples)
+{
+    uint8_t reg;
+    int rc;
+
+    rc = lis2dh12_read8(itf, LIS2DH12_REG_FIFO_SRC_REG, &reg);
+    if (rc == 0) {
+        *samples = reg & LIS2DH12_FIFO_SRC_FSS;
+    }
+
+    return rc;
+}
+
 /**
  *
  * Get operating mode
@@ -762,32 +978,42 @@ lis2dh12_set_op_mode(struct sensor_itf *itf, uint8_t mode)
     int rc;
     uint8_t reg;
 
-    rc = lis2dh12_readlen(itf, LIS2DH12_REG_CTRL_REG1, &reg, 1);
+    /* reset filtering block */
+    rc = lis2dh12_readlen(itf, LIS2DH12_REG_REFERENCE, &reg, 1);
     if (rc) {
         goto err;
     }
 
-    reg &= ~LIS2DH12_CTRL_REG1_LPEN;
-    reg |= ((mode & 0x80) >> 4);
+    rc = lis2dh12_readlen(itf, LIS2DH12_REG_CTRL_REG4, &reg, 1);
+    if (rc) {
+        goto err;
+    }
 
-    rc = lis2dh12_writelen(itf, LIS2DH12_REG_CTRL_REG1, &reg, 1);
+    /* Set HR bit */
+    reg &= ~LIS2DH12_CTRL_REG4_HR;
+    reg |= (mode & 0x08);
+
+    rc = lis2dh12_writelen(itf, LIS2DH12_REG_CTRL_REG4, &reg, 1);
     if (rc) {
         goto err;
     }
 
-    rc = lis2dh12_readlen(itf, LIS2DH12_REG_CTRL_REG4, &reg, 1);
+    /* Set LP bit */
+    rc = lis2dh12_readlen(itf, LIS2DH12_REG_CTRL_REG1, &reg, 1);
     if (rc) {
         goto err;
     }
 
-    reg &= ~LIS2DH12_CTRL_REG4_HR;
-    reg |= (mode & 0x08);
+    reg &= ~LIS2DH12_CTRL_REG1_LPEN;
+    reg |= ((mode & 0x80) >> 4);
 
-    rc = lis2dh12_writelen(itf, LIS2DH12_REG_CTRL_REG4, &reg, 1);
+    rc = lis2dh12_writelen(itf, LIS2DH12_REG_CTRL_REG1, &reg, 1);
     if (rc) {
         goto err;
     }
 
+
+
     os_time_delay(OS_TICKS_PER_SEC/1000 + 1);
 
     return 0;
@@ -795,6 +1021,31 @@ lis2dh12_set_op_mode(struct sensor_itf *itf, uint8_t mode)
     return rc;
 }
 
+int
+lis2dh12_get_fs(struct sensor_itf *itf, uint8_t *fs)
+{
+    int rc;
+
+    rc = lis2dh12_get_full_scale(itf, fs);
+    if (rc) {
+        return rc;
+    }
+
+    if (*fs == LIS2DH12_FS_2G) {
+        *fs = 2;
+    } else if (*fs == LIS2DH12_FS_4G) {
+        *fs = 4;
+    } else if (*fs == LIS2DH12_FS_8G) {
+        *fs = 8;
+    } else if (*fs == LIS2DH12_FS_16G) {
+        *fs = 16;
+    } else {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
 /**
  * Gets a new data sample from the light sensor.
  *
@@ -806,45 +1057,27 @@ lis2dh12_set_op_mode(struct sensor_itf *itf, uint8_t mode)
  * @return 0 on success, non-zero on failure
  */
 int
-lis2dh12_get_data(struct sensor_itf *itf, int16_t *x, int16_t *y, int16_t *z)
+lis2dh12_get_data(struct sensor_itf *itf, uint8_t fs, int16_t *x, int16_t *y, int16_t *z)
 {
     int rc;
-    uint8_t payload[6] = {0};
-    uint8_t fs;
 
+    uint8_t payload[6] = {0};
+    uint8_t status;
     *x = *y = *z = 0;
 
-    rc = lis2dh12_readlen(itf, LIS2DH12_REG_OUT_X_L, payload, 1);
-    rc |= lis2dh12_readlen(itf, LIS2DH12_REG_OUT_X_H, &payload[1], 1);
-    rc |= lis2dh12_readlen(itf, LIS2DH12_REG_OUT_Y_L, &payload[2], 1);
-    rc |= lis2dh12_readlen(itf, LIS2DH12_REG_OUT_Y_H, &payload[3], 1);
-    rc |= lis2dh12_readlen(itf, LIS2DH12_REG_OUT_Z_L, &payload[4], 1);
-    rc |= lis2dh12_readlen(itf, LIS2DH12_REG_OUT_Z_H, &payload[5], 1);
+    rc = lis2dh12_readlen(itf, LIS2DH12_REG_STATUS_REG, &status, 1);
     if (rc) {
         goto err;
     }
 
-    *x = payload[0] | (payload[1] << 8);
-    *y = payload[2] | (payload[3] << 8);
-    *z = payload[4] | (payload[5] << 8);
-
-    rc = lis2dh12_get_full_scale(itf, &fs);
+    rc = lis2dh12_readlen(itf, LIS2DH12_REG_OUT_X_L, payload, 6);
     if (rc) {
         goto err;
     }
 
-    if (fs == LIS2DH12_FS_2G) {
-        fs = 2;
-    } else if (fs == LIS2DH12_FS_4G) {
-        fs = 4;
-    } else if (fs == LIS2DH12_FS_8G) {
-        fs = 8;
-    } else if (fs == LIS2DH12_FS_16G) {
-        fs = 16;
-    } else {
-        rc = SYS_EINVAL;
-        goto err;
-    }
+    *x = payload[0] | (payload[1] << 8);
+    *y = payload[2] | (payload[3] << 8);
+    *z = payload[4] | (payload[5] << 8);
 
     /*
      * Since full scale is +/-(fs)g,
@@ -864,6 +1097,136 @@ lis2dh12_get_data(struct sensor_itf *itf, int16_t *x, int16_t *y, int16_t *z)
     return rc;
 }
 
+static int
+init_intpin(struct lis2dh12 *lis2dh12, int int_num, hal_gpio_irq_handler_t handler,
+            void *arg)
+{
+    hal_gpio_irq_trig_t trig;
+    int pin;
+    int rc;
+
+    pin = lis2dh12->sensor.s_itf.si_ints[int_num].host_pin;
+    if (pin >= 0) {
+        trig = lis2dh12->sensor.s_itf.si_ints[int_num].active;
+
+        rc = hal_gpio_irq_init(pin,
+                               handler,
+                               arg,
+                               trig,
+                               HAL_GPIO_PULL_NONE);
+    }
+    if (pin < 0) {
+        LIS2DH12_LOG(ERROR, "Interrupt pin not configured\n");
+        return SYS_EINVAL;
+    }
+
+    if (rc != 0) {
+        LIS2DH12_LOG(ERROR, "Failed to initialize interrupt pin %d\n", pin);
+        return rc;
+    }
+
+    return 0;
+}
+
+static void
+init_interrupt(struct lis2dh12_int *interrupt, struct sensor_int *ints)
+{
+    os_error_t error;
+
+    error = os_sem_init(&interrupt->wait, 0);
+    assert(error == OS_OK);
+
+    interrupt->active = false;
+    interrupt->asleep = false;
+    interrupt->ints = ints;
+}
+
+static void
+undo_interrupt(struct lis2dh12_int *interrupt)
+{
+    OS_ENTER_CRITICAL(interrupt->lock);
+    interrupt->active = false;
+    interrupt->asleep = false;
+    OS_EXIT_CRITICAL(interrupt->lock);
+}
+
+static int
+wait_interrupt(struct lis2dh12_int *interrupt, uint8_t int_num)
+{
+    bool wait;
+    os_error_t error;
+
+    OS_ENTER_CRITICAL(interrupt->lock);
+
+    /* Check if we did not missed interrupt */
+    if (hal_gpio_read(interrupt->ints[int_num].host_pin) ==
+                                            interrupt->ints[int_num].active) {
+        OS_EXIT_CRITICAL(interrupt->lock);
+        return OS_OK;
+    }
+
+    if (interrupt->active) {
+        interrupt->active = false;
+        wait = false;
+    } else {
+        interrupt->asleep = true;
+        wait = true;
+    }
+    OS_EXIT_CRITICAL(interrupt->lock);
+
+    if (wait) {
+        error = os_sem_pend(&interrupt->wait, LIS2DH12_MAX_INT_WAIT);
+        if (error == OS_TIMEOUT) {
+            return error;
+        }
+        assert(error == OS_OK);
+    }
+    return OS_OK;
+}
+
+static void
+wake_interrupt(struct lis2dh12_int *interrupt)
+{
+    bool wake;
+
+    OS_ENTER_CRITICAL(interrupt->lock);
+    if (interrupt->asleep) {
+        interrupt->asleep = false;
+        wake = true;
+    } else {
+        interrupt->active = true;
+        wake = false;
+    }
+    OS_EXIT_CRITICAL(interrupt->lock);
+
+    if (wake) {
+        os_error_t error;
+
+        error = os_sem_release(&interrupt->wait);
+        assert(error == OS_OK);
+    }
+}
+
+/**
+ * IRQ handler for interrupts for high/low threshold
+ *
+ * @param arg
+ */
+static void
+lis2dh12_int_irq_handler(void *arg)
+{
+    struct sensor *sensor = arg;
+    struct lis2dh12 *lis2dh12;
+
+    lis2dh12 = (struct lis2dh12 *)SENSOR_GET_DEVICE(sensor);
+
+    if (lis2dh12->pdd.interrupt) {
+        wake_interrupt(lis2dh12->pdd.interrupt);
+    }
+
+    sensor_mgr_put_interrupt_evt(sensor);
+}
+
 /**
  * Expects to be called back through os_dev_create().
  *
@@ -949,6 +1312,19 @@ lis2dh12_init(struct os_dev *dev, void *arg)
         }
     }
 
+    init_interrupt(&lis2dh12->intr, lis2dh12->sensor.s_itf.si_ints);
+
+    lis2dh12->pdd.notify_ctx.snec_sensor = sensor;
+    lis2dh12->pdd.interrupt = NULL;
+
+    rc = init_intpin(lis2dh12, 0, lis2dh12_int_irq_handler, sensor);
+    if (rc) {
+        return rc;
+    }
+    rc = init_intpin(lis2dh12, 1, lis2dh12_int_irq_handler, sensor);
+    if (rc) {
+        return rc;
+    }
     return 0;
 err:
     return rc;
@@ -983,71 +1359,771 @@ lis2dh12_set_self_test_mode(struct sensor_itf *itf, uint8_t mode)
     return rc;
 }
 
-static int
-lis2dh12_sensor_read(struct sensor *sensor, sensor_type_t type,
-        sensor_data_func_t data_func, void *data_arg, uint32_t timeout)
+/**
+ * Sets the interrupt push-pull/open-drain selection
+ *
+ * @param The sensor interface
+ * @param interrupt setting (0 = push-pull, 1 = open-drain)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dh12_set_int_pp_od(struct sensor_itf *itf, uint8_t mode)
 {
-    struct sensor_accel_data sad;
-    struct sensor_itf *itf;
-    int16_t x, y ,z;
-    float fx, fy ,fz;
     int rc;
+    uint8_t reg;
 
-    /* If the read isn't looking for accel or mag data, don't do anything. */
-    if (!(type & SENSOR_TYPE_ACCELEROMETER)) {
-        rc = SYS_EINVAL;
-        goto err;
+    rc = lis2dh12_read8(itf, LIS2DH12_REG_CTRL_REG6, &reg);
+    if (rc) {
+        return rc;
     }
 
-    itf = SENSOR_GET_ITF(sensor);
-
-    x = y = z = 0;
-
-    if (itf->si_type == SENSOR_ITF_SPI) {
-
-        rc = hal_spi_disable(sensor->s_itf.si_num);
-        if (rc) {
-            goto err;
-        }
+    reg &= ~LIS2DH12_CTRL_REG6_INT_POLARITY;
+    reg |= mode ? LIS2DH12_CTRL_REG6_INT_POLARITY : 0;
 
-        rc = hal_spi_config(sensor->s_itf.si_num, &spi_lis2dh12_settings);
-        if (rc == EINVAL) {
-            /* If spi is already enabled, for nrf52, it returns -1, We should not
-             * fail if the spi is already enabled
-             */
-            goto err;
-        }
+    return lis2dh12_write8(itf, LIS2DH12_REG_CTRL_REG6, reg);
+}
 
-        rc = hal_spi_enable(sensor->s_itf.si_num);
-        if (rc) {
-            goto err;
-        }
-    }
+/**
+ * Gets the interrupt push-pull/open-drain selection
+ *
+ * @param The sensor interface
+ * @param ptr to store setting (0 = push-pull, 1 = open-drain)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dh12_get_int_pp_od(struct sensor_itf *itf, uint8_t *mode)
+{
+    int rc;
+    uint8_t reg;
 
-    rc = lis2dh12_get_data(itf, &x, &y, &z);
+    rc = lis2dh12_read8(itf, LIS2DH12_REG_CTRL_REG6, &reg);
     if (rc) {
-        goto err;
+        return rc;
     }
 
-    /* converting values from mg to ms^2 */
+    *mode = (reg & LIS2DH12_CTRL_REG6_INT_POLARITY) ? 1 : 0;
+
+    return 0;
+}
+
+int
+lis2dh12_clear_click(struct sensor_itf *itf, uint8_t *src)
+{
+    return lis2dh12_read8(itf, LIS2DH12_REG_CLICK_SRC, src);
+}
+
+int
+lis2dh12_set_click_cfg(struct sensor_itf *itf, uint8_t cfg)
+{
+    return lis2dh12_write8(itf, LIS2DH12_REG_CLICK_CFG, cfg);
+}
+
+int
+lis2dh12_set_click_threshold(struct sensor_itf *itf, uint8_t cfg)
+{
+    return lis2dh12_write8(itf, LIS2DH12_REG_CLICK_THS, cfg);
+}
+
+int
+lis2dh12_set_click_time_limit(struct sensor_itf *itf, uint8_t limit)
+{
+    return lis2dh12_write8(itf, LIS2DH12_REG_TIME_LIMIT, limit);
+}
+
+int
+lis2dh12_set_click_time_latency(struct sensor_itf *itf, uint8_t latency)
+{
+    return lis2dh12_write8(itf, LIS2DH12_REG_TIME_LATENCY, latency);
+}
+
+int
+lis2dh12_set_click_time_window(struct sensor_itf *itf, uint8_t window)
+{
+    return lis2dh12_write8(itf, LIS2DH12_REG_TIME_WINDOW, window);
+}
+
+int
+lis2dh12_set_activity_threshold(struct sensor_itf *itf, uint8_t threshold)
+{
+    return lis2dh12_write8(itf, LIS2DH12_REG_ACT_THS, threshold);
+}
+
+int
+lis2dh12_set_activity_duration(struct sensor_itf *itf, uint8_t duration)
+{
+    return lis2dh12_write8(itf, LIS2DH12_REG_ACT_DUR, duration);
+}
+
+static int
+disable_interrupt(struct sensor *sensor, uint8_t int_to_disable, uint8_t int_num)
+{
+    struct lis2dh12 *lis2dh12;
+    struct lis2dh12_pdd *pdd;
+    struct sensor_itf *itf;
+    int rc;
+
+    if (int_to_disable == 0) {
+        return SYS_EINVAL;
+    }
+
+    lis2dh12 = (struct lis2dh12 *)SENSOR_GET_DEVICE(sensor);
+    itf = SENSOR_GET_ITF(sensor);
+    pdd = &lis2dh12->pdd;
+
+    pdd->int_enable[int_num] &= ~(int_to_disable);
+
+    /* disable GPIO int if no longer needed */
+    if (!pdd->int_enable[int_num]) {
+        hal_gpio_irq_disable(itf->si_ints[int_num].host_pin);
+    }
+
+    /* update interrupt setup in device */
+    if (int_num == 0) {
+        rc = lis2dh12_set_int1_pin_cfg(itf, pdd->int_enable[int_num]);
+    } else {
+        rc = lis2dh12_set_int2_pin_cfg(itf, pdd->int_enable[int_num]);
+    }
+
+    return rc;
+}
+
+
+static int
+enable_interrupt(struct sensor *sensor, uint8_t int_to_enable, uint8_t int_num)
+{
+    struct lis2dh12 *lis2dh12;
+    struct lis2dh12_pdd *pdd;
+    struct sensor_itf *itf;
+    int rc;
+
+    if (!int_to_enable) {
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    lis2dh12 = (struct lis2dh12 *)SENSOR_GET_DEVICE(sensor);
+    itf = SENSOR_GET_ITF(sensor);
+    pdd = &lis2dh12->pdd;
+
+    /* if no interrupts are currently in use enable int pin */
+    if (!pdd->int_enable[int_num]) {
+        hal_gpio_irq_enable(itf->si_ints[int_num].host_pin);
+    }
+
+    if ((pdd->int_enable[int_num] & int_to_enable) == 0) {
+        pdd->int_enable[int_num] |= int_to_enable;
+
+        /* enable interrupt in device */
+        if (int_num == 0) {
+            rc = lis2dh12_set_int1_pin_cfg(itf, pdd->int_enable[int_num]);
+        } else {
+            rc = lis2dh12_set_int2_pin_cfg(itf, pdd->int_enable[int_num]);
+        }
+
+        if (rc) {
+            disable_interrupt(sensor, int_to_enable, int_num);
+            goto err;
+        }
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+static int
+lis2dh12_do_read(struct sensor *sensor, sensor_data_func_t data_func,
+                 void * data_arg, uint8_t fs)
+{
+    struct sensor_accel_data sad;
+    struct sensor_itf *itf;
+    int16_t x, y ,z;
+    float fx, fy ,fz;
+    int rc;
+
+    itf = SENSOR_GET_ITF(sensor);
+
+    x = y = z = 0;
+
+    rc = lis2dh12_get_data(itf, fs, &x, &y, &z);
+    if (rc) {
+        goto err;
+    }
+
+    /* converting values from mg to ms^2 */
     lis2dh12_calc_acc_ms2(x, &fx);
     lis2dh12_calc_acc_ms2(y, &fy);
     lis2dh12_calc_acc_ms2(z, &fz);
 
-    sad.sad_x = fx;
-    sad.sad_y = fy;
-    sad.sad_z = fz;
+    sad.sad_x = fx;
+    sad.sad_y = fy;
+    sad.sad_z = fz;
+
+    sad.sad_x_is_valid = 1;
+    sad.sad_y_is_valid = 1;
+    sad.sad_z_is_valid = 1;
+
+    /* Call data function */
+    rc = data_func(sensor, data_arg, &sad, SENSOR_TYPE_ACCELEROMETER);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Do accelerometer polling reads
+ *
+ * @param The sensor ptr
+ * @param The sensor type
+ * @param The function pointer to invoke for each accelerometer reading.
+ * @param The opaque pointer that will be passed in to the function.
+ * @param If non-zero, how long the stream should run in milliseconds.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+lis2dh12_poll_read(struct sensor *sensor, sensor_type_t sensor_type,
+                   sensor_data_func_t data_func, void *data_arg,
+                   uint32_t timeout)
+{
+    struct lis2dh12 *lis2dh12;
+    struct lis2dh12_cfg *cfg;
+    struct sensor_itf *itf;
+    uint8_t fs;
+    int rc;
+
+    lis2dh12 = (struct lis2dh12 *)SENSOR_GET_DEVICE(sensor);
+    itf = SENSOR_GET_ITF(sensor);
+    cfg = &lis2dh12->cfg;
+
+    /* If the read isn't looking for accel data, don't do anything. */
+    if (!(sensor_type & SENSOR_TYPE_ACCELEROMETER)) {
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    if (cfg->read_mode.mode != LIS2DH12_READ_M_POLL) {
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    rc = lis2dh12_get_fs(itf, &fs);
+    if (rc) {
+        goto err;
+    }
+
+    rc = lis2dh12_do_read(sensor, data_func, data_arg, fs);
+    if (rc) {
+        goto err;
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+int
+lis2dh12_stream_read(struct sensor *sensor,
+                     sensor_type_t sensor_type,
+                     sensor_data_func_t read_func,
+                     void *read_arg,
+                     uint32_t time_ms)
+{
+    struct lis2dh12_pdd *pdd;
+    struct lis2dh12 *lis2dh12;
+    struct sensor_itf *itf;
+    struct lis2dh12_cfg *cfg;
+    os_time_t time_ticks;
+    os_time_t stop_ticks = 0;
+    uint8_t fifo_samples;
+    uint8_t fs;
+    int rc, rc2;
+
+    /* If the read isn't looking for accel data, don't do anything. */
+    if (!(sensor_type & SENSOR_TYPE_ACCELEROMETER)) {
+        return SYS_EINVAL;
+    }
+
+    lis2dh12 = (struct lis2dh12 *)SENSOR_GET_DEVICE(sensor);
+    itf = SENSOR_GET_ITF(sensor);
+    pdd = &lis2dh12->pdd;
+    cfg = &lis2dh12->cfg;
+
+    if (cfg->read_mode.mode != LIS2DH12_READ_M_STREAM) {
+        return SYS_EINVAL;
+    }
+
+    undo_interrupt(&lis2dh12->intr);
+
+    if (pdd->interrupt) {
+        return SYS_EBUSY;
+    }
+
+    /* enable interrupt */
+    pdd->interrupt = &lis2dh12->intr;
+
+    rc = enable_interrupt(sensor, cfg->read_mode.int_cfg,
+                          cfg->read_mode.int_num);
+    if (rc) {
+        return rc;
+    }
+
+    if (time_ms != 0) {
+        rc = os_time_ms_to_ticks(time_ms, &time_ticks);
+        if (rc) {
+            goto err;
+        }
+        stop_ticks = os_time_get() + time_ticks;
+    }
+
+    rc = lis2dh12_get_fs(itf, &fs);
+    if (rc) {
+        goto err;
+    }
+
+    for (;;) {
+        /* force at least one read for cases when fifo is disabled */
+        rc = wait_interrupt(&lis2dh12->intr, cfg->read_mode.int_num);
+        if (rc) {
+            goto err;
+        }
+        fifo_samples = 1;
+
+        while (fifo_samples > 0) {
+
+            /* read all data we believe is currently in fifo */
+            while (fifo_samples > 0) {
+                rc = lis2dh12_do_read(sensor, read_func, read_arg, fs);
+                if (rc) {
+                    goto err;
+                }
+                fifo_samples--;
+
+            }
+
+            /* check if any data is available in fifo */
+            rc = lis2dh12_get_fifo_samples(itf, &fifo_samples);
+            if (rc) {
+                goto err;
+            }
+
+        }
+
+        if (time_ms != 0 && OS_TIME_TICK_GT(os_time_get(), stop_ticks)) {
+            break;
+        }
+
+    }
+
+err:
+    /* disable interrupt */
+    pdd->interrupt = NULL;
+    rc2 = disable_interrupt(sensor, cfg->read_mode.int_cfg,
+                            cfg->read_mode.int_num);
+    if (rc) {
+        return rc;
+    } else {
+        return rc2;
+    }
+}
+
+static int
+lis2dh12_sensor_read(struct sensor *sensor, sensor_type_t type,
+        sensor_data_func_t data_func, void *data_arg, uint32_t timeout)
+{
+    int rc;
+    const struct lis2dh12_cfg *cfg;
+    struct lis2dh12 *lis2dh12;
+    struct sensor_itf *itf;
+
+    /* If the read isn't looking for accel data, don't do anything. */
+    if (!(type & SENSOR_TYPE_ACCELEROMETER)) {
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    itf = SENSOR_GET_ITF(sensor);
+
+    if (itf->si_type == SENSOR_ITF_SPI) {
+
+        rc = hal_spi_disable(sensor->s_itf.si_num);
+        if (rc) {
+            goto err;
+        }
+
+        rc = hal_spi_config(sensor->s_itf.si_num, &spi_lis2dh12_settings);
+        if (rc == EINVAL) {
+            /* If spi is already enabled, for nrf52, it returns -1, We should not
+             * fail if the spi is already enabled
+             */
+            goto err;
+        }
+
+        rc = hal_spi_enable(sensor->s_itf.si_num);
+        if (rc) {
+            goto err;
+        }
+    }
+
+    lis2dh12 = (struct lis2dh12 *)SENSOR_GET_DEVICE(sensor);
+    cfg = &lis2dh12->cfg;
+
+    if (cfg->read_mode.mode == LIS2DH12_READ_M_POLL) {
+        rc = lis2dh12_poll_read(sensor, type, data_func, data_arg, timeout);
+    } else {
+        rc = lis2dh12_stream_read(sensor, type, data_func, data_arg, timeout);
+    }
+err:
+    if (rc) {
+        return SYS_EINVAL; /* XXX */
+    } else {
+        return SYS_EOK;
+    }
+}
+
+static struct lis2dh12_notif_cfg *
+lis2dh12_find_notif_cfg_by_event(sensor_event_type_t event,
+                                 struct lis2dh12_cfg *cfg)
+{
+    int i;
+    struct lis2dh12_notif_cfg *notif_cfg = NULL;
+
+    if (!cfg) {
+        goto err;
+    }
+
+    for (i = 0; i < cfg->max_num_notif; i++) {
+        if (event == cfg->notif_cfg[i].event) {
+            notif_cfg = &cfg->notif_cfg[i];
+            break;
+        }
+    }
+
+    if (i == cfg->max_num_notif) {
+       /* here if type is set to a non valid event or more than one event
+        * we do not currently support registering for more than one event
+        * per notification
+        */
+        goto err;
+    }
+
+    return notif_cfg;
+err:
+    return NULL;
+}
+
+static int
+lis2dh12_sensor_set_notification(struct sensor *sensor, sensor_event_type_t event)
+{
+    struct lis2dh12 *lis2dh12;
+    struct lis2dh12_pdd *pdd;
+    struct lis2dh12_notif_cfg *notif_cfg;
+    int rc;
+
+    lis2dh12 = (struct lis2dh12 *)SENSOR_GET_DEVICE(sensor);
+    pdd = &lis2dh12->pdd;
+
+    notif_cfg = lis2dh12_find_notif_cfg_by_event(event, &lis2dh12->cfg);
+    if (!notif_cfg) {
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    rc = enable_interrupt(sensor, notif_cfg->int_cfg, notif_cfg->int_num);
+    if (rc) {
+        goto err;
+    }
+
+    pdd->notify_ctx.snec_evtype |= event;
 
-    sad.sad_x_is_valid = 1;
-    sad.sad_y_is_valid = 1;
-    sad.sad_z_is_valid = 1;
+    return 0;
+err:
+    return rc;
+}
 
-    /* Call data function */
-    rc = data_func(sensor, data_arg, &sad, SENSOR_TYPE_ACCELEROMETER);
-    if (rc != 0) {
+static int
+lis2dh12_sensor_set_config(struct sensor *sensor, void *cfg)
+{
+    struct lis2dh12 *lis2dh12;
+
+    lis2dh12 = (struct lis2dh12 *)SENSOR_GET_DEVICE(sensor);
+
+    return lis2dh12_config(lis2dh12, (struct lis2dh12_cfg*)cfg);
+}
+
+static int
+lis2dh12_sensor_unset_notification(struct sensor *sensor, sensor_event_type_t event)
+{
+    struct lis2dh12_notif_cfg *notif_cfg;
+    struct lis2dh12 *lis2dh12;
+    int rc;
+
+    lis2dh12 = (struct lis2dh12 *)SENSOR_GET_DEVICE(sensor);
+
+    notif_cfg = lis2dh12_find_notif_cfg_by_event(event, &lis2dh12->cfg);
+    if (!notif_cfg) {
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    lis2dh12->pdd.notify_ctx.snec_evtype &= ~event;
+
+    rc = disable_interrupt(sensor, notif_cfg->int_cfg, notif_cfg->int_num);
+
+err:
+    return rc;
+}
+
+static void
+lis2dh12_inc_notif_stats(sensor_event_type_t event)
+{
+
+#if MYNEWT_VAL(LIS2DH12_NOTIF_STATS)
+    switch (event) {
+        case SENSOR_EVENT_TYPE_SLEEP:
+            STATS_INC(g_lis2dh12stats, sleep_notify);
+            break;
+        case SENSOR_EVENT_TYPE_SINGLE_TAP:
+            STATS_INC(g_lis2dh12stats, single_tap_notify);
+            break;
+        case SENSOR_EVENT_TYPE_DOUBLE_TAP:
+            STATS_INC(g_lis2dh12stats, double_tap_notify);
+            break;
+        case SENSOR_EVENT_TYPE_ORIENT_CHANGE:
+            STATS_INC(g_lis2dh12stats, orient_chg_notify);
+            break;
+        case SENSOR_EVENT_TYPE_ORIENT_X_CHANGE:
+            STATS_INC(g_lis2dh12stats, orient_chg_x_notify);
+            break;
+        case SENSOR_EVENT_TYPE_ORIENT_Y_CHANGE:
+            STATS_INC(g_lis2dh12stats, orient_chg_y_notify);
+            break;
+        case SENSOR_EVENT_TYPE_ORIENT_Z_CHANGE:
+            STATS_INC(g_lis2dh12stats, orient_chg_z_notify);
+            break;
+        case SENSOR_EVENT_TYPE_SLEEP_CHANGE:
+            STATS_INC(g_lis2dh12stats, sleep_chg_notify);
+            break;
+        case SENSOR_EVENT_TYPE_WAKEUP:
+            STATS_INC(g_lis2dh12stats, wakeup_notify);
+            break;
+        case SENSOR_EVENT_TYPE_FREE_FALL:
+            STATS_INC(g_lis2dh12stats, free_fall_notify);
+            break;
+        default:
+            break;
+    }
+#endif
+
+    return;
+}
+
+static int
+lis2dh12_notify(struct lis2dh12 *lis2dh12, uint16_t src,
+                    sensor_event_type_t event_type)
+{
+    struct lis2dh12_notif_cfg *notif_cfg;
+
+    notif_cfg = lis2dh12_find_notif_cfg_by_event(event_type, &lis2dh12->cfg);
+    if (!notif_cfg) {
+        return SYS_EINVAL;
+    }
+
+    if (src & notif_cfg->notif_src) {
+        sensor_mgr_put_notify_evt(&lis2dh12->pdd.notify_ctx, event_type);
+        lis2dh12_inc_notif_stats(event_type);
+    }
+
+    return 0;
+}
+
+static int
+lis2dh12_sensor_handle_interrupt(struct sensor *sensor)
+{
+    struct lis2dh12 *lis2dh12;
+    struct sensor_itf *itf;
+    uint8_t int_src_bytes[2];
+    uint16_t int_src;
+    uint8_t click_src;
+    uint8_t int2_pin_state;
+    struct lis2dh12_notif_cfg *notif_cfg;
+    struct lis2dh12_pdd *pdd;
+    int rc;
+
+    lis2dh12 = (struct lis2dh12 *)SENSOR_GET_DEVICE(sensor);
+    itf = SENSOR_GET_ITF(sensor);
+    pdd = &lis2dh12->pdd;
+
+    rc = lis2dh12_clear_int1(itf, &int_src_bytes[0]);
+    if (rc) {
+        LIS2DH12_LOG(ERROR, "Could not read INT1_SRC (err=0x%02x)\n", rc);
+        goto err;
+    }
+
+    /* Read pin state of interrupt 2 before clearing the int */
+    int2_pin_state = hal_gpio_read(itf->si_ints[1].host_pin);
+
+    rc = lis2dh12_clear_int2(itf, &int_src_bytes[1]);
+    if (rc) {
+        LIS2DH12_LOG(ERROR, "Could not read INT1_SRC (err=0x%02x)\n", rc);
         goto err;
     }
 
+    int_src = (int_src_bytes[1] << 8) | int_src_bytes[0];
+
+#if LIS2DH12_PRINT_INTR
+    console_printf("INT_SRC = 0x%02X 0x%02X\n", int_src_bytes[0],
+                    int_src_bytes[1]);
+
+    if (int_src) {
+        int16_t x, y, z;
+        lis2dh12_get_data(itf, 16, &x, &y, &z);
+        console_printf("X = %-5d Y = %-5d Z = %-5d\n", x, y, z);
+    }
+#endif
+
+    if (pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_ORIENT_CHANGE) {
+        rc = lis2dh12_notify(lis2dh12, int_src, SENSOR_EVENT_TYPE_ORIENT_CHANGE);
+        if (rc) {
+            goto err;
+        }
+    }
+
+    if (pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_ORIENT_X_L_CHANGE) {
+        rc = lis2dh12_notify(lis2dh12, int_src, SENSOR_EVENT_TYPE_ORIENT_X_L_CHANGE);
+        if (rc) {
+            goto err;
+        }
+    }
+
+    if (pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_ORIENT_Y_L_CHANGE) {
+        rc = lis2dh12_notify(lis2dh12, int_src, SENSOR_EVENT_TYPE_ORIENT_Y_L_CHANGE);
+        if (rc) {
+            goto err;
+        }
+    }
+
+    if (pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_ORIENT_Z_L_CHANGE) {
+        rc = lis2dh12_notify(lis2dh12, int_src, SENSOR_EVENT_TYPE_ORIENT_Z_L_CHANGE);
+        if (rc) {
+            goto err;
+        }
+    }
+
+    if (pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_ORIENT_X_H_CHANGE) {
+        rc = lis2dh12_notify(lis2dh12, int_src, SENSOR_EVENT_TYPE_ORIENT_X_H_CHANGE);
+        if (rc) {
+            goto err;
+        }
+    }
+
+    if (pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_ORIENT_Y_H_CHANGE) {
+        rc = lis2dh12_notify(lis2dh12, int_src, SENSOR_EVENT_TYPE_ORIENT_Y_H_CHANGE);
+        if (rc) {
+            goto err;
+        }
+    }
+
+    if (pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_ORIENT_Z_H_CHANGE) {
+        rc = lis2dh12_notify(lis2dh12, int_src, SENSOR_EVENT_TYPE_ORIENT_Z_H_CHANGE);
+        if (rc) {
+            goto err;
+        }
+    }
+
+    /* Check is single/double detection was requested, if not interrupt
+     * did not happened and there is no need to query device about it
+     */
+    if ((pdd->notify_ctx.snec_evtype &
+            (SENSOR_EVENT_TYPE_DOUBLE_TAP | SENSOR_EVENT_TYPE_DOUBLE_TAP)) != 0) {
+        /* Read click interrupt state from device */
+        rc = lis2dh12_clear_click(itf, &click_src);
+        if (rc) {
+            LIS2DH12_LOG(ERROR, "Could not read int src err=0x%02x\n", rc);
+            return rc;
+        }
+
+        if ((pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_SINGLE_TAP) &&
+                (click_src & LIS2DH12_CLICK_SRC_SCLICK)) {
+            rc = lis2dh12_notify(lis2dh12, click_src, SENSOR_EVENT_TYPE_SINGLE_TAP);
+            if (rc) {
+                goto err;
+            }
+            return 0;
+        }
+
+        if ((pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_DOUBLE_TAP) &&
+                (click_src & LIS2DH12_CLICK_SRC_DCLICK)) {
+            rc = lis2dh12_notify(lis2dh12, click_src, SENSOR_EVENT_TYPE_DOUBLE_TAP);
+            if (rc) {
+                goto err;
+            }
+            return 0;
+        }
+    }
+
+    /* Free fall */
+    notif_cfg = lis2dh12_find_notif_cfg_by_event(SENSOR_EVENT_TYPE_FREE_FALL,
+                                                 &lis2dh12->cfg);
+    if (NULL != notif_cfg &&
+        0 != (int_src & notif_cfg->notif_src)) {
+        /* Free-fall is detected */
+        sensor_mgr_put_notify_evt(&lis2dh12->pdd.notify_ctx,
+                                  SENSOR_EVENT_TYPE_FREE_FALL);
+        lis2dh12_inc_notif_stats(SENSOR_EVENT_TYPE_FREE_FALL);
+    }
+
+    /* Sleep and wake up */
+
+    /* Sleep/wake up notifications on */
+    if (pdd->notify_ctx.snec_evtype &
+        (SENSOR_EVENT_TYPE_SLEEP | SENSOR_EVENT_TYPE_SLEEP_CHANGE | SENSOR_EVENT_TYPE_WAKEUP)) {
+        /*
+         * Sleep state can be routed to INT2 pin, pin is active when device stays active
+         * Notification will be sent only on activity pin state change.
+         */
+        if (int2_pin_state != lis2dh12->pdd.int2_pin_state) {
+            lis2dh12->pdd.int2_pin_state = int2_pin_state;
+
+            if ((!int2_pin_state) &&
+                0 != (pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_WAKEUP)) {
+                /* Just become active */
+                notif_cfg = lis2dh12_find_notif_cfg_by_event(SENSOR_EVENT_TYPE_WAKEUP,
+                                                             &lis2dh12->cfg);
+                sensor_mgr_put_notify_evt(&lis2dh12->pdd.notify_ctx,
+                                          SENSOR_EVENT_TYPE_WAKEUP);
+                lis2dh12_inc_notif_stats(SENSOR_EVENT_TYPE_WAKEUP);
+            } else if (int2_pin_state &&
+                       0 != (pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_SLEEP)) {
+                /* Just went to sleep */
+                notif_cfg = lis2dh12_find_notif_cfg_by_event(SENSOR_EVENT_TYPE_SLEEP,
+                                                             &lis2dh12->cfg);
+                sensor_mgr_put_notify_evt(&lis2dh12->pdd.notify_ctx,
+                                           SENSOR_EVENT_TYPE_SLEEP);
+                lis2dh12_inc_notif_stats(SENSOR_EVENT_TYPE_SLEEP);
+            } else{
+                notif_cfg = lis2dh12_find_notif_cfg_by_event(SENSOR_EVENT_TYPE_SLEEP_CHANGE,
+                                                             &lis2dh12->cfg);
+                /* Sleep change interrupt must be configured for int2 */
+                if ((notif_cfg && int2_pin_state && itf->si_ints[1].active == HAL_GPIO_TRIG_RISING) ||
+                        (notif_cfg && !int2_pin_state && itf->si_ints[1].active == HAL_GPIO_TRIG_FALLING) ||
+                        (notif_cfg && itf->si_ints[1].active == HAL_GPIO_TRIG_BOTH))
+                {
+                    /* Sleep change detected, either wake-up or sleep */
+                    sensor_mgr_put_notify_evt(&lis2dh12->pdd.notify_ctx,
+                                              SENSOR_EVENT_TYPE_SLEEP_CHANGE);
+                    lis2dh12_inc_notif_stats(SENSOR_EVENT_TYPE_SLEEP_CHANGE);
+                }
+            }
+        }
+    }
+
     return 0;
 err:
     return rc;
@@ -1071,6 +2147,29 @@ lis2dh12_sensor_get_config(struct sensor *sensor, sensor_type_t type,
     return rc;
 }
 
+/**
+ * Set reference threshold
+ *
+ * @param the sensor interface
+ * @param threshold
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dh12_set_ref_thresh(struct sensor_itf *itf, uint8_t ths)
+{
+    int rc;
+
+    rc = lis2dh12_writelen(itf, LIS2DH12_REG_REFERENCE, &ths, 1);
+    if (rc) {
+        goto err;
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
 /**
  * Set interrupt threshold for int 2
  *
@@ -1124,11 +2223,9 @@ lis2dh12_set_int1_thresh(struct sensor_itf *itf, uint8_t ths)
  * @param the sensor interface
  */
 int
-lis2dh12_clear_int2(struct sensor_itf *itf)
+lis2dh12_clear_int2(struct sensor_itf *itf, uint8_t *src)
 {
-    uint8_t reg;
-
-    return lis2dh12_readlen(itf, LIS2DH12_REG_INT2_SRC, &reg, 1);
+    return lis2dh12_readlen(itf, LIS2DH12_REG_INT2_SRC, src, 1);
 }
 
 /**
@@ -1137,11 +2234,9 @@ lis2dh12_clear_int2(struct sensor_itf *itf)
  * @param the sensor interface
  */
 int
-lis2dh12_clear_int1(struct sensor_itf *itf)
+lis2dh12_clear_int1(struct sensor_itf *itf, uint8_t *src)
 {
-    uint8_t reg;
-
-    return lis2dh12_readlen(itf, LIS2DH12_REG_INT1_SRC, &reg, 1);
+    return lis2dh12_readlen(itf, LIS2DH12_REG_INT1_SRC, src, 1);
 }
 
 /**
@@ -1151,9 +2246,9 @@ lis2dh12_clear_int1(struct sensor_itf *itf)
  * @param events to enable int for
  */
 int
-lis2dh12_enable_int2(struct sensor_itf *itf, uint8_t *reg)
+lis2dh12_enable_int2(struct sensor_itf *itf, uint8_t reg)
 {
-    return lis2dh12_writelen(itf, LIS2DH12_REG_INT2_CFG, reg, 1);
+    return lis2dh12_write8(itf, LIS2DH12_REG_INT2_CFG, reg);
 }
 
 /**
@@ -1278,13 +2373,13 @@ lis2dh12_disable_int1(struct sensor_itf *itf)
     uint8_t reg;
     int rc;
 
-    reg = 0;
-
-    rc = lis2dh12_clear_int1(itf);
+    rc = lis2dh12_clear_int1(itf, &reg);
     if (rc) {
         goto err;
     }
 
+    reg = 0;
+
     os_time_delay((OS_TICKS_PER_SEC * 20)/1000 + 1);
 
     rc = lis2dh12_writelen(itf, LIS2DH12_REG_INT1_CFG, &reg, 1);
@@ -1305,13 +2400,13 @@ lis2dh12_disable_int2(struct sensor_itf *itf)
     uint8_t reg;
     int rc;
 
-    reg = 0;
-
-    rc = lis2dh12_clear_int2(itf);
+    rc = lis2dh12_clear_int2(itf, &reg);
     if (rc) {
         goto err;
     }
 
+    reg = 0;
+
     os_time_delay((OS_TICKS_PER_SEC * 20)/1000 + 1);
 
     rc = lis2dh12_writelen(itf, LIS2DH12_REG_INT2_CFG, &reg, 1);
@@ -1327,20 +2422,9 @@ lis2dh12_disable_int2(struct sensor_itf *itf)
  * @param events to enable int for
  */
 int
-lis2dh12_enable_int1(struct sensor_itf *itf, uint8_t *reg)
-{
-    return lis2dh12_writelen(itf, LIS2DH12_REG_INT1_CFG, reg, 1);
-}
-
-/**
- * IRQ handler for interrupts for high/low threshold
- *
- * @param arg
- */
-static void
-lis2dh12_int_irq_handler(void *arg)
+lis2dh12_enable_int1(struct sensor_itf *itf, uint8_t reg)
 {
-    sensor_mgr_put_read_evt(arg);
+    return lis2dh12_write8(itf, LIS2DH12_REG_INT1_CFG, reg);
 }
 
 /**
@@ -1420,7 +2504,8 @@ lis2dh12_set_low_thresh(struct sensor_itf *itf,
                         struct sensor_type_traits *stt)
 {
     int16_t acc_mg;
-    uint8_t reg;
+    uint8_t reg = 0xFF;
+    uint8_t int_src;
     int rc;
 
     rc = 0;
@@ -1478,7 +2563,7 @@ lis2dh12_set_low_thresh(struct sensor_itf *itf,
         reg |= low_thresh.sad->sad_y_is_valid ? LIS2DH12_INT2_CFG_YLIE : 0;
         reg |= low_thresh.sad->sad_z_is_valid ? LIS2DH12_INT2_CFG_ZLIE : 0;
 
-        rc = lis2dh12_clear_int1(itf);
+        rc = lis2dh12_clear_int1(itf, &int_src);
         if (rc) {
             goto err;
         }
@@ -1487,7 +2572,7 @@ lis2dh12_set_low_thresh(struct sensor_itf *itf,
 
         hal_gpio_irq_enable(itf->si_low_pin);
 
-        rc = lis2dh12_enable_int1(itf, &reg);
+        rc = lis2dh12_enable_int1(itf, reg);
         if (rc) {
             goto err;
         }
@@ -1505,7 +2590,8 @@ lis2dh12_set_high_thresh(struct sensor_itf *itf,
                          struct sensor_type_traits *stt)
 {
     int16_t acc_mg;
-    uint8_t reg;
+    uint8_t reg = 0;
+    uint8_t int_src;
     int rc;
 
     rc = 0;
@@ -1563,14 +2649,14 @@ lis2dh12_set_high_thresh(struct sensor_itf *itf,
         reg |= high_thresh.sad->sad_y_is_valid ? LIS2DH12_INT2_CFG_YHIE : 0;
         reg |= high_thresh.sad->sad_z_is_valid ? LIS2DH12_INT2_CFG_ZHIE : 0;
 
-        rc = lis2dh12_clear_int2(itf);
+        rc = lis2dh12_clear_int2(itf, &int_src);
         if (rc) {
             goto err;
         }
 
         hal_gpio_irq_enable(itf->si_high_pin);
 
-        rc = lis2dh12_enable_int2(itf, &reg);
+        rc = lis2dh12_enable_int2(itf, reg);
         if (rc) {
             goto err;
         }
@@ -1648,6 +2734,52 @@ lis2dh12_sensor_set_trigger_thresh(struct sensor *sensor,
     return rc;
 }
 
+/**
+ * Set tap detection configuration
+ *
+ * @param the sensor interface
+ * @param the tap settings
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dh12_set_tap_cfg(struct sensor_itf *itf, struct lis2dh12_tap_settings *cfg)
+{
+    int rc;
+    uint8_t reg;
+
+    reg = cfg->en_xs ? LIS2DH12_CLICK_CFG_XS : 0;
+    reg |= cfg->en_ys ? LIS2DH12_CLICK_CFG_YS : 0;
+    reg |= cfg->en_zs ? LIS2DH12_CLICK_CFG_ZS : 0;
+    reg |= cfg->en_xd ? LIS2DH12_CLICK_CFG_XD : 0;
+    reg |= cfg->en_yd ? LIS2DH12_CLICK_CFG_YD : 0;
+    reg |= cfg->en_zd ? LIS2DH12_CLICK_CFG_ZD : 0;
+    rc = lis2dh12_set_click_cfg(itf, reg);
+    if (rc) {
+        return rc;
+    }
+
+    lis2dh12_set_click_threshold(itf, cfg->click_ths);
+    if (rc) {
+        return rc;
+    }
+
+    lis2dh12_set_click_time_limit(itf, cfg->time_limit);
+    if (rc) {
+        return rc;
+    }
+
+    lis2dh12_set_click_time_latency(itf, cfg->time_latency);
+    if (rc) {
+        return rc;
+    }
+
+    lis2dh12_set_click_time_window(itf, cfg->time_window);
+    if (rc) {
+        return rc;
+    }
+
+    return 0;
+}
+
 /**
  * Configure the sensor
  *
@@ -1701,6 +2833,12 @@ lis2dh12_config(struct lis2dh12 *lis2dh12, struct lis2dh12_cfg *cfg)
         goto err;
     }
 
+    rc = lis2dh12_set_int_pp_od(itf, cfg->int_pp_od);
+    if (rc) {
+        goto err;
+    }
+    lis2dh12->cfg.int_pp_od = cfg->int_pp_od;
+
     rc = lis2dh12_pull_up_disc(itf, cfg->lc_pull_up_disc);
     if (rc) {
         goto err;
@@ -1708,7 +2846,9 @@ lis2dh12_config(struct lis2dh12 *lis2dh12, struct lis2dh12_cfg *cfg)
 
     lis2dh12->cfg.lc_pull_up_disc = cfg->lc_pull_up_disc;
 
-    rc = lis2dh12_hpf_cfg(itf, 0x00);
+    rc = lis2dh12_hpf_cfg(itf, (cfg->hp_mode << 6) | (cfg->hp_cut_off << 4) |
+                               (cfg->hp_fds << 3) | (cfg->hp_click << 2) |
+                               (cfg->hp_ia2 << 1) | cfg->hp_ia1);
     if (rc) {
         goto err;
     }
@@ -1727,6 +2867,7 @@ lis2dh12_config(struct lis2dh12 *lis2dh12, struct lis2dh12_cfg *cfg)
 
     lis2dh12->cfg.lc_rate = cfg->lc_rate;
 
+    /*sets xen yen and xen */
     rc = lis2dh12_chan_enable(itf, LIS2DH12_CTRL_REG1_XPEN |
                                    LIS2DH12_CTRL_REG1_YPEN |
                                    LIS2DH12_CTRL_REG1_ZPEN);
@@ -1739,12 +2880,74 @@ lis2dh12_config(struct lis2dh12 *lis2dh12, struct lis2dh12_cfg *cfg)
         goto err;
     }
 
-    rc = lis2dh12_set_op_mode(itf, LIS2DH12_OM_HIGH_RESOLUTION);
+    rc = lis2dh12_set_op_mode(itf, cfg->power_mode);
+    if (rc) {
+        goto err;
+    }
+
+    rc = lis2dh12_set_fifo_mode(itf, cfg->fifo_mode);
+    if (rc) {
+        goto err;
+    }
+
+    rc = lis2dh12_set_ref_thresh(itf, cfg->reference);
+    if (rc)
+    {
+        goto err;
+    }
+
+    if (cfg->int_cfg[0].ths) {
+        rc = lis2dh12_set_int1_thresh(itf, cfg->int_cfg[0].ths);
+        if (rc) {
+            goto err;
+        }
+        rc = lis2dh12_enable_int1(itf, cfg->int_cfg[0].cfg);
+        if (rc) {
+            goto err;
+        }
+        rc = lis2dh12_set_int1_duration(itf, cfg->int_cfg[0].dur);
+        if (rc) {
+            goto err;
+        }
+        lis2dh12->cfg.int_cfg[0] = cfg->int_cfg[0];
+    }
+
+    if (cfg->int_cfg[1].ths) {
+        rc = lis2dh12_set_int2_thresh(itf, cfg->int_cfg[1].ths);
+        if (rc) {
+            goto err;
+        }
+        rc = lis2dh12_enable_int2(itf, cfg->int_cfg[1].cfg);
+        if (rc) {
+            goto err;
+        }
+        rc = lis2dh12_set_int2_duration(itf, cfg->int_cfg[1].dur);
+        if (rc) {
+            goto err;
+        }
+        lis2dh12->cfg.int_cfg[0] = cfg->int_cfg[0];
+    }
+
+    if (cfg->latch_int1) {
+        rc = lis2dh12_latch_int1(itf);
+    }
+    if (rc) {
+        goto err;
+    }
+
+    if (cfg->latch_int2) {
+        rc = lis2dh12_latch_int2(itf);
+    }
+    if (rc) {
+        goto err;
+    }
+
+    rc = lis2dh12_set_activity_threshold(itf, cfg->act_ths);
     if (rc) {
         goto err;
     }
 
-    rc = lis2dh12_set_fifo_mode(itf, LIS2DH12_FIFO_M_BYPASS);
+    rc = lis2dh12_set_activity_duration(itf, cfg->act_dur);
     if (rc) {
         goto err;
     }
@@ -1753,10 +2956,41 @@ lis2dh12_config(struct lis2dh12 *lis2dh12, struct lis2dh12_cfg *cfg)
     if (rc) {
         goto err;
     }
+//    lis2dh12_shell_init();
+    lis2dh12->cfg.read_mode.int_cfg = cfg->read_mode.int_cfg;
+    lis2dh12->cfg.read_mode.int_num = cfg->read_mode.int_num;
+    lis2dh12->cfg.read_mode.mode = cfg->read_mode.mode;
+
+    if (!cfg->notif_cfg) {
+        lis2dh12->cfg.notif_cfg = (struct lis2dh12_notif_cfg *)dflt_notif_cfg;
+        lis2dh12->cfg.max_num_notif = sizeof(dflt_notif_cfg)/sizeof(dflt_notif_cfg[0]);
+    } else {
+        lis2dh12->cfg.notif_cfg = cfg->notif_cfg;
+        lis2dh12->cfg.max_num_notif = cfg->max_num_notif;
+    }
+
+    lis2dh12->cfg.read_mode.int_cfg = cfg->read_mode.int_cfg;
+    lis2dh12->cfg.read_mode.int_num = cfg->read_mode.int_num;
+    lis2dh12->cfg.read_mode.mode = cfg->read_mode.mode;
+
+    if (!cfg->notif_cfg) {
+        lis2dh12->cfg.notif_cfg = (struct lis2dh12_notif_cfg *)dflt_notif_cfg;
+        lis2dh12->cfg.max_num_notif = sizeof(dflt_notif_cfg)/sizeof(dflt_notif_cfg[0]);
+    } else {
+        lis2dh12->cfg.notif_cfg = cfg->notif_cfg;
+        lis2dh12->cfg.max_num_notif = cfg->max_num_notif;
+    }
 
     lis2dh12->cfg.lc_s_mask = cfg->lc_s_mask;
 
+    rc = lis2dh12_set_tap_cfg(itf, &cfg->tap);
+    if (rc) {
+        goto err;
+    }
+    lis2dh12->cfg.tap = cfg->tap;
+
     return 0;
 err:
+
     return rc;
 }
diff --git a/hw/drivers/sensors/lis2dh12/src/lis2dh12_priv.h b/hw/drivers/sensors/lis2dh12/src/lis2dh12_priv.h
index d37c26933e..6848b15bdd 100644
--- a/hw/drivers/sensors/lis2dh12/src/lis2dh12_priv.h
+++ b/hw/drivers/sensors/lis2dh12/src/lis2dh12_priv.h
@@ -61,12 +61,6 @@ extern "C" {
 #define LIS2DH12_CTRL_REG2_HPIA1              (1)
 
 #define LIS2DH12_REG_CTRL_REG3               0x22
-#define LIS2DH12_CTRL_REG3_I1_CLICK      (1 << 7)
-#define LIS2DH12_CTRL_REG3_I1_IA1        (1 << 6)
-#define LIS2DH12_CTRL_REG3_I1_IA2        (1 << 5)
-#define LIS2DH12_CTRL_REG3_I1_ZYXDA      (1 << 4)
-#define LIS2DH12_CTRL_REG3_I1_WTM        (1 << 2)
-#define LIS2DH12_CTRL_REG3_I1_OVERRUN    (1 << 1)
 
 #define LIS2DH12_REG_CTRL_REG4               0x23
 #define LIS2DH12_CTRL_REG4_BDU           (1 << 7)
@@ -85,12 +79,6 @@ extern "C" {
 #define LIS2DH12_CTRL_REG5_D4D_INT2           (1)
 
 #define LIS2DH12_REG_CTRL_REG6               0x25
-#define LIS2DH12_CTRL_REG6_I2_CLICK      (1 << 7)
-#define LIS2DH12_CTRL_REG6_I2_IA1        (1 << 6)
-#define LIS2DH12_CTRL_REG6_I2_IA2        (1 << 5)
-#define LIS2DH12_CTRL_REG6_I2_BOOT       (1 << 4)
-#define LIS2DH12_CTRL_REG6_I2_ACT        (1 << 3)
-#define LIS2DH12_CTRL_REG6_INT_POLARITY  (1 << 1)
 
 #define LIS2DH12_REG_REFERENCE               0x26
 
@@ -133,13 +121,6 @@ extern "C" {
 #define LIS2DH12_INT1_CFG_XLIE                (1)
 
 #define LIS2DH12_REG_INT1_SRC                0x31
-#define LIS2DH12_INT1_IA                 (1 << 5)
-#define LIS2DH12_INT1_ZH                 (1 << 5)
-#define LIS2DH12_INT1_ZL                 (1 << 4)
-#define LIS2DH12_INT1_YH                 (1 << 3)
-#define LIS2DH12_INT1_YL                 (1 << 2)
-#define LIS2DH12_INT1_XH                 (1 << 1)
-#define LIS2DH12_INT1_XL                      (1)
 
 #define LIS2DH12_REG_INT1_THS                0x32
 #define LIS2DH12_INT1_THS                  (0x7f)
@@ -157,13 +138,6 @@ extern "C" {
 #define LIS2DH12_INT2_CFG_XLIE                (1)
 
 #define LIS2DH12_REG_INT2_SRC                0x35
-#define LIS2DH12_INT1_IA                 (1 << 5)
-#define LIS2DH12_INT1_ZH                 (1 << 5)
-#define LIS2DH12_INT1_ZL                 (1 << 4)
-#define LIS2DH12_INT1_YH                 (1 << 3)
-#define LIS2DH12_INT1_YL                 (1 << 2)
-#define LIS2DH12_INT1_XH                 (1 << 1)
-#define LIS2DH12_INT1_XL                      (1)
 
 #define LIS2DH12_REG_INT2_THS                0x36
 #define LIS2DH12_INT2_THS                  (0x7f)
@@ -179,13 +153,6 @@ extern "C" {
 #define LIS2DH12_CLICK_CFG_XS                 (1)
 
 #define LIS2DH12_REG_CLICK_SRC               0x39
-#define LIS2DH12_CLICK_SRC_IA            (1 << 6)
-#define LIS2DH12_CLICK_SRC_DCLICK        (1 << 5)
-#define LIS2DH12_CLICK_SRC_SCLICK        (1 << 4)
-#define LIS2DH12_CLICK_SRC_SIGN          (1 << 3)
-#define LIS2DH12_CLICK_SRC_Z             (1 << 2)
-#define LIS2DH12_CLICK_SRC_Y             (1 << 1)
-#define LIS2DH12_CLICK_SRC_X             (1 << 0)
 
 #define LIS2DH12_REG_CLICK_THS               0x3A
 #define LIS2DH12_CLICK_LIR               (1 << 7)
@@ -209,6 +176,10 @@ extern "C" {
 
 int lis2dh12_writelen(struct sensor_itf *itf, uint8_t addr, uint8_t *payload, uint8_t len);
 int lis2dh12_readlen(struct sensor_itf *itf, uint8_t addr, uint8_t *payload, uint8_t len);
+int lis2dh12_write8(struct sensor_itf *itf, uint8_t reg, uint8_t value);
+int lis2dh12_read8(struct sensor_itf *itf, uint8_t reg, uint8_t *value);
+int lis2dh12_get_data(struct sensor_itf *itf, uint8_t fs, int16_t *x, int16_t *y, int16_t *z);
+int lis2dh12_get_fs(struct sensor_itf *itf, uint8_t *fs);
 
 #ifdef __cplusplus
 }
diff --git a/hw/drivers/sensors/lis2dh12/src/lis2dh12_shell.c b/hw/drivers/sensors/lis2dh12/src/lis2dh12_shell.c
new file mode 100644
index 0000000000..7b9beb712b
--- /dev/null
+++ b/hw/drivers/sensors/lis2dh12/src/lis2dh12_shell.c
@@ -0,0 +1,387 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include "os/mynewt.h"
+#include "console/console.h"
+#include "sensor/accel.h"
+#include "lis2dh12/lis2dh12.h"
+#include "lis2dh12_priv.h"
+
+#if MYNEWT_VAL(LIS2DH12_CLI) && MYNEWT_VAL(SENSOR_CLI)
+
+#include "shell/shell.h"
+#include "parse/parse.h"
+
+#define LIS2DH12_CLI_FIRST_REGISTER 0x07
+#define LIS2DH12_CLI_LAST_REGISTER 0x3F
+
+static int lis2dh12_shell_cmd(int argc, char **argv);
+
+static struct shell_cmd lis2dh12_shell_cmd_struct = {
+    .sc_cmd = "lis2dh12",
+    .sc_cmd_func = lis2dh12_shell_cmd
+};
+
+static struct sensor_itf g_sensor_itf = {
+    .si_type = MYNEWT_VAL(LIS2DH12_SHELL_ITF_TYPE),
+    .si_num = MYNEWT_VAL(LIS2DH12_SHELL_ITF_NUM),
+    .si_cs_pin = MYNEWT_VAL(LIS2DH12_SHELL_CSPIN),
+    .si_addr = MYNEWT_VAL(LIS2DH12_SHELL_ITF_ADDR)
+};
+
+static int
+lis2dh12_shell_err_too_many_args(char *cmd_name)
+{
+    console_printf("Error: too many arguments for command \"%s\"\n",
+                   cmd_name);
+    return EINVAL;
+}
+
+static int
+lis2dh12_shell_err_too_few_args(char *cmd_name)
+{
+    console_printf("Error: too few arguments for command \"%s\"\n",
+                   cmd_name);
+    return EINVAL;
+}
+
+static int
+lis2dh12_shell_err_unknown_arg(char *cmd_name)
+{
+    console_printf("Error: unknown argument \"%s\"\n",
+                   cmd_name);
+    return EINVAL;
+}
+
+static int
+lis2dh12_shell_err_invalid_arg(char *cmd_name)
+{
+    console_printf("Error: invalid argument \"%s\"\n",
+                   cmd_name);
+    return EINVAL;
+}
+
+static int
+lis2dh12_shell_help(void)
+{
+    console_printf("%s cmd [flags...]\n", lis2dh12_shell_cmd_struct.sc_cmd);
+    console_printf("cmd:\n");
+    console_printf("\tr    [n_samples]\n");
+    console_printf("\tchipid\n");
+    console_printf("\tdump\n");
+    console_printf("\tpeek [reg]\n");
+    console_printf("\tpoke [reg value]\n");
+    console_printf("\ttest\n");
+    
+    return 0;
+}
+
+static int
+lis2dh12_shell_cmd_read_chipid(int argc, char **argv)
+{
+    int rc;
+    uint8_t chipid;
+
+    rc = lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_WHO_AM_I, &chipid);
+    if (rc) {
+        goto err;
+    }
+
+    console_printf("CHIP_ID:0x%02X\n", chipid);
+
+    return 0;
+err:
+    return rc;
+}
+
+static int
+lis2dh12_shell_cmd_read(int argc, char **argv)
+{
+    uint16_t samples = 1;
+    uint16_t val;
+    int rc;
+    char tmpstr[13];
+    int16_t x,y,z;
+    float fx,fy,fz;
+    uint8_t fs;
+
+    if (argc > 3) {
+        return lis2dh12_shell_err_too_many_args(argv[1]);
+    }
+
+    /* Check if more than one sample requested */
+    if (argc == 3) {
+        val = parse_ll_bounds(argv[2], 1, UINT16_MAX, &rc);
+        if (rc) {
+            return lis2dh12_shell_err_invalid_arg(argv[2]);
+        }
+        samples = val;
+    }
+
+    while (samples--) {
+
+        rc = lis2dh12_get_fs(&g_sensor_itf, &fs);
+        if (rc) {
+            return rc;
+        }
+        
+        rc = lis2dh12_get_data(&g_sensor_itf, fs,&x, &y, &z);
+        if (rc) {
+            console_printf("Read failed: %d\n", rc);
+            return rc;
+        }
+
+        lis2dh12_calc_acc_ms2(x, &fx);
+        lis2dh12_calc_acc_ms2(y, &fy);
+        lis2dh12_calc_acc_ms2(z, &fz);
+                
+        console_printf("x:%s ", sensor_ftostr(fx, tmpstr, 13));
+        console_printf("y:%s ", sensor_ftostr(fy, tmpstr, 13));
+        console_printf("z:%s\n", sensor_ftostr(fz, tmpstr, 13));
+    }
+
+    return 0;
+}
+
+static int
+lis2dh12_shell_cmd_dump(int argc, char **argv)
+{
+    uint8_t val;
+    
+    if (argc > 2) {
+        return lis2dh12_shell_err_too_many_args(argv[1]);
+    }
+    
+    /* Dump all the register values for debug purposes */
+    val = 0;
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_OUT_TEMP_L, &val));
+    console_printf("0x%02X (OUT_TEMP_L): 0x%02X\n", LIS2DH12_REG_OUT_TEMP_L, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_OUT_TEMP_H, &val));
+    console_printf("0x%02X (OUT_TEMP_H): 0x%02X\n", LIS2DH12_REG_OUT_TEMP_H, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_WHO_AM_I, &val));
+    console_printf("0x%02X (WHO_AM_I): 0x%02X\n", LIS2DH12_REG_WHO_AM_I, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_CTRL_REG0, &val));
+    console_printf("0x%02X (CTRL0): 0x%02X\n", LIS2DH12_REG_CTRL_REG0, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_TEMP_CFG, &val));
+    console_printf("0x%02X (TEMP_CFG): 0x%02X\n", LIS2DH12_REG_TEMP_CFG, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_CTRL_REG1, &val));
+    console_printf("0x%02X (CTRL1): 0x%02X\n", LIS2DH12_REG_CTRL_REG1, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_CTRL_REG2, &val));
+    console_printf("0x%02X (CTRL2): 0x%02X\n", LIS2DH12_REG_CTRL_REG2, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_CTRL_REG3, &val));
+    console_printf("0x%02X (CTRL3): 0x%02X\n", LIS2DH12_REG_CTRL_REG3, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_CTRL_REG4, &val));
+    console_printf("0x%02X (CTRL4): 0x%02X\n", LIS2DH12_REG_CTRL_REG4, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_CTRL_REG5, &val));
+    console_printf("0x%02X (CTRL5): 0x%02X\n", LIS2DH12_REG_CTRL_REG5, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_CTRL_REG6, &val));
+    console_printf("0x%02X (CTRL6): 0x%02X\n", LIS2DH12_REG_CTRL_REG6, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_REFERENCE, &val));
+    console_printf("0x%02X (REFERENCE): 0x%02X\n", LIS2DH12_REG_REFERENCE, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_STATUS_REG, &val));
+    console_printf("0x%02X (STATUS): 0x%02X\n", LIS2DH12_REG_STATUS_REG, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_OUT_X_L, &val));
+    console_printf("0x%02X (OUT_X_L): 0x%02X\n", LIS2DH12_REG_OUT_X_L, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_OUT_X_H, &val));
+    console_printf("0x%02X (OUT_X_H): 0x%02X\n", LIS2DH12_REG_OUT_X_H, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_OUT_Y_L, &val));
+    console_printf("0x%02X (OUT_Y_L): 0x%02X\n", LIS2DH12_REG_OUT_Y_L, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_OUT_Y_H, &val));
+    console_printf("0x%02X (OUT_Y_H): 0x%02X\n", LIS2DH12_REG_OUT_Y_H, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_OUT_Z_L, &val));
+    console_printf("0x%02X (OUT_Z_L): 0x%02X\n", LIS2DH12_REG_OUT_Z_L, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_OUT_Z_H, &val));
+    console_printf("0x%02X (OUT_Z_H): 0x%02X\n", LIS2DH12_REG_OUT_Z_H, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_FIFO_CTRL_REG, &val));
+    console_printf("0x%02X (FIFO_CTRL): 0x%02X\n", LIS2DH12_REG_FIFO_CTRL_REG, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_FIFO_SRC_REG, &val));
+    console_printf("0x%02X (FIFO_SRC): 0x%02X\n", LIS2DH12_REG_FIFO_SRC_REG, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_INT1_CFG, &val));
+    console_printf("0x%02X (INT1_CFG): 0x%02X\n", LIS2DH12_REG_INT1_CFG, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_INT1_SRC, &val));
+    console_printf("0x%02X (INT1_SRC): 0x%02X\n", LIS2DH12_REG_INT1_SRC, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_INT1_THS, &val));
+    console_printf("0x%02X (INT1_THS): 0x%02X\n", LIS2DH12_REG_INT1_THS, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_INT1_DURATION, &val));
+    console_printf("0x%02X (INT1_DURATION): 0x%02X\n", LIS2DH12_REG_INT1_DURATION, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_INT2_CFG, &val));
+    console_printf("0x%02X (INT2_CFG): 0x%02X\n", LIS2DH12_REG_INT2_CFG, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_INT2_SRC, &val));
+    console_printf("0x%02X (INT2_SRC): 0x%02X\n", LIS2DH12_REG_INT2_SRC, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_INT2_THS, &val));
+    console_printf("0x%02X (INT2_THS): 0x%02X\n", LIS2DH12_REG_INT2_THS, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_INT2_DURATION, &val));
+    console_printf("0x%02X (INT2_DURATION): 0x%02X\n", LIS2DH12_REG_INT2_DURATION, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_CLICK_CFG, &val));
+    console_printf("0x%02X (CLICK_CFG): 0x%02X\n", LIS2DH12_REG_CLICK_CFG, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_CLICK_SRC, &val));
+    console_printf("0x%02X (CLICK_SRC): 0x%02X\n", LIS2DH12_REG_CLICK_SRC, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_CLICK_THS, &val));
+    console_printf("0x%02X (CLICK_THS): 0x%02X\n", LIS2DH12_REG_CLICK_THS, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_TIME_LIMIT, &val));
+    console_printf("0x%02X (TIME_LIMIT): 0x%02X\n", LIS2DH12_REG_TIME_LIMIT, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_TIME_LATENCY, &val));
+    console_printf("0x%02X (TIME_LATENCY): 0x%02X\n", LIS2DH12_REG_TIME_LATENCY, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_TIME_WINDOW, &val));
+    console_printf("0x%02X (TIME_WINDOW): 0x%02X\n", LIS2DH12_REG_TIME_WINDOW, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_ACT_THS, &val));
+    console_printf("0x%02X (ACT_THS): 0x%02X\n", LIS2DH12_REG_ACT_THS, val);
+    assert(0 == lis2dh12_read8(&g_sensor_itf, LIS2DH12_REG_ACT_DUR, &val));
+    console_printf("0x%02X (ACT_DUR): 0x%02X\n", LIS2DH12_REG_ACT_DUR, val);
+    
+    return 0;
+}
+
+static int
+lis2dh12_shell_cmd_peek(int argc, char **argv)
+{
+    int rc;
+    uint8_t value;
+    uint8_t reg;
+
+    if (argc > 3) {
+        return lis2dh12_shell_err_too_many_args(argv[1]);
+    } else if (argc < 3) {
+        return lis2dh12_shell_err_too_few_args(argv[1]);
+    }
+
+    reg = parse_ll_bounds(argv[2], LIS2DH12_CLI_FIRST_REGISTER, LIS2DH12_CLI_LAST_REGISTER, &rc);
+    if (rc != 0) {
+        return lis2dh12_shell_err_invalid_arg(argv[2]);
+    }
+
+    rc = lis2dh12_read8(&g_sensor_itf, reg, &value);
+    if (rc) {
+        console_printf("peek failed %d\n", rc);
+    }else{
+        console_printf("reg 0x%02X(%d) = 0x%02X\n", reg, reg, value);
+    }
+
+    return 0;
+}
+
+static int
+lis2dh12_shell_cmd_poke(int argc, char **argv)
+{
+    int rc;
+    uint8_t reg;
+    uint8_t value;
+
+    if (argc > 4) {
+        return lis2dh12_shell_err_too_many_args(argv[1]);
+    } else if (argc < 4) {
+        return lis2dh12_shell_err_too_few_args(argv[1]);
+    }
+
+    reg = parse_ll_bounds(argv[2], LIS2DH12_CLI_FIRST_REGISTER, LIS2DH12_CLI_LAST_REGISTER, &rc);
+    if (rc != 0) {
+        return lis2dh12_shell_err_invalid_arg(argv[2]);
+   }
+
+    value = parse_ll_bounds(argv[3], 0, 255, &rc);
+    if (rc != 0) {
+        return lis2dh12_shell_err_invalid_arg(argv[3]);
+    }
+
+    rc = lis2dh12_write8(&g_sensor_itf, reg, value);
+    if (rc) {
+        console_printf("poke failed %d\n", rc);
+    }else{
+        console_printf("wrote: 0x%02X(%d) to 0x%02X\n", value, value, reg);
+    }
+
+    return 0;
+}
+
+static int
+lis2dh12_shell_cmd_test(int argc, char **argv)
+{
+    int rc;
+    int result = 0;
+
+    rc = 0; //lis2dh12_run_self_test(&g_sensor_itf, &result);
+    if (rc) {
+        goto err;
+    }
+
+    if (result) {
+        console_printf("SELF TEST: FAILED\n");        
+    } else {
+        console_printf("SELF TEST: PASSED\n");        
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+static int
+lis2dh12_shell_cmd(int argc, char **argv)
+{
+    if (argc == 1) {
+        return lis2dh12_shell_help();
+    }
+
+    /* Read command (get a new data sample) */
+    if (argc > 1 && strcmp(argv[1], "r") == 0) {
+        return lis2dh12_shell_cmd_read(argc, argv);
+    }
+
+    /* Chip ID */
+    if (argc > 1 && strcmp(argv[1], "chipid") == 0) {
+        return lis2dh12_shell_cmd_read_chipid(argc, argv);
+    }
+
+    /* Dump */
+    if (argc > 1 && strcmp(argv[1], "dump") == 0) {
+        return lis2dh12_shell_cmd_dump(argc, argv);
+    }
+    
+    /* Peek */
+    if (argc > 1 && strcmp(argv[1], "peek") == 0) {
+        return lis2dh12_shell_cmd_peek(argc, argv);
+    }
+    
+    /* Poke */
+    if (argc > 1 && strcmp(argv[1], "poke") == 0) {
+        return lis2dh12_shell_cmd_poke(argc, argv);
+    }
+
+    /* Test */
+    if (argc > 1 && strcmp(argv[1], "test") == 0) {
+        return lis2dh12_shell_cmd_test(argc, argv);
+    }
+    
+    return lis2dh12_shell_err_unknown_arg(argv[1]);
+}
+
+int
+lis2dh12_shell_init(void)
+{
+    int rc;
+
+    rc = shell_cmd_register(&lis2dh12_shell_cmd_struct);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    return rc;
+}
+
+#endif
diff --git a/hw/drivers/sensors/lis2dh12/syscfg.yml b/hw/drivers/sensors/lis2dh12/syscfg.yml
index 9cdc2bef4e..72cd520dca 100644
--- a/hw/drivers/sensors/lis2dh12/syscfg.yml
+++ b/hw/drivers/sensors/lis2dh12/syscfg.yml
@@ -33,4 +33,39 @@ syscfg.defs:
         description: >
             Number of OS ticks to wait for each I2C transaction to complete.
         value: 3
- 
\ No newline at end of file
+    LIS2DH12_SHELL_ITF_NUM:
+        description: 'Shell interface number for the LIS2DH12'
+        value: 0
+    LIS2DH12_SHELL_ITF_TYPE:
+        description: 'Shell interface type for the LIS2DH12'
+        value: 1
+    LIS2DH12_SHELL_CSPIN:
+        description: 'CS pin for LIS2DH12'
+        value : -1
+    LIS2DH12_SHELL_ITF_ADDR:
+        description: 'Slave address for LIS2DH12'
+        value : 0x19
+    LIS2DH12_CLI:
+        description: 'Enable shell support for the LIS2DH12'
+        value: 0
+    LIS2DH12_NOTIF_STATS:
+        description: 'Enable notification stats'
+        value: 1
+    LIS2DH12_INT1_PIN_HOST:
+        description: 'Interrupt pin number on host device connected to INT1 on device'
+        value: 25
+    LIS2DH12_INT1_PIN_DEVICE:
+        description: 'Interrupt pin number 1 or 2 on accelerometer device'
+        value: 1
+    LIS2DH12_INT1_CFG_ACTIVE:
+        description: 'Set 0 for active-low, 1 for active-high'
+        value: 0
+    LIS2DH12_INT2_PIN_HOST:
+        description: 'Interrupt pin number on host device connected to INT1 on device'
+        value: 31
+    LIS2DH12_INT2_PIN_DEVICE:
+        description: 'Interrupt pin number 1 or 2 on accelerometer device'
+        value: 2
+    LIS2DH12_INT2_CFG_ACTIVE:
+        description: 'Set 0 for active-low, 1 for active-high'
+        value: 0


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services