You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by vi...@apache.org on 2018/03/22 00:11:30 UTC

[mynewt-core] branch master updated: Add Driver for LIS2DW12 (#926)

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 40bb23b  Add Driver for LIS2DW12 (#926)
40bb23b is described below

commit 40bb23be258811c16eaed54a13eb44cb284d0c49
Author: matthewwarnes <36...@users.noreply.github.com>
AuthorDate: Thu Mar 22 00:11:27 2018 +0000

    Add Driver for LIS2DW12 (#926)
    
    * Create driver for lis2dw12 accelerometer
    * Add lis2dw12 to sensor_creator
    * Add stream reading
    * Get stream_read to dump all data in FIFO
---
 .../sensors/lis2dw12/include/lis2dw12/lis2dw12.h   |  553 ++++++
 hw/drivers/sensors/lis2dw12/pkg.yml                |   35 +
 hw/drivers/sensors/lis2dw12/src/lis2dw12.c         | 2065 ++++++++++++++++++++
 hw/drivers/sensors/lis2dw12/src/lis2dw12_priv.h    |  157 ++
 hw/drivers/sensors/lis2dw12/syscfg.yml             |   28 +
 hw/sensor/creator/src/sensor_creator.c             |   85 +
 hw/sensor/creator/syscfg.yml                       |    4 +
 7 files changed, 2927 insertions(+)

diff --git a/hw/drivers/sensors/lis2dw12/include/lis2dw12/lis2dw12.h b/hw/drivers/sensors/lis2dw12/include/lis2dw12/lis2dw12.h
new file mode 100644
index 0000000..d780923
--- /dev/null
+++ b/hw/drivers/sensors/lis2dw12/include/lis2dw12/lis2dw12.h
@@ -0,0 +1,553 @@
+/*
+ * 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
+ * resarding 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.
+ */
+
+#ifndef __LIS2DW12_H__
+#define __LIS2DW12_H__
+
+#include <os/os.h>
+#include "os/os_dev.h"
+#include "sensor/sensor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIS2DW12_PM_LP_MODE1                    0x00
+#define LIS2DW12_PM_LP_MODE2                    0x01
+#define LIS2DW12_PM_LP_MODE3                    0x02
+#define LIS2DW12_PM_LP_MODE4                    0x03
+#define LIS2DW12_PM_HIGH_PERF                   0x04
+    
+#define LIS2DW12_DATA_RATE_0HZ                  0x00
+#define LIS2DW12_DATA_RATE_1_6HZ                0x10
+#define LIS2DW12_DATA_RATE_12_5HZ               0x20
+#define LIS2DW12_DATA_RATE_25HZ                 0x30
+#define LIS2DW12_DATA_RATE_50HZ                 0x40
+#define LIS2DW12_DATA_RATE_100HZ                0x50
+#define LIS2DW12_DATA_RATE_200HZ                0x60
+#define LIS2DW12_DATA_RATE_400HZ                0x70
+#define LIS2DW12_DATA_RATE_800HZ                0x80
+#define LIS2DW12_DATA_RATE_1600HZ               0x90
+
+#define LIS2DW12_ST_MODE_DISABLE                0x00
+#define LIS2DW12_ST_MODE_MODE1                  0x40
+#define LIS2DW12_ST_MODE_MODE2                  0x80
+
+#define LIS2DW12_HPF_M_NORMAL0                  0x00
+#define LIS2DW12_HPF_M_REF                      0x01
+#define LIS2DW12_HPF_M_NORMAL1                  0x02
+#define LIS2DW12_HPF_M_AIE                      0x03
+
+#define LIS2DW12_FILTER_BW_ODR_DIV_2            0x00
+#define LIS2DW12_FILTER_BW_ODR_DIV_4            0x40
+#define LIS2DW12_FILTER_BW_ODR_DIV_10           0x80
+#define LIS2DW12_FILTER_BW_ODR_DIV_20           0xC0
+
+#define LIS2DW12_FS_2G                          0x00
+#define LIS2DW12_FS_4G                          0x10
+#define LIS2DW12_FS_8G                          0x20
+#define LIS2DW12_FS_16G                         0x30
+
+#define LIS2DW12_INT1_CFG_DRDY                  0x01
+#define LIS2DW12_INT1_CFG_FTH                   0x02
+#define LIS2DW12_INT1_CFG_DIFF5                 0x04
+#define LIS2DW12_INT1_CFG_DOUBLE_TAP            0x08
+#define LIS2DW12_INT1_CFG_FF                    0x10
+#define LIS2DW12_INT1_CFG_WU                    0x20
+#define LIS2DW12_INT1_CFG_SINGLE_TAP            0x40
+#define LIS2DW12_INT1_CFG_6D                    0x80
+
+#define LIS2DW12_INT2_CFG_DRDY                  0x01
+#define LIS2DW12_INT2_CFG_FTH                   0x02
+#define LIS2DW12_INT2_CFG_DIFF5                 0x04
+#define LIS2DW12_INT2_CFG_OVR                   0x08
+#define LIS2DW12_INT2_CFG_DRDY_T                0x10
+#define LIS2DW12_INT2_CFG_BOOT                  0x20
+#define LIS2DW12_INT2_CFG_SLEEP_CHG             0x40
+#define LIS2DW12_INT2_CFG_SLEEP_STATE           0x80
+
+#define LIS2DW12_INT_SRC_SLP_CHG                0x20
+#define LIS2DW12_INT_SRC_6D_IA                  0x10
+#define LIS2DW12_INT_SRC_DTAP                   0x08
+#define LIS2DW12_INT_SRC_STAP                   0x04
+#define LIS2DW12_INT_SRC_WU_IA                  0x02
+#define LIS2DW12_INT_SRC_FF_IA                  0x01
+
+    
+enum lis2dw12_ths_6d {
+    LIS2DW12_6D_THS_80_DEG = 0,
+    LIS2DW12_6D_THS_70_DEG = 1,
+    LIS2DW12_6D_THS_60_DEG = 2,
+    LIS2DW12_6D_THS_50_DEG = 3
+};
+
+enum lis2dw12_tap_priority {
+    LIS2DW12_TAP_PRIOR_XYZ = 0,
+    LIS2DW12_TAP_PRIOR_YXZ = 1,
+    LIS2DW12_TAP_PRIOR_XZY = 2,
+    LIS2DW12_TAP_PRIOR_ZYX = 3,
+    LIS2DW12_TAP_PRIOR_YZX = 5,
+    LIS2DW12_TAP_PRIOR_ZXY = 6
+};
+
+enum lis2dw12_fifo_mode {
+    LIS2DW12_FIFO_M_BYPASS               = 0,
+    LIS2DW12_FIFO_M_FIFO                 = 1,
+    LIS2DW12_FIFO_M_CONTINUOUS_TO_FIFO   = 3,
+    LIS2DW12_FIFO_M_BYPASS_TO_CONTINUOUS = 4,
+    LIS2DW12_FIFO_M_CONTINUOUS           = 6
+};
+    
+enum lis2dw12_read_mode {
+    LIS2DW12_READ_M_POLL = 0,
+    LIS2DW12_READ_M_STREAM = 1,
+};
+    
+struct lis2dw12_tap_settings {
+    uint8_t en_x;
+    uint8_t en_y; 
+    uint8_t en_z;
+    
+    uint8_t en_4d;
+    enum lis2dw12_ths_6d ths_6d;
+    enum lis2dw12_tap_priority tap_priority;
+
+    /* ths data is 5 bits, fs = +-2g */
+    int8_t tap_ths_x;
+    int8_t tap_ths_y;
+    int8_t tap_ths_z;
+
+    /* latency is time between taps in double tap, 0 = 16 *1/ODR, LSB = 32*1/ODR */
+    uint8_t latency;
+    /* quiet is time after tap data bust be below threshold
+       0 = 2*1/ODR, LSB = 4*1/ODR */
+    uint8_t quiet;
+    /* shock is maximum time data can be over threshold to register as tap
+       0 = 2*1/ODR, LSB = 4*1/ODR */
+    uint8_t shock;
+    
+};
+
+    
+struct lis2dw12_cfg {
+    uint8_t rate;
+    uint8_t fs;
+
+    int8_t offset_x;
+    int8_t offset_y;
+    int8_t offset_z;
+    uint8_t offset_weight;
+    uint8_t offset_en;
+
+    struct lis2dw12_tap_settings tap_cfg;
+
+    uint8_t int1_pin_cfg;
+    uint8_t int2_pin_cfg;
+    uint8_t int_enable;
+
+    enum lis2dw12_fifo_mode fifo_mode;
+    uint8_t fifo_threshold;
+    
+    enum lis2dw12_read_mode read_mode;
+    uint8_t stream_read_interrupt;
+    
+    sensor_type_t mask;
+};
+
+/* Used to track interrupt state to wake any present waiters */
+struct lis2dw12_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;
+};
+
+    
+struct lis2dw12_private_driver_data {
+    struct sensor_notify_ev_ctx notify_ctx;
+    uint8_t registered_mask;
+
+    struct lis2dw12_int * interrupt;
+    
+    uint8_t int_num;
+    uint8_t int_enable;
+};
+        
+    
+struct lis2dw12 {
+    struct os_dev dev;
+    struct sensor sensor;
+    struct lis2dw12_cfg cfg;
+    struct lis2dw12_int intr;
+
+    struct lis2dw12_private_driver_data pdd;
+};
+
+/**
+ * Reset lis2dw12
+ *
+ * @param The sensor interface
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_reset(struct sensor_itf *itf);
+
+/**
+ * Get chip ID
+ *
+ * @param sensor interface
+ * @param ptr to chip id to be filled up
+ */
+int lis2dw12_get_chip_id(struct sensor_itf *itf, uint8_t *chip_id);
+    
+/**
+ * Sets the full scale selection
+ *
+ * @param The sensor interface
+ * @param fs to set
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_full_scale(struct sensor_itf *itf, uint8_t fs);
+
+/**
+ * Gets the full scale selection
+ *
+ * @param The sensor interface
+ * @param ptr to fs
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_full_scale(struct sensor_itf *itf, uint8_t *fs);
+
+/**
+ * Sets the rate
+ *
+ * @param The sensor interface
+ * @param The rate
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_rate(struct sensor_itf *itf, uint8_t rate);
+
+/**
+ * Gets the current rate
+ *
+ * @param The sensor interface
+ * @param ptr to rate read from the sensor
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_rate(struct sensor_itf *itf, uint8_t *rate);
+
+/**
+ * Sets the low noise enable
+ *
+ * @param The sensor interface
+ * @param low noise enabled
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_low_noise(struct sensor_itf *itf, uint8_t en);
+
+/**
+ * Gets whether low noise is enabled
+ *
+ * @param The sensor interface
+ * @param ptr to low noise settings read from sensor
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_low_noise(struct sensor_itf *itf, uint8_t *en);
+
+/**
+ * Sets the power mode of the sensor
+ *
+ * @param The sensor interface
+ * @param power mode
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_power_mode(struct sensor_itf *itf, uint8_t mode);
+
+/**
+ * Gets the power mode of the sensor
+ *
+ * @param The sensor interface
+ * @param ptr to power mode setting read from sensor
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_power_mode(struct sensor_itf *itf, uint8_t *mode);
+
+/**
+ * Sets the self test mode of the sensor
+ *
+ * @param The sensor interface
+ * @param self test mode
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_self_test(struct sensor_itf *itf, uint8_t mode);
+
+/**
+ * Gets the power mode of the sensor
+ *
+ * @param The sensor interface
+ * @param ptr to self test mode read from sensor
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_self_test(struct sensor_itf *itf, uint8_t *mode);
+
+/**
+ * Set filter config
+ *
+ * @param the sensor interface
+ * @param the filter bandwidth
+ * @param filter type (1 = high pass, 0 = low pass)
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_filter_cfg(struct sensor_itf *itf, uint8_t bw, uint8_t type);
+
+/**
+ * Get filter config
+ *
+ * @param the sensor interface
+ * @param ptr to the filter bandwidth
+ * @param ptr to filter type (1 = high pass, 0 = low pass)
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_filter_cfg(struct sensor_itf *itf, uint8_t *bw, uint8_t *type);
+    
+/**
+ * Sets new offsets in sensor
+ *
+ * @param The sensor interface
+ * @param X offset
+ * @param Y offset
+ * @param Z offset
+ * @param Value Weight (0 = 977ug/LSB, 1 = 15.6mg/LSB)
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int lis2dw12_set_offsets(struct sensor_itf *itf, int8_t offset_x,
+                         int8_t offset_y, int8_t offset_z, uint8_t weight);
+
+/**
+ * Gets the offsets currently set
+ *
+ * @param The sensor interface
+ * @param Pointer to location to store X offset
+ * @param Pointer to location to store Y offset
+ * @param Pointer to location to store Z offset
+ * @param Pointer to value weight
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int lis2dw12_get_offsets(struct sensor_itf *itf, int8_t *offset_x,
+                         int8_t *offset_y, int8_t *offset_z, uint8_t * weight);
+
+/**
+ * Sets whether offset are enabled (only work when low pass filtering is enabled)
+ *
+ * @param The sensor interface
+ * @param value to set (0 = disabled, 1 = enabled)
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int lis2dw12_set_offset_enable(struct sensor_itf *itf, uint8_t enabled);
+   
+/**
+ * Set tap detection configuration
+ *
+ * @param the sensor interface
+ * @param the tap settings
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_tap_cfg(struct sensor_itf *itf, struct lis2dw12_tap_settings *cfg);
+
+/**
+ * Get tap detection config
+ *
+ * @param the sensor interface
+ * @param ptr to the tap settings
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_tap_cfg(struct sensor_itf *itf, struct lis2dw12_tap_settings *cfg);
+
+/**
+ * Set freefall detection configuration
+ *
+ * @param the sensor interface
+ * @param freefall duration (5 bits LSB = 1/ODR)
+ * @param freefall threshold (3 bits)
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_freefall(struct sensor_itf *itf, uint8_t dur, uint8_t ths);
+
+/**
+ * Get freefall detection config
+ *
+ * @param the sensor interface
+ * @param ptr to freefall duration
+ * @param ptr to freefall threshold
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_freefall(struct sensor_itf *itf, uint8_t *dur, uint8_t *ths);
+    
+/**
+ * Set interrupt pin configuration for interrupt 1
+ *
+ * @param the sensor interface
+ * @param config
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_set_int1_pin_cfg(struct sensor_itf *itf, uint8_t cfg);
+
+/**
+ * Set interrupt pin configuration for interrupt 2
+ *
+ * @param the sensor interface
+ * @param config
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_int2_pin_cfg(struct sensor_itf *itf, uint8_t cfg);
+
+/**
+ * Set whether interrupts are enabled
+ *
+ * @param the sensor interface
+ * @param value to set (0 = disabled, 1 = enabled)
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_int_enable(struct sensor_itf *itf, uint8_t enabled);
+
+/**
+ * Clear interrupts
+ *
+ * @param the sensor interface
+ * @param pointer to return interrupt source in
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_clear_int(struct sensor_itf *itf, uint8_t *src);
+
+/**
+ * Get Interrupt Source
+ *
+ * @param the sensor interface
+ * @param pointer to return interrupt source in
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_int_src(struct sensor_itf *itf, uint8_t *status);
+
+/**
+ * Setup FIFO
+ *
+ * @param the sensor interface
+ * @param FIFO mode to setup
+ * @patam Threshold to set for FIFO
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_fifo_cfg(struct sensor_itf *itf, enum lis2dw12_fifo_mode mode, uint8_t fifo_ths);
+
+/**
+ * Get Number of Samples in FIFO
+ *
+ * @param the sensor interface
+ * @patam Pointer to return number of samples in
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_fifo_samples(struct sensor_itf *itf, uint8_t *samples);
+    
+/**
+ * Run Self test on sensor
+ *
+ * @param the sensor interface
+ * @param pointer to return test result in (0 on pass, non-zero on failure)
+ *
+ * @return 0 on sucess, non-zero on failure
+ */
+int lis2dw12_run_self_test(struct sensor_itf *itf, int *result);
+
+/**
+ * Provide a continuous stream of accelerometer readings.
+ *
+ * @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 lis2dw12_stream_read(struct sensor *sensor,
+                         sensor_type_t sensor_type,
+                         sensor_data_func_t read_func,
+                         void *read_arg,
+                         uint32_t time_ms);
+
+/**
+ * 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 lis2dw12_poll_read(struct sensor * sensor,
+                       sensor_type_t sensor_type,
+                       sensor_data_func_t data_func,
+                       void * data_arg,
+                       uint32_t timeout);
+
+/**
+ * Expects to be called back through os_dev_create().
+ *
+ * @param ptr to the device object associated with this accelerometer
+ * @param argument passed to OS device init
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int lis2dw12_init(struct os_dev *dev, void *arg);
+
+/**
+ * Configure the sensor
+ *
+ * @param ptr to sensor driver
+ * @param ptr to sensor driver config
+ */
+int lis2dw12_config(struct lis2dw12 *, struct lis2dw12_cfg *);
+
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LIS2DW12_H__ */
diff --git a/hw/drivers/sensors/lis2dw12/pkg.yml b/hw/drivers/sensors/lis2dw12/pkg.yml
new file mode 100644
index 0000000..f188c49
--- /dev/null
+++ b/hw/drivers/sensors/lis2dw12/pkg.yml
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+pkg.name: hw/drivers/sensors/lis2dw12
+pkg.description: Driver for the LIS2DW12 accelerometer
+pkg.keywords:
+    - lis2dw12
+    - i2c
+    - spi
+    - sensor
+
+pkg.deps:
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-core/hw/hal"
+    - "@apache-mynewt-core/hw/sensor"
+
+pkg.req_apis:
+    - stats
+    - log
diff --git a/hw/drivers/sensors/lis2dw12/src/lis2dw12.c b/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
new file mode 100644
index 0000000..c977acf
--- /dev/null
+++ b/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
@@ -0,0 +1,2065 @@
+/*
+ * 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
+ * resarding 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 <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "sysinit/sysinit.h"
+#include "defs/error.h"
+#include "os/os.h"
+#include "hal/hal_spi.h"
+#include "hal/hal_i2c.h"
+#include "sensor/sensor.h"
+#include "sensor/accel.h"
+#include "lis2dw12/lis2dw12.h"
+#include "lis2dw12_priv.h"
+#include "hal/hal_gpio.h"
+#include "log/log.h"
+#include "stats/stats.h"
+
+static struct hal_spi_settings spi_lis2dw12_settings = {
+    .data_order = HAL_SPI_MSB_FIRST,
+    .data_mode  = HAL_SPI_MODE3,
+    .baudrate   = 4000,
+    .word_size  = HAL_SPI_WORD_SIZE_8BIT,
+};
+
+/* Define the stats section and records */
+STATS_SECT_START(lis2dw12_stat_section)
+    STATS_SECT_ENTRY(write_errors)
+    STATS_SECT_ENTRY(read_errors)
+STATS_SECT_END
+
+/* Define stat names for querying */
+STATS_NAME_START(lis2dw12_stat_section)
+    STATS_NAME(lis2dw12_stat_section, write_errors)
+    STATS_NAME(lis2dw12_stat_section, read_errors)
+STATS_NAME_END(lis2dw12_stat_section)
+
+/* Global variable used to hold stats data */
+STATS_SECT_DECL(lis2dw12_stat_section) g_lis2dw12stats;
+
+#define LOG_MODULE_LIS2DW12    (212)
+#define LIS2DW12_INFO(...)     LOG_INFO(&_log, LOG_MODULE_LIS2DW12, __VA_ARGS__)
+#define LIS2DW12_ERR(...)      LOG_ERROR(&_log, LOG_MODULE_LIS2DW12, __VA_ARGS__)
+static struct log _log;
+
+#define LIS2DW12_NOTIFY_MASK 0x01
+
+/* Exports for the sensor API */
+static int lis2dw12_sensor_read(struct sensor *, sensor_type_t,
+        sensor_data_func_t, void *, uint32_t);
+static int lis2dw12_sensor_get_config(struct sensor *, sensor_type_t,
+        struct sensor_cfg *);
+static int lis2dw12_sensor_set_notification(struct sensor *,
+                                            sensor_event_type_t);
+static int lis2dw12_sensor_unset_notification(struct sensor *,
+                                              sensor_event_type_t);
+static int lis2dw12_sensor_handle_interrupt(struct sensor *);
+
+static const struct sensor_driver g_lis2dw12_sensor_driver = {
+    .sd_read = lis2dw12_sensor_read,
+    .sd_get_config = lis2dw12_sensor_get_config,
+    .sd_set_notification = lis2dw12_sensor_set_notification,
+    .sd_unset_notification = lis2dw12_sensor_unset_notification,
+    .sd_handle_interrupt = lis2dw12_sensor_handle_interrupt
+
+};
+
+/**
+ * Writes a single byte to the specified register using i2c
+ *
+ * @param The sensor interface
+ * @param The register address to write to
+ * @param The value to write
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+lis2dw12_i2c_write8(struct sensor_itf *itf, uint8_t reg, uint8_t value)
+{
+    int rc;
+    uint8_t payload[2] = { reg, value };
+    
+    struct hal_i2c_master_data data_struct = {
+        .address = itf->si_addr,
+        .len = 2,
+        .buffer = payload
+    };
+
+    rc = hal_i2c_master_write(itf->si_num, &data_struct,
+                              OS_TICKS_PER_SEC / 10, 1);
+
+    if (rc) {
+        LIS2DW12_ERR("Failed to write to 0x%02X:0x%02X with value 0x%02X\n",
+                    itf->si_addr, reg, value);
+        STATS_INC(g_lis2dw12stats, read_errors);
+    }
+
+    return rc;
+}
+
+/**
+ * Read multiple bytes starting from specified register over i2c
+ *    
+ * @param The sensor interface
+ * @param The register address start reading from
+ * @param Pointer to where the register value should be written
+ * @param Number of bytes to read
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+lis2dw12_i2c_readlen(struct sensor_itf *itf, uint8_t reg, uint8_t *buffer, uint8_t len)
+{
+    int rc;
+
+    struct hal_i2c_master_data data_struct = {
+        .address = itf->si_addr,
+        .len = 1,
+        .buffer = &reg
+    };
+
+    /* Register write */
+    rc = hal_i2c_master_write(itf->si_num, &data_struct,
+                              OS_TICKS_PER_SEC / 10, 1);
+    if (rc) {
+        LIS2DW12_ERR("I2C access failed at address 0x%02X\n", itf->si_addr);
+        STATS_INC(g_lis2dw12stats, write_errors);
+        return rc;
+    }
+
+    /* Read data */
+    data_struct.len = len;
+    data_struct.buffer = buffer;
+    rc = hal_i2c_master_read(itf->si_num, &data_struct,
+                             OS_TICKS_PER_SEC / 10, 1);
+
+    if (rc) {
+        LIS2DW12_ERR("Failed to read from 0x%02X:0x%02X\n", itf->si_addr, reg);
+        STATS_INC(g_lis2dw12stats, read_errors);
+    }
+
+    return rc;
+}
+
+/**
+ * Writes a single byte to the specified register using SPI
+ *
+ * @param The sensor interface
+ * @param The register address to write to
+ * @param The value to write
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+lis2dw12_spi_write8(struct sensor_itf *itf, uint8_t reg, uint8_t value)
+{
+    int rc;
+
+    /* Select the device */
+    hal_gpio_write(itf->si_cs_pin, 0);
+
+    /* Send the address */
+    rc = hal_spi_tx_val(itf->si_num, reg & ~LIS2DW12_SPI_READ_CMD_BIT);
+    if (rc == 0xFFFF) {
+        rc = SYS_EINVAL;
+        LIS2DW12_ERR("SPI_%u register write failed addr:0x%02X\n",
+                   itf->si_num, reg);
+        STATS_INC(g_lis2dw12stats, write_errors);
+        goto err;
+    }
+
+    /* Read data */
+    rc = hal_spi_tx_val(itf->si_num, value);
+    if (rc == 0xFFFF) {
+        rc = SYS_EINVAL;
+        LIS2DW12_ERR("SPI_%u write failed addr:0x%02X:0x%02X\n",
+                   itf->si_num, reg);
+        STATS_INC(g_lis2dw12stats, write_errors);
+        goto err;
+    }
+
+    rc = 0;
+
+err:
+    /* De-select the device */
+    hal_gpio_write(itf->si_cs_pin, 1);
+
+    return rc;
+}
+
+/**
+ * Read multiple bytes starting from specified register over SPI
+ *
+ * @param The sensor interface
+ * @param The register address start reading from
+ * @param Pointer to where the register value should be written
+ * @param Number of bytes to read
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_spi_readlen(struct sensor_itf *itf, uint8_t reg, uint8_t *buffer,
+                    uint8_t len)
+{
+    int i;
+    uint16_t retval;
+    int rc = 0;
+
+    /* Select the device */
+    hal_gpio_write(itf->si_cs_pin, 0);
+
+    /* Send the address */
+    retval = hal_spi_tx_val(itf->si_num, reg | LIS2DW12_SPI_READ_CMD_BIT);
+    
+    if (retval == 0xFFFF) {
+        rc = SYS_EINVAL;
+        LIS2DW12_ERR("SPI_%u register write failed addr:0x%02X\n",
+                   itf->si_num, reg);
+        STATS_INC(g_lis2dw12stats, read_errors);
+        goto err;
+    }
+
+    for (i = 0; i < len; i++) {
+        /* Read data */
+        retval = hal_spi_tx_val(itf->si_num, 0);
+        if (retval == 0xFFFF) {
+            rc = SYS_EINVAL;
+            LIS2DW12_ERR("SPI_%u read failed addr:0x%02X\n",
+                       itf->si_num, reg);
+            STATS_INC(g_lis2dw12stats, read_errors);
+            goto err;
+        }
+        buffer[i] = retval;
+    }
+
+err:
+    /* De-select the device */
+    hal_gpio_write(itf->si_cs_pin, 1);
+
+    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
+lis2dw12_write8(struct sensor_itf *itf, uint8_t reg, uint8_t value)
+{
+    int rc;
+
+    if (itf->si_type == SENSOR_ITF_I2C) {
+        rc = lis2dw12_i2c_write8(itf, reg, value);
+    } else {
+        rc = lis2dw12_spi_write8(itf, reg, value);
+    }
+
+    return rc;
+}
+
+/**
+ * Read byte data from sensor over different interfaces
+ *
+ * @param The sensor interface
+ * @param The register address to read from
+ * @param Pointer to where the register value should be written
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_read8(struct sensor_itf *itf, uint8_t reg, uint8_t *value)
+{
+    int rc;
+
+    if (itf->si_type == SENSOR_ITF_I2C) {
+        rc = lis2dw12_i2c_readlen(itf, reg, value, 1);
+    } else {
+        rc = lis2dw12_spi_readlen(itf, reg, value, 1);
+    }
+
+    return rc;
+}
+
+/**
+ * Read multiple bytes starting from specified register over different interfaces
+ *
+ * @param The sensor interface
+ * @param The register address start reading from
+ * @param Pointer to where the register value should be written
+ * @param Number of bytes to read
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_readlen(struct sensor_itf *itf, uint8_t reg, uint8_t *buffer,
+                uint8_t len)
+{
+    int rc;
+
+    if (itf->si_type == SENSOR_ITF_I2C) {
+        rc = lis2dw12_i2c_readlen(itf, reg, buffer, len);
+    } else {
+        rc = lis2dw12_spi_readlen(itf, reg, buffer, len);
+    }
+
+    return rc;
+}
+
+/**
+ * Calculates the acceleration in m/s^2 from mg
+ *
+ * @param acc value in mg
+ * @param float ptr to return calculated value in ms2
+ */
+void
+lis2dw12_calc_acc_ms2(int16_t acc_mg, float *acc_ms2)
+{
+    *acc_ms2 = (acc_mg * STANDARD_ACCEL_GRAVITY)/1000;
+}
+
+/**
+ * Calculates the acceleration in mg from m/s^2
+ *
+ * @param acc value in m/s^2
+ * @param int16 ptr to return calculated value in mg
+ */
+void
+lis2dw12_calc_acc_mg(float acc_ms2, int16_t *acc_mg)
+{
+    *acc_mg = (acc_ms2 * 1000)/STANDARD_ACCEL_GRAVITY;
+}
+
+/**
+ * Reset lis2dw12
+ *
+ * @param The sensor interface
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_reset(struct sensor_itf *itf)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG2, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    reg |= LIS2DW12_CTRL_REG2_SOFT_RESET | LIS2DW12_CTRL_REG2_BOOT;
+
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG2, reg);
+    if (rc) {
+        goto err;
+    }
+
+    os_time_delay((OS_TICKS_PER_SEC * 6/1000) + 1);
+
+err:
+    return rc;
+}
+
+/**
+ * Get chip ID
+ *
+ * @param sensor interface
+ * @param ptr to chip id to be filled up
+ */
+int
+lis2dw12_get_chip_id(struct sensor_itf *itf, uint8_t *chip_id)
+{
+    uint8_t reg;
+    int rc;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_WHO_AM_I, &reg);
+
+    if (rc) {
+        goto err;
+    }
+
+    *chip_id = reg;
+
+err:
+    return rc;
+}
+
+/**
+ * Sets the full scale selection
+ *
+ * @param The sensor interface
+ * @param The fs setting
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_set_full_scale(struct sensor_itf *itf, uint8_t fs)
+{
+    int rc;
+    uint8_t reg;
+
+    if (fs > LIS2DW12_FS_16G) {
+        LIS2DW12_ERR("Invalid full scale value\n");
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG6, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    reg = (reg & ~LIS2DW12_CTRL_REG6_FS) | fs;
+
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG6, reg);
+    if (rc) {
+        goto err;
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Gets the full scale selection
+ *
+ * @param The sensor interface
+ * @param ptr to fs
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_get_full_scale(struct sensor_itf *itf, uint8_t *fs)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG6, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    *fs = reg & LIS2DW12_CTRL_REG6_FS;
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Sets the rate
+ *
+ * @param The sensor interface
+ * @param The rate
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_set_rate(struct sensor_itf *itf, uint8_t rate)
+{
+    int rc;
+    uint8_t reg;
+
+    if (rate > LIS2DW12_DATA_RATE_1600HZ) {
+        LIS2DW12_ERR("Invalid rate value\n");
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG1, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    reg = (reg & ~LIS2DW12_CTRL_REG1_ODR) | rate;
+
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG1, reg);
+    if (rc) {
+        goto err;
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Gets the rate
+ *
+ * @param The sensor ineterface
+ * @param ptr to the rate
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_get_rate(struct sensor_itf *itf, uint8_t *rate)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG1, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    *rate = reg & LIS2DW12_CTRL_REG1_ODR;
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Sets the low noise enable
+ *
+ * @param The sensor interface
+ * @param low noise enabled
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_set_low_noise(struct sensor_itf *itf, uint8_t en)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG6, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    if (en) {
+        reg |= LIS2DW12_CTRL_REG6_LOW_NOISE;
+    } else {
+        reg &= ~LIS2DW12_CTRL_REG6_LOW_NOISE;
+    }
+
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG6, reg);
+    if (rc) {
+        goto err;
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Gets whether low noise is enabled
+ *
+ * @param The sensor interface
+ * @param ptr to low noise settings read from sensor
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_get_low_noise(struct sensor_itf *itf, uint8_t *en)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG6, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    *en = (reg & LIS2DW12_CTRL_REG6_LOW_NOISE) > 0;
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Sets the power mode of the sensor
+ *
+ * @param The sensor interface
+ * @param power mode
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_set_power_mode(struct sensor_itf *itf, uint8_t mode)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG1, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    reg &= ~LIS2DW12_CTRL_REG1_MODE;
+    reg &= ~LIS2DW12_CTRL_REG1_LP_MODE;
+    reg |= mode;
+    
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG1, reg);
+    if (rc) {
+        goto err;
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Gets the power mode of the sensor
+ *
+ * @param The sensor interface
+ * @param ptr to power mode setting read from sensor
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_get_power_mode(struct sensor_itf *itf, uint8_t *mode)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG1, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    *mode = reg & (LIS2DW12_CTRL_REG1_MODE | LIS2DW12_CTRL_REG1_LP_MODE);
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Sets the self test mode of the sensor
+ *
+ * @param The sensor interface
+ * @param self test mode
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_set_self_test(struct sensor_itf *itf, uint8_t mode)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG3, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    reg &= ~LIS2DW12_CTRL_REG3_ST_MODE;
+    reg |= (mode & LIS2DW12_CTRL_REG3_ST_MODE);
+    
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG3, reg);
+    if (rc) {
+        goto err;
+    }
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Gets the self test mode of the sensor
+ *
+ * @param The sensor interface
+ * @param ptr to self test mode read from sensor
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_get_self_test(struct sensor_itf *itf, uint8_t *mode)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG3, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    *mode = reg & LIS2DW12_CTRL_REG3_ST_MODE;
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Set filter config
+ *
+ * @param the sensor interface
+ * @param the filter bandwidth
+ * @param filter type (1 = high pass, 0 = low pass)
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_set_filter_cfg(struct sensor_itf *itf, uint8_t bw, uint8_t type)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG6, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    reg &= ~LIS2DW12_CTRL_REG6_BW_FILT;
+    reg &= ~LIS2DW12_CTRL_REG6_FDS;
+    reg |= (bw & LIS2DW12_CTRL_REG6_BW_FILT);
+    if (type) {
+        reg |= LIS2DW12_CTRL_REG6_FDS;
+    }
+    
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG6, reg);
+    if (rc) {
+        goto err;
+    }
+
+    return 0;
+err:
+    return rc;
+
+}
+
+/**
+ * Get filter config
+ *
+ * @param the sensor interface
+ * @param ptr to the filter bandwidth
+ * @param ptr to filter type (1 = high pass, 0 = low pass)
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_get_filter_cfg(struct sensor_itf *itf, uint8_t *bw, uint8_t *type)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG6, &reg);
+    if (rc) {
+        goto err;
+    }
+
+    *bw = reg & LIS2DW12_CTRL_REG6_BW_FILT;
+    *type = (reg & LIS2DW12_CTRL_REG6_FDS) > 0;
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Sets new offsets in sensor
+ *
+ * @param The sensor interface
+ * @param X offset
+ * @param Y offset
+ * @param Z offset
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+lis2dw12_set_offsets(struct sensor_itf *itf, int8_t offset_x,
+                     int8_t offset_y, int8_t offset_z, uint8_t weight)
+{
+    uint8_t reg;
+    int rc;
+  
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_X_OFS, offset_x);
+    if (rc) {
+        return rc;
+    }
+
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_Y_OFS, offset_y);
+    if (rc) {
+        return rc;
+    }
+
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_Z_OFS, offset_z);
+    if (rc) {
+        return rc;
+    }
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG7, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    if (weight) {
+        reg |= LIS2DW12_CTRL_REG7_USR_OFF_W;
+    } else {
+        reg &= ~LIS2DW12_CTRL_REG7_USR_OFF_W;
+    }
+
+    return lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG7, reg);
+}
+
+/**
+ * Gets the offsets currently set
+ *
+ * @param The sensor interface
+ * @param Pointer to location to store X offset
+ * @param Pointer to location to store Y offset
+ * @param Pointer to location to store Z offset
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+lis2dw12_get_offsets(struct sensor_itf *itf, int8_t *offset_x,
+                     int8_t *offset_y, int8_t *offset_z, uint8_t *weight)
+{
+    uint8_t reg;
+    int rc;
+  
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_X_OFS, (uint8_t *)offset_x);
+    if (rc) {
+        return rc;
+    }
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_Y_OFS, (uint8_t *)offset_y);
+    if (rc) {
+        return rc;
+    }
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_Z_OFS, (uint8_t *)offset_z);
+    if (rc) {
+        return rc;
+    }
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG7, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    *weight = reg & LIS2DW12_CTRL_REG7_USR_OFF_W ? 1 : 0;
+
+    return 0;
+}
+
+/**
+ * Sets whether offset are enabled (only work when low pass filtering is enabled)
+ *
+ * @param The sensor interface
+ * @param value to set (0 = disabled, 1 = enabled)
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int lis2dw12_set_offset_enable(struct sensor_itf *itf, uint8_t enabled)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG7, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    if (enabled) {
+        reg |= LIS2DW12_CTRL_REG7_USR_OFF_OUT;
+    } else {
+        reg &= ~LIS2DW12_CTRL_REG7_USR_OFF_OUT;
+    }
+
+    return lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG7, reg);
+}
+
+
+/**
+ * Set tap detection configuration
+ *
+ * @param the sensor interface
+ * @param the tap settings
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_tap_cfg(struct sensor_itf *itf, struct lis2dw12_tap_settings *cfg)
+{
+    int rc;
+    uint8_t reg;
+
+    reg = cfg->en_4d ? LIS2DW12_TAP_THS_X_4D_EN : 0;
+    reg |= (cfg->ths_6d & 0x3) << 5;
+    reg |= cfg->tap_ths_x & LIS2DW12_TAP_THS_X_THS;
+
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_TAP_THS_X, reg);
+    if (rc) {
+        return rc;
+    }
+
+    reg = 0;
+    reg |= (cfg->tap_priority & 0x7) << 5;
+    reg |= cfg->tap_ths_y & LIS2DW12_TAP_THS_Y_THS;
+
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_TAP_THS_Y, reg);
+    if (rc) {
+        return rc;
+    }
+
+    reg = 0;
+    reg |= cfg->en_x ? LIS2DW12_TAP_THS_Z_X_EN : 0;
+    reg |= cfg->en_y ? LIS2DW12_TAP_THS_Z_Y_EN : 0;
+    reg |= cfg->en_z ? LIS2DW12_TAP_THS_Z_Z_EN : 0;
+    reg |= cfg->tap_ths_z & LIS2DW12_REG_TAP_THS_Z;
+    
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_TAP_THS_Z, reg);
+    if (rc) {
+        return rc;
+    }
+
+    reg = 0;
+    reg |= (cfg->latency & LIS2DW12_INT_DUR_LATENCY) << 4;
+    reg |= (cfg->quiet & LIS2DW12_INT_DUR_QUIET) << 2;
+    reg |= cfg->shock & LIS2DW12_INT_DUR_SHOCK;
+
+    return 0;
+}
+
+/**
+ * Get tap detection config
+ *
+ * @param the sensor interface
+ * @param ptr to the tap settings
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_tap_cfg(struct sensor_itf *itf, struct lis2dw12_tap_settings *cfg)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_TAP_THS_X, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    cfg->en_4d = (reg & LIS2DW12_TAP_THS_X_4D_EN) > 0;
+    cfg->ths_6d = (reg & LIS2DW12_TAP_THS_X_6D_THS) >> 5;
+    cfg->tap_ths_x = reg & LIS2DW12_TAP_THS_X_THS;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_TAP_THS_Y, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    cfg->tap_priority = (reg & LIS2DW12_TAP_THS_Y_PRIOR) >> 5;
+    cfg->tap_ths_y = reg & LIS2DW12_TAP_THS_Y_THS;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_TAP_THS_Z, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    cfg->en_x = (reg & LIS2DW12_TAP_THS_Z_X_EN) > 0;
+    cfg->en_y = (reg & LIS2DW12_TAP_THS_Z_Y_EN) > 0;
+    cfg->en_z = (reg & LIS2DW12_TAP_THS_Z_Z_EN) > 0;
+    cfg->tap_ths_z = reg & LIS2DW12_TAP_THS_Z_THS;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_INT_DUR, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    cfg->latency = (reg & LIS2DW12_INT_DUR_LATENCY) >> 4;
+    cfg->quiet = (reg & LIS2DW12_INT_DUR_QUIET) >> 2;
+    cfg->shock = reg & LIS2DW12_INT_DUR_SHOCK;
+    
+    return 0;
+}
+
+/**
+ * Set freefall detection configuration
+ *
+ * @param the sensor interface
+ * @param freefall duration (5 bits LSB = 1/ODR)
+ * @param freefall threshold (3 bits)
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_freefall(struct sensor_itf *itf, uint8_t dur, uint8_t ths)
+{
+    uint8_t reg;
+
+    reg = 0;
+    reg |= (dur & 0x1F) << 3;
+    reg |= ths & LIS2DW12_FREEFALL_THS;
+
+    return lis2dw12_write8(itf, LIS2DW12_REG_FREEFALL, reg);
+}
+
+/**
+ * Get freefall detection config
+ *
+ * @param the sensor interface
+ * @param ptr to freefall duration
+ * @param ptr to freefall threshold
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_freefall(struct sensor_itf *itf, uint8_t *dur, uint8_t *ths)
+{
+    int rc;
+    uint8_t reg;
+    
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_FREEFALL, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    *dur = (reg & LIS2DW12_FREEFALL_DUR) >> 3;
+    *ths = reg & LIS2DW12_FREEFALL_THS;
+
+    return 0;
+}
+
+/**
+ * Setup FIFO
+ *
+ * @param the sensor interface
+ * @param FIFO mode to setup
+ * @patam Threshold to set for FIFO
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_fifo_cfg(struct sensor_itf *itf, enum lis2dw12_fifo_mode mode, uint8_t fifo_ths)
+{
+    uint8_t reg = 0;
+
+    reg |= fifo_ths & LIS2DW12_FIFO_CTRL_FTH;
+    reg |= (mode & 0x7) << 5;
+
+    return lis2dw12_write8(itf, LIS2DW12_REG_FIFO_CTRL, reg);
+}
+
+/**
+ * Get Number of Samples in FIFO
+ *
+ * @param the sensor interface
+ * @patam Pointer to return number of samples in
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_fifo_samples(struct sensor_itf *itf, uint8_t *samples)
+{
+    uint8_t reg;
+    int rc;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_FIFO_SAMPLES, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    *samples = reg & LIS2DW12_FIFO_SAMPLES;
+
+    return 0;
+}
+
+
+/**
+ * Set interrupt pin configuration for interrupt 1
+ *
+ * @param the sensor interface
+ * @param config
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_set_int1_pin_cfg(struct sensor_itf *itf, uint8_t cfg)
+{
+    return lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG4, cfg);
+}
+
+/**
+ * Set interrupt pin configuration for interrupt 2
+ *
+ * @param the sensor interface
+ * @param config
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_set_int2_pin_cfg(struct sensor_itf *itf, uint8_t cfg)
+{
+    return lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG5, cfg);
+}
+
+/**
+ * Clear interrupt 1
+ *
+ * @param the sensor interface
+ */
+int
+lis2dw12_clear_int(struct sensor_itf *itf, uint8_t *src)
+{
+    return lis2dw12_read8(itf, LIS2DW12_REG_INT_SRC, src);  
+}
+
+/**
+ * Get Interrupt Source
+ *
+ * @param the sensor interface
+ * @param pointer to return interrupt source in
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_int_src(struct sensor_itf *itf, uint8_t *status)
+{
+    return lis2dw12_read8(itf, LIS2DW12_REG_STATUS_REG, status);
+}
+
+/**
+ * Set whether interrupts are enabled
+ *
+ * @param the sensor interface
+ * @param value to set (0 = disabled, 1 = enabled)
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_int_enable(struct sensor_itf *itf, uint8_t enabled)
+{
+    uint8_t reg;
+    int rc;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG7, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    if (enabled) {
+        reg |= LIS2DW12_CTRL_REG7_INT_EN;
+    } else {
+        reg &= ~LIS2DW12_CTRL_REG7_INT_EN;
+    }
+
+    return lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG7, reg);
+}
+
+/**
+ * Run Self test on sensor
+ *
+ * @param the sensor interface
+ * @param pointer to return test result in (0 on pass, non-zero on failure)
+ *
+ * @return 0 on sucess, non-zero on failure
+ */
+int lis2dw12_run_self_test(struct sensor_itf *itf, int *result)
+{
+    int rc;
+    int16_t base[3], pos[3];
+    int i;
+    int16_t change;
+    
+    /* ensure self test mode is disabled */
+    rc = lis2dw12_set_self_test(itf, LIS2DW12_ST_MODE_DISABLE);
+    if (rc) {
+        return rc;
+    }
+    
+    os_time_delay(OS_TICKS_PER_SEC / 10);
+    
+    /* take base reading */
+    rc = lis2dw12_get_data(itf, &(base[0]), &(base[1]), &(base[2]));
+    if (rc) {
+        return rc;
+    }
+
+    /* set self test mode to positive self test */
+    rc = lis2dw12_set_self_test(itf, LIS2DW12_ST_MODE_MODE1);
+    if (rc) {
+        return rc;
+    }
+
+    os_time_delay(OS_TICKS_PER_SEC / 10);
+
+    /* take self test reading */
+    rc = lis2dw12_get_data(itf, &(pos[0]), &(pos[1]), &(pos[2]));
+    if (rc) {
+        return rc;
+    }
+
+    /* disable self test mod */
+    rc = lis2dw12_set_self_test(itf, LIS2DW12_ST_MODE_DISABLE);
+    if (rc) {
+        return rc;
+    }
+
+    /* calculate accel data difference */
+    change = 0;
+    for(i = 0; i < 3; i++) {
+        change += pos[i] - base[i];
+    }
+
+    if ((change > 70) && (change < 1500)) {
+        *result = 0;
+    } else {
+        *result = -1;
+    }
+
+    return 0;
+}
+
+
+static void
+init_interrupt(struct lis2dw12_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 lis2dw12_int * interrupt)
+{
+    OS_ENTER_CRITICAL(interrupt->lock);
+    interrupt->active = false;
+    interrupt->asleep = false;
+    OS_EXIT_CRITICAL(interrupt->lock);
+}
+
+static void
+wait_interrupt(struct lis2dw12_int * interrupt, uint8_t int_num)
+{
+    bool wait;
+
+    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;
+    }
+
+    if (interrupt->active) {
+        interrupt->active = false;
+        wait = false;
+    } else {
+        interrupt->asleep = true;
+        wait = true;
+    }
+    OS_EXIT_CRITICAL(interrupt->lock);
+
+    if (wait) {
+        os_error_t error;
+
+        error = os_sem_pend(&interrupt->wait, -1);
+        assert(error == OS_OK);
+    }
+}
+
+static void
+wake_interrupt(struct lis2dw12_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);
+    }
+}
+
+static void
+lis2dw12_int_irq_handler(void *arg)
+{
+    struct sensor *sensor = arg;
+    struct lis2dw12 *lis2dw12;
+
+    lis2dw12 = (struct lis2dw12 *)SENSOR_GET_DEVICE(sensor);
+
+    if(lis2dw12->pdd.interrupt) {
+        wake_interrupt(lis2dw12->pdd.interrupt);
+    }
+    
+    sensor_mgr_put_interrupt_evt(sensor);
+}
+
+static int
+init_intpin(struct lis2dw12 * lis2dw12, hal_gpio_irq_handler_t handler,
+            void * arg)
+{
+    struct lis2dw12_private_driver_data *pdd = &lis2dw12->pdd;
+    hal_gpio_irq_trig_t trig;
+    int pin = -1;
+    int rc;
+    int i;
+
+    for (i = 0; i < MYNEWT_VAL(SENSOR_MAX_INTERRUPTS_PINS); i++){
+        pin = lis2dw12->sensor.s_itf.si_ints[i].host_pin;
+        if (pin >= 0) {
+            break;
+        }
+    }
+
+    if (pin < 0) {
+        LIS2DW12_ERR("Interrupt pin not configured\n");
+        return SYS_EINVAL;
+    }
+
+    pdd->int_num = i;
+    if (lis2dw12->sensor.s_itf.si_ints[pdd->int_num].active) {
+        trig = HAL_GPIO_TRIG_RISING;
+    } else {
+        trig = HAL_GPIO_TRIG_FALLING;
+    }
+  
+    rc = hal_gpio_irq_init(pin,
+                           handler,
+                           arg,
+                           trig,
+                           HAL_GPIO_PULL_NONE);
+    if (rc != 0) {
+        LIS2DW12_ERR("Failed to initialise interrupt pin %d\n", pin);
+        return rc;
+    } 
+
+    return 0;
+}
+
+static int
+enable_interrupt(struct sensor * sensor, uint8_t int_to_enable)
+{
+    struct lis2dw12 *lis2dw12;
+    struct lis2dw12_private_driver_data *pdd;
+    struct sensor_itf *itf;
+    uint8_t reg;
+    int rc;
+
+    lis2dw12 = (struct lis2dw12 *)SENSOR_GET_DEVICE(sensor);
+    itf = SENSOR_GET_ITF(sensor);
+    pdd = &lis2dw12->pdd;
+
+    rc = lis2dw12_clear_int(itf, &reg);
+    if (rc) {
+        return rc;
+    }
+    
+    /* if no interrupts are currently in use enable int pin */
+    if (pdd->int_enable == 0) {
+        hal_gpio_irq_enable(itf->si_ints[pdd->int_num].host_pin);
+
+        rc = lis2dw12_set_int_enable(itf, 1);
+        if (rc) {
+            return rc;
+        }
+    }
+
+    /*update which interrupts are enabled */
+    pdd->int_enable |= int_to_enable;
+    
+    /* enable interrupt in device */
+    rc = lis2dw12_set_int1_pin_cfg(itf, pdd->int_enable);
+    if (rc) {
+        return rc;
+    }
+
+    return 0;
+    
+}
+
+static int
+disable_interrupt(struct sensor * sensor, uint8_t int_to_disable)
+{
+    struct lis2dw12 *lis2dw12;
+    struct lis2dw12_private_driver_data *pdd;
+    struct sensor_itf *itf;
+    int rc;
+
+    if (int_to_disable == 0) {
+        return SYS_EINVAL;
+    }
+    
+    lis2dw12 = (struct lis2dw12 *)SENSOR_GET_DEVICE(sensor);
+    itf = SENSOR_GET_ITF(sensor);
+    pdd = &lis2dw12->pdd;
+
+    pdd->int_enable &= ~int_to_disable;
+    
+    /* disable int pin */
+    if (pdd->int_enable == 0) {
+        hal_gpio_irq_disable(itf->si_ints[pdd->int_num].host_pin);
+           
+        rc = lis2dw12_set_int_enable(itf, 0);
+        if (rc) {
+            return rc;
+        }
+    }
+    
+    /* update interrupt setup in device */
+    return lis2dw12_set_int1_pin_cfg(itf, pdd->int_enable);
+}
+
+/**
+ * Gets a new data sample from the sensor.
+ *
+ * @param The sensor interface
+ * @param x axis data
+ * @param y axis data
+ * @param z axis data
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_get_data(struct sensor_itf *itf, int16_t *x, int16_t *y, int16_t *z)
+{
+    int rc;
+    uint8_t payload[6] = {0};
+    uint8_t fs;
+
+    *x = *y = *z = 0;
+
+    rc = lis2dw12_readlen(itf, LIS2DW12_REG_OUT_X_L, payload, 6);
+    if (rc) {
+        goto err;
+    }
+
+    *x = payload[0] | (payload[1] << 8);
+    *y = payload[2] | (payload[3] << 8);
+    *z = payload[4] | (payload[5] << 8);
+
+    rc = lis2dw12_get_full_scale(itf, &fs);
+    if (rc) {
+        goto err;
+    }
+
+    if (fs == LIS2DW12_FS_2G) {
+        fs = 2;
+    } else if (fs == LIS2DW12_FS_4G) {
+        fs = 4;
+    } else if (fs == LIS2DW12_FS_8G) {
+        fs = 8;
+    } else if (fs == LIS2DW12_FS_16G) {
+        fs = 16;
+    } else {
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    /*
+     * Since full scale is +/-(fs)g,
+     * fs should be multiplied by 2 to account for full scale.
+     * To calculate mg from g we use the 1000 multiple.
+     * Since the full scale is represented by 16 bit value,
+     * we use that as a divisor.
+     */
+    *x = (fs * 2 * 1000 * *x)/UINT16_MAX;
+    *y = (fs * 2 * 1000 * *y)/UINT16_MAX;
+    *z = (fs * 2 * 1000 * *z)/UINT16_MAX;
+
+    return 0;
+err:
+    return rc;
+}
+
+static int lis2dw12_do_read(struct sensor *sensor, sensor_data_func_t data_func,
+                            void * data_arg)
+{
+    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 = lis2dw12_get_data(itf, &x, &y, &z);
+    if (rc) {
+        goto err;
+    }
+
+    /* converting values from mg to ms^2 */
+    lis2dw12_calc_acc_ms2(x, &fx);
+    lis2dw12_calc_acc_ms2(y, &fy);
+    lis2dw12_calc_acc_ms2(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
+lis2dw12_poll_read(struct sensor * sensor, sensor_type_t sensor_type,
+                 sensor_data_func_t data_func, void * data_arg,
+                 uint32_t timeout)
+{
+    /* If the read isn't looking for accel data, don't do anything. */
+    if (!(sensor_type & SENSOR_TYPE_ACCELEROMETER)) {
+        return SYS_EINVAL;
+    }
+
+    return lis2dw12_do_read(sensor, data_func, data_arg);
+}
+
+int
+lis2dw12_stream_read(struct sensor *sensor,
+                   sensor_type_t sensor_type,
+                   sensor_data_func_t read_func,
+                   void *read_arg,
+                   uint32_t time_ms)
+{
+    struct lis2dw12 *lis2dw12;
+    struct sensor_itf *itf;
+    int rc;
+    os_time_t time_ticks;
+    os_time_t stop_ticks = 0;
+    struct lis2dw12_private_driver_data *pdd;
+    uint8_t fifo_samples;
+
+    /* If the read isn't looking for accel data, don't do anything. */
+    if (!(sensor_type & SENSOR_TYPE_ACCELEROMETER)) {
+        return SYS_EINVAL;
+    }
+
+    lis2dw12 = (struct lis2dw12 *)SENSOR_GET_DEVICE(sensor);
+    itf = SENSOR_GET_ITF(sensor);
+    pdd = &lis2dw12->pdd;
+
+    undo_interrupt(&lis2dw12->intr);
+
+    if (pdd->interrupt) {
+        return SYS_EBUSY;
+    }
+
+    /* enable interrupt */
+    pdd->interrupt = &lis2dw12->intr;
+
+    rc = enable_interrupt(sensor, lis2dw12->cfg.stream_read_interrupt);
+    if (rc) {
+        goto done;
+    }
+
+    if (time_ms != 0) {
+        rc = os_time_ms_to_ticks(time_ms, &time_ticks);
+        if (rc) {
+            goto done;
+        }
+        stop_ticks = os_time_get() + time_ticks;
+    }
+
+    for (;;) {
+        wait_interrupt(&lis2dw12->intr, pdd->int_num);
+        fifo_samples = 1;
+        
+        while(fifo_samples > 0) {
+            rc = lis2dw12_do_read(sensor, read_func, read_arg);
+            if (rc) {
+                goto done;
+            }
+
+            rc = lis2dw12_get_fifo_samples(itf, &fifo_samples);
+            if (rc) {
+                goto done;
+            }
+        }
+        
+        if (time_ms != 0 && OS_TIME_TICK_GT(os_time_get(), stop_ticks)) {
+                break;
+        }
+    }
+
+done:
+    /* disable interrupt */
+    pdd->interrupt = NULL;
+    rc = disable_interrupt(sensor, lis2dw12->cfg.stream_read_interrupt);
+
+    return rc;
+}
+
+static int
+lis2dw12_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 lis2dw12_cfg *cfg;
+    struct lis2dw12 *lis2dw12;
+    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_lis2dw12_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;
+        }
+    }
+    
+    lis2dw12 = (struct lis2dw12 *)SENSOR_GET_DEVICE(sensor);
+    cfg = &lis2dw12->cfg;
+
+    if (cfg->read_mode == LIS2DW12_READ_M_POLL) {
+        rc = lis2dw12_poll_read(sensor, type, data_func, data_arg, timeout);
+    } else {
+        rc = lis2dw12_stream_read(sensor, type, data_func, data_arg, timeout);
+    }
+
+err:
+    return rc;
+}
+
+static int
+lis2dw12_sensor_set_notification(struct sensor *sensor, sensor_event_type_t type)
+{
+    struct lis2dw12 * lis2dw12;
+    uint8_t int_cfg = 0;
+    struct lis2dw12_private_driver_data *pdd;
+    int rc;
+
+    if ((type & ~(SENSOR_EVENT_TYPE_DOUBLE_TAP |
+                  SENSOR_EVENT_TYPE_SINGLE_TAP)) != 0) {
+        return SYS_EINVAL;
+    }
+
+    /*XXX for now we do not support registering for both events */
+    if (type == (SENSOR_EVENT_TYPE_DOUBLE_TAP |
+                 SENSOR_EVENT_TYPE_SINGLE_TAP)) {
+        return SYS_EINVAL;
+    }
+
+    lis2dw12 = (struct lis2dw12 *)SENSOR_GET_DEVICE(sensor);
+    pdd = &lis2dw12->pdd;
+
+    if (pdd->registered_mask & LIS2DW12_NOTIFY_MASK) {
+        return SYS_EBUSY;
+    }
+
+    /* Enable tap interrupt */
+    if(type == SENSOR_EVENT_TYPE_DOUBLE_TAP) {
+        int_cfg |= LIS2DW12_INT1_CFG_DOUBLE_TAP;
+    }
+    if(type == SENSOR_EVENT_TYPE_SINGLE_TAP) {
+        int_cfg |= LIS2DW12_INT1_CFG_SINGLE_TAP;
+    }
+
+    rc = enable_interrupt(sensor, int_cfg);
+    if (rc) {
+        return rc;
+    }
+
+    pdd->notify_ctx.snec_evtype |= type;
+    pdd->registered_mask |= LIS2DW12_NOTIFY_MASK;
+
+    return 0;
+}
+
+static int
+lis2dw12_sensor_unset_notification(struct sensor *sensor, sensor_event_type_t type)
+{
+    struct lis2dw12 * lis2dw12;
+    
+    if ((type & ~(SENSOR_EVENT_TYPE_DOUBLE_TAP |
+                  SENSOR_EVENT_TYPE_SINGLE_TAP)) != 0) {
+        return SYS_EINVAL;
+    }
+    
+    /*XXX for now we do not support registering for both events */
+    if (type == (SENSOR_EVENT_TYPE_DOUBLE_TAP |
+                 SENSOR_EVENT_TYPE_SINGLE_TAP)) {
+        return SYS_EINVAL;
+    }
+    
+    lis2dw12 = (struct lis2dw12 *)SENSOR_GET_DEVICE(sensor);
+    
+    lis2dw12->pdd.notify_ctx.snec_evtype &= ~type;
+    lis2dw12->pdd.registered_mask &= ~LIS2DW12_NOTIFY_MASK;
+    
+    return disable_interrupt(sensor, 0);
+}
+
+static int
+lis2dw12_sensor_handle_interrupt(struct sensor * sensor)
+{
+    struct lis2dw12 * lis2dw12;
+    struct lis2dw12_private_driver_data *pdd;
+    struct sensor_itf *itf;
+    uint8_t int_src;
+    
+    int rc;
+
+    lis2dw12 = (struct lis2dw12 *)SENSOR_GET_DEVICE(sensor);
+    itf = SENSOR_GET_ITF(sensor);
+
+    pdd = &lis2dw12->pdd;
+
+    rc = lis2dw12_clear_int(itf, &int_src);
+    if (rc) {
+        LIS2DW12_ERR("Cound not read int status err=0x%02x\n", rc);
+        return rc;
+    }
+
+    if ((pdd->registered_mask & LIS2DW12_NOTIFY_MASK) &&
+        ((int_src & LIS2DW12_INT_SRC_STAP) ||
+         (int_src & LIS2DW12_INT_SRC_DTAP))) {
+        sensor_mgr_put_notify_evt(&pdd->notify_ctx);
+    }
+
+    return 0;
+}
+
+static int
+lis2dw12_sensor_get_config(struct sensor *sensor, sensor_type_t type,
+        struct sensor_cfg *cfg)
+{
+    int rc;
+
+    if (type != SENSOR_TYPE_ACCELEROMETER) {
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    cfg->sc_valtype = SENSOR_VALUE_TYPE_FLOAT_TRIPLET;
+
+    return 0;
+err:
+    return rc;
+}
+
+/**
+ * Expects to be called back through os_dev_create().
+ *
+ * @param The device object associated with this accelerometer
+ * @param Argument passed to OS device init, unused
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+lis2dw12_init(struct os_dev *dev, void *arg)
+{
+    struct lis2dw12 *lis2dw12;
+    struct sensor *sensor;
+    int rc;
+
+    if (!arg || !dev) {
+        rc = SYS_ENODEV;
+        goto err;
+    }
+
+    lis2dw12 = (struct lis2dw12 *) dev;
+
+    lis2dw12->cfg.mask = SENSOR_TYPE_ALL;
+
+    log_register(dev->od_name, &_log, &log_console_handler, NULL, LOG_SYSLEVEL);
+
+    sensor = &lis2dw12->sensor;
+
+    /* Initialise the stats entry */
+    rc = stats_init(
+        STATS_HDR(g_lis2dw12stats),
+        STATS_SIZE_INIT_PARMS(g_lis2dw12stats, STATS_SIZE_32),
+        STATS_NAME_INIT_PARMS(lis2dw12_stat_section));
+    SYSINIT_PANIC_ASSERT(rc == 0);
+    /* Register the entry with the stats registry */
+    rc = stats_register(dev->od_name, STATS_HDR(g_lis2dw12stats));
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = sensor_init(sensor, dev);
+    if (rc) {
+        goto err;
+    }
+
+    /* Add the light driver */
+    rc = sensor_set_driver(sensor, SENSOR_TYPE_ACCELEROMETER,
+            (struct sensor_driver *) &g_lis2dw12_sensor_driver);
+    if (rc) {
+        goto err;
+    }
+
+    /* Set the interface */
+    rc = sensor_set_interface(sensor, arg);
+    if (rc) {
+        goto err;
+    }
+
+    rc = sensor_mgr_register(sensor);
+    if (rc) {
+        goto err;
+    }
+
+    if (sensor->s_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_lis2dw12_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;
+        }
+
+        rc = hal_gpio_init_out(sensor->s_itf.si_cs_pin, 1);
+        if (rc) {
+            goto err;
+        }
+    }
+
+
+    init_interrupt(&lis2dw12->intr, lis2dw12->sensor.s_itf.si_ints);
+    
+    lis2dw12->pdd.notify_ctx.snec_sensor = sensor;
+    lis2dw12->pdd.registered_mask = 0;
+    lis2dw12->pdd.interrupt = NULL;
+
+    rc = init_intpin(lis2dw12, lis2dw12_int_irq_handler, sensor);
+    if (rc) {
+        return rc;
+    }
+
+    return 0;
+err:
+    return rc;
+
+}
+
+/**
+ * Configure the sensor
+ *
+ * @param ptr to sensor driver
+ * @param ptr to sensor driver config
+ */
+int
+lis2dw12_config(struct lis2dw12 *lis2dw12, struct lis2dw12_cfg *cfg)
+{
+    int rc;
+    struct sensor_itf *itf;
+    uint8_t chip_id;
+    struct sensor *sensor;
+
+    itf = SENSOR_GET_ITF(&(lis2dw12->sensor));
+    sensor = &(lis2dw12->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_lis2dw12_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;
+        }
+    }
+
+    rc = lis2dw12_get_chip_id(itf, &chip_id);
+    if (rc) {
+        goto err;
+    }
+
+    if (chip_id != LIS2DW12_ID) {
+        rc = SYS_EINVAL;
+        goto err;
+    }
+
+    rc = lis2dw12_reset(itf);
+    if (rc) {
+        goto err;
+    }
+
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG2, 0x40);
+    if (rc) {
+        goto err;
+    }
+
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG3, 0x10);
+    if (rc) {
+        goto err;
+    }
+    
+    rc = lis2dw12_set_offsets(itf, cfg->offset_x, cfg->offset_y, cfg->offset_z,
+                              cfg->offset_weight);
+    if (rc) {
+        goto err;
+    }
+
+    lis2dw12->cfg.offset_x = cfg->offset_x;
+    lis2dw12->cfg.offset_y = cfg->offset_y;
+    lis2dw12->cfg.offset_z = cfg->offset_z;
+    lis2dw12->cfg.offset_weight = cfg->offset_weight;
+
+    rc = lis2dw12_set_offset_enable(itf, cfg->offset_en);
+    if (rc) {
+        goto err;
+    }
+    
+    lis2dw12->cfg.offset_en = cfg->offset_en;
+    
+    rc = lis2dw12_set_filter_cfg(itf, LIS2DW12_FILTER_BW_ODR_DIV_2, 0);
+    if (rc) {
+        goto err;
+    }
+
+    rc = lis2dw12_set_full_scale(itf, cfg->fs);
+    if (rc) {
+        goto err;
+    }
+
+    lis2dw12->cfg.fs = cfg->fs;
+
+    rc = lis2dw12_set_rate(itf, cfg->rate);
+    if (rc) {
+        goto err;
+    }
+
+    lis2dw12->cfg.rate = cfg->rate;
+
+    rc = lis2dw12_set_self_test(itf, LIS2DW12_ST_MODE_DISABLE);
+    if (rc) {
+        goto err;
+    }
+
+    rc = lis2dw12_set_power_mode(itf, LIS2DW12_PM_HIGH_PERF);
+    if (rc) {
+        goto err;
+    }
+
+    rc = lis2dw12_set_low_noise(itf, 1);
+    if (rc) {
+        goto err;
+    }
+
+    rc = lis2dw12_set_fifo_cfg(itf, cfg->fifo_mode, cfg->fifo_threshold);
+    if (rc) {
+        goto err;
+    }
+
+    lis2dw12->cfg.fifo_mode = cfg->fifo_mode;
+    lis2dw12->cfg.fifo_threshold = cfg->fifo_threshold;
+    
+    rc = lis2dw12_set_int_enable(itf, cfg->int_enable);
+    if (rc) {
+        goto err;
+    }
+
+    lis2dw12->cfg.int_enable = cfg->int_enable;
+
+    rc = lis2dw12_set_int1_pin_cfg(itf, cfg->int1_pin_cfg);
+    if (rc) {
+        goto err;
+    }
+
+    lis2dw12->cfg.int1_pin_cfg = cfg->int1_pin_cfg;
+    
+    rc = lis2dw12_set_int2_pin_cfg(itf, cfg->int2_pin_cfg);
+    if (rc) {
+        goto err;
+    }
+
+    lis2dw12->cfg.int2_pin_cfg = cfg->int2_pin_cfg;
+
+    rc = lis2dw12_set_tap_cfg(itf, &cfg->tap_cfg);
+    if (rc) {
+        goto err;
+    }
+    lis2dw12->cfg.tap_cfg = cfg->tap_cfg;
+
+    lis2dw12_write8(itf, 0x34, 0x80);
+    
+    rc = sensor_set_type_mask(&(lis2dw12->sensor), cfg->mask);
+    if (rc) {
+        goto err;
+    }
+
+    lis2dw12->cfg.stream_read_interrupt = cfg->stream_read_interrupt;
+    lis2dw12->cfg.read_mode = cfg->read_mode;    
+    lis2dw12->cfg.mask = cfg->mask;
+
+    return 0;
+err:
+    return rc;
+}
diff --git a/hw/drivers/sensors/lis2dw12/src/lis2dw12_priv.h b/hw/drivers/sensors/lis2dw12/src/lis2dw12_priv.h
new file mode 100644
index 0000000..157112e
--- /dev/null
+++ b/hw/drivers/sensors/lis2dw12/src/lis2dw12_priv.h
@@ -0,0 +1,157 @@
+/*
+ * 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
+ * resarding 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.
+ */
+
+#ifndef __LIS2DW12_PRIV_H__
+#define __LIS2DW12_PRIV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIS2DW12_ID                          0x44
+
+#define LIS2DW12_REG_OUT_TEMP_L              0x0D
+#define LIS2DW12_REG_OUT_TEMP_H              0x0E
+
+#define LIS2DW12_REG_WHO_AM_I                0x0F
+
+#define LIS2DW12_REG_CTRL_REG1               0x20
+#define LIS2DW12_CTRL_REG1_ODR         (0xf << 4)
+#define LIS2DW12_CTRL_REG1_MODE        (0x3 << 2)
+#define LIS2DW12_CTRL_REG1_LP_MODE     (0x3 << 0)
+
+#define LIS2DW12_REG_CTRL_REG2               0x21
+#define LIS2DW12_CTRL_REG2_BOOT          (1 << 7)
+#define LIS2DW12_CTRL_REG2_SOFT_RESET    (1 << 6)
+#define LIS2DW12_CTRL_REG2_CS_PU_DISC    (1 << 4)
+#define LIS2DW12_CTRL_REG2_BDU           (1 << 3)
+#define LIS2DW12_CTRL_REG2_IF_ADD_INC    (1 << 2)
+#define LIS2DW12_CTRL_REG2_I2C_DISABLE   (1 << 1)
+#define LIS2DW12_CTRL_REG2_SIM           (1 << 0)
+
+#define LIS2DW12_REG_CTRL_REG3               0x22
+#define LIS2DW12_CTRL_REG3_ST_MODE     (0x3 << 6)
+#define LIS2DW12_CTRL_REG3_PP_OD         (1 << 5)
+#define LIS2DW12_CTRL_REG3_LIR           (1 << 4)
+#define LIS2DW12_CTRL_REG3_H_LACTIVE     (1 << 3)
+#define LIS2DW12_CTRL_REG3_SLP_MODE    (0x3 << 0)
+    
+#define LIS2DW12_REG_CTRL_REG4               0x23
+
+#define LIS2DW12_REG_CTRL_REG5               0x24
+    
+#define LIS2DW12_REG_CTRL_REG6               0x25
+#define LIS2DW12_CTRL_REG6_BW_FILT     (0x3 << 6)
+#define LIS2DW12_CTRL_REG6_FS          (0x3 << 4)
+#define LIS2DW12_CTRL_REG6_FDS           (1 << 3)
+#define LIS2DW12_CTRL_REG6_LOW_NOISE     (1 << 2)
+
+#define LIS2DW12_REG_TEMP_OUT                0x26
+
+#define LIS2DW12_REG_STATUS_REG              0x27
+#define LIS2DW12_STATUS_FIFO_THS         (1 << 7)
+#define LIS2DW12_STATUS_WU_IA            (1 << 6)
+#define LIS2DW12_STATUS_SLEEP_STATE      (1 << 5)    
+#define LIS2DW12_STATUS_DOUBLE_TAP       (1 << 4)
+#define LIS2DW12_STATUS_SINGLE_TAP       (1 << 3)
+#define LIS2DW12_STATUS_6D_IA            (1 << 2)
+#define LIS2DW12_STATUS_FF_IA            (1 << 1)
+#define LIS2DW12_STATUS_DRDY             (1 << 0)
+
+
+#define LIS2DW12_REG_OUT_X_L                 0x28
+#define LIS2DW12_REG_OUT_X_H                 0x29
+#define LIS2DW12_REG_OUT_Y_L                 0x2A
+#define LIS2DW12_REG_OUT_Y_H                 0x2B
+#define LIS2DW12_REG_OUT_Z_L                 0x2C
+#define LIS2DW12_REG_OUT_Z_H                 0x2D
+
+#define LIS2DW12_REG_FIFO_CTRL               0x2E
+#define LIS2DW12_FIFO_CTRL_FMODE       (0x7 << 5)
+#define LIS2DW12_FIFO_CTRL_FTH             (0x1F)
+
+#define LIS2DW12_REG_FIFO_SAMPLES            0x2F
+#define LIS2DW12_FIFO_SAMPLES_FTH        (1 << 7)
+#define LIS2DW12_FIFO_SAMPLES_OVR        (1 << 6)
+#define LIS2DW12_FIFO_SAMPLES              (0x3F)
+    
+#define LIS2DW12_REG_TAP_THS_X               0x30
+#define LIS2DW12_TAP_THS_X_4D_EN         (1 << 7)
+#define LIS2DW12_TAP_THS_X_6D_THS      (0x3 << 5)
+#define LIS2DW12_TAP_THS_X_THS             (0x1F)
+
+#define LIS2DW12_REG_TAP_THS_Y               0x31
+#define LIS2DW12_TAP_THS_Y_PRIOR       (0x7 << 5)
+#define LIS2DW12_TAP_THS_Y_THS             (0x1F)
+
+#define LIS2DW12_REG_TAP_THS_Z               0x32
+#define LIS2DW12_TAP_THS_Z_X_EN          (1 << 7)
+#define LIS2DW12_TAP_THS_Z_Y_EN          (1 << 6)
+#define LIS2DW12_TAP_THS_Z_Z_EN          (1 << 5)
+#define LIS2DW12_TAP_THS_Z_THS             (0x1F)
+
+#define LIS2DW12_REG_INT_DUR                 0x33
+#define LIS2DW12_INT_DUR_LATENCY       (0xf << 4)
+#define LIS2DW12_INT_DUR_QUIET         (0x3 << 2)
+#define LIS2DW12_INT_DUR_SHOCK         (0x3 << 0)
+
+#define LIS2DW12_REG_FREEFALL                0x36
+#define LIS2DW12_FREEFALL_DUR         (0x1F << 3)
+#define LIS2DW12_FREEFALL_THS          (0x7 << 0)
+
+#define LIS2DW12_REG_INT_SRC                 0x3B
+
+#define LIS2DW12_REG_X_OFS                   0x3C
+#define LIS2DW12_REG_Y_OFS                   0x3D
+#define LIS2DW12_REG_Z_OFS                   0x3E
+
+#define LIS2DW12_REG_CTRL_REG7               0x3F
+#define LIS2DW12_CTRL_REG7_DRDY_PULSES   (1 << 7)
+#define LIS2DW12_CTRL_REG7_INT2_ON_INT1  (1 << 6)
+#define LIS2DW12_CTRL_REG7_INT_EN        (1 << 5)
+#define LIS2DW12_CTRL_REG7_USR_OFF_OUT   (1 << 4)
+#define LIS2DW12_CTRL_REG7_USR_OFF_WU    (1 << 3)
+#define LIS2DW12_CTRL_REG7_USR_OFF_W     (1 << 2)
+#define LIS2DW12_CTRL_REG7_HP_REF        (1 << 1)
+#define LIS2DW12_CTRL_REG7_LPASS_6D      (1 << 0)  
+
+#define LIS2DW12_SPI_READ_CMD_BIT            0x80
+
+
+int lis2dw12_i2c_write8(struct sensor_itf *itf, uint8_t reg, uint8_t value);
+int lis2dw12_i2c_readlen(struct sensor_itf *itf, uint8_t reg, uint8_t *buffer, uint8_t len);
+
+int lis2dw12_spi_write8(struct sensor_itf *itf, uint8_t reg, uint8_t value);
+int lis2dw12_spi_readlen(struct sensor_itf *itf, uint8_t reg, uint8_t *buffer, uint8_t len);
+
+int lis2dw12_write8(struct sensor_itf *itf, uint8_t reg, uint8_t value);
+int lis2dw12_read8(struct sensor_itf *itf, uint8_t reg, uint8_t *value);
+int lis2dw12_readlen(struct sensor_itf *itf, uint8_t reg, uint8_t *buffer, uint8_t len);
+
+void lis2dw12_calc_acc_ms2(int16_t raw_acc, float *facc);
+void lis2dw12_calc_acc_mg(float acc_ms2, int16_t *acc_mg);
+
+int lis2dw12_get_data(struct sensor_itf *itf, int16_t *x, int16_t *y, int16_t *z);
+
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LIS2DW12_PRIV_H_ */
diff --git a/hw/drivers/sensors/lis2dw12/syscfg.yml b/hw/drivers/sensors/lis2dw12/syscfg.yml
new file mode 100644
index 0000000..e37774b
--- /dev/null
+++ b/hw/drivers/sensors/lis2dw12/syscfg.yml
@@ -0,0 +1,28 @@
+# 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.
+#
+
+syscfg.defs:
+    LIS2DW12_INT1_PIN_HOST:
+        description: 'Interrupt pin number on host device connected to INT1 on device'
+        value: 1
+    LIS2DW12_INT1_PIN_DEVICE:
+        description: 'Interrupt pin number 1 or 2 on accelerometer device'
+        value: 1
+    LIS2DW12_INT1_CFG_ACTIVE:
+        description: 'Set 0 for active-low, 1 for active-high'
+        value: 1
diff --git a/hw/sensor/creator/src/sensor_creator.c b/hw/sensor/creator/src/sensor_creator.c
index 27ac84a..40e3939 100644
--- a/hw/sensor/creator/src/sensor_creator.c
+++ b/hw/sensor/creator/src/sensor_creator.c
@@ -67,6 +67,10 @@
 #include <lps33hw/lps33hw.h>
 #endif
 
+#if MYNEWT_VAL(LIS2DW12_OFB)
+#include <lis2dw12/lis2dw12.h>
+#endif
+
 /* Driver definitions */
 #if MYNEWT_VAL(DRV2605_OFB)
 static struct drv2605 drv2605;
@@ -116,6 +120,10 @@ static struct adxl345 adxl345;
 static struct lps33hw lps33hw;
 #endif
 
+#if MYNEWT_VAL(LIS2DW12_OFB)
+static struct lis2dw12 lis2dw12;
+#endif
+
 /**
  * If a UART sensor needs to be created, interface is defined in
  * the following way
@@ -245,6 +253,17 @@ static struct sensor_itf i2c_0_itf_lps = {
 };
 #endif
 
+#if MYNEWT_VAL(I2C_0) && MYNEWT_VAL(LIS2DW12_OFB)
+static struct sensor_itf i2c_0_itf_lis2dw12 = {
+    .si_type = SENSOR_ITF_I2C,
+    .si_num  = 0,
+    .si_addr = 0x18,
+    .si_ints = {
+        { MYNEWT_VAL(LIS2DW12_INT1_PIN_HOST), MYNEWT_VAL(LIS2DW12_INT1_PIN_DEVICE),
+          MYNEWT_VAL(LIS2DW12_INT1_CFG_ACTIVE)}}
+};
+#endif
+
 /**
  * MS5837 Sensor default configuration used by the creator package
  *
@@ -662,6 +681,63 @@ config_lps33hw_sensor(void)
 }
 #endif
 
+/**
+ * LIS2DW12 Sensor default configuration used by the creator package
+ *
+ * @return 0 on success, non-zero on failure
+ */
+#if MYNEWT_VAL(LIS2DW12_OFB)
+static int
+config_lis2dw12_sensor(void)
+{
+    int rc;
+    struct os_dev *dev;
+    struct lis2dw12_cfg cfg;
+
+    dev = (struct os_dev *) os_dev_open("lis2dw12_0", OS_TIMEOUT_NEVER, NULL);
+    assert(dev != NULL);
+
+    cfg.rate = LIS2DW12_DATA_RATE_200HZ;
+    cfg.fs = LIS2DW12_FS_2G;
+
+    cfg.offset_x = 0;
+    cfg.offset_y = 0;
+    cfg.offset_z = 0;
+    cfg.offset_weight = 0;
+    cfg.offset_en = 0;
+
+    cfg.tap_cfg.en_x = 1;
+    cfg.tap_cfg.en_y = 1;
+    cfg.tap_cfg.en_z = 1;
+    cfg.tap_cfg.en_4d = 0;
+    cfg.tap_cfg.ths_6d = LIS2DW12_6D_THS_80_DEG;
+    cfg.tap_cfg.tap_priority = LIS2DW12_TAP_PRIOR_XYZ;
+    cfg.tap_cfg.tap_ths_x = 0x3;
+    cfg.tap_cfg.tap_ths_y = 0x3;
+    cfg.tap_cfg.tap_ths_z = 0x3;
+    cfg.tap_cfg.latency = 8; /* 640ms */
+    cfg.tap_cfg.quiet = 0; /* 10ms */
+    cfg.tap_cfg.shock = 3; /* 120ms */
+        
+    cfg.int1_pin_cfg = 0;
+    cfg.int2_pin_cfg = 0;
+    cfg.int_enable = 0;
+
+    cfg.fifo_mode = LIS2DW12_FIFO_M_BYPASS;
+    cfg.fifo_threshold = 32;
+    cfg.stream_read_interrupt = LIS2DW12_INT1_CFG_DRDY;
+    
+    cfg.read_mode = LIS2DW12_READ_M_POLL;
+    cfg.mask = SENSOR_TYPE_ACCELEROMETER;
+
+    rc = lis2dw12_config((struct lis2dw12 *) dev, &cfg);
+    assert(rc == 0);
+    
+    os_dev_close(dev);
+    return rc;
+}
+#endif
+
 /* Sensor device creation */
 void
 sensor_dev_create(void)
@@ -786,4 +862,13 @@ sensor_dev_create(void)
     assert(rc == 0);
 #endif
 
+#if MYNEWT_VAL(LIS2DW12_OFB)
+    rc = os_dev_create((struct os_dev *) &lis2dw12, "lis2dw12_0",
+      OS_DEV_INIT_PRIMARY, 0, lis2dw12_init, (void *)&i2c_0_itf_lis2dw12);
+    assert(rc == 0);
+
+    rc = config_lis2dw12_sensor();
+    assert(rc == 0);
+#endif
+
 }
diff --git a/hw/sensor/creator/syscfg.yml b/hw/sensor/creator/syscfg.yml
index ab9d90f..1f76199 100644
--- a/hw/sensor/creator/syscfg.yml
+++ b/hw/sensor/creator/syscfg.yml
@@ -55,3 +55,7 @@ syscfg.defs:
     LPS33HW_OFB:
         description: 'LPS33HW is present'
         value : 0
+    LIS2DW12_OFB:
+        description: 'LIS2DW12 is present'
+        value : 0
+

-- 
To stop receiving notification emails like this one, please contact
vipulrahane@apache.org.