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/04/11 20:24:30 UTC

[mynewt-core] branch master updated: WIP: Improvements to LIS2DW12 driver (#997)

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 efe8d5f  WIP: Improvements to LIS2DW12 driver (#997)
efe8d5f is described below

commit efe8d5f6bc0719b5a1cbb1d3537edafe2bd1c854
Author: matthewwarnes <36...@users.noreply.github.com>
AuthorDate: Wed Apr 11 21:24:27 2018 +0100

    WIP: Improvements to LIS2DW12 driver (#997)
    
    * improve lis2dw12 driver, add free fall event, configuration of ctrl3 and reduce devices access on stream read
    * add new LIS2DW12 config to sensor_creator and FREEFALL event to sensor.h
---
 .../sensors/lis2dw12/include/lis2dw12/lis2dw12.h   | 102 ++++-
 hw/drivers/sensors/lis2dw12/src/lis2dw12.c         | 441 ++++++++++++++++++---
 hw/drivers/sensors/lis2dw12/src/lis2dw12_priv.h    |   6 +-
 hw/drivers/sensors/lis2dw12/src/lis2dw12_shell.c   |   8 +-
 hw/sensor/creator/src/sensor_creator.c             |   9 +
 hw/sensor/include/sensor/sensor.h                  |   2 +
 6 files changed, 501 insertions(+), 67 deletions(-)

diff --git a/hw/drivers/sensors/lis2dw12/include/lis2dw12/lis2dw12.h b/hw/drivers/sensors/lis2dw12/include/lis2dw12/lis2dw12.h
index d6241f8..f399255 100644
--- a/hw/drivers/sensors/lis2dw12/include/lis2dw12/lis2dw12.h
+++ b/hw/drivers/sensors/lis2dw12/include/lis2dw12/lis2dw12.h
@@ -32,6 +32,7 @@ extern "C" {
 #define LIS2DW12_PM_LP_MODE3                    0x02
 #define LIS2DW12_PM_LP_MODE4                    0x03
 #define LIS2DW12_PM_HIGH_PERF                   0x04
+#define LIS2DW12_PM_ON_DEMAND                   0x08
     
 #define LIS2DW12_DATA_RATE_0HZ                  0x00
 #define LIS2DW12_DATA_RATE_1_6HZ                0x10
@@ -182,12 +183,21 @@ struct lis2dw12_cfg {
 
     struct lis2dw12_tap_settings tap_cfg;
     uint8_t double_tap_event_enable;
+
+    uint8_t freefall_dur;
+    uint8_t freefall_ths;
     
     uint8_t int1_pin_cfg;
     uint8_t int2_pin_cfg;
     bool map_int2_to_int1;
     uint8_t int_enable;
 
+    uint8_t int_pp_od;
+    uint8_t int_latched;
+    uint8_t int_active;
+    uint8_t slp_mode;
+    uint8_t self_test_mode;
+
     enum lis2dw12_fifo_mode fifo_mode;
     uint8_t fifo_threshold;
 
@@ -350,7 +360,7 @@ int lis2dw12_get_power_mode(struct sensor_itf *itf, uint8_t *mode);
 int lis2dw12_set_self_test(struct sensor_itf *itf, uint8_t mode);
 
 /**
- * Gets the power mode of the sensor
+ * Gets the self test mode of the sensor
  *
  * @param The sensor interface
  * @param ptr to self test mode read from sensor
@@ -360,6 +370,96 @@ int lis2dw12_set_self_test(struct sensor_itf *itf, uint8_t mode);
 int lis2dw12_get_self_test(struct sensor_itf *itf, uint8_t *mode);
 
 /**
+ * Sets the interrupt push-pull/open-drain selection
+ *
+ * @param The sensor interface
+ * @param interrupt setting (0 = push-pull, 1 = open-drain)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_int_pp_od(struct sensor_itf *itf, uint8_t mode);
+
+/**
+ * Gets the interrupt push-pull/open-drain selection
+ *
+ * @param The sensor interface
+ * @param ptr to store setting (0 = push-pull, 1 = open-drain)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_int_pp_od(struct sensor_itf *itf, uint8_t *mode);
+
+/**
+ * Sets whether latched interrupts are enabled
+ *
+ * @param The sensor interface
+ * @param value to set (0 = not latched, 1 = latched)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_latched_int(struct sensor_itf *itf, uint8_t en);
+
+/**
+ * Gets whether latched interrupts are enabled
+ *
+ * @param The sensor interface
+ * @param ptr to store value (0 = not latched, 1 = latched)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_latched_int(struct sensor_itf *itf, uint8_t *en);
+
+/**
+ * Sets whether interrupts are active high or low
+ *
+ * @param The sensor interface
+ * @param value to set (0 = active high, 1 = active low)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_int_active(struct sensor_itf *itf, uint8_t low);
+
+/**
+ * Gets whether interrupts are active high or low
+ *
+ * @param The sensor interface
+ * @param ptr to store value (0 = active high, 1 = active low)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_int_active(struct sensor_itf *itf, uint8_t *low);
+
+/**
+ * Sets single data conversion mode
+ *
+ * @param The sensor interface
+ * @param value to set (0 = trigger on INT2 pin, 1 = trigger on write to SLP_MODE_1)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_set_slp_mode(struct sensor_itf *itf, uint8_t mode);
+
+/**
+ * Gets single data conversion mode
+ *
+ * @param The sensor interface
+ * @param ptr to store value (0 = trigger on INT2 pin, 1 = trigger on write to SLP_MODE_1)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_get_slp_mode(struct sensor_itf *itf, uint8_t *mode);
+
+/**
+ * Starts a data conversion in on demand mode
+ *
+ * @param The sensor interface
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int lis2dw12_start_on_demand_conversion(struct sensor_itf *itf);
+
+    
+/**
  * Set filter config
  *
  * @param the sensor interface
diff --git a/hw/drivers/sensors/lis2dw12/src/lis2dw12.c b/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
index 85d253c..d2113a7 100644
--- a/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
+++ b/hw/drivers/sensors/lis2dw12/src/lis2dw12.c
@@ -713,6 +713,229 @@ err:
 }
 
 /**
+ * Sets the interrupt push-pull/open-drain selection
+ *
+ * @param The sensor interface
+ * @param interrupt setting (0 = push-pull, 1 = open-drain)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_set_int_pp_od(struct sensor_itf *itf, uint8_t mode)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG3, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    reg &= ~LIS2DW12_CTRL_REG3_PP_OD;
+    reg |= mode ? LIS2DW12_CTRL_REG3_PP_OD : 0;
+    
+    return lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG3, reg);
+}
+
+/**
+ * Gets the interrupt push-pull/open-drain selection
+ *
+ * @param The sensor interface
+ * @param ptr to store setting (0 = push-pull, 1 = open-drain)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_get_int_pp_od(struct sensor_itf *itf, uint8_t *mode)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG3, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    *mode = (reg & LIS2DW12_CTRL_REG3_PP_OD) ? 1 : 0;
+
+    return 0;
+}
+
+/**
+ * Sets whether latched interrupts are enabled
+ *
+ * @param The sensor interface
+ * @param value to set (0 = not latched, 1 = latched)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_set_latched_int(struct sensor_itf *itf, uint8_t en)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG3, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    reg &= ~LIS2DW12_CTRL_REG3_LIR;
+    reg |= en ? LIS2DW12_CTRL_REG3_LIR : 0;
+    
+    return lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG3, reg);
+
+}
+
+/**
+ * Gets whether latched interrupts are enabled
+ *
+ * @param The sensor interface
+ * @param ptr to store value (0 = not latched, 1 = latched)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_get_latched_int(struct sensor_itf *itf, uint8_t *en)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG3, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    *en = (reg & LIS2DW12_CTRL_REG3_LIR) ? 1 : 0;
+
+    return 0;
+}
+
+/**
+ * Sets whether interrupts are active high or low
+ *
+ * @param The sensor interface
+ * @param value to set (0 = active high, 1 = active low)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_set_int_active(struct sensor_itf *itf, uint8_t low)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG3, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    reg &= ~LIS2DW12_CTRL_REG3_H_LACTIVE;
+    reg |= low ? LIS2DW12_CTRL_REG3_H_LACTIVE : 0;
+    
+    return lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG3, reg);
+
+}
+
+/**
+ * Gets whether interrupts are active high or low
+ *
+ * @param The sensor interface
+ * @param ptr to store value (0 = active high, 1 = active low)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_get_int_active(struct sensor_itf *itf, uint8_t *low)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG3, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    *low = (reg & LIS2DW12_CTRL_REG3_H_LACTIVE) ? 1 : 0;
+
+    return 0;
+
+}
+
+/**
+ * Sets single data conversion mode
+ *
+ * @param The sensor interface
+ * @param value to set (0 = trigger on INT2 pin, 1 = trigger on write to SLP_MODE_1)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_set_slp_mode(struct sensor_itf *itf, uint8_t mode)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG3, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    reg &= ~LIS2DW12_CTRL_REG3_SLP_MODE_SEL;
+    reg |= mode ? LIS2DW12_CTRL_REG3_SLP_MODE_SEL : 0;
+    
+    return lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG3, reg);
+}
+
+/**
+ * Gets single data conversion mode
+ *
+ * @param The sensor interface
+ * @param ptr to store value (0 = trigger on INT2 pin, 1 = trigger on write to SLP_MODE_1)
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_get_slp_mode(struct sensor_itf *itf, uint8_t *mode)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG3, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    *mode = (reg & LIS2DW12_CTRL_REG3_SLP_MODE_SEL) ? 1 : 0;
+
+    return 0;
+}
+
+/**
+ * Starts a data conversion in on demand mode
+ *
+ * @param The sensor interface
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+lis2dw12_start_on_demand_conversion(struct sensor_itf *itf)
+{
+    int rc;
+    uint8_t reg;
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_CTRL_REG3, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    reg |= LIS2DW12_CTRL_REG3_SLP_MODE_1;
+    
+    return lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG3, reg);
+}
+
+
+/**
  * Set filter config
  *
  * @param the sensor interface
@@ -1002,13 +1225,27 @@ int lis2dw12_get_tap_cfg(struct sensor_itf *itf, struct lis2dw12_tap_settings *c
  */
 int lis2dw12_set_freefall(struct sensor_itf *itf, uint8_t dur, uint8_t ths)
 {
+    int rc;
     uint8_t reg;
 
     reg = 0;
     reg |= (dur & 0x1F) << 3;
     reg |= ths & LIS2DW12_FREEFALL_THS;
 
-    return lis2dw12_write8(itf, LIS2DW12_REG_FREEFALL, reg);
+    rc = lis2dw12_write8(itf, LIS2DW12_REG_FREEFALL, reg);
+    if (rc) {
+        return rc;
+    }
+
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_WAKE_UP_DUR, &reg);
+    if (rc) {
+        return rc;
+    }
+
+    reg &= ~LIS2DW12_WAKE_DUR_FF_DUR;
+    reg |= dur & 0x20 ? LIS2DW12_WAKE_DUR_FF_DUR : 0;
+
+    return lis2dw12_write8(itf, LIS2DW12_REG_WAKE_UP_DUR, reg);
 }
 
 /**
@@ -1022,15 +1259,22 @@ int lis2dw12_set_freefall(struct sensor_itf *itf, uint8_t dur, uint8_t ths)
 int lis2dw12_get_freefall(struct sensor_itf *itf, uint8_t *dur, uint8_t *ths)
 {
     int rc;
-    uint8_t reg;
+    uint8_t ff_reg, wake_reg;
     
-    rc = lis2dw12_read8(itf, LIS2DW12_REG_FREEFALL, &reg);
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_FREEFALL, &ff_reg);
     if (rc) {
         return rc;
     }
 
-    *dur = (reg & LIS2DW12_FREEFALL_DUR) >> 3;
-    *ths = reg & LIS2DW12_FREEFALL_THS;
+    rc = lis2dw12_read8(itf, LIS2DW12_REG_WAKE_UP_DUR, &wake_reg);
+    if (rc) {
+        return rc;
+    }
+
+    
+    *dur = (ff_reg & LIS2DW12_FREEFALL_DUR) >> 3;
+    *dur |= wake_reg & LIS2DW12_WAKE_DUR_FF_DUR ? (1 << 5) : 0;
+    *ths = wake_reg & LIS2DW12_FREEFALL_THS;
 
     return 0;
 }
@@ -1517,6 +1761,12 @@ int lis2dw12_run_self_test(struct sensor_itf *itf, int *result)
     int16_t base[3], pos[3];
     int i;
     int16_t change;
+    uint8_t fs;
+
+    rc = lis2dw12_get_fs(itf, &fs);
+    if (rc) {
+        return rc;
+    }
     
     /* ensure self test mode is disabled */
     rc = lis2dw12_set_self_test(itf, LIS2DW12_ST_MODE_DISABLE);
@@ -1527,7 +1777,7 @@ int lis2dw12_run_self_test(struct sensor_itf *itf, int *result)
     os_time_delay(OS_TICKS_PER_SEC / 10);
     
     /* take base reading */
-    rc = lis2dw12_get_data(itf, &(base[0]), &(base[1]), &(base[2]));
+    rc = lis2dw12_get_data(itf, fs, &(base[0]), &(base[1]), &(base[2]));
     if (rc) {
         return rc;
     }
@@ -1541,7 +1791,7 @@ int lis2dw12_run_self_test(struct sensor_itf *itf, int *result)
     os_time_delay(OS_TICKS_PER_SEC / 10);
 
     /* take self test reading */
-    rc = lis2dw12_get_data(itf, &(pos[0]), &(pos[1]), &(pos[2]));
+    rc = lis2dw12_get_data(itf, fs, &(pos[0]), &(pos[1]), &(pos[2]));
     if (rc) {
         return rc;
     }
@@ -1774,6 +2024,31 @@ disable_interrupt(struct sensor * sensor, uint8_t int_to_disable)
     return lis2dw12_set_int1_pin_cfg(itf, pdd->int_enable);
 }
 
+int
+lis2dw12_get_fs(struct sensor_itf *itf, uint8_t *fs)
+{
+    int rc;
+    
+    rc = lis2dw12_get_full_scale(itf, fs);
+    if (rc) {
+        return rc;
+    }
+
+    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 {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
 /**
  * Gets a new data sample from the sensor.
  *
@@ -1785,11 +2060,10 @@ disable_interrupt(struct sensor * sensor, uint8_t int_to_disable)
  * @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)
+lis2dw12_get_data(struct sensor_itf *itf, uint8_t fs, int16_t *x, int16_t *y, int16_t *z)
 {
     int rc;
     uint8_t payload[6] = {0};
-    uint8_t fs;
 
     *x = *y = *z = 0;
 
@@ -1802,24 +2076,6 @@ lis2dw12_get_data(struct sensor_itf *itf, int16_t *x, int16_t *y, int16_t *z)
     *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.
@@ -1837,7 +2093,7 @@ err:
 }
 
 static int lis2dw12_do_read(struct sensor *sensor, sensor_data_func_t data_func,
-                            void * data_arg)
+                            void * data_arg, uint8_t fs)
 {
     struct sensor_accel_data sad;
     struct sensor_itf *itf;
@@ -1849,7 +2105,7 @@ static int lis2dw12_do_read(struct sensor *sensor, sensor_data_func_t data_func,
 
     x = y = z = 0;
 
-    rc = lis2dw12_get_data(itf, &x, &y, &z);
+    rc = lis2dw12_get_data(itf, fs, &x, &y, &z);
     if (rc) {
         goto err;
     }
@@ -1894,12 +2150,23 @@ lis2dw12_poll_read(struct sensor * sensor, sensor_type_t sensor_type,
                  sensor_data_func_t data_func, void * data_arg,
                  uint32_t timeout)
 {
+    int rc;
+    struct sensor_itf *itf;
+    uint8_t fs;
+
+    itf = SENSOR_GET_ITF(sensor);
+    
     /* 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);
+    rc = lis2dw12_get_fs(itf, &fs);
+    if (rc) {
+        return rc;
+    }
+
+    return lis2dw12_do_read(sensor, data_func, data_arg, fs);
 }
 
 int
@@ -1916,6 +2183,7 @@ lis2dw12_stream_read(struct sensor *sensor,
     os_time_t stop_ticks = 0;
     struct lis2dw12_private_driver_data *pdd;
     uint8_t fifo_samples;
+    uint8_t fs;
 
     /* If the read isn't looking for accel data, don't do anything. */
     if (!(sensor_type & SENSOR_TYPE_ACCELEROMETER)) {
@@ -1948,25 +2216,42 @@ lis2dw12_stream_read(struct sensor *sensor,
         stop_ticks = os_time_get() + time_ticks;
     }
 
+    
+    rc = lis2dw12_get_fs(itf, &fs);
+    if (rc) {
+        goto done;
+    }
+
     for (;;) {
         wait_interrupt(&lis2dw12->intr, pdd->int_num);
+        
+        /* force at least one read for cases when fifo is disabled */
         fifo_samples = 1;
         
         while(fifo_samples > 0) {
-            rc = lis2dw12_do_read(sensor, read_func, read_arg);
-            if (rc) {
-                goto done;
+
+            /* read all data we beleive is currently in fifo */
+            while(fifo_samples > 0) {
+                rc = lis2dw12_do_read(sensor, read_func, read_arg, fs);
+                if (rc) {
+                    goto done;
+                }
+                fifo_samples--;
+
             }
 
+            /* check if any data is available in fifo */
             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;
+            break;
         }
+
     }
 
 done:
@@ -2037,14 +2322,17 @@ lis2dw12_sensor_set_notification(struct sensor *sensor, sensor_event_type_t type
     struct lis2dw12_private_driver_data *pdd;
     int rc;
 
-    if ((type & ~(SENSOR_EVENT_TYPE_DOUBLE_TAP |
-                  SENSOR_EVENT_TYPE_SINGLE_TAP)) != 0) {
-        return SYS_EINVAL;
+    if(type == SENSOR_EVENT_TYPE_DOUBLE_TAP) {
+        int_cfg |= LIS2DW12_INT1_CFG_DOUBLE_TAP;
     }
-
-    /*XXX for now we do not support registering for both events */
-    if (type == (SENSOR_EVENT_TYPE_DOUBLE_TAP |
-                 SENSOR_EVENT_TYPE_SINGLE_TAP)) {
+    else if(type == SENSOR_EVENT_TYPE_SINGLE_TAP) {
+        int_cfg |= LIS2DW12_INT1_CFG_SINGLE_TAP;
+    }
+    else if(type == SENSOR_EVENT_TYPE_FREE_FALL) {
+        int_cfg |= LIS2DW12_INT1_CFG_FF;
+    } else {
+        /* here if type is set to no valid event or more than one event */
+        /* we do not currently support registering for more than one event */
         return SYS_EINVAL;
     }
 
@@ -2055,15 +2343,7 @@ lis2dw12_sensor_set_notification(struct sensor *sensor, sensor_event_type_t type
     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;
@@ -2099,18 +2379,22 @@ lis2dw12_sensor_unset_notification(struct sensor *sensor, sensor_event_type_t ty
     struct lis2dw12 * lis2dw12;
     struct sensor_itf *itf;
     int rc;
+    uint8_t int_cfg = 0;
     
-    if ((type & ~(SENSOR_EVENT_TYPE_DOUBLE_TAP |
-                  SENSOR_EVENT_TYPE_SINGLE_TAP)) != 0) {
-        return SYS_EINVAL;
+    if(type == SENSOR_EVENT_TYPE_DOUBLE_TAP) {
+        int_cfg |= LIS2DW12_INT1_CFG_DOUBLE_TAP;
     }
-    
-    /*XXX for now we do not support registering for both events */
-    if (type == (SENSOR_EVENT_TYPE_DOUBLE_TAP |
-                 SENSOR_EVENT_TYPE_SINGLE_TAP)) {
+    else if(type == SENSOR_EVENT_TYPE_SINGLE_TAP) {
+        int_cfg |= LIS2DW12_INT1_CFG_SINGLE_TAP;
+    }
+    else if(type == SENSOR_EVENT_TYPE_FREE_FALL) {
+        int_cfg |= LIS2DW12_INT1_CFG_FF;
+    } else {
+        /* here if type is set to no valid event or more than one event */
+        /* we do not currently support registering for more than one event */
         return SYS_EINVAL;
     }
-    
+        
     lis2dw12 = (struct lis2dw12 *)SENSOR_GET_DEVICE(sensor);
     itf = SENSOR_GET_ITF(sensor);
 
@@ -2122,7 +2406,7 @@ lis2dw12_sensor_unset_notification(struct sensor *sensor, sensor_event_type_t ty
         return rc;
     }
     
-    return disable_interrupt(sensor, 0);
+    return disable_interrupt(sensor, int_cfg);
 }
 
 static int
@@ -2148,7 +2432,8 @@ lis2dw12_sensor_handle_interrupt(struct sensor * sensor)
 
     if ((pdd->registered_mask & LIS2DW12_NOTIFY_MASK) &&
         ((int_src & LIS2DW12_INT_SRC_STAP) ||
-         (int_src & LIS2DW12_INT_SRC_DTAP))) {
+         (int_src & LIS2DW12_INT_SRC_DTAP) ||
+         (int_src & LIS2DW12_INT_SRC_FF_IA))) {
         sensor_mgr_put_notify_evt(&pdd->notify_ctx);
     }
 
@@ -2331,10 +2616,30 @@ lis2dw12_config(struct lis2dw12 *lis2dw12, struct lis2dw12_cfg *cfg)
         goto err;
     }
 
-    rc = lis2dw12_write8(itf, LIS2DW12_REG_CTRL_REG3, LIS2DW12_CTRL_REG3_LIR);
+    rc = lis2dw12_set_int_pp_od(itf, cfg->int_pp_od);
     if (rc) {
         goto err;
     }
+    lis2dw12->cfg.int_pp_od = cfg->int_pp_od;
+
+    rc = lis2dw12_set_latched_int(itf, cfg->int_latched);
+    if (rc) {
+        goto err;
+    }
+    lis2dw12->cfg.int_latched = cfg->int_latched;
+
+    rc = lis2dw12_set_int_active(itf, cfg->int_active);
+    if (rc) {
+        goto err;
+    }
+    lis2dw12->cfg.int_active = cfg->int_active;
+
+    rc = lis2dw12_set_slp_mode(itf, cfg->slp_mode);
+    if (rc) {
+        goto err;
+    }
+    lis2dw12->cfg.slp_mode = cfg->slp_mode;
+
     
     rc = lis2dw12_set_offsets(itf, cfg->offset_x, cfg->offset_y, cfg->offset_z,
                               cfg->offset_weight);
@@ -2376,10 +2681,11 @@ lis2dw12_config(struct lis2dw12 *lis2dw12, struct lis2dw12_cfg *cfg)
 
     lis2dw12->cfg.rate = cfg->rate;
 
-    rc = lis2dw12_set_self_test(itf, LIS2DW12_ST_MODE_DISABLE);
+    rc = lis2dw12_set_self_test(itf, cfg->self_test_mode);
     if (rc) {
         goto err;
     }
+    lis2dw12->cfg.self_test_mode = cfg->self_test_mode;
 
     rc = lis2dw12_set_power_mode(itf, cfg->power_mode);
     if (rc) {
@@ -2439,6 +2745,15 @@ lis2dw12_config(struct lis2dw12 *lis2dw12, struct lis2dw12_cfg *cfg)
     }
     lis2dw12->cfg.double_tap_event_enable = cfg->double_tap_event_enable;
     
+    rc = lis2dw12_set_freefall(itf, cfg->freefall_dur, cfg->freefall_ths);
+    if (rc) {
+        goto err;
+    }
+    
+    lis2dw12->cfg.freefall_dur = cfg->freefall_dur;
+    lis2dw12->cfg.freefall_ths = cfg->freefall_ths;
+
+
     rc = lis2dw12_set_int_enable(itf, cfg->int_enable);
     if (rc) {
         goto err;
diff --git a/hw/drivers/sensors/lis2dw12/src/lis2dw12_priv.h b/hw/drivers/sensors/lis2dw12/src/lis2dw12_priv.h
index 95760a0..795a16a 100644
--- a/hw/drivers/sensors/lis2dw12/src/lis2dw12_priv.h
+++ b/hw/drivers/sensors/lis2dw12/src/lis2dw12_priv.h
@@ -50,7 +50,8 @@ extern "C" {
 #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_CTRL_REG3_SLP_MODE_SEL  (1 << 1)
+#define LIS2DW12_CTRL_REG3_SLP_MODE_1    (1 << 0)
     
 #define LIS2DW12_REG_CTRL_REG4               0x23
 
@@ -162,8 +163,9 @@ int lis2dw12_readlen(struct sensor_itf *itf, uint8_t reg, uint8_t *buffer, uint8
 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);
+int lis2dw12_get_data(struct sensor_itf *itf, uint8_t fs, int16_t *x, int16_t *y, int16_t *z);
 
+int lis2dw12_get_fs(struct sensor_itf *itf, uint8_t *fs);
     
 #ifdef __cplusplus
 }
diff --git a/hw/drivers/sensors/lis2dw12/src/lis2dw12_shell.c b/hw/drivers/sensors/lis2dw12/src/lis2dw12_shell.c
index 3ebe98c..66bfdc0 100644
--- a/hw/drivers/sensors/lis2dw12/src/lis2dw12_shell.c
+++ b/hw/drivers/sensors/lis2dw12/src/lis2dw12_shell.c
@@ -120,6 +120,7 @@ lis2dw12_shell_cmd_read(int argc, char **argv)
     char tmpstr[13];
     int16_t x,y,z;
     float fx,fy,fz;
+    uint8_t fs;
 
     if (argc > 3) {
         return lis2dw12_shell_err_too_many_args(argv[1]);
@@ -136,7 +137,12 @@ lis2dw12_shell_cmd_read(int argc, char **argv)
 
     while(samples--) {
 
-        rc = lis2dw12_get_data(&g_sensor_itf, &x, &y, &z);
+        rc = lis2dw12_get_fs(&g_sensor_itf, &fs);
+        if (rc) {
+            return rc;
+        }
+        
+        rc = lis2dw12_get_data(&g_sensor_itf, fs,&x, &y, &z);
         if (rc) {
             console_printf("Read failed: %d\n", rc);
             return rc;
diff --git a/hw/sensor/creator/src/sensor_creator.c b/hw/sensor/creator/src/sensor_creator.c
index 3c7b0f3..69df71c 100644
--- a/hw/sensor/creator/src/sensor_creator.c
+++ b/hw/sensor/creator/src/sensor_creator.c
@@ -770,11 +770,20 @@ config_lis2dw12_sensor(void)
     cfg.tap_cfg.quiet = 0; /* 10ms */
     cfg.tap_cfg.shock = 3; /* 120ms */
     cfg.double_tap_event_enable = 0;
+
+    cfg.freefall_dur = 6; 
+    cfg.freefall_ths = 3; /* ~312mg */
     
     cfg.int1_pin_cfg = 0;
     cfg.int2_pin_cfg = 0;
     cfg.int_enable = 0;
 
+    cfg.int_pp_od = 0;
+    cfg.int_latched = 0;
+    cfg.int_active = 0;
+    cfg.slp_mode = 0;
+    cfg.self_test_mode = LIS2DW12_ST_MODE_DISABLE;
+    
     cfg.fifo_mode = LIS2DW12_FIFO_M_BYPASS;
     cfg.fifo_threshold = 32;
     cfg.stream_read_interrupt = LIS2DW12_INT1_CFG_DRDY;
diff --git a/hw/sensor/include/sensor/sensor.h b/hw/sensor/include/sensor/sensor.h
index 7bb2b64..c78839e 100644
--- a/hw/sensor/include/sensor/sensor.h
+++ b/hw/sensor/include/sensor/sensor.h
@@ -102,6 +102,8 @@ typedef enum {
     SENSOR_EVENT_TYPE_DOUBLE_TAP     = (1 << 0),
     /* Accelerometer single tap event */
     SENSOR_EVENT_TYPE_SINGLE_TAP     = (1 << 1),
+    /* Accelerometer free fall event */
+    SENSOR_EVENT_TYPE_FREE_FALL      = (1 << 2)
 } sensor_event_type_t;
 
 

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