This is an automated email from the ASF dual-hosted git repository.

vipulrahane pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git


The following commit(s) were added to refs/heads/master by this push:
     new 151bb20  Lis2dh12 driver (#1520)
151bb20 is described below

commit 151bb202f317409319c1ca10ca11ca32d03f866a
Author: JustineKH <35044800+justin...@users.noreply.github.com>
AuthorDate: Wed Nov 14 16:59:18 2018 -0800

    Lis2dh12 driver (#1520)
    
    - Add notifications support and various fixes
---
 .../sensors/lis2dh12/include/lis2dh12/lis2dh12.h   |  316 ++++-
 hw/drivers/sensors/lis2dh12/src/lis2dh12.c         | 1472 ++++++++++++++++++--
 hw/drivers/sensors/lis2dh12/src/lis2dh12_priv.h    |   37 +-
 hw/drivers/sensors/lis2dh12/src/lis2dh12_shell.c   |  387 +++++
 hw/drivers/sensors/lis2dh12/syscfg.yml             |   37 +-
 5 files changed, 2092 insertions(+), 157 deletions(-)

diff --git a/hw/drivers/sensors/lis2dh12/include/lis2dh12/lis2dh12.h 
b/hw/drivers/sensors/lis2dh12/include/lis2dh12/lis2dh12.h
index 7e13fcb..ab4b807 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;
 };
 
 /**
@@ -200,13 +373,24 @@ 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
  *
  * @param the sensor interface
  * @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 fcb961e..fcc272a 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};
@@ -380,6 +514,66 @@ lis2dh12_readlen(struct sensor_itf *itf, uint8_t addr, 
uint8_t *payload,
 }
 
 /**
+ * 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
  *
  * @param The sensor interface
@@ -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) {
@@ -699,6 +894,27 @@ err:
 }
 
 /**
+ * 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 @@ err:
     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 @@ err:
  * @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 @@ err:
     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 @@ err:
     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;
@@ -1072,6 +2148,29 @@ err:
 }
 
 /**
+ * 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
  *
  * @param the sensor interface
@@ -1124,11 +2223,9 @@ err:
  * @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 @@ err:
  * @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;
         }
@@ -1649,6 +2735,52 @@ err:
 }
 
 /**
+ * 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
  *
  * @param ptr to sensor driver
@@ -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 d37c269..6848b15 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 0000000..7b9beb7
--- /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 9cdc2be..72cd520 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

Reply via email to