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

[GitHub] vrahane closed pull request #926: Add Driver for LIS2DW12

vrahane closed pull request #926: Add Driver for LIS2DW12
URL: https://github.com/apache/mynewt-core/pull/926
 
 
   

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

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

diff --git a/hw/drivers/sensors/lis2dw12/include/lis2dw12/lis2dw12.h b/hw/drivers/sensors/lis2dw12/include/lis2dw12/lis2dw12.h
new file mode 100644
index 000000000..d78092362
--- /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 000000000..f188c4924
--- /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 000000000..c977acf60
--- /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 000000000..157112e99
--- /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 000000000..e37774bdf
--- /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 d81befae6..5b47f86b2 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
  *
@@ -661,6 +680,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)
@@ -785,4 +861,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 ab9d90f68..1f761998b 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
+


 

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


With regards,
Apache Git Services