Ivan Podogov před 3 roky
rodič
revize
0553ae1a32
51 změnil soubory, kde provedl 24229 přidání a 0 odebrání
  1. 143 0
      air_mouse.c
  2. 30 0
      air_mouse.h
  3. 9 0
      application.fam
  4. 85 0
      tracking/calibration_data.cc
  5. 108 0
      tracking/calibration_data.h
  6. 6428 0
      tracking/imu/bmi160.c
  7. 969 0
      tracking/imu/bmi160.h
  8. 1647 0
      tracking/imu/bmi160_defs.h
  9. 29 0
      tracking/imu/imu.c
  10. 18 0
      tracking/imu/imu.h
  11. 86 0
      tracking/imu/imu_bmi160.c
  12. 96 0
      tracking/imu/imu_lsm6ds3trc.c
  13. 8209 0
      tracking/imu/lsm6ds3tr-c_reg.c
  14. 2798 0
      tracking/imu/lsm6ds3tr-c_reg.h
  15. 188 0
      tracking/main_loop.cc
  16. 21 0
      tracking/main_loop.h
  17. 95 0
      tracking/orientation_tracker.cc
  18. 68 0
      tracking/orientation_tracker.h
  19. 38 0
      tracking/sensors/accelerometer_data.h
  20. 313 0
      tracking/sensors/gyroscope_bias_estimator.cc
  21. 134 0
      tracking/sensors/gyroscope_bias_estimator.h
  22. 38 0
      tracking/sensors/gyroscope_data.h
  23. 84 0
      tracking/sensors/lowpass_filter.cc
  24. 75 0
      tracking/sensors/lowpass_filter.h
  25. 46 0
      tracking/sensors/mean_filter.cc
  26. 48 0
      tracking/sensors/mean_filter.h
  27. 69 0
      tracking/sensors/median_filter.cc
  28. 53 0
      tracking/sensors/median_filter.h
  29. 71 0
      tracking/sensors/pose_prediction.cc
  30. 55 0
      tracking/sensors/pose_prediction.h
  31. 56 0
      tracking/sensors/pose_state.h
  32. 333 0
      tracking/sensors/sensor_fusion_ekf.cc
  33. 187 0
      tracking/sensors/sensor_fusion_ekf.h
  34. 38 0
      tracking/util/logging.h
  35. 121 0
      tracking/util/matrix_3x3.cc
  36. 104 0
      tracking/util/matrix_3x3.h
  37. 87 0
      tracking/util/matrix_4x4.cc
  38. 37 0
      tracking/util/matrix_4x4.h
  39. 148 0
      tracking/util/matrixutils.cc
  40. 65 0
      tracking/util/matrixutils.h
  41. 117 0
      tracking/util/rotation.cc
  42. 156 0
      tracking/util/rotation.h
  43. 229 0
      tracking/util/vector.h
  44. 40 0
      tracking/util/vectorutils.cc
  45. 73 0
      tracking/util/vectorutils.h
  46. 156 0
      views/bt_mouse.c
  47. 14 0
      views/bt_mouse.h
  48. 69 0
      views/calibration.c
  49. 12 0
      views/calibration.h
  50. 124 0
      views/usb_mouse.c
  51. 12 0
      views/usb_mouse.h

+ 143 - 0
air_mouse.c

@@ -0,0 +1,143 @@
+#include "air_mouse.h"
+
+#include <furi.h>
+#include <dolphin/dolphin.h>
+
+#include "tracking/imu/imu.h"
+
+#define TAG "AirMouseApp"
+
+enum AirMouseSubmenuIndex {
+    AirMouseSubmenuIndexBtMouse,
+    AirMouseSubmenuIndexUsbMouse,
+    AirMouseSubmenuIndexCalibration,
+};
+
+void air_mouse_submenu_callback(void* context, uint32_t index) {
+    furi_assert(context);
+    AirMouse* app = context;
+    if (index == AirMouseSubmenuIndexBtMouse) {
+        app->view_id = AirMouseViewBtMouse;
+        view_dispatcher_switch_to_view(app->view_dispatcher, AirMouseViewBtMouse);
+    } else if (index == AirMouseSubmenuIndexUsbMouse) {
+        app->view_id = AirMouseViewUsbMouse;
+        view_dispatcher_switch_to_view(app->view_dispatcher, AirMouseViewUsbMouse);
+    } else if (index == AirMouseSubmenuIndexCalibration) {
+        app->view_id = AirMouseViewCalibration;
+        view_dispatcher_switch_to_view(app->view_dispatcher, AirMouseViewCalibration);
+    }
+}
+
+void air_mouse_dialog_callback(DialogExResult result, void* context) {
+    furi_assert(context);
+    AirMouse* app = context;
+    if (result == DialogExResultLeft) {
+        view_dispatcher_switch_to_view(app->view_dispatcher, VIEW_NONE); // Exit
+    } else if (result == DialogExResultRight) {
+        view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id); // Show last view
+    } else if (result == DialogExResultCenter) {
+        view_dispatcher_switch_to_view(app->view_dispatcher, AirMouseViewSubmenu); // Menu
+    }
+}
+
+uint32_t air_mouse_exit_confirm_view(void* context) {
+    UNUSED(context);
+    return AirMouseViewExitConfirm;
+}
+
+uint32_t air_mouse_exit(void* context) {
+    UNUSED(context);
+    return VIEW_NONE;
+}
+
+AirMouse* air_mouse_app_alloc() {
+    AirMouse* app = malloc(sizeof(AirMouse));
+
+    // Gui
+    app->gui = furi_record_open(RECORD_GUI);
+
+    // View dispatcher
+    app->view_dispatcher = view_dispatcher_alloc();
+    view_dispatcher_enable_queue(app->view_dispatcher);
+    view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
+
+    // Submenu view
+    app->submenu = submenu_alloc();
+    submenu_add_item(app->submenu, "Bluetooth", AirMouseSubmenuIndexBtMouse, air_mouse_submenu_callback, app);
+    submenu_add_item(app->submenu, "USB", AirMouseSubmenuIndexUsbMouse, air_mouse_submenu_callback, app);
+    submenu_add_item(app->submenu, "Calibration", AirMouseSubmenuIndexCalibration, air_mouse_submenu_callback, app);
+    view_set_previous_callback(submenu_get_view(app->submenu), air_mouse_exit);
+    view_dispatcher_add_view(app->view_dispatcher, AirMouseViewSubmenu, submenu_get_view(app->submenu));
+
+    // Dialog view
+    app->dialog = dialog_ex_alloc();
+    dialog_ex_set_result_callback(app->dialog, air_mouse_dialog_callback);
+    dialog_ex_set_context(app->dialog, app);
+    dialog_ex_set_left_button_text(app->dialog, "Exit");
+    dialog_ex_set_right_button_text(app->dialog, "Stay");
+    dialog_ex_set_center_button_text(app->dialog, "Menu");
+    dialog_ex_set_header(app->dialog, "Close Current App?", 16, 12, AlignLeft, AlignTop);
+    view_dispatcher_add_view(app->view_dispatcher, AirMouseViewExitConfirm, dialog_ex_get_view(app->dialog));
+
+    // Bluetooth view
+    app->bt_mouse = bt_mouse_alloc(app->view_dispatcher);
+    view_set_previous_callback(bt_mouse_get_view(app->bt_mouse), air_mouse_exit_confirm_view);
+    view_dispatcher_add_view(app->view_dispatcher, AirMouseViewBtMouse, bt_mouse_get_view(app->bt_mouse));
+
+    // USB view
+    app->usb_mouse = usb_mouse_alloc(app->view_dispatcher);
+    view_set_previous_callback(usb_mouse_get_view(app->usb_mouse), air_mouse_exit_confirm_view);
+    view_dispatcher_add_view(app->view_dispatcher, AirMouseViewUsbMouse, usb_mouse_get_view(app->usb_mouse));
+
+    // Calibration view
+    app->calibration = calibration_alloc(app->view_dispatcher);
+    view_set_previous_callback(calibration_get_view(app->calibration), air_mouse_exit_confirm_view);
+    view_dispatcher_add_view(app->view_dispatcher, AirMouseViewCalibration, calibration_get_view(app->calibration));
+
+    app->view_id = AirMouseViewSubmenu;
+    view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id);
+
+    return app;
+}
+
+void air_mouse_app_free(AirMouse* app) {
+    furi_assert(app);
+
+    // Free views
+    view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewSubmenu);
+    submenu_free(app->submenu);
+    view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewExitConfirm);
+    dialog_ex_free(app->dialog);
+    view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewBtMouse);
+    bt_mouse_free(app->bt_mouse);
+    view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewUsbMouse);
+    usb_mouse_free(app->usb_mouse);
+    view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewCalibration);
+    calibration_free(app->calibration);
+    view_dispatcher_free(app->view_dispatcher);
+
+    // Close records
+    furi_record_close(RECORD_GUI);
+    app->gui = NULL;
+
+    // Free rest
+    free(app);
+}
+
+int32_t air_mouse_app(void* p) {
+    UNUSED(p);
+
+    AirMouse* app = air_mouse_app_alloc();
+    if (!imu_begin()) {
+        air_mouse_app_free(app);
+        return -1;
+    }
+
+    DOLPHIN_DEED(DolphinDeedPluginStart);
+    view_dispatcher_run(app->view_dispatcher);
+
+    imu_end();
+    air_mouse_app_free(app);
+
+    return 0;
+}

+ 30 - 0
air_mouse.h

@@ -0,0 +1,30 @@
+#pragma once
+
+#include <gui/gui.h>
+#include <gui/view.h>
+#include <gui/view_dispatcher.h>
+#include <gui/modules/submenu.h>
+#include <gui/modules/dialog_ex.h>
+
+#include "views/bt_mouse.h"
+#include "views/usb_mouse.h"
+#include "views/calibration.h"
+
+typedef struct {
+    Gui* gui;
+    ViewDispatcher* view_dispatcher;
+    Submenu* submenu;
+    DialogEx* dialog;
+    BtMouse* bt_mouse;
+    UsbMouse* usb_mouse;
+    Calibration* calibration;
+    uint32_t view_id;
+} AirMouse;
+
+typedef enum {
+    AirMouseViewSubmenu,
+    AirMouseViewBtMouse,
+    AirMouseViewUsbMouse,
+    AirMouseViewCalibration,
+    AirMouseViewExitConfirm,
+} AirMouseView;

+ 9 - 0
application.fam

@@ -0,0 +1,9 @@
+App(
+    appid="air_mouse",
+    name="Air Mouse",
+    apptype=FlipperAppType.EXTERNAL,
+    entry_point="air_mouse_app",
+    stack_size=10 * 1024,
+    fap_category="Tools",
+    icon="A_Plugins_14",
+)

+ 85 - 0
tracking/calibration_data.cc

@@ -0,0 +1,85 @@
+#include <furi.h>
+#include <furi_hal.h>
+
+#define TAG "tracker"
+
+#include "calibration_data.h"
+
+#include <cmath>
+#include <algorithm>
+
+// Student's distribution T value for 95% (two-sided) confidence interval.
+static const double Tn = 1.960;
+
+// Number of samples (degrees of freedom) for the corresponding T values.
+static const int Nn = 200;
+
+void CalibrationData::reset()
+{
+    complete = false;
+    count = 0;
+    sum = Vector::Zero();
+    sumSq = Vector::Zero();
+    mean = Vector::Zero();
+    median = Vector::Zero();
+    sigma = Vector::Zero();
+    delta = Vector::Zero();
+    xData.clear();
+    yData.clear();
+    zData.clear();
+}
+
+bool CalibrationData::add(Vector& data)
+{
+    if (complete) {
+        return true;
+    }
+
+    xData.push_back(data[0]);
+    yData.push_back(data[1]);
+    zData.push_back(data[2]);
+
+    sum += data;
+    sumSq += data * data;
+    count++;
+
+    if (count >= Nn) {
+        calcDelta();
+        complete = true;
+    }
+
+    return complete;
+}
+
+static inline double medianOf(std::vector<double>& list)
+{
+    std::sort(list.begin(), list.end());
+    int count = list.size();
+    int middle = count / 2;
+    return (count % 2 == 1) ? list[middle] : (list[middle - 1] + list[middle]) / 2.0l;
+}
+
+void CalibrationData::calcDelta()
+{
+    median.Set(medianOf(xData), medianOf(yData), medianOf(zData));
+
+    mean = sum / count;
+    Vector m2 = mean * mean;
+    Vector d = sumSq / count - m2;
+    Vector s2 = (d * count) / (count - 1);
+    sigma = Vector(std::sqrt(d[0]), std::sqrt(d[1]), std::sqrt(d[2]));
+    Vector s = Vector(std::sqrt(s2[0]), std::sqrt(s2[1]), std::sqrt(s2[2]));
+    delta = s * Tn / std::sqrt((double)count);
+    Vector low = mean - delta;
+    Vector high = mean + delta;
+
+    FURI_LOG_I(TAG,
+        "M[x] = { %f ... %f }  //  median = %f  //  avg = %f  //  delta = %f  //  sigma = %f",
+        low[0], high[0], median[0], mean[0], delta[0], sigma[0]);
+    FURI_LOG_I(TAG,
+        "M[y] = { %f ... %f }  //  median = %f  //  avg = %f  //  delta = %f  //  sigma = %f",
+        low[1], high[1], median[1], mean[1], delta[1], sigma[1]);
+    FURI_LOG_I(TAG,
+        "M[z] = { %f ... %f }  //  median = %f  //  avg = %f  //  delta = %f  //  sigma = %f",
+        low[2], high[2], median[2], mean[2], delta[2], sigma[2]);
+}

+ 108 - 0
tracking/calibration_data.h

@@ -0,0 +1,108 @@
+#pragma once
+
+#include <toolbox/saved_struct.h>
+#include <storage/storage.h>
+#include <vector>
+
+#include "util/vector.h"
+
+#define CALIBRATION_DATA_VER (1)
+#define CALIBRATION_DATA_FILE_NAME ".calibration.data"
+#define CALIBRATION_DATA_PATH INT_PATH(CALIBRATION_DATA_FILE_NAME)
+#define CALIBRATION_DATA_MAGIC (0x23)
+
+#define CALIBRATION_DATA_SAVE(x) \
+    saved_struct_save(           \
+        CALIBRATION_DATA_PATH,   \
+        (x),                     \
+        sizeof(CalibrationMedian), \
+        CALIBRATION_DATA_MAGIC,  \
+        CALIBRATION_DATA_VER)
+
+#define CALIBRATION_DATA_LOAD(x) \
+    saved_struct_load(           \
+        CALIBRATION_DATA_PATH,   \
+        (x),                     \
+        sizeof(CalibrationMedian), \
+        CALIBRATION_DATA_MAGIC,  \
+        CALIBRATION_DATA_VER)
+
+typedef struct {
+    double x;
+    double y;
+    double z;
+} CalibrationMedian;
+
+typedef cardboard::Vector3 Vector;
+
+/**
+ * Helper class to gather some stats and store the calibration data. Right now it calculates a lot
+ * more stats than actually needed. Some of them are used for logging the sensors quality (and
+ * filing bugs), other may be required in the future, e.g. for bias.
+ */
+class CalibrationData {
+
+public:
+    /**
+     * Check if the sensors were calibrated before.
+     *
+     * @return {@code true} if calibration data is available, or {@code false} otherwise.
+     */
+    bool isComplete() { return complete; }
+
+    /** Prepare to collect new calibration data. */
+    void reset();
+
+    /**
+     * Retrieve the median gyroscope readings.
+     *
+     * @return Three-axis median vector.
+     */
+    Vector getMedian() { return median; }
+
+    /**
+     * Retrieve the mean gyroscope readings.
+     *
+     * @return Three-axis mean vector.
+     */
+    Vector getMean() { return mean; }
+
+    /**
+     * Retrieve the standard deviation of gyroscope readings.
+     *
+     * @return Three-axis standard deviation vector.
+     */
+    Vector getSigma() { return sigma; }
+
+    /**
+     * Retrieve the confidence interval size of gyroscope readings.
+     *
+     * @return Three-axis confidence interval size vector.
+     */
+    Vector getDelta() { return delta; }
+
+    /**
+     * Add a new gyroscope reading to the stats.
+     *
+     * @param data gyroscope values vector.
+     * @return {@code true} if we now have enough data for calibration, or {@code false} otherwise.
+     */
+    bool add(Vector& data);
+
+private:
+    // Calculates the confidence interval (mean +- delta) and some other related values, like
+    // standard deviation, etc. See https://en.wikipedia.org/wiki/Student%27s_t-distribution
+    void calcDelta();
+
+    int count;
+    bool complete;
+    Vector sum;
+    Vector sumSq;
+    Vector mean;
+    Vector median;
+    Vector sigma;
+    Vector delta;
+    std::vector<double> xData;
+    std::vector<double> yData;
+    std::vector<double> zData;
+};

+ 6428 - 0
tracking/imu/bmi160.c

@@ -0,0 +1,6428 @@
+/**
+* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved.
+*
+* BSD-3-Clause
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+* 2. Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+* 3. Neither the name of the copyright holder nor the names of its
+*    contributors may be used to endorse or promote products derived from
+*    this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+* @file       bmi160.c
+* @date       2021-10-05
+* @version    v3.9.2
+*
+*/
+
+#include "bmi160.h"
+
+/* Below look up table follows the enum bmi160_int_types.
+ * Hence any change should match to the enum bmi160_int_types
+ */
+const uint8_t int_mask_lookup_table[13] = {
+    BMI160_INT1_SLOPE_MASK, BMI160_INT1_SLOPE_MASK, BMI160_INT2_LOW_STEP_DETECT_MASK, BMI160_INT1_DOUBLE_TAP_MASK,
+    BMI160_INT1_SINGLE_TAP_MASK, BMI160_INT1_ORIENT_MASK, BMI160_INT1_FLAT_MASK, BMI160_INT1_HIGH_G_MASK,
+    BMI160_INT1_LOW_G_MASK, BMI160_INT1_NO_MOTION_MASK, BMI160_INT2_DATA_READY_MASK, BMI160_INT2_FIFO_FULL_MASK,
+    BMI160_INT2_FIFO_WM_MASK
+};
+
+/*********************************************************************/
+/* Static function declarations */
+
+/*!
+ * @brief This API configures the pins to fire the
+ * interrupt signal when it occurs
+ *
+ * @param[in] int_config  : Structure instance of bmi160_int_settg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_intr_pin_config(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API sets the any-motion interrupt of the sensor.
+ * This interrupt occurs when accel values exceeds preset threshold
+ * for a certain period of time.
+ *
+ * @param[in] int_config  : Structure instance of bmi160_int_settg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_accel_any_motion_int(struct bmi160_int_settg *int_config, struct bmi160_dev *dev);
+
+/*!
+ * @brief This API sets tap interrupts.Interrupt is fired when
+ * tap movements happen.
+ *
+ * @param[in] int_config  : Structure instance of bmi160_int_settg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_accel_tap_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API sets the data ready interrupt for both accel and gyro.
+ * This interrupt occurs when new accel and gyro data come.
+ *
+ * @param[in] int_config  : Structure instance of bmi160_int_settg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_accel_gyro_data_ready_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API sets the significant motion interrupt of the sensor.This
+ * interrupt occurs when there is change in user location.
+ *
+ * @param[in] int_config  : Structure instance of bmi160_int_settg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_accel_sig_motion_int(struct bmi160_int_settg *int_config, struct bmi160_dev *dev);
+
+/*!
+ * @brief This API sets the no motion/slow motion interrupt of the sensor.
+ * Slow motion is similar to any motion interrupt.No motion interrupt
+ * occurs when slope bet. two accel values falls below preset threshold
+ * for preset duration.
+ *
+ * @param[in] int_config  : Structure instance of bmi160_int_settg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_accel_no_motion_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API sets the step detection interrupt.This interrupt
+ * occurs when the single step causes accel values to go above
+ * preset threshold.
+ *
+ * @param[in] int_config  : Structure instance of bmi160_int_settg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_accel_step_detect_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API sets the orientation interrupt of the sensor.This
+ * interrupt occurs when there is orientation change in the sensor
+ * with respect to gravitational field vector g.
+ *
+ * @param[in] int_config  : Structure instance of bmi160_int_settg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_accel_orientation_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API sets the flat interrupt of the sensor.This interrupt
+ * occurs in case of flat orientation
+ *
+ * @param[in] int_config  : Structure instance of bmi160_int_settg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_accel_flat_detect_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API sets the low-g interrupt of the sensor.This interrupt
+ * occurs during free-fall.
+ *
+ * @param[in] int_config  : Structure instance of bmi160_int_settg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_accel_low_g_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API sets the high-g interrupt of the sensor.The interrupt
+ * occurs if the absolute value of acceleration data of any enabled axis
+ * exceeds the programmed threshold and the sign of the value does not
+ * change for a preset duration.
+ *
+ * @param[in] int_config  : Structure instance of bmi160_int_settg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_accel_high_g_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API sets the default configuration parameters of accel & gyro.
+ * Also maintain the previous state of configurations.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static void default_param_settg(struct bmi160_dev *dev);
+
+/*!
+ * @brief This API is used to validate the device structure pointer for
+ * null conditions.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t null_ptr_check(const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API set the accel configuration.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_accel_conf(struct bmi160_dev *dev);
+
+/*!
+ * @brief This API gets the accel configuration.
+ *
+ * @param[out] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t get_accel_conf(struct bmi160_dev *dev);
+
+/*!
+ * @brief This API check the accel configuration.
+ *
+ * @param[in] data        : Pointer to store the updated accel config.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t check_accel_config(uint8_t *data, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API process the accel odr.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t process_accel_odr(uint8_t *data, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API process the accel bandwidth.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t process_accel_bw(uint8_t *data, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API process the accel range.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t process_accel_range(uint8_t *data, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API checks the invalid settings for ODR & Bw for Accel and Gyro.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t check_invalid_settg(const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API set the gyro configuration.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_gyro_conf(struct bmi160_dev *dev);
+
+/*!
+ * @brief This API get the gyro configuration.
+ *
+ * @param[out] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t get_gyro_conf(struct bmi160_dev *dev);
+
+/*!
+ * @brief This API check the gyro configuration.
+ *
+ * @param[in] data        : Pointer to store the updated gyro config.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t check_gyro_config(uint8_t *data, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API process the gyro odr.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t process_gyro_odr(uint8_t *data, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API process the gyro bandwidth.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t process_gyro_bw(uint8_t *data, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API process the gyro range.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t process_gyro_range(uint8_t *data, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API sets the accel power mode.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_accel_pwr(struct bmi160_dev *dev);
+
+/*!
+ * @brief This API process the undersampling setting of Accel.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t process_under_sampling(uint8_t *data, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API sets the gyro power mode.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error.
+ */
+static int8_t set_gyro_pwr(struct bmi160_dev *dev);
+
+/*!
+ * @brief This API reads accel data along with sensor time if time is requested
+ * by user. Kindly refer the user guide(README.md) for more info.
+ *
+ * @param[in] len    : len to read no of bytes
+ * @param[out] accel    : Structure pointer to store accel data
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t get_accel_data(uint8_t len, struct bmi160_sensor_data *accel, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API reads accel data along with sensor time if time is requested
+ * by user. Kindly refer the user guide(README.md) for more info.
+ *
+ * @param[in] len    : len to read no of bytes
+ * @param[out] gyro    : Structure pointer to store accel data
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t get_gyro_data(uint8_t len, struct bmi160_sensor_data *gyro, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API reads accel and gyro data along with sensor time
+ * if time is requested by user.
+ * Kindly refer the user guide(README.md) for more info.
+ *
+ * @param[in] len    : len to read no of bytes
+ * @param[out] accel    : Structure pointer to store accel data
+ * @param[out] gyro    : Structure pointer to store accel data
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t get_accel_gyro_data(uint8_t len,
+                                  struct bmi160_sensor_data *accel,
+                                  struct bmi160_sensor_data *gyro,
+                                  const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API enables the any-motion interrupt for accel.
+ *
+ * @param[in] any_motion_int_cfg   : Structure instance of
+ *                   bmi160_acc_any_mot_int_cfg.
+ * @param[in] dev          : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_accel_any_motion_int(const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg,
+                                          struct bmi160_dev *dev);
+
+/*!
+ * @brief This API disable the sig-motion interrupt.
+ *
+ * @param[in] dev   : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t disable_sig_motion_int(const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the source of data(filter & pre-filter)
+ * for any-motion interrupt.
+ *
+ * @param[in] any_motion_int_cfg  : Structure instance of
+ *                  bmi160_acc_any_mot_int_cfg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_any_motion_src(const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg,
+                                    const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the duration and threshold of
+ * any-motion interrupt.
+ *
+ * @param[in] any_motion_int_cfg  : Structure instance of
+ *                  bmi160_acc_any_mot_int_cfg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_any_dur_threshold(const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg,
+                                       const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure necessary setting of any-motion interrupt.
+ *
+ * @param[in] int_config       : Structure instance of bmi160_int_settg.
+ * @param[in] any_motion_int_cfg   : Structure instance of
+ *                   bmi160_acc_any_mot_int_cfg.
+ * @param[in] dev          : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_any_motion_int_settg(const struct bmi160_int_settg *int_config,
+                                          const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg,
+                                          const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API enable the data ready interrupt.
+ *
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_data_ready_int(const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API enables the no motion/slow motion interrupt.
+ *
+ * @param[in] no_mot_int_cfg    : Structure instance of
+ *                bmi160_acc_no_motion_int_cfg.
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_no_motion_int(const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg,
+                                   const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the interrupt PIN setting for
+ * no motion/slow motion interrupt.
+ *
+ * @param[in] int_config    : structure instance of bmi160_int_settg.
+ * @param[in] no_mot_int_cfg    : Structure instance of
+ *                bmi160_acc_no_motion_int_cfg.
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_no_motion_int_settg(const struct bmi160_int_settg *int_config,
+                                         const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg,
+                                         const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the source of interrupt for no motion.
+ *
+ * @param[in] no_mot_int_cfg    : Structure instance of
+ *                bmi160_acc_no_motion_int_cfg.
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_no_motion_data_src(const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg,
+                                        const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the duration and threshold of
+ * no motion/slow motion interrupt along with selection of no/slow motion.
+ *
+ * @param[in] no_mot_int_cfg    : Structure instance of
+ *                bmi160_acc_no_motion_int_cfg.
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_no_motion_dur_thr(const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg,
+                                       const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API enables the sig-motion motion interrupt.
+ *
+ * @param[in] sig_mot_int_cfg   : Structure instance of
+ *                bmi160_acc_sig_mot_int_cfg.
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_sig_motion_int(const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg, struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the interrupt PIN setting for
+ * significant motion interrupt.
+ *
+ * @param[in] int_config    : Structure instance of bmi160_int_settg.
+ * @param[in] sig_mot_int_cfg   : Structure instance of
+ *                bmi160_acc_sig_mot_int_cfg.
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_sig_motion_int_settg(const struct bmi160_int_settg *int_config,
+                                          const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg,
+                                          const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the source of data(filter & pre-filter)
+ * for sig motion interrupt.
+ *
+ * @param[in] sig_mot_int_cfg   : Structure instance of
+ *                bmi160_acc_sig_mot_int_cfg.
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_sig_motion_data_src(const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg,
+                                         const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the threshold, skip and proof time of
+ * sig motion interrupt.
+ *
+ * @param[in] sig_mot_int_cfg   : Structure instance of
+ *                bmi160_acc_sig_mot_int_cfg.
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_sig_dur_threshold(const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg,
+                                       const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API enables the step detector interrupt.
+ *
+ * @param[in] step_detect_int_cfg   : Structure instance of
+ *                    bmi160_acc_step_detect_int_cfg.
+ * @param[in] dev           : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_step_detect_int(const struct bmi160_acc_step_detect_int_cfg *step_detect_int_cfg,
+                                     const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the step detector parameter.
+ *
+ * @param[in] step_detect_int_cfg   : Structure instance of
+ *                    bmi160_acc_step_detect_int_cfg.
+ * @param[in] dev           : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_step_detect(const struct bmi160_acc_step_detect_int_cfg *step_detect_int_cfg,
+                                 const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API enables the single/double tap interrupt.
+ *
+ * @param[in] int_config    : Structure instance of bmi160_int_settg.
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_tap_int(const struct bmi160_int_settg *int_config,
+                             const struct bmi160_acc_tap_int_cfg *tap_int_cfg,
+                             const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the interrupt PIN setting for
+ * tap interrupt.
+ *
+ * @param[in] int_config    : Structure instance of bmi160_int_settg.
+ * @param[in] tap_int_cfg   : Structure instance of bmi160_acc_tap_int_cfg.
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_tap_int_settg(const struct bmi160_int_settg *int_config,
+                                   const struct bmi160_acc_tap_int_cfg *tap_int_cfg,
+                                   const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the source of data(filter & pre-filter)
+ * for tap interrupt.
+ *
+ * @param[in] tap_int_cfg   : Structure instance of bmi160_acc_tap_int_cfg.
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_tap_data_src(const struct bmi160_acc_tap_int_cfg *tap_int_cfg, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the  parameters of tap interrupt.
+ * Threshold, quite, shock, and duration.
+ *
+ * @param[in] int_config    : Structure instance of bmi160_int_settg.
+ * @param[in] tap_int_cfg   : Structure instance of bmi160_acc_tap_int_cfg.
+ * @param[in] dev       : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_tap_param(const struct bmi160_int_settg *int_config,
+                               const struct bmi160_acc_tap_int_cfg *tap_int_cfg,
+                               const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API enable the external mode configuration.
+ *
+ * @param[in] dev   : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_sec_if(const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the ODR of the auxiliary sensor.
+ *
+ * @param[in] dev   : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_aux_odr(const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API maps the actual burst read length set by user.
+ *
+ * @param[in] len   : Pointer to store the read length.
+ * @param[in] dev   : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t map_read_len(uint16_t *len, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the settings of auxiliary sensor.
+ *
+ * @param[in] dev   : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_aux_settg(const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API extract the read data from auxiliary sensor.
+ *
+ * @param[in] map_len     : burst read value.
+ * @param[in] reg_addr    : Address of register to read.
+ * @param[in] aux_data    : Pointer to store the read data.
+ * @param[in] len     : length to read the data.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ * @note : Refer user guide for detailed info.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success / -ve value -> Error
+ */
+static int8_t extract_aux_read(uint16_t map_len,
+                               uint8_t reg_addr,
+                               uint8_t *aux_data,
+                               uint16_t len,
+                               const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API enables the orient interrupt.
+ *
+ * @param[in] orient_int_cfg : Structure instance of bmi160_acc_orient_int_cfg.
+ * @param[in] dev        : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_orient_int(const struct bmi160_acc_orient_int_cfg *orient_int_cfg, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the necessary setting of orientation interrupt.
+ *
+ * @param[in] orient_int_cfg : Structure instance of bmi160_acc_orient_int_cfg.
+ * @param[in] dev        : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_orient_int_settg(const struct bmi160_acc_orient_int_cfg *orient_int_cfg,
+                                      const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API enables the flat interrupt.
+ *
+ * @param[in] flat_int  : Structure instance of bmi160_acc_flat_detect_int_cfg.
+ * @param[in] dev       : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_flat_int(const struct bmi160_acc_flat_detect_int_cfg *flat_int, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the necessary setting of flat interrupt.
+ *
+ * @param[in] flat_int  : Structure instance of bmi160_acc_flat_detect_int_cfg.
+ * @param[in] dev   : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_flat_int_settg(const struct bmi160_acc_flat_detect_int_cfg *flat_int,
+                                    const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API enables the Low-g interrupt.
+ *
+ * @param[in] low_g_int : Structure instance of bmi160_acc_low_g_int_cfg.
+ * @param[in] dev   : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_low_g_int(const struct bmi160_acc_low_g_int_cfg *low_g_int, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the source of data(filter & pre-filter) for low-g interrupt.
+ *
+ * @param[in] low_g_int : Structure instance of bmi160_acc_low_g_int_cfg.
+ * @param[in] dev   : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_low_g_data_src(const struct bmi160_acc_low_g_int_cfg *low_g_int, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the necessary setting of low-g interrupt.
+ *
+ * @param[in] low_g_int : Structure instance of bmi160_acc_low_g_int_cfg.
+ * @param[in] dev   : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_low_g_int_settg(const struct bmi160_acc_low_g_int_cfg *low_g_int, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API enables the high-g interrupt.
+ *
+ * @param[in] high_g_int_cfg : Structure instance of bmi160_acc_high_g_int_cfg.
+ * @param[in] dev        : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_high_g_int(const struct bmi160_acc_high_g_int_cfg *high_g_int_cfg, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the source of data(filter & pre-filter)
+ * for high-g interrupt.
+ *
+ * @param[in] high_g_int_cfg : Structure instance of bmi160_acc_high_g_int_cfg.
+ * @param[in] dev        : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_high_g_data_src(const struct bmi160_acc_high_g_int_cfg *high_g_int_cfg,
+                                     const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the necessary setting of high-g interrupt.
+ *
+ * @param[in] high_g_int_cfg : Structure instance of bmi160_acc_high_g_int_cfg.
+ * @param[in] dev        : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_high_g_int_settg(const struct bmi160_acc_high_g_int_cfg *high_g_int_cfg,
+                                      const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the behavioural setting of interrupt pin.
+ *
+ * @param[in] int_config    : Structure instance of bmi160_int_settg.
+ * @param[in] dev       : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_int_out_ctrl(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API configure the mode(input enable, latch or non-latch) of interrupt pin.
+ *
+ * @param[in] int_config    : Structure instance of bmi160_int_settg.
+ * @param[in] dev       : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t config_int_latch(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API performs the self test for accelerometer of BMI160
+ *
+ * @param[in] dev   : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t perform_accel_self_test(struct bmi160_dev *dev);
+
+/*!
+ * @brief This API enables to perform the accel self test by setting proper
+ * configurations to facilitate accel self test
+ *
+ * @param[in] dev   : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_accel_self_test(struct bmi160_dev *dev);
+
+/*!
+ * @brief This API performs accel self test with positive excitation
+ *
+ * @param[in] accel_pos : Structure pointer to store accel data
+ *                        for positive excitation
+ * @param[in] dev   : structure instance of bmi160_dev
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t accel_self_test_positive_excitation(struct bmi160_sensor_data *accel_pos, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API performs accel self test with negative excitation
+ *
+ * @param[in] accel_neg : Structure pointer to store accel data
+ *                        for negative excitation
+ * @param[in] dev   : structure instance of bmi160_dev
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t accel_self_test_negative_excitation(struct bmi160_sensor_data *accel_neg, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API validates the accel self test results
+ *
+ * @param[in] accel_pos : Structure pointer to store accel data
+ *                        for positive excitation
+ * @param[in] accel_neg : Structure pointer to store accel data
+ *                        for negative excitation
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error / +ve value -> Self test fail
+ */
+static int8_t validate_accel_self_test(const struct bmi160_sensor_data *accel_pos,
+                                       const struct bmi160_sensor_data *accel_neg);
+
+/*!
+ * @brief This API performs the self test for gyroscope of BMI160
+ *
+ * @param[in] dev   : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t perform_gyro_self_test(const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API enables the self test bit to trigger self test for gyro
+ *
+ * @param[in] dev   : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_gyro_self_test(const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API validates the self test results of gyro
+ *
+ * @param[in] dev   : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t validate_gyro_self_test(const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API sets FIFO full interrupt of the sensor.This interrupt
+ *  occurs when the FIFO is full and the next full data sample would cause
+ *  a FIFO overflow, which may delete the old samples.
+ *
+ * @param[in] int_config    : Structure instance of bmi160_int_settg.
+ * @param[in] dev       : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t set_fifo_full_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This enable the FIFO full interrupt engine.
+ *
+ * @param[in] int_config    : Structure instance of bmi160_int_settg.
+ * @param[in] dev       : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_fifo_full_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API sets FIFO watermark interrupt of the sensor.The FIFO
+ *  watermark interrupt is fired, when the FIFO fill level is above a fifo
+ *  watermark.
+ *
+ * @param[in] int_config    : Structure instance of bmi160_int_settg.
+ * @param[in] dev       : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t set_fifo_watermark_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This enable the FIFO watermark interrupt engine.
+ *
+ * @param[in] int_config    : Structure instance of bmi160_int_settg.
+ * @param[in] dev       : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t enable_fifo_wtm_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ * @brief This API is used to reset the FIFO related configurations
+ *  in the fifo_frame structure.
+ *
+ * @param[in] dev       : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static void reset_fifo_data_structure(const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to read number of bytes filled
+ *  currently in FIFO buffer.
+ *
+ *  @param[in] bytes_to_read  : Number of bytes available in FIFO at the
+ *                              instant which is obtained from FIFO counter.
+ *  @param[in] dev            : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success / -ve value -> Error.
+ *  @retval Any non zero value -> Fail
+ *
+ */
+static int8_t get_fifo_byte_counter(uint16_t *bytes_to_read, struct bmi160_dev const *dev);
+
+/*!
+ *  @brief This API is used to compute the number of bytes of accel FIFO data
+ *  which is to be parsed in header-less mode
+ *
+ *  @param[out] data_index        : The start index for parsing data
+ *  @param[out] data_read_length  : Number of bytes to be parsed
+ *  @param[in]  acc_frame_count   : Number of accelerometer frames to be read
+ *  @param[in]  dev               : Structure instance of bmi160_dev.
+ *
+ */
+static void get_accel_len_to_parse(uint16_t *data_index,
+                                   uint16_t *data_read_length,
+                                   const uint8_t *acc_frame_count,
+                                   const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to parse the accelerometer data from the
+ *  FIFO data in both header mode and header-less mode.
+ *  It updates the idx value which is used to store the index of
+ *  the current data byte which is parsed.
+ *
+ *  @param[in,out] acc      : structure instance of sensor data
+ *  @param[in,out] idx      : Index value of number of bytes parsed
+ *  @param[in,out] acc_idx  : Index value of accelerometer data
+ *                                (x,y,z axes) frames parsed
+ *  @param[in] frame_info       : It consists of either fifo_data_enable
+ *                                parameter in header-less mode or
+ *                                frame header data in header mode
+ *  @param[in] dev      : structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static void unpack_accel_frame(struct bmi160_sensor_data *acc,
+                               uint16_t *idx,
+                               uint8_t *acc_idx,
+                               uint8_t frame_info,
+                               const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to parse the accelerometer data from the
+ *  FIFO data and store it in the instance of the structure bmi160_sensor_data.
+ *
+ * @param[in,out] accel_data        : structure instance of sensor data
+ * @param[in,out] data_start_index  : Index value of number of bytes parsed
+ * @param[in] dev           : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static void unpack_accel_data(struct bmi160_sensor_data *accel_data,
+                              uint16_t data_start_index,
+                              const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to parse the accelerometer data from the
+ *  FIFO data in header mode.
+ *
+ *  @param[in,out] accel_data    : Structure instance of sensor data
+ *  @param[in,out] accel_length  : Number of accelerometer frames
+ *  @param[in] dev               : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static void extract_accel_header_mode(struct bmi160_sensor_data *accel_data,
+                                      uint8_t *accel_length,
+                                      const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API computes the number of bytes of gyro FIFO data
+ *  which is to be parsed in header-less mode
+ *
+ *  @param[out] data_index       : The start index for parsing data
+ *  @param[out] data_read_length : No of bytes to be parsed from FIFO buffer
+ *  @param[in] gyro_frame_count  : Number of Gyro data frames to be read
+ *  @param[in] dev               : Structure instance of bmi160_dev.
+ */
+static void get_gyro_len_to_parse(uint16_t *data_index,
+                                  uint16_t *data_read_length,
+                                  const uint8_t *gyro_frame_count,
+                                  const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to parse the gyroscope's data from the
+ *  FIFO data in both header mode and header-less mode.
+ *  It updates the idx value which is used to store the index of
+ *  the current data byte which is parsed.
+ *
+ *  @param[in,out] gyro     : structure instance of sensor data
+ *  @param[in,out] idx      : Index value of number of bytes parsed
+ *  @param[in,out] gyro_idx : Index value of gyro data
+ *                                (x,y,z axes) frames parsed
+ *  @param[in] frame_info       : It consists of either fifo_data_enable
+ *                                parameter in header-less mode or
+ *                                frame header data in header mode
+ *  @param[in] dev      : structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static void unpack_gyro_frame(struct bmi160_sensor_data *gyro,
+                              uint16_t *idx,
+                              uint8_t *gyro_idx,
+                              uint8_t frame_info,
+                              const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to parse the gyro data from the
+ *  FIFO data and store it in the instance of the structure bmi160_sensor_data.
+ *
+ *  @param[in,out] gyro_data         : structure instance of sensor data
+ *  @param[in,out] data_start_index  : Index value of number of bytes parsed
+ *  @param[in] dev           : structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static void unpack_gyro_data(struct bmi160_sensor_data *gyro_data,
+                             uint16_t data_start_index,
+                             const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to parse the gyro data from the
+ *  FIFO data in header mode.
+ *
+ *  @param[in,out] gyro_data     : Structure instance of sensor data
+ *  @param[in,out] gyro_length   : Number of gyro frames
+ *  @param[in] dev               : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static void extract_gyro_header_mode(struct bmi160_sensor_data *gyro_data,
+                                     uint8_t *gyro_length,
+                                     const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API computes the number of bytes of aux FIFO data
+ *  which is to be parsed in header-less mode
+ *
+ *  @param[out] data_index       : The start index for parsing data
+ *  @param[out] data_read_length : No of bytes to be parsed from FIFO buffer
+ *  @param[in] aux_frame_count   : Number of Aux data frames to be read
+ *  @param[in] dev               : Structure instance of bmi160_dev.
+ */
+static void get_aux_len_to_parse(uint16_t *data_index,
+                                 uint16_t *data_read_length,
+                                 const uint8_t *aux_frame_count,
+                                 const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to parse the aux's data from the
+ *  FIFO data in both header mode and header-less mode.
+ *  It updates the idx value which is used to store the index of
+ *  the current data byte which is parsed
+ *
+ *  @param[in,out] aux_data : structure instance of sensor data
+ *  @param[in,out] idx      : Index value of number of bytes parsed
+ *  @param[in,out] aux_index    : Index value of gyro data
+ *                                (x,y,z axes) frames parsed
+ *  @param[in] frame_info       : It consists of either fifo_data_enable
+ *                                parameter in header-less mode or
+ *                                frame header data in header mode
+ *  @param[in] dev      : structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static void unpack_aux_frame(struct bmi160_aux_data *aux_data,
+                             uint16_t *idx,
+                             uint8_t *aux_index,
+                             uint8_t frame_info,
+                             const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to parse the aux data from the
+ *  FIFO data and store it in the instance of the structure bmi160_aux_data.
+ *
+ * @param[in,out] aux_data      : structure instance of sensor data
+ * @param[in,out] data_start_index  : Index value of number of bytes parsed
+ * @param[in] dev           : structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval zero -> Success  / -ve value -> Error
+ */
+static void unpack_aux_data(struct bmi160_aux_data *aux_data, uint16_t data_start_index, const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to parse the aux data from the
+ *  FIFO data in header mode.
+ *
+ *  @param[in,out] aux_data     : Structure instance of sensor data
+ *  @param[in,out] aux_length   : Number of aux frames
+ *  @param[in] dev              : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static void extract_aux_header_mode(struct bmi160_aux_data *aux_data, uint8_t *aux_length,
+                                    const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API checks the presence of non-valid frames in the read fifo data.
+ *
+ *  @param[in,out] data_index    : The index of the current data to
+ *                                be parsed from fifo data
+ *  @param[in] dev               : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static void check_frame_validity(uint16_t *data_index, const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to move the data index ahead of the
+ *  current_frame_length parameter when unnecessary FIFO data appears while
+ *  extracting the user specified data.
+ *
+ *  @param[in,out] data_index       : Index of the FIFO data which
+ *                                  is to be moved ahead of the
+ *                                  current_frame_length
+ *  @param[in] current_frame_length : Number of bytes in a particular frame
+ *  @param[in] dev                  : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static void move_next_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to parse and store the sensor time from the
+ *  FIFO data in the structure instance dev.
+ *
+ *  @param[in,out] data_index : Index of the FIFO data which
+ *                              has the sensor time.
+ *  @param[in] dev            : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static void unpack_sensortime_frame(uint16_t *data_index, const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to parse and store the skipped_frame_count from
+ *  the FIFO data in the structure instance dev.
+ *
+ *  @param[in,out] data_index   : Index of the FIFO data which
+ *                                    has the skipped frame count.
+ *  @param[in] dev              : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static void unpack_skipped_frame(uint16_t *data_index, const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to get the FOC status from the sensor
+ *
+ *  @param[in,out] foc_status   : Result of FOC status.
+ *  @param[in] dev              : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t get_foc_status(uint8_t *foc_status, struct bmi160_dev const *dev);
+
+/*!
+ *  @brief This API is used to configure the offset enable bits in the sensor
+ *
+ *  @param[in,out] foc_conf   : Structure instance of bmi160_foc_conf which
+ *                                   has the FOC and offset configurations
+ *  @param[in] dev            : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t configure_offset_enable(const struct bmi160_foc_conf *foc_conf, struct bmi160_dev const *dev);
+
+/*!
+ *  @brief This API is used to trigger the FOC in the sensor
+ *
+ *  @param[in,out] offset     : Structure instance of bmi160_offsets which
+ *                              reads and stores the offset values after FOC
+ *  @param[in] dev            : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t trigger_foc(struct bmi160_offsets *offset, struct bmi160_dev const *dev);
+
+/*!
+ *  @brief This API is used to map/unmap the Dataready(Accel & Gyro), FIFO full
+ *  and FIFO watermark interrupt
+ *
+ *  @param[in] int_config     : Structure instance of bmi160_int_settg which
+ *                              stores the interrupt type and interrupt channel
+ *              configurations to map/unmap the interrupt pins
+ *  @param[in] dev            : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t map_hardware_interrupt(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API is used to map/unmap the Any/Sig motion, Step det/Low-g,
+ *  Double tap, Single tap, Orientation, Flat, High-G, Nomotion interrupt pins.
+ *
+ *  @param[in] int_config     : Structure instance of bmi160_int_settg which
+ *                              stores the interrupt type and interrupt channel
+ *              configurations to map/unmap the interrupt pins
+ *  @param[in] dev            : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t map_feature_interrupt(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev);
+
+/*********************** User function definitions ****************************/
+
+/*!
+ * @brief This API reads the data from the given register address
+ * of sensor.
+ */
+int8_t bmi160_get_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_dev *dev)
+{
+    int8_t rslt = BMI160_OK;
+
+    /* Null-pointer check */
+    if ((dev == NULL) || (dev->read == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else if (len == 0)
+    {
+        rslt = BMI160_E_READ_WRITE_LENGTH_INVALID;
+    }
+    else
+    {
+        /* Configuring reg_addr for SPI Interface */
+        if (dev->intf == BMI160_SPI_INTF)
+        {
+            reg_addr = (reg_addr | BMI160_SPI_RD_MASK);
+        }
+
+        rslt = dev->read(dev->id, reg_addr, data, len);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API writes the given data to the register address
+ * of sensor.
+ */
+int8_t bmi160_set_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_dev *dev)
+{
+    int8_t rslt = BMI160_OK;
+    uint8_t count = 0;
+
+    /* Null-pointer check */
+    if ((dev == NULL) || (dev->write == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else if (len == 0)
+    {
+        rslt = BMI160_E_READ_WRITE_LENGTH_INVALID;
+    }
+    else
+    {
+        /* Configuring reg_addr for SPI Interface */
+        if (dev->intf == BMI160_SPI_INTF)
+        {
+            reg_addr = (reg_addr & BMI160_SPI_WR_MASK);
+        }
+
+        if ((dev->prev_accel_cfg.power == BMI160_ACCEL_NORMAL_MODE) ||
+            (dev->prev_gyro_cfg.power == BMI160_GYRO_NORMAL_MODE))
+        {
+            rslt = dev->write(dev->id, reg_addr, data, len);
+
+            /* Kindly refer bmi160 data sheet section 3.2.4 */
+            dev->delay_ms(1);
+
+        }
+        else
+        {
+            /*Burst write is not allowed in
+             * suspend & low power mode */
+            for (; count < len; count++)
+            {
+                rslt = dev->write(dev->id, reg_addr, &data[count], 1);
+                reg_addr++;
+
+                /* Kindly refer bmi160 data sheet section 3.2.4 */
+                dev->delay_ms(1);
+
+            }
+        }
+
+        if (rslt != BMI160_OK)
+        {
+            rslt = BMI160_E_COM_FAIL;
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API is the entry point for sensor.It performs
+ *  the selection of I2C/SPI read mechanism according to the
+ *  selected interface and reads the chip-id of bmi160 sensor.
+ */
+int8_t bmi160_init(struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data;
+    uint8_t try = 3;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+
+    /* Dummy read of 0x7F register to enable SPI Interface
+     * if SPI is used */
+    if ((rslt == BMI160_OK) && (dev->intf == BMI160_SPI_INTF))
+    {
+        rslt = bmi160_get_regs(BMI160_SPI_COMM_TEST_ADDR, &data, 1, dev);
+    }
+
+    if (rslt == BMI160_OK)
+    {
+        /* Assign chip id as zero */
+        dev->chip_id = 0;
+
+        while ((try--) && (dev->chip_id != BMI160_CHIP_ID))
+        {
+            /* Read chip_id */
+            rslt = bmi160_get_regs(BMI160_CHIP_ID_ADDR, &dev->chip_id, 1, dev);
+        }
+
+        if ((rslt == BMI160_OK) && (dev->chip_id == BMI160_CHIP_ID))
+        {
+            dev->any_sig_sel = BMI160_BOTH_ANY_SIG_MOTION_DISABLED;
+
+            /* Soft reset */
+            rslt = bmi160_soft_reset(dev);
+        }
+        else
+        {
+            rslt = BMI160_E_DEV_NOT_FOUND;
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API resets and restarts the device.
+ * All register values are overwritten with default parameters.
+ */
+int8_t bmi160_soft_reset(struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = BMI160_SOFT_RESET_CMD;
+
+    /* Null-pointer check */
+    if ((dev == NULL) || (dev->delay_ms == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* Reset the device */
+        rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &data, 1, dev);
+        dev->delay_ms(BMI160_SOFT_RESET_DELAY_MS);
+        if ((rslt == BMI160_OK) && (dev->intf == BMI160_SPI_INTF))
+        {
+            /* Dummy read of 0x7F register to enable SPI Interface
+             * if SPI is used */
+            rslt = bmi160_get_regs(BMI160_SPI_COMM_TEST_ADDR, &data, 1, dev);
+        }
+
+        if (rslt == BMI160_OK)
+        {
+            /* Update the default parameters */
+            default_param_settg(dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configures the power mode, range and bandwidth
+ * of sensor.
+ */
+int8_t bmi160_set_sens_conf(struct bmi160_dev *dev)
+{
+    int8_t rslt = BMI160_OK;
+
+    /* Null-pointer check */
+    if ((dev == NULL) || (dev->delay_ms == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        rslt = set_accel_conf(dev);
+        if (rslt == BMI160_OK)
+        {
+            rslt = set_gyro_conf(dev);
+            if (rslt == BMI160_OK)
+            {
+                /* write power mode for accel and gyro */
+                rslt = bmi160_set_power_mode(dev);
+                if (rslt == BMI160_OK)
+                {
+                    rslt = check_invalid_settg(dev);
+                }
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API gets accel and gyro configurations.
+ */
+int8_t bmi160_get_sens_conf(struct bmi160_dev *dev)
+{
+    int8_t rslt = BMI160_OK;
+
+    /* Null-pointer check */
+    if ((dev == NULL) || (dev->delay_ms == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        rslt = get_accel_conf(dev);
+        if (rslt == BMI160_OK)
+        {
+            rslt = get_gyro_conf(dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets the power mode of the sensor.
+ */
+int8_t bmi160_set_power_mode(struct bmi160_dev *dev)
+{
+    int8_t rslt = 0;
+
+    /* Null-pointer check */
+    if ((dev == NULL) || (dev->delay_ms == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        rslt = set_accel_pwr(dev);
+        if (rslt == BMI160_OK)
+        {
+            rslt = set_gyro_pwr(dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API gets the power mode of the sensor.
+ */
+int8_t bmi160_get_power_mode(struct bmi160_dev *dev)
+{
+    int8_t rslt = 0;
+    uint8_t power_mode = 0;
+
+    /* Null-pointer check */
+    if ((dev == NULL) || (dev->delay_ms == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        rslt = bmi160_get_regs(BMI160_PMU_STATUS_ADDR, &power_mode, 1, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Power mode of the accel, gyro sensor is obtained */
+            dev->gyro_cfg.power = BMI160_GET_BITS(power_mode, BMI160_GYRO_POWER_MODE);
+            dev->accel_cfg.power = BMI160_GET_BITS(power_mode, BMI160_ACCEL_POWER_MODE);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API reads sensor data, stores it in
+ * the bmi160_sensor_data structure pointer passed by the user.
+ */
+int8_t bmi160_get_sensor_data(uint8_t select_sensor,
+                              struct bmi160_sensor_data *accel,
+                              struct bmi160_sensor_data *gyro,
+                              const struct bmi160_dev *dev)
+{
+    int8_t rslt = BMI160_OK;
+    uint8_t time_sel;
+    uint8_t sen_sel;
+    uint8_t len = 0;
+
+    /*Extract the sensor  and time select information*/
+    sen_sel = select_sensor & BMI160_SEN_SEL_MASK;
+    time_sel = ((sen_sel & BMI160_TIME_SEL) >> 2);
+    sen_sel = sen_sel & (BMI160_ACCEL_SEL | BMI160_GYRO_SEL);
+    if (time_sel == 1)
+    {
+        len = 3;
+    }
+
+    /* Null-pointer check */
+    if (dev != NULL)
+    {
+        switch (sen_sel)
+        {
+            case BMI160_ACCEL_ONLY:
+
+                /* Null-pointer check */
+                if (accel == NULL)
+                {
+                    rslt = BMI160_E_NULL_PTR;
+                }
+                else
+                {
+                    rslt = get_accel_data(len, accel, dev);
+                }
+
+                break;
+            case BMI160_GYRO_ONLY:
+
+                /* Null-pointer check */
+                if (gyro == NULL)
+                {
+                    rslt = BMI160_E_NULL_PTR;
+                }
+                else
+                {
+                    rslt = get_gyro_data(len, gyro, dev);
+                }
+
+                break;
+            case BMI160_BOTH_ACCEL_AND_GYRO:
+
+                /* Null-pointer check */
+                if ((gyro == NULL) || (accel == NULL))
+                {
+                    rslt = BMI160_E_NULL_PTR;
+                }
+                else
+                {
+                    rslt = get_accel_gyro_data(len, accel, gyro, dev);
+                }
+
+                break;
+            default:
+                rslt = BMI160_E_INVALID_INPUT;
+                break;
+        }
+    }
+    else
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configures the necessary interrupt based on
+ *  the user settings in the bmi160_int_settg structure instance.
+ */
+int8_t bmi160_set_int_config(struct bmi160_int_settg *int_config, struct bmi160_dev *dev)
+{
+    int8_t rslt = BMI160_OK;
+
+    switch (int_config->int_type)
+    {
+        case BMI160_ACC_ANY_MOTION_INT:
+
+            /*Any-motion  interrupt*/
+            rslt = set_accel_any_motion_int(int_config, dev);
+            break;
+        case BMI160_ACC_SIG_MOTION_INT:
+
+            /* Significant motion interrupt */
+            rslt = set_accel_sig_motion_int(int_config, dev);
+            break;
+        case BMI160_ACC_SLOW_NO_MOTION_INT:
+
+            /* Slow or no motion interrupt */
+            rslt = set_accel_no_motion_int(int_config, dev);
+            break;
+        case BMI160_ACC_DOUBLE_TAP_INT:
+        case BMI160_ACC_SINGLE_TAP_INT:
+
+            /* Double tap and single tap Interrupt */
+            rslt = set_accel_tap_int(int_config, dev);
+            break;
+        case BMI160_STEP_DETECT_INT:
+
+            /* Step detector interrupt */
+            rslt = set_accel_step_detect_int(int_config, dev);
+            break;
+        case BMI160_ACC_ORIENT_INT:
+
+            /* Orientation interrupt */
+            rslt = set_accel_orientation_int(int_config, dev);
+            break;
+        case BMI160_ACC_FLAT_INT:
+
+            /* Flat detection interrupt */
+            rslt = set_accel_flat_detect_int(int_config, dev);
+            break;
+        case BMI160_ACC_LOW_G_INT:
+
+            /* Low-g interrupt */
+            rslt = set_accel_low_g_int(int_config, dev);
+            break;
+        case BMI160_ACC_HIGH_G_INT:
+
+            /* High-g interrupt */
+            rslt = set_accel_high_g_int(int_config, dev);
+            break;
+        case BMI160_ACC_GYRO_DATA_RDY_INT:
+
+            /* Data ready interrupt */
+            rslt = set_accel_gyro_data_ready_int(int_config, dev);
+            break;
+        case BMI160_ACC_GYRO_FIFO_FULL_INT:
+
+            /* Fifo full interrupt */
+            rslt = set_fifo_full_int(int_config, dev);
+            break;
+        case BMI160_ACC_GYRO_FIFO_WATERMARK_INT:
+
+            /* Fifo water-mark interrupt */
+            rslt = set_fifo_watermark_int(int_config, dev);
+            break;
+        case BMI160_FIFO_TAG_INT_PIN:
+
+            /* Fifo tagging feature support */
+            /* Configure Interrupt pins */
+            rslt = set_intr_pin_config(int_config, dev);
+            break;
+        default:
+            break;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API enables or disable the step counter feature.
+ * 1 - enable step counter (0 - disable)
+ */
+int8_t bmi160_set_step_counter(uint8_t step_cnt_enable, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if (rslt != BMI160_OK)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        rslt = bmi160_get_regs(BMI160_INT_STEP_CONFIG_1_ADDR, &data, 1, dev);
+        if (rslt == BMI160_OK)
+        {
+            if (step_cnt_enable == BMI160_ENABLE)
+            {
+                data |= (uint8_t)(step_cnt_enable << 3);
+            }
+            else
+            {
+                data &= ~BMI160_STEP_COUNT_EN_BIT_MASK;
+            }
+
+            rslt = bmi160_set_regs(BMI160_INT_STEP_CONFIG_1_ADDR, &data, 1, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API reads the step counter value.
+ */
+int8_t bmi160_read_step_counter(uint16_t *step_val, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data[2] = { 0, 0 };
+    uint16_t msb = 0;
+    uint8_t lsb = 0;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if (rslt != BMI160_OK)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        rslt = bmi160_get_regs(BMI160_INT_STEP_CNT_0_ADDR, data, 2, dev);
+        if (rslt == BMI160_OK)
+        {
+            lsb = data[0];
+            msb = data[1] << 8;
+            *step_val = msb | lsb;
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API reads the mention no of byte of data from the given
+ * register address of auxiliary sensor.
+ */
+int8_t bmi160_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev)
+{
+    int8_t rslt = BMI160_OK;
+    uint16_t map_len = 0;
+
+    /* Null-pointer check */
+    if ((dev == NULL) || (dev->read == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        if (dev->aux_cfg.aux_sensor_enable == BMI160_ENABLE)
+        {
+            rslt = map_read_len(&map_len, dev);
+            if (rslt == BMI160_OK)
+            {
+                rslt = extract_aux_read(map_len, reg_addr, aux_data, len, dev);
+            }
+        }
+        else
+        {
+            rslt = BMI160_E_INVALID_INPUT;
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API writes the mention no of byte of data to the given
+ * register address of auxiliary sensor.
+ */
+int8_t bmi160_aux_write(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev)
+{
+    int8_t rslt = BMI160_OK;
+    uint8_t count = 0;
+
+    /* Null-pointer check */
+    if ((dev == NULL) || (dev->write == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        for (; count < len; count++)
+        {
+            /* set data to write */
+            rslt = bmi160_set_regs(BMI160_AUX_IF_4_ADDR, aux_data, 1, dev);
+            dev->delay_ms(BMI160_AUX_COM_DELAY);
+            if (rslt == BMI160_OK)
+            {
+                /* set address to write */
+                rslt = bmi160_set_regs(BMI160_AUX_IF_3_ADDR, &reg_addr, 1, dev);
+                dev->delay_ms(BMI160_AUX_COM_DELAY);
+                if (rslt == BMI160_OK && (count < len - 1))
+                {
+                    aux_data++;
+                    reg_addr++;
+                }
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API initialize the auxiliary sensor
+ * in order to access it.
+ */
+int8_t bmi160_aux_init(const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if (rslt != BMI160_OK)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        if (dev->aux_cfg.aux_sensor_enable == BMI160_ENABLE)
+        {
+            /* Configures the auxiliary sensor interface settings */
+            rslt = config_aux_settg(dev);
+        }
+        else
+        {
+            rslt = BMI160_E_INVALID_INPUT;
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API is used to setup the auxiliary sensor of bmi160 in auto mode
+ * Thus enabling the auto update of 8 bytes of data from auxiliary sensor
+ * to BMI160 register address 0x04 to 0x0B
+ */
+int8_t bmi160_set_aux_auto_mode(uint8_t *data_addr, struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if (rslt != BMI160_OK)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        if (dev->aux_cfg.aux_sensor_enable == BMI160_ENABLE)
+        {
+            /* Write the aux. address to read in 0x4D of BMI160*/
+            rslt = bmi160_set_regs(BMI160_AUX_IF_2_ADDR, data_addr, 1, dev);
+            dev->delay_ms(BMI160_AUX_COM_DELAY);
+            if (rslt == BMI160_OK)
+            {
+                /* Configure the polling ODR for
+                 * auxiliary sensor */
+                rslt = config_aux_odr(dev);
+                if (rslt == BMI160_OK)
+                {
+                    /* Disable the aux. manual mode, i.e aux.
+                     * sensor is in auto-mode (data-mode) */
+                    dev->aux_cfg.manual_enable = BMI160_DISABLE;
+                    rslt = bmi160_config_aux_mode(dev);
+
+                    /*  Auxiliary sensor data is obtained
+                     * in auto mode from this point */
+                }
+            }
+        }
+        else
+        {
+            rslt = BMI160_E_INVALID_INPUT;
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configures the 0x4C register and settings like
+ * Auxiliary sensor manual enable/ disable and aux burst read length.
+ */
+int8_t bmi160_config_aux_mode(const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t aux_if[2] = { (uint8_t)(dev->aux_cfg.aux_i2c_addr * 2), 0 };
+
+    rslt = bmi160_get_regs(BMI160_AUX_IF_1_ADDR, &aux_if[1], 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* update the Auxiliary interface to manual/auto mode */
+        aux_if[1] = BMI160_SET_BITS(aux_if[1], BMI160_MANUAL_MODE_EN, dev->aux_cfg.manual_enable);
+
+        /* update the burst read length defined by user */
+        aux_if[1] = BMI160_SET_BITS_POS_0(aux_if[1], BMI160_AUX_READ_BURST, dev->aux_cfg.aux_rd_burst_len);
+
+        /* Set the secondary interface address and manual mode
+         * along with burst read length */
+        rslt = bmi160_set_regs(BMI160_AUX_IF_0_ADDR, &aux_if[0], 2, dev);
+        dev->delay_ms(BMI160_AUX_COM_DELAY);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API is used to read the raw uncompensated auxiliary sensor
+ * data of 8 bytes from BMI160 register address 0x04 to 0x0B
+ */
+int8_t bmi160_read_aux_data_auto_mode(uint8_t *aux_data, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if (rslt != BMI160_OK)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        if ((dev->aux_cfg.aux_sensor_enable == BMI160_ENABLE) && (dev->aux_cfg.manual_enable == BMI160_DISABLE))
+        {
+            /* Read the aux. sensor's raw data */
+            rslt = bmi160_get_regs(BMI160_AUX_DATA_ADDR, aux_data, 8, dev);
+        }
+        else
+        {
+            rslt = BMI160_E_INVALID_INPUT;
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This is used to perform self test of accel/gyro of the BMI160 sensor
+ */
+int8_t bmi160_perform_self_test(uint8_t select_sensor, struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    int8_t self_test_rslt = 0;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if (rslt != BMI160_OK)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+
+        /* Proceed if null check is fine */
+        switch (select_sensor)
+        {
+            case BMI160_ACCEL_ONLY:
+                rslt = perform_accel_self_test(dev);
+                break;
+            case BMI160_GYRO_ONLY:
+
+                /* Set the power mode as normal mode */
+                dev->gyro_cfg.power = BMI160_GYRO_NORMAL_MODE;
+                rslt = bmi160_set_power_mode(dev);
+
+                /* Perform gyro self test */
+                if (rslt == BMI160_OK)
+                {
+                    /* Perform gyro self test */
+                    rslt = perform_gyro_self_test(dev);
+                }
+
+                break;
+            default:
+                rslt = BMI160_E_INVALID_INPUT;
+                break;
+        }
+
+        /* Check to ensure bus error does not occur */
+        if (rslt >= BMI160_OK)
+        {
+            /* Store the status of self test result */
+            self_test_rslt = rslt;
+
+            /* Perform soft reset */
+            rslt = bmi160_soft_reset(dev);
+
+        }
+
+        /* Check to ensure bus operations are success */
+        if (rslt == BMI160_OK)
+        {
+            /* Restore self_test_rslt as return value */
+            rslt = self_test_rslt;
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API reads the data from fifo buffer.
+ */
+int8_t bmi160_get_fifo_data(struct bmi160_dev const *dev)
+{
+    int8_t rslt = 0;
+    uint16_t bytes_to_read = 0;
+    uint16_t user_fifo_len = 0;
+
+    /* check the bmi160 structure as NULL*/
+    if ((dev == NULL) || (dev->fifo->data == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        reset_fifo_data_structure(dev);
+
+        /* get current FIFO fill-level*/
+        rslt = get_fifo_byte_counter(&bytes_to_read, dev);
+        if (rslt == BMI160_OK)
+        {
+            user_fifo_len = dev->fifo->length;
+            if ((dev->fifo->length > bytes_to_read))
+            {
+                /* Handling the case where user requests
+                 * more data than available in FIFO */
+                dev->fifo->length = bytes_to_read;
+            }
+
+            if ((dev->fifo->fifo_time_enable == BMI160_FIFO_TIME_ENABLE) &&
+                (bytes_to_read + BMI160_FIFO_BYTES_OVERREAD <= user_fifo_len))
+            {
+                /* Handling case of sensor time availability*/
+                dev->fifo->length = dev->fifo->length + BMI160_FIFO_BYTES_OVERREAD;
+            }
+
+            /* read only the filled bytes in the FIFO Buffer */
+            rslt = bmi160_get_regs(BMI160_FIFO_DATA_ADDR, dev->fifo->data, dev->fifo->length, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API writes fifo_flush command to command register.This
+ *  action clears all data in the Fifo without changing fifo configuration
+ *  settings
+ */
+int8_t bmi160_set_fifo_flush(const struct bmi160_dev *dev)
+{
+    int8_t rslt = 0;
+    uint8_t data = BMI160_FIFO_FLUSH_VALUE;
+    uint8_t reg_addr = BMI160_COMMAND_REG_ADDR;
+
+    /* Check the bmi160_dev structure for NULL address*/
+    if (dev == NULL)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        rslt = bmi160_set_regs(reg_addr, &data, BMI160_ONE, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets the FIFO configuration in the sensor.
+ */
+int8_t bmi160_set_fifo_config(uint8_t config, uint8_t enable, struct bmi160_dev const *dev)
+{
+    int8_t rslt = 0;
+    uint8_t data = 0;
+    uint8_t reg_addr = BMI160_FIFO_CONFIG_1_ADDR;
+    uint8_t fifo_config = config & BMI160_FIFO_CONFIG_1_MASK;
+
+    /* Check the bmi160_dev structure for NULL address*/
+    if (dev == NULL)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        rslt = bmi160_get_regs(reg_addr, &data, BMI160_ONE, dev);
+        if (rslt == BMI160_OK)
+        {
+            if (fifo_config > 0)
+            {
+                if (enable == BMI160_ENABLE)
+                {
+                    data = data | fifo_config;
+                }
+                else
+                {
+                    data = data & (~fifo_config);
+                }
+            }
+
+            /* write fifo frame content configuration*/
+            rslt = bmi160_set_regs(reg_addr, &data, BMI160_ONE, dev);
+            if (rslt == BMI160_OK)
+            {
+                /* read fifo frame content configuration*/
+                rslt = bmi160_get_regs(reg_addr, &data, BMI160_ONE, dev);
+                if (rslt == BMI160_OK)
+                {
+                    /* extract fifo header enabled status */
+                    dev->fifo->fifo_header_enable = data & BMI160_FIFO_HEAD_ENABLE;
+
+                    /* extract accel/gyr/aux. data enabled status */
+                    dev->fifo->fifo_data_enable = data & BMI160_FIFO_M_G_A_ENABLE;
+
+                    /* extract fifo sensor time enabled status */
+                    dev->fifo->fifo_time_enable = data & BMI160_FIFO_TIME_ENABLE;
+                }
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*! @brief This API is used to configure the down sampling ratios of
+ *  the accel and gyro data for FIFO.Also, it configures filtered or
+ *  pre-filtered data for accel and gyro.
+ *
+ */
+int8_t bmi160_set_fifo_down(uint8_t fifo_down, const struct bmi160_dev *dev)
+{
+    int8_t rslt = 0;
+    uint8_t data = 0;
+    uint8_t reg_addr = BMI160_FIFO_DOWN_ADDR;
+
+    /* Check the bmi160_dev structure for NULL address*/
+    if (dev == NULL)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        rslt = bmi160_get_regs(reg_addr, &data, BMI160_ONE, dev);
+        if (rslt == BMI160_OK)
+        {
+            data = data | fifo_down;
+            rslt = bmi160_set_regs(reg_addr, &data, BMI160_ONE, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API sets the FIFO watermark level in the sensor.
+ *
+ */
+int8_t bmi160_set_fifo_wm(uint8_t fifo_wm, const struct bmi160_dev *dev)
+{
+    int8_t rslt = 0;
+    uint8_t data = fifo_wm;
+    uint8_t reg_addr = BMI160_FIFO_CONFIG_0_ADDR;
+
+    /* Check the bmi160_dev structure for NULL address*/
+    if (dev == NULL)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        rslt = bmi160_set_regs(reg_addr, &data, BMI160_ONE, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API parses and extracts the accelerometer frames from
+ *  FIFO data read by the "bmi160_get_fifo_data" API and stores it in
+ *  the "accel_data" structure instance.
+ */
+int8_t bmi160_extract_accel(struct bmi160_sensor_data *accel_data, uint8_t *accel_length, struct bmi160_dev const *dev)
+{
+    int8_t rslt = 0;
+    uint16_t data_index = 0;
+    uint16_t data_read_length = 0;
+    uint8_t accel_index = 0;
+    uint8_t fifo_data_enable = 0;
+
+    if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* Parsing the FIFO data in header-less mode */
+        if (dev->fifo->fifo_header_enable == 0)
+        {
+            /* Number of bytes to be parsed from FIFO */
+            get_accel_len_to_parse(&data_index, &data_read_length, accel_length, dev);
+            for (; data_index < data_read_length;)
+            {
+                /*Check for the availability of next two bytes of FIFO data */
+                check_frame_validity(&data_index, dev);
+                fifo_data_enable = dev->fifo->fifo_data_enable;
+                unpack_accel_frame(accel_data, &data_index, &accel_index, fifo_data_enable, dev);
+            }
+
+            /* update number of accel data read*/
+            *accel_length = accel_index;
+
+            /*update the accel byte index*/
+            dev->fifo->accel_byte_start_idx = data_index;
+        }
+        else
+        {
+            /* Parsing the FIFO data in header mode */
+            extract_accel_header_mode(accel_data, accel_length, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API parses and extracts the gyro frames from
+ *  FIFO data read by the "bmi160_get_fifo_data" API and stores it in
+ *  the "gyro_data" structure instance.
+ */
+int8_t bmi160_extract_gyro(struct bmi160_sensor_data *gyro_data, uint8_t *gyro_length, struct bmi160_dev const *dev)
+{
+    int8_t rslt = 0;
+    uint16_t data_index = 0;
+    uint16_t data_read_length = 0;
+    uint8_t gyro_index = 0;
+    uint8_t fifo_data_enable = 0;
+
+    if (dev == NULL || dev->fifo->data == NULL)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* Parsing the FIFO data in header-less mode */
+        if (dev->fifo->fifo_header_enable == 0)
+        {
+            /* Number of bytes to be parsed from FIFO */
+            get_gyro_len_to_parse(&data_index, &data_read_length, gyro_length, dev);
+            for (; data_index < data_read_length;)
+            {
+                /*Check for the availability of next two bytes of FIFO data */
+                check_frame_validity(&data_index, dev);
+                fifo_data_enable = dev->fifo->fifo_data_enable;
+                unpack_gyro_frame(gyro_data, &data_index, &gyro_index, fifo_data_enable, dev);
+            }
+
+            /* update number of gyro data read */
+            *gyro_length = gyro_index;
+
+            /* update the gyro byte index */
+            dev->fifo->gyro_byte_start_idx = data_index;
+        }
+        else
+        {
+            /* Parsing the FIFO data in header mode */
+            extract_gyro_header_mode(gyro_data, gyro_length, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API parses and extracts the aux frames from
+ *  FIFO data read by the "bmi160_get_fifo_data" API and stores it in
+ *  the "aux_data" structure instance.
+ */
+int8_t bmi160_extract_aux(struct bmi160_aux_data *aux_data, uint8_t *aux_len, struct bmi160_dev const *dev)
+{
+    int8_t rslt = 0;
+    uint16_t data_index = 0;
+    uint16_t data_read_length = 0;
+    uint8_t aux_index = 0;
+    uint8_t fifo_data_enable = 0;
+
+    if ((dev == NULL) || (dev->fifo->data == NULL) || (aux_data == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* Parsing the FIFO data in header-less mode */
+        if (dev->fifo->fifo_header_enable == 0)
+        {
+            /* Number of bytes to be parsed from FIFO */
+            get_aux_len_to_parse(&data_index, &data_read_length, aux_len, dev);
+            for (; data_index < data_read_length;)
+            {
+                /* Check for the availability of next two
+                 * bytes of FIFO data */
+                check_frame_validity(&data_index, dev);
+                fifo_data_enable = dev->fifo->fifo_data_enable;
+                unpack_aux_frame(aux_data, &data_index, &aux_index, fifo_data_enable, dev);
+            }
+
+            /* update number of aux data read */
+            *aux_len = aux_index;
+
+            /* update the aux byte index */
+            dev->fifo->aux_byte_start_idx = data_index;
+        }
+        else
+        {
+            /* Parsing the FIFO data in header mode */
+            extract_aux_header_mode(aux_data, aux_len, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API starts the FOC of accel and gyro
+ *
+ *  @note FOC should not be used in low-power mode of sensor
+ *
+ *  @note Accel FOC targets values of +1g , 0g , -1g
+ *  Gyro FOC always targets value of 0 dps
+ */
+int8_t bmi160_start_foc(const struct bmi160_foc_conf *foc_conf,
+                        struct bmi160_offsets *offset,
+                        struct bmi160_dev const *dev)
+{
+    int8_t rslt;
+    uint8_t data;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if (rslt != BMI160_OK)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* Set the offset enable bits */
+        rslt = configure_offset_enable(foc_conf, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Read the FOC config from the sensor */
+            rslt = bmi160_get_regs(BMI160_FOC_CONF_ADDR, &data, 1, dev);
+
+            /* Set the FOC config for gyro */
+            data = BMI160_SET_BITS(data, BMI160_GYRO_FOC_EN, foc_conf->foc_gyr_en);
+
+            /* Set the FOC config for accel xyz axes */
+            data = BMI160_SET_BITS(data, BMI160_ACCEL_FOC_X_CONF, foc_conf->foc_acc_x);
+            data = BMI160_SET_BITS(data, BMI160_ACCEL_FOC_Y_CONF, foc_conf->foc_acc_y);
+            data = BMI160_SET_BITS_POS_0(data, BMI160_ACCEL_FOC_Z_CONF, foc_conf->foc_acc_z);
+            if (rslt == BMI160_OK)
+            {
+                /* Set the FOC config in the sensor */
+                rslt = bmi160_set_regs(BMI160_FOC_CONF_ADDR, &data, 1, dev);
+                if (rslt == BMI160_OK)
+                {
+                    /* Procedure to trigger
+                     * FOC and check status */
+                    rslt = trigger_foc(offset, dev);
+                }
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API reads and stores the offset values of accel and gyro
+ */
+int8_t bmi160_get_offsets(struct bmi160_offsets *offset, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data[7];
+    uint8_t lsb, msb;
+    int16_t offset_msb, offset_lsb;
+    int16_t offset_data;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if (rslt != BMI160_OK)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* Read the FOC config from the sensor */
+        rslt = bmi160_get_regs(BMI160_OFFSET_ADDR, data, 7, dev);
+
+        /* Accel offsets */
+        offset->off_acc_x = (int8_t)data[0];
+        offset->off_acc_y = (int8_t)data[1];
+        offset->off_acc_z = (int8_t)data[2];
+
+        /* Gyro x-axis offset */
+        lsb = data[3];
+        msb = BMI160_GET_BITS_POS_0(data[6], BMI160_GYRO_OFFSET_X);
+        offset_msb = (int16_t)(msb << 14);
+        offset_lsb = lsb << 6;
+        offset_data = offset_msb | offset_lsb;
+
+        /* Divide by 64 to get the Right shift by 6 value */
+        offset->off_gyro_x = (int16_t)(offset_data / 64);
+
+        /* Gyro y-axis offset */
+        lsb = data[4];
+        msb = BMI160_GET_BITS(data[6], BMI160_GYRO_OFFSET_Y);
+        offset_msb = (int16_t)(msb << 14);
+        offset_lsb = lsb << 6;
+        offset_data = offset_msb | offset_lsb;
+
+        /* Divide by 64 to get the Right shift by 6 value */
+        offset->off_gyro_y = (int16_t)(offset_data / 64);
+
+        /* Gyro z-axis offset */
+        lsb = data[5];
+        msb = BMI160_GET_BITS(data[6], BMI160_GYRO_OFFSET_Z);
+        offset_msb = (int16_t)(msb << 14);
+        offset_lsb = lsb << 6;
+        offset_data = offset_msb | offset_lsb;
+
+        /* Divide by 64 to get the Right shift by 6 value */
+        offset->off_gyro_z = (int16_t)(offset_data / 64);
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API writes the offset values of accel and gyro to
+ *  the sensor but these values will be reset on POR or soft reset.
+ */
+int8_t bmi160_set_offsets(const struct bmi160_foc_conf *foc_conf,
+                          const struct bmi160_offsets *offset,
+                          struct bmi160_dev const *dev)
+{
+    int8_t rslt;
+    uint8_t data[7];
+    uint8_t x_msb, y_msb, z_msb;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if (rslt != BMI160_OK)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* Update the accel offset */
+        data[0] = (uint8_t)offset->off_acc_x;
+        data[1] = (uint8_t)offset->off_acc_y;
+        data[2] = (uint8_t)offset->off_acc_z;
+
+        /* Update the LSB of gyro offset */
+        data[3] = BMI160_GET_LSB(offset->off_gyro_x);
+        data[4] = BMI160_GET_LSB(offset->off_gyro_y);
+        data[5] = BMI160_GET_LSB(offset->off_gyro_z);
+
+        /* Update the MSB of gyro offset */
+        x_msb = BMI160_GET_BITS(offset->off_gyro_x, BMI160_GYRO_OFFSET);
+        y_msb = BMI160_GET_BITS(offset->off_gyro_y, BMI160_GYRO_OFFSET);
+        z_msb = BMI160_GET_BITS(offset->off_gyro_z, BMI160_GYRO_OFFSET);
+        data[6] = (uint8_t)(z_msb << 4 | y_msb << 2 | x_msb);
+
+        /* Set the offset enable/disable for gyro and accel */
+        data[6] = BMI160_SET_BITS(data[6], BMI160_GYRO_OFFSET_EN, foc_conf->gyro_off_en);
+        data[6] = BMI160_SET_BITS(data[6], BMI160_ACCEL_OFFSET_EN, foc_conf->acc_off_en);
+
+        /* Set the offset config and values in the sensor */
+        rslt = bmi160_set_regs(BMI160_OFFSET_ADDR, data, 7, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API writes the image registers values to NVM which is
+ *  stored even after POR or soft reset
+ */
+int8_t bmi160_update_nvm(struct bmi160_dev const *dev)
+{
+    int8_t rslt;
+    uint8_t data;
+    uint8_t cmd = BMI160_NVM_BACKUP_EN;
+
+    /* Read the nvm_prog_en configuration */
+    rslt = bmi160_get_regs(BMI160_CONF_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        data = BMI160_SET_BITS(data, BMI160_NVM_UPDATE, 1);
+
+        /* Set the nvm_prog_en bit in the sensor */
+        rslt = bmi160_set_regs(BMI160_CONF_ADDR, &data, 1, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Update NVM */
+            rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &cmd, 1, dev);
+            if (rslt == BMI160_OK)
+            {
+                /* Check for NVM ready status */
+                rslt = bmi160_get_regs(BMI160_STATUS_ADDR, &data, 1, dev);
+                if (rslt == BMI160_OK)
+                {
+                    data = BMI160_GET_BITS(data, BMI160_NVM_STATUS);
+                    if (data != BMI160_ENABLE)
+                    {
+                        /* Delay to update NVM */
+                        dev->delay_ms(25);
+                    }
+                }
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API gets the interrupt status from the sensor.
+ */
+int8_t bmi160_get_int_status(enum bmi160_int_status_sel int_status_sel,
+                             union bmi160_int_status *int_status,
+                             struct bmi160_dev const *dev)
+{
+    int8_t rslt = 0;
+
+    /* To get the status of all interrupts */
+    if (int_status_sel == BMI160_INT_STATUS_ALL)
+    {
+        rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR, &int_status->data[0], 4, dev);
+    }
+    else
+    {
+        if (int_status_sel & BMI160_INT_STATUS_0)
+        {
+            rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR, &int_status->data[0], 1, dev);
+        }
+
+        if (int_status_sel & BMI160_INT_STATUS_1)
+        {
+            rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR + 1, &int_status->data[1], 1, dev);
+        }
+
+        if (int_status_sel & BMI160_INT_STATUS_2)
+        {
+            rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR + 2, &int_status->data[2], 1, dev);
+        }
+
+        if (int_status_sel & BMI160_INT_STATUS_3)
+        {
+            rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR + 3, &int_status->data[3], 1, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*********************** Local function definitions ***************************/
+
+/*!
+ * @brief This API sets the any-motion interrupt of the sensor.
+ * This interrupt occurs when accel values exceeds preset threshold
+ * for a certain period of time.
+ */
+static int8_t set_accel_any_motion_int(struct bmi160_int_settg *int_config, struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if ((rslt != BMI160_OK) || (int_config == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* updating the interrupt structure to local structure */
+        struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg = &(int_config->int_type_cfg.acc_any_motion_int);
+        rslt = enable_accel_any_motion_int(any_motion_int_cfg, dev);
+        if (rslt == BMI160_OK)
+        {
+            rslt = config_any_motion_int_settg(int_config, any_motion_int_cfg, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets tap interrupts.Interrupt is fired when
+ * tap movements happen.
+ */
+static int8_t set_accel_tap_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if ((rslt != BMI160_OK) || (int_config == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* updating the interrupt structure to local structure */
+        struct bmi160_acc_tap_int_cfg *tap_int_cfg = &(int_config->int_type_cfg.acc_tap_int);
+        rslt = enable_tap_int(int_config, tap_int_cfg, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Configure Interrupt pins */
+            rslt = set_intr_pin_config(int_config, dev);
+            if (rslt == BMI160_OK)
+            {
+                rslt = config_tap_int_settg(int_config, tap_int_cfg, dev);
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets the data ready interrupt for both accel and gyro.
+ * This interrupt occurs when new accel and gyro data comes.
+ */
+static int8_t set_accel_gyro_data_ready_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if ((rslt != BMI160_OK) || (int_config == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        rslt = enable_data_ready_int(dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Configure Interrupt pins */
+            rslt = set_intr_pin_config(int_config, dev);
+            if (rslt == BMI160_OK)
+            {
+                rslt = map_hardware_interrupt(int_config, dev);
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets the significant motion interrupt of the sensor.This
+ * interrupt occurs when there is change in user location.
+ */
+static int8_t set_accel_sig_motion_int(struct bmi160_int_settg *int_config, struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if ((rslt != BMI160_OK) || (int_config == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* updating the interrupt structure to local structure */
+        struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg = &(int_config->int_type_cfg.acc_sig_motion_int);
+        rslt = enable_sig_motion_int(sig_mot_int_cfg, dev);
+        if (rslt == BMI160_OK)
+        {
+            rslt = config_sig_motion_int_settg(int_config, sig_mot_int_cfg, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets the no motion/slow motion interrupt of the sensor.
+ * Slow motion is similar to any motion interrupt.No motion interrupt
+ * occurs when slope bet. two accel values falls below preset threshold
+ * for preset duration.
+ */
+static int8_t set_accel_no_motion_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if ((rslt != BMI160_OK) || (int_config == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* updating the interrupt structure to local structure */
+        struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg = &(int_config->int_type_cfg.acc_no_motion_int);
+        rslt = enable_no_motion_int(no_mot_int_cfg, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Configure the INT PIN settings*/
+            rslt = config_no_motion_int_settg(int_config, no_mot_int_cfg, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets the step detection interrupt.This interrupt
+ * occurs when the single step causes accel values to go above
+ * preset threshold.
+ */
+static int8_t set_accel_step_detect_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if ((rslt != BMI160_OK) || (int_config == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* updating the interrupt structure to local structure */
+        struct bmi160_acc_step_detect_int_cfg *step_detect_int_cfg = &(int_config->int_type_cfg.acc_step_detect_int);
+        rslt = enable_step_detect_int(step_detect_int_cfg, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Configure Interrupt pins */
+            rslt = set_intr_pin_config(int_config, dev);
+            if (rslt == BMI160_OK)
+            {
+                rslt = map_feature_interrupt(int_config, dev);
+                if (rslt == BMI160_OK)
+                {
+                    rslt = config_step_detect(step_detect_int_cfg, dev);
+                }
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets the orientation interrupt of the sensor.This
+ * interrupt occurs when there is orientation change in the sensor
+ * with respect to gravitational field vector g.
+ */
+static int8_t set_accel_orientation_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if ((rslt != BMI160_OK) || (int_config == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* updating the interrupt structure to local structure */
+        struct bmi160_acc_orient_int_cfg *orient_int_cfg = &(int_config->int_type_cfg.acc_orient_int);
+        rslt = enable_orient_int(orient_int_cfg, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Configure Interrupt pins */
+            rslt = set_intr_pin_config(int_config, dev);
+            if (rslt == BMI160_OK)
+            {
+                /* map INT pin to orient interrupt */
+                rslt = map_feature_interrupt(int_config, dev);
+                if (rslt == BMI160_OK)
+                {
+                    /* configure the
+                     * orientation setting*/
+                    rslt = config_orient_int_settg(orient_int_cfg, dev);
+                }
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets the flat interrupt of the sensor.This interrupt
+ * occurs in case of flat orientation
+ */
+static int8_t set_accel_flat_detect_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if ((rslt != BMI160_OK) || (int_config == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* updating the interrupt structure to local structure */
+        struct bmi160_acc_flat_detect_int_cfg *flat_detect_int = &(int_config->int_type_cfg.acc_flat_int);
+
+        /* enable the flat interrupt */
+        rslt = enable_flat_int(flat_detect_int, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Configure Interrupt pins */
+            rslt = set_intr_pin_config(int_config, dev);
+            if (rslt == BMI160_OK)
+            {
+                /* map INT pin to flat interrupt */
+                rslt = map_feature_interrupt(int_config, dev);
+                if (rslt == BMI160_OK)
+                {
+                    /* configure the flat setting*/
+                    rslt = config_flat_int_settg(flat_detect_int, dev);
+                }
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets the low-g interrupt of the sensor.This interrupt
+ * occurs during free-fall.
+ */
+static int8_t set_accel_low_g_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if ((rslt != BMI160_OK) || (int_config == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* updating the interrupt structure to local structure */
+        struct bmi160_acc_low_g_int_cfg *low_g_int = &(int_config->int_type_cfg.acc_low_g_int);
+
+        /* Enable the low-g interrupt*/
+        rslt = enable_low_g_int(low_g_int, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Configure Interrupt pins */
+            rslt = set_intr_pin_config(int_config, dev);
+            if (rslt == BMI160_OK)
+            {
+                /* Map INT pin to low-g interrupt */
+                rslt = map_feature_interrupt(int_config, dev);
+                if (rslt == BMI160_OK)
+                {
+                    /* configure the data source
+                     * for low-g interrupt*/
+                    rslt = config_low_g_data_src(low_g_int, dev);
+                    if (rslt == BMI160_OK)
+                    {
+                        rslt = config_low_g_int_settg(low_g_int, dev);
+                    }
+                }
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets the high-g interrupt of the sensor.The interrupt
+ * occurs if the absolute value of acceleration data of any enabled axis
+ * exceeds the programmed threshold and the sign of the value does not
+ * change for a preset duration.
+ */
+static int8_t set_accel_high_g_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if ((rslt != BMI160_OK) || (int_config == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* updating the interrupt structure to local structure */
+        struct bmi160_acc_high_g_int_cfg *high_g_int_cfg = &(int_config->int_type_cfg.acc_high_g_int);
+
+        /* Enable the high-g interrupt */
+        rslt = enable_high_g_int(high_g_int_cfg, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Configure Interrupt pins */
+            rslt = set_intr_pin_config(int_config, dev);
+            if (rslt == BMI160_OK)
+            {
+                /* Map INT pin to high-g interrupt */
+                rslt = map_feature_interrupt(int_config, dev);
+                if (rslt == BMI160_OK)
+                {
+                    /* configure the data source
+                     * for high-g interrupt*/
+                    rslt = config_high_g_data_src(high_g_int_cfg, dev);
+                    if (rslt == BMI160_OK)
+                    {
+                        rslt = config_high_g_int_settg(high_g_int_cfg, dev);
+                    }
+                }
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configures the pins to fire the
+ * interrupt signal when it occurs.
+ */
+static int8_t set_intr_pin_config(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* configure the behavioural settings of interrupt pin */
+    rslt = config_int_out_ctrl(int_config, dev);
+    if (rslt == BMI160_OK)
+    {
+        rslt = config_int_latch(int_config, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This internal API is used to validate the device structure pointer for
+ * null conditions.
+ */
+static int8_t null_ptr_check(const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* Device structure is fine */
+        rslt = BMI160_OK;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets the default configuration parameters of accel & gyro.
+ * Also maintain the previous state of configurations.
+ */
+static void default_param_settg(struct bmi160_dev *dev)
+{
+    /* Initializing accel and gyro params with
+     * default values */
+    dev->accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4;
+    dev->accel_cfg.odr = BMI160_ACCEL_ODR_100HZ;
+    dev->accel_cfg.power = BMI160_ACCEL_SUSPEND_MODE;
+    dev->accel_cfg.range = BMI160_ACCEL_RANGE_2G;
+    dev->gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE;
+    dev->gyro_cfg.odr = BMI160_GYRO_ODR_100HZ;
+    dev->gyro_cfg.power = BMI160_GYRO_SUSPEND_MODE;
+    dev->gyro_cfg.range = BMI160_GYRO_RANGE_2000_DPS;
+
+    /* To maintain the previous state of accel configuration */
+    dev->prev_accel_cfg = dev->accel_cfg;
+
+    /* To maintain the previous state of gyro configuration */
+    dev->prev_gyro_cfg = dev->gyro_cfg;
+}
+
+/*!
+ * @brief This API set the accel configuration.
+ */
+static int8_t set_accel_conf(struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data[2] = { 0 };
+
+    rslt = check_accel_config(data, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* Write output data rate and bandwidth */
+        rslt = bmi160_set_regs(BMI160_ACCEL_CONFIG_ADDR, &data[0], 1, dev);
+        if (rslt == BMI160_OK)
+        {
+            dev->prev_accel_cfg.odr = dev->accel_cfg.odr;
+            dev->prev_accel_cfg.bw = dev->accel_cfg.bw;
+
+            /* write accel range */
+            rslt = bmi160_set_regs(BMI160_ACCEL_RANGE_ADDR, &data[1], 1, dev);
+            if (rslt == BMI160_OK)
+            {
+                dev->prev_accel_cfg.range = dev->accel_cfg.range;
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API gets the accel configuration.
+ */
+static int8_t get_accel_conf(struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data[2] = { 0 };
+
+    /* Get accel configurations */
+    rslt = bmi160_get_regs(BMI160_ACCEL_CONFIG_ADDR, data, 2, dev);
+    if (rslt == BMI160_OK)
+    {
+        dev->accel_cfg.odr = (data[0] & BMI160_ACCEL_ODR_MASK);
+        dev->accel_cfg.bw = (data[0] & BMI160_ACCEL_BW_MASK) >> BMI160_ACCEL_BW_POS;
+        dev->accel_cfg.range = (data[1] & BMI160_ACCEL_RANGE_MASK);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API check the accel configuration.
+ */
+static int8_t check_accel_config(uint8_t *data, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* read accel Output data rate and bandwidth */
+    rslt = bmi160_get_regs(BMI160_ACCEL_CONFIG_ADDR, data, 2, dev);
+    if (rslt == BMI160_OK)
+    {
+        rslt = process_accel_odr(&data[0], dev);
+        if (rslt == BMI160_OK)
+        {
+            rslt = process_accel_bw(&data[0], dev);
+            if (rslt == BMI160_OK)
+            {
+                rslt = process_accel_range(&data[1], dev);
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API process the accel odr.
+ */
+static int8_t process_accel_odr(uint8_t *data, const struct bmi160_dev *dev)
+{
+    int8_t rslt = 0;
+    uint8_t temp = 0;
+    uint8_t odr = 0;
+
+    if (dev->accel_cfg.odr <= BMI160_ACCEL_ODR_1600HZ)
+    {
+        if (dev->accel_cfg.odr != dev->prev_accel_cfg.odr)
+        {
+            odr = (uint8_t)dev->accel_cfg.odr;
+            temp = *data & ~BMI160_ACCEL_ODR_MASK;
+
+            /* Adding output data rate */
+            *data = temp | (odr & BMI160_ACCEL_ODR_MASK);
+        }
+    }
+    else
+    {
+        rslt = BMI160_E_OUT_OF_RANGE;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API process the accel bandwidth.
+ */
+static int8_t process_accel_bw(uint8_t *data, const struct bmi160_dev *dev)
+{
+    int8_t rslt = 0;
+    uint8_t temp = 0;
+    uint8_t bw = 0;
+
+    if (dev->accel_cfg.bw <= BMI160_ACCEL_BW_RES_AVG128)
+    {
+        if (dev->accel_cfg.bw != dev->prev_accel_cfg.bw)
+        {
+            bw = (uint8_t)dev->accel_cfg.bw;
+            temp = *data & ~BMI160_ACCEL_BW_MASK;
+
+            /* Adding bandwidth */
+            *data = temp | ((bw << 4) & BMI160_ACCEL_BW_MASK);
+        }
+    }
+    else
+    {
+        rslt = BMI160_E_OUT_OF_RANGE;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API process the accel range.
+ */
+static int8_t process_accel_range(uint8_t *data, const struct bmi160_dev *dev)
+{
+    int8_t rslt = 0;
+    uint8_t temp = 0;
+    uint8_t range = 0;
+
+    if (dev->accel_cfg.range <= BMI160_ACCEL_RANGE_16G)
+    {
+        if (dev->accel_cfg.range != dev->prev_accel_cfg.range)
+        {
+            range = (uint8_t)dev->accel_cfg.range;
+            temp = *data & ~BMI160_ACCEL_RANGE_MASK;
+
+            /* Adding range */
+            *data = temp | (range & BMI160_ACCEL_RANGE_MASK);
+        }
+    }
+    else
+    {
+        rslt = BMI160_E_OUT_OF_RANGE;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API checks the invalid settings for ODR & Bw for
+ * Accel and Gyro.
+ */
+static int8_t check_invalid_settg(const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+
+    /* read the error reg */
+    rslt = bmi160_get_regs(BMI160_ERROR_REG_ADDR, &data, 1, dev);
+    data = data >> 1;
+    data = data & BMI160_ERR_REG_MASK;
+    if (data == 1)
+    {
+        rslt = BMI160_E_ACCEL_ODR_BW_INVALID;
+    }
+    else if (data == 2)
+    {
+        rslt = BMI160_E_GYRO_ODR_BW_INVALID;
+    }
+    else if (data == 3)
+    {
+        rslt = BMI160_E_LWP_PRE_FLTR_INT_INVALID;
+    }
+    else if (data == 7)
+    {
+        rslt = BMI160_E_LWP_PRE_FLTR_INVALID;
+    }
+
+    return rslt;
+}
+static int8_t set_gyro_conf(struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data[2] = { 0 };
+
+    rslt = check_gyro_config(data, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* Write output data rate and bandwidth */
+        rslt = bmi160_set_regs(BMI160_GYRO_CONFIG_ADDR, &data[0], 1, dev);
+        if (rslt == BMI160_OK)
+        {
+            dev->prev_gyro_cfg.odr = dev->gyro_cfg.odr;
+            dev->prev_gyro_cfg.bw = dev->gyro_cfg.bw;
+
+            /* Write gyro range */
+            rslt = bmi160_set_regs(BMI160_GYRO_RANGE_ADDR, &data[1], 1, dev);
+            if (rslt == BMI160_OK)
+            {
+                dev->prev_gyro_cfg.range = dev->gyro_cfg.range;
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API gets the gyro configuration.
+ */
+static int8_t get_gyro_conf(struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data[2] = { 0 };
+
+    /* Get accel configurations */
+    rslt = bmi160_get_regs(BMI160_GYRO_CONFIG_ADDR, data, 2, dev);
+    if (rslt == BMI160_OK)
+    {
+        dev->gyro_cfg.odr = (data[0] & BMI160_GYRO_ODR_MASK);
+        dev->gyro_cfg.bw = (data[0] & BMI160_GYRO_BW_MASK) >> BMI160_GYRO_BW_POS;
+        dev->gyro_cfg.range = (data[1] & BMI160_GYRO_RANGE_MASK);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API check the gyro configuration.
+ */
+static int8_t check_gyro_config(uint8_t *data, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* read gyro Output data rate and bandwidth */
+    rslt = bmi160_get_regs(BMI160_GYRO_CONFIG_ADDR, data, 2, dev);
+    if (rslt == BMI160_OK)
+    {
+        rslt = process_gyro_odr(&data[0], dev);
+        if (rslt == BMI160_OK)
+        {
+            rslt = process_gyro_bw(&data[0], dev);
+            if (rslt == BMI160_OK)
+            {
+                rslt = process_gyro_range(&data[1], dev);
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API process the gyro odr.
+ */
+static int8_t process_gyro_odr(uint8_t *data, const struct bmi160_dev *dev)
+{
+    int8_t rslt = 0;
+    uint8_t temp = 0;
+    uint8_t odr = 0;
+
+    if (dev->gyro_cfg.odr <= BMI160_GYRO_ODR_3200HZ)
+    {
+        if (dev->gyro_cfg.odr != dev->prev_gyro_cfg.odr)
+        {
+            odr = (uint8_t)dev->gyro_cfg.odr;
+            temp = (*data & ~BMI160_GYRO_ODR_MASK);
+
+            /* Adding output data rate */
+            *data = temp | (odr & BMI160_GYRO_ODR_MASK);
+        }
+    }
+    else
+    {
+        rslt = BMI160_E_OUT_OF_RANGE;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API process the gyro bandwidth.
+ */
+static int8_t process_gyro_bw(uint8_t *data, const struct bmi160_dev *dev)
+{
+    int8_t rslt = 0;
+    uint8_t temp = 0;
+    uint8_t bw = 0;
+
+    if (dev->gyro_cfg.bw <= BMI160_GYRO_BW_NORMAL_MODE)
+    {
+        bw = (uint8_t)dev->gyro_cfg.bw;
+        temp = *data & ~BMI160_GYRO_BW_MASK;
+
+        /* Adding bandwidth */
+        *data = temp | ((bw << 4) & BMI160_GYRO_BW_MASK);
+    }
+    else
+    {
+        rslt = BMI160_E_OUT_OF_RANGE;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API process the gyro range.
+ */
+static int8_t process_gyro_range(uint8_t *data, const struct bmi160_dev *dev)
+{
+    int8_t rslt = 0;
+    uint8_t temp = 0;
+    uint8_t range = 0;
+
+    if (dev->gyro_cfg.range <= BMI160_GYRO_RANGE_125_DPS)
+    {
+        if (dev->gyro_cfg.range != dev->prev_gyro_cfg.range)
+        {
+            range = (uint8_t)dev->gyro_cfg.range;
+            temp = *data & ~BMI160_GYRO_RANGE_MASK;
+
+            /* Adding range */
+            *data = temp | (range & BMI160_GYRO_RANGE_MASK);
+        }
+    }
+    else
+    {
+        rslt = BMI160_E_OUT_OF_RANGE;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets the accel power.
+ */
+static int8_t set_accel_pwr(struct bmi160_dev *dev)
+{
+    int8_t rslt = 0;
+    uint8_t data = 0;
+
+    if ((dev->accel_cfg.power >= BMI160_ACCEL_SUSPEND_MODE) && (dev->accel_cfg.power <= BMI160_ACCEL_LOWPOWER_MODE))
+    {
+        if (dev->accel_cfg.power != dev->prev_accel_cfg.power)
+        {
+            rslt = process_under_sampling(&data, dev);
+            if (rslt == BMI160_OK)
+            {
+                /* Write accel power */
+                rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &dev->accel_cfg.power, 1, dev);
+
+                /* Add delay of 3.8 ms - refer data sheet table 24*/
+                if (dev->prev_accel_cfg.power == BMI160_ACCEL_SUSPEND_MODE)
+                {
+                    dev->delay_ms(BMI160_ACCEL_DELAY_MS);
+                }
+
+                dev->prev_accel_cfg.power = dev->accel_cfg.power;
+            }
+        }
+    }
+    else
+    {
+        rslt = BMI160_E_INVALID_CONFIG;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API process the undersampling setting of Accel.
+ */
+static int8_t process_under_sampling(uint8_t *data, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t temp = 0;
+    uint8_t pre_filter[2] = { 0 };
+
+    rslt = bmi160_get_regs(BMI160_ACCEL_CONFIG_ADDR, data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        if (dev->accel_cfg.power == BMI160_ACCEL_LOWPOWER_MODE)
+        {
+            temp = *data & ~BMI160_ACCEL_UNDERSAMPLING_MASK;
+
+            /* Set under-sampling parameter */
+            *data = temp | ((1 << 7) & BMI160_ACCEL_UNDERSAMPLING_MASK);
+
+            /* Write data */
+            rslt = bmi160_set_regs(BMI160_ACCEL_CONFIG_ADDR, data, 1, dev);
+
+            /* Disable the pre-filter data in low power mode */
+            if (rslt == BMI160_OK)
+            {
+                /* Disable the Pre-filter data*/
+                rslt = bmi160_set_regs(BMI160_INT_DATA_0_ADDR, pre_filter, 2, dev);
+            }
+        }
+        else if (*data & BMI160_ACCEL_UNDERSAMPLING_MASK)
+        {
+            temp = *data & ~BMI160_ACCEL_UNDERSAMPLING_MASK;
+
+            /* Disable under-sampling parameter if already enabled */
+            *data = temp;
+
+            /* Write data */
+            rslt = bmi160_set_regs(BMI160_ACCEL_CONFIG_ADDR, data, 1, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API sets the gyro power mode.
+ */
+static int8_t set_gyro_pwr(struct bmi160_dev *dev)
+{
+    int8_t rslt = 0;
+
+    if ((dev->gyro_cfg.power == BMI160_GYRO_SUSPEND_MODE) || (dev->gyro_cfg.power == BMI160_GYRO_NORMAL_MODE) ||
+        (dev->gyro_cfg.power == BMI160_GYRO_FASTSTARTUP_MODE))
+    {
+        if (dev->gyro_cfg.power != dev->prev_gyro_cfg.power)
+        {
+            /* Write gyro power */
+            rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &dev->gyro_cfg.power, 1, dev);
+            if (dev->prev_gyro_cfg.power == BMI160_GYRO_SUSPEND_MODE)
+            {
+                /* Delay of 80 ms - datasheet Table 24 */
+                dev->delay_ms(BMI160_GYRO_DELAY_MS);
+            }
+            else if ((dev->prev_gyro_cfg.power == BMI160_GYRO_FASTSTARTUP_MODE) &&
+                     (dev->gyro_cfg.power == BMI160_GYRO_NORMAL_MODE))
+            {
+                /* This delay is required for transition from
+                 * fast-startup mode to normal mode - datasheet Table 3 */
+                dev->delay_ms(10);
+            }
+            else
+            {
+                /* do nothing */
+            }
+
+            dev->prev_gyro_cfg.power = dev->gyro_cfg.power;
+        }
+    }
+    else
+    {
+        rslt = BMI160_E_INVALID_CONFIG;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API reads accel data along with sensor time if time is requested
+ * by user. Kindly refer the user guide(README.md) for more info.
+ */
+static int8_t get_accel_data(uint8_t len, struct bmi160_sensor_data *accel, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t idx = 0;
+    uint8_t data_array[9] = { 0 };
+    uint8_t time_0 = 0;
+    uint16_t time_1 = 0;
+    uint32_t time_2 = 0;
+    uint8_t lsb;
+    uint8_t msb;
+    int16_t msblsb;
+
+    /* read accel sensor data along with time if requested */
+    rslt = bmi160_get_regs(BMI160_ACCEL_DATA_ADDR, data_array, 6 + len, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* Accel Data */
+        lsb = data_array[idx++];
+        msb = data_array[idx++];
+        msblsb = (int16_t)((msb << 8) | lsb);
+        accel->x = msblsb; /* Data in X axis */
+        lsb = data_array[idx++];
+        msb = data_array[idx++];
+        msblsb = (int16_t)((msb << 8) | lsb);
+        accel->y = msblsb; /* Data in Y axis */
+        lsb = data_array[idx++];
+        msb = data_array[idx++];
+        msblsb = (int16_t)((msb << 8) | lsb);
+        accel->z = msblsb; /* Data in Z axis */
+        if (len == 3)
+        {
+            time_0 = data_array[idx++];
+            time_1 = (uint16_t)(data_array[idx++] << 8);
+            time_2 = (uint32_t)(data_array[idx++] << 16);
+            accel->sensortime = (uint32_t)(time_2 | time_1 | time_0);
+        }
+        else
+        {
+            accel->sensortime = 0;
+        }
+    }
+    else
+    {
+        rslt = BMI160_E_COM_FAIL;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API reads accel data along with sensor time if time is requested
+ * by user. Kindly refer the user guide(README.md) for more info.
+ */
+static int8_t get_gyro_data(uint8_t len, struct bmi160_sensor_data *gyro, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t idx = 0;
+    uint8_t data_array[15] = { 0 };
+    uint8_t time_0 = 0;
+    uint16_t time_1 = 0;
+    uint32_t time_2 = 0;
+    uint8_t lsb;
+    uint8_t msb;
+    int16_t msblsb;
+
+    if (len == 0)
+    {
+        /* read gyro data only */
+        rslt = bmi160_get_regs(BMI160_GYRO_DATA_ADDR, data_array, 6, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Gyro Data */
+            lsb = data_array[idx++];
+            msb = data_array[idx++];
+            msblsb = (int16_t)((msb << 8) | lsb);
+            gyro->x = msblsb; /* Data in X axis */
+            lsb = data_array[idx++];
+            msb = data_array[idx++];
+            msblsb = (int16_t)((msb << 8) | lsb);
+            gyro->y = msblsb; /* Data in Y axis */
+            lsb = data_array[idx++];
+            msb = data_array[idx++];
+            msblsb = (int16_t)((msb << 8) | lsb);
+            gyro->z = msblsb; /* Data in Z axis */
+            gyro->sensortime = 0;
+        }
+        else
+        {
+            rslt = BMI160_E_COM_FAIL;
+        }
+    }
+    else
+    {
+        /* read gyro sensor data along with time */
+        rslt = bmi160_get_regs(BMI160_GYRO_DATA_ADDR, data_array, 12 + len, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Gyro Data */
+            lsb = data_array[idx++];
+            msb = data_array[idx++];
+            msblsb = (int16_t)((msb << 8) | lsb);
+            gyro->x = msblsb; /* gyro X axis data */
+            lsb = data_array[idx++];
+            msb = data_array[idx++];
+            msblsb = (int16_t)((msb << 8) | lsb);
+            gyro->y = msblsb; /* gyro Y axis data */
+            lsb = data_array[idx++];
+            msb = data_array[idx++];
+            msblsb = (int16_t)((msb << 8) | lsb);
+            gyro->z = msblsb; /* gyro Z axis data */
+            idx = idx + 6;
+            time_0 = data_array[idx++];
+            time_1 = (uint16_t)(data_array[idx++] << 8);
+            time_2 = (uint32_t)(data_array[idx++] << 16);
+            gyro->sensortime = (uint32_t)(time_2 | time_1 | time_0);
+        }
+        else
+        {
+            rslt = BMI160_E_COM_FAIL;
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API reads accel and gyro data along with sensor time
+ * if time is requested by user.
+ *  Kindly refer the user guide(README.md) for more info.
+ */
+static int8_t get_accel_gyro_data(uint8_t len,
+                                  struct bmi160_sensor_data *accel,
+                                  struct bmi160_sensor_data *gyro,
+                                  const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t idx = 0;
+    uint8_t data_array[15] = { 0 };
+    uint8_t time_0 = 0;
+    uint16_t time_1 = 0;
+    uint32_t time_2 = 0;
+    uint8_t lsb;
+    uint8_t msb;
+    int16_t msblsb;
+
+    /* read both accel and gyro sensor data
+     * along with time if requested */
+    rslt = bmi160_get_regs(BMI160_GYRO_DATA_ADDR, data_array, 12 + len, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* Gyro Data */
+        lsb = data_array[idx++];
+        msb = data_array[idx++];
+        msblsb = (int16_t)((msb << 8) | lsb);
+        gyro->x = msblsb; /* gyro X axis data */
+        lsb = data_array[idx++];
+        msb = data_array[idx++];
+        msblsb = (int16_t)((msb << 8) | lsb);
+        gyro->y = msblsb; /* gyro Y axis data */
+        lsb = data_array[idx++];
+        msb = data_array[idx++];
+        msblsb = (int16_t)((msb << 8) | lsb);
+        gyro->z = msblsb; /* gyro Z axis data */
+        /* Accel Data */
+        lsb = data_array[idx++];
+        msb = data_array[idx++];
+        msblsb = (int16_t)((msb << 8) | lsb);
+        accel->x = (int16_t)msblsb; /* accel X axis data */
+        lsb = data_array[idx++];
+        msb = data_array[idx++];
+        msblsb = (int16_t)((msb << 8) | lsb);
+        accel->y = (int16_t)msblsb; /* accel Y axis data */
+        lsb = data_array[idx++];
+        msb = data_array[idx++];
+        msblsb = (int16_t)((msb << 8) | lsb);
+        accel->z = (int16_t)msblsb; /* accel Z axis data */
+        if (len == 3)
+        {
+            time_0 = data_array[idx++];
+            time_1 = (uint16_t)(data_array[idx++] << 8);
+            time_2 = (uint32_t)(data_array[idx++] << 16);
+            accel->sensortime = (uint32_t)(time_2 | time_1 | time_0);
+            gyro->sensortime = (uint32_t)(time_2 | time_1 | time_0);
+        }
+        else
+        {
+            accel->sensortime = 0;
+            gyro->sensortime = 0;
+        }
+    }
+    else
+    {
+        rslt = BMI160_E_COM_FAIL;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API enables the any-motion interrupt for accel.
+ */
+static int8_t enable_accel_any_motion_int(const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg,
+                                          struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Enable any motion x, any motion y, any motion z
+     * in Int Enable 0 register */
+    rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        if (any_motion_int_cfg->anymotion_en == BMI160_ENABLE)
+        {
+            temp = data & ~BMI160_ANY_MOTION_X_INT_EN_MASK;
+
+            /* Adding Any_motion x axis */
+            data = temp | (any_motion_int_cfg->anymotion_x & BMI160_ANY_MOTION_X_INT_EN_MASK);
+            temp = data & ~BMI160_ANY_MOTION_Y_INT_EN_MASK;
+
+            /* Adding Any_motion y axis */
+            data = temp | ((any_motion_int_cfg->anymotion_y << 1) & BMI160_ANY_MOTION_Y_INT_EN_MASK);
+            temp = data & ~BMI160_ANY_MOTION_Z_INT_EN_MASK;
+
+            /* Adding Any_motion z axis */
+            data = temp | ((any_motion_int_cfg->anymotion_z << 2) & BMI160_ANY_MOTION_Z_INT_EN_MASK);
+
+            /* any-motion feature selected*/
+            dev->any_sig_sel = BMI160_ANY_MOTION_ENABLED;
+        }
+        else
+        {
+            data = data & ~BMI160_ANY_MOTION_ALL_INT_EN_MASK;
+
+            /* neither any-motion feature nor sig-motion selected */
+            dev->any_sig_sel = BMI160_BOTH_ANY_SIG_MOTION_DISABLED;
+        }
+
+        /* write data to Int Enable 0 register */
+        rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API disable the sig-motion interrupt.
+ */
+static int8_t disable_sig_motion_int(const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Disabling Significant motion interrupt if enabled */
+    rslt = bmi160_get_regs(BMI160_INT_MOTION_3_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = (data & BMI160_SIG_MOTION_SEL_MASK);
+        if (temp)
+        {
+            temp = data & ~BMI160_SIG_MOTION_SEL_MASK;
+            data = temp;
+
+            /* Write data to register */
+            rslt = bmi160_set_regs(BMI160_INT_MOTION_3_ADDR, &data, 1, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API is used to map/unmap the Any/Sig motion, Step det/Low-g,
+ *  Double tap, Single tap, Orientation, Flat, High-G, Nomotion interrupt pins.
+ */
+static int8_t map_feature_interrupt(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data[3] = { 0, 0, 0 };
+    uint8_t temp[3] = { 0, 0, 0 };
+
+    rslt = bmi160_get_regs(BMI160_INT_MAP_0_ADDR, data, 3, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp[0] = data[0] & ~int_mask_lookup_table[int_config->int_type];
+        temp[2] = data[2] & ~int_mask_lookup_table[int_config->int_type];
+        switch (int_config->int_channel)
+        {
+            case BMI160_INT_CHANNEL_NONE:
+                data[0] = temp[0];
+                data[2] = temp[2];
+                break;
+            case BMI160_INT_CHANNEL_1:
+                data[0] = temp[0] | int_mask_lookup_table[int_config->int_type];
+                data[2] = temp[2];
+                break;
+            case BMI160_INT_CHANNEL_2:
+                data[2] = temp[2] | int_mask_lookup_table[int_config->int_type];
+                data[0] = temp[0];
+                break;
+            case BMI160_INT_CHANNEL_BOTH:
+                data[0] = temp[0] | int_mask_lookup_table[int_config->int_type];
+                data[2] = temp[2] | int_mask_lookup_table[int_config->int_type];
+                break;
+            default:
+                rslt = BMI160_E_OUT_OF_RANGE;
+        }
+        if (rslt == BMI160_OK)
+        {
+            rslt = bmi160_set_regs(BMI160_INT_MAP_0_ADDR, data, 3, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API is used to map/unmap the Dataready(Accel & Gyro), FIFO full
+ *  and FIFO watermark interrupt.
+ */
+static int8_t map_hardware_interrupt(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    rslt = bmi160_get_regs(BMI160_INT_MAP_1_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data & ~int_mask_lookup_table[int_config->int_type];
+        temp = temp & ~((uint8_t)(int_mask_lookup_table[int_config->int_type] << 4));
+        switch (int_config->int_channel)
+        {
+            case BMI160_INT_CHANNEL_NONE:
+                data = temp;
+                break;
+            case BMI160_INT_CHANNEL_1:
+                data = temp | (uint8_t)((int_mask_lookup_table[int_config->int_type]) << 4);
+                break;
+            case BMI160_INT_CHANNEL_2:
+                data = temp | int_mask_lookup_table[int_config->int_type];
+                break;
+            case BMI160_INT_CHANNEL_BOTH:
+                data = temp | int_mask_lookup_table[int_config->int_type];
+                data = data | (uint8_t)((int_mask_lookup_table[int_config->int_type]) << 4);
+                break;
+            default:
+                rslt = BMI160_E_OUT_OF_RANGE;
+        }
+        if (rslt == BMI160_OK)
+        {
+            rslt = bmi160_set_regs(BMI160_INT_MAP_1_ADDR, &data, 1, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the source of data(filter & pre-filter)
+ * for any-motion interrupt.
+ */
+static int8_t config_any_motion_src(const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg,
+                                    const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Configure Int data 1 register to add source of interrupt */
+    rslt = bmi160_get_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data & ~BMI160_MOTION_SRC_INT_MASK;
+        data = temp | ((any_motion_int_cfg->anymotion_data_src << 7) & BMI160_MOTION_SRC_INT_MASK);
+
+        /* Write data to DATA 1 address */
+        rslt = bmi160_set_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the duration and threshold of
+ * any-motion interrupt.
+ */
+static int8_t config_any_dur_threshold(const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg,
+                                       const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+    uint8_t data_array[2] = { 0 };
+    uint8_t dur;
+
+    /* Configure Int Motion 0 register */
+    rslt = bmi160_get_regs(BMI160_INT_MOTION_0_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* slope duration */
+        dur = (uint8_t)any_motion_int_cfg->anymotion_dur;
+        temp = data & ~BMI160_SLOPE_INT_DUR_MASK;
+        data = temp | (dur & BMI160_MOTION_SRC_INT_MASK);
+        data_array[0] = data;
+
+        /* add slope threshold */
+        data_array[1] = any_motion_int_cfg->anymotion_thr;
+
+        /* INT MOTION 0 and INT MOTION 1 address lie consecutively,
+         * hence writing data to respective registers at one go */
+
+        /* Writing to Int_motion 0 and
+         * Int_motion 1 Address simultaneously */
+        rslt = bmi160_set_regs(BMI160_INT_MOTION_0_ADDR, data_array, 2, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure necessary setting of any-motion interrupt.
+ */
+static int8_t config_any_motion_int_settg(const struct bmi160_int_settg *int_config,
+                                          const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg,
+                                          const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Configure Interrupt pins */
+    rslt = set_intr_pin_config(int_config, dev);
+    if (rslt == BMI160_OK)
+    {
+        rslt = disable_sig_motion_int(dev);
+        if (rslt == BMI160_OK)
+        {
+            rslt = map_feature_interrupt(int_config, dev);
+            if (rslt == BMI160_OK)
+            {
+                rslt = config_any_motion_src(any_motion_int_cfg, dev);
+                if (rslt == BMI160_OK)
+                {
+                    rslt = config_any_dur_threshold(any_motion_int_cfg, dev);
+                }
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API enable the data ready interrupt.
+ */
+static int8_t enable_data_ready_int(const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Enable data ready interrupt in Int Enable 1 register */
+    rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data & ~BMI160_DATA_RDY_INT_EN_MASK;
+        data = temp | ((1 << 4) & BMI160_DATA_RDY_INT_EN_MASK);
+
+        /* Writing data to INT ENABLE 1 Address */
+        rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API enables the no motion/slow motion interrupt.
+ */
+static int8_t enable_no_motion_int(const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg,
+                                   const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Enable no motion x, no motion y, no motion z
+     * in Int Enable 2 register */
+    rslt = bmi160_get_regs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        if (no_mot_int_cfg->no_motion_x == 1)
+        {
+            temp = data & ~BMI160_NO_MOTION_X_INT_EN_MASK;
+
+            /* Adding No_motion x axis */
+            data = temp | (1 & BMI160_NO_MOTION_X_INT_EN_MASK);
+        }
+
+        if (no_mot_int_cfg->no_motion_y == 1)
+        {
+            temp = data & ~BMI160_NO_MOTION_Y_INT_EN_MASK;
+
+            /* Adding No_motion x axis */
+            data = temp | ((1 << 1) & BMI160_NO_MOTION_Y_INT_EN_MASK);
+        }
+
+        if (no_mot_int_cfg->no_motion_z == 1)
+        {
+            temp = data & ~BMI160_NO_MOTION_Z_INT_EN_MASK;
+
+            /* Adding No_motion x axis */
+            data = temp | ((1 << 2) & BMI160_NO_MOTION_Z_INT_EN_MASK);
+        }
+
+        /* write data to Int Enable 2 register */
+        rslt = bmi160_set_regs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the interrupt PIN setting for
+ * no motion/slow motion interrupt.
+ */
+static int8_t config_no_motion_int_settg(const struct bmi160_int_settg *int_config,
+                                         const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg,
+                                         const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Configure Interrupt pins */
+    rslt = set_intr_pin_config(int_config, dev);
+    if (rslt == BMI160_OK)
+    {
+        rslt = map_feature_interrupt(int_config, dev);
+        if (rslt == BMI160_OK)
+        {
+            rslt = config_no_motion_data_src(no_mot_int_cfg, dev);
+            if (rslt == BMI160_OK)
+            {
+                rslt = config_no_motion_dur_thr(no_mot_int_cfg, dev);
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the source of interrupt for no motion.
+ */
+static int8_t config_no_motion_data_src(const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg,
+                                        const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Configure Int data 1 register to add source of interrupt */
+    rslt = bmi160_get_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data & ~BMI160_MOTION_SRC_INT_MASK;
+        data = temp | ((no_mot_int_cfg->no_motion_src << 7) & BMI160_MOTION_SRC_INT_MASK);
+
+        /* Write data to DATA 1 address */
+        rslt = bmi160_set_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the duration and threshold of
+ * no motion/slow motion interrupt along with selection of no/slow motion.
+ */
+static int8_t config_no_motion_dur_thr(const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg,
+                                       const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+    uint8_t temp_1 = 0;
+    uint8_t reg_addr;
+    uint8_t data_array[2] = { 0 };
+
+    /* Configuring INT_MOTION register */
+    reg_addr = BMI160_INT_MOTION_0_ADDR;
+    rslt = bmi160_get_regs(reg_addr, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data & ~BMI160_NO_MOTION_INT_DUR_MASK;
+
+        /* Adding no_motion duration */
+        data = temp | ((no_mot_int_cfg->no_motion_dur << 2) & BMI160_NO_MOTION_INT_DUR_MASK);
+
+        /* Write data to NO_MOTION 0 address */
+        rslt = bmi160_set_regs(reg_addr, &data, 1, dev);
+        if (rslt == BMI160_OK)
+        {
+            reg_addr = BMI160_INT_MOTION_3_ADDR;
+            rslt = bmi160_get_regs(reg_addr, &data, 1, dev);
+            if (rslt == BMI160_OK)
+            {
+                temp = data & ~BMI160_NO_MOTION_SEL_BIT_MASK;
+
+                /* Adding no_motion_sel bit */
+                temp_1 = (no_mot_int_cfg->no_motion_sel & BMI160_NO_MOTION_SEL_BIT_MASK);
+                data = (temp | temp_1);
+                data_array[1] = data;
+
+                /* Adding no motion threshold */
+                data_array[0] = no_mot_int_cfg->no_motion_thres;
+                reg_addr = BMI160_INT_MOTION_2_ADDR;
+
+                /* writing data to INT_MOTION 2 and INT_MOTION 3
+                 * address simultaneously */
+                rslt = bmi160_set_regs(reg_addr, data_array, 2, dev);
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API enables the sig-motion motion interrupt.
+ */
+static int8_t enable_sig_motion_int(const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg, struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* For significant motion,enable any motion x,any motion y,
+     * any motion z in Int Enable 0 register */
+    rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        if (sig_mot_int_cfg->sig_en == BMI160_ENABLE)
+        {
+            temp = data & ~BMI160_SIG_MOTION_INT_EN_MASK;
+            data = temp | (7 & BMI160_SIG_MOTION_INT_EN_MASK);
+
+            /* sig-motion feature selected*/
+            dev->any_sig_sel = BMI160_SIG_MOTION_ENABLED;
+        }
+        else
+        {
+            data = data & ~BMI160_SIG_MOTION_INT_EN_MASK;
+
+            /* neither any-motion feature nor sig-motion selected */
+            dev->any_sig_sel = BMI160_BOTH_ANY_SIG_MOTION_DISABLED;
+        }
+
+        /* write data to Int Enable 0 register */
+        rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the interrupt PIN setting for
+ * significant motion interrupt.
+ */
+static int8_t config_sig_motion_int_settg(const struct bmi160_int_settg *int_config,
+                                          const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg,
+                                          const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Configure Interrupt pins */
+    rslt = set_intr_pin_config(int_config, dev);
+    if (rslt == BMI160_OK)
+    {
+        rslt = map_feature_interrupt(int_config, dev);
+        if (rslt == BMI160_OK)
+        {
+            rslt = config_sig_motion_data_src(sig_mot_int_cfg, dev);
+            if (rslt == BMI160_OK)
+            {
+                rslt = config_sig_dur_threshold(sig_mot_int_cfg, dev);
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the source of data(filter & pre-filter)
+ * for sig motion interrupt.
+ */
+static int8_t config_sig_motion_data_src(const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg,
+                                         const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Configure Int data 1 register to add source of interrupt */
+    rslt = bmi160_get_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data & ~BMI160_MOTION_SRC_INT_MASK;
+        data = temp | ((sig_mot_int_cfg->sig_data_src << 7) & BMI160_MOTION_SRC_INT_MASK);
+
+        /* Write data to DATA 1 address */
+        rslt = bmi160_set_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the threshold, skip and proof time of
+ * sig motion interrupt.
+ */
+static int8_t config_sig_dur_threshold(const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg,
+                                       const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data;
+    uint8_t temp = 0;
+
+    /* Configuring INT_MOTION registers */
+
+    /* Write significant motion threshold.
+     * This threshold is same as any motion threshold */
+    data = sig_mot_int_cfg->sig_mot_thres;
+
+    /* Write data to INT_MOTION 1 address */
+    rslt = bmi160_set_regs(BMI160_INT_MOTION_1_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        rslt = bmi160_get_regs(BMI160_INT_MOTION_3_ADDR, &data, 1, dev);
+        if (rslt == BMI160_OK)
+        {
+            temp = data & ~BMI160_SIG_MOTION_SKIP_MASK;
+
+            /* adding skip time of sig_motion interrupt*/
+            data = temp | ((sig_mot_int_cfg->sig_mot_skip << 2) & BMI160_SIG_MOTION_SKIP_MASK);
+            temp = data & ~BMI160_SIG_MOTION_PROOF_MASK;
+
+            /* adding proof time of sig_motion interrupt */
+            data = temp | ((sig_mot_int_cfg->sig_mot_proof << 4) & BMI160_SIG_MOTION_PROOF_MASK);
+
+            /* configure the int_sig_mot_sel bit to select
+             * significant motion interrupt */
+            temp = data & ~BMI160_SIG_MOTION_SEL_MASK;
+            data = temp | ((sig_mot_int_cfg->sig_en << 1) & BMI160_SIG_MOTION_SEL_MASK);
+            rslt = bmi160_set_regs(BMI160_INT_MOTION_3_ADDR, &data, 1, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API enables the step detector interrupt.
+ */
+static int8_t enable_step_detect_int(const struct bmi160_acc_step_detect_int_cfg *step_detect_int_cfg,
+                                     const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Enable data ready interrupt in Int Enable 2 register */
+    rslt = bmi160_get_regs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data & ~BMI160_STEP_DETECT_INT_EN_MASK;
+        data = temp | ((step_detect_int_cfg->step_detector_en << 3) & BMI160_STEP_DETECT_INT_EN_MASK);
+
+        /* Writing data to INT ENABLE 2 Address */
+        rslt = bmi160_set_regs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the step detector parameter.
+ */
+static int8_t config_step_detect(const struct bmi160_acc_step_detect_int_cfg *step_detect_int_cfg,
+                                 const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t temp = 0;
+    uint8_t data_array[2] = { 0 };
+
+    if (step_detect_int_cfg->step_detector_mode == BMI160_STEP_DETECT_NORMAL)
+    {
+        /* Normal mode setting */
+        data_array[0] = 0x15;
+        data_array[1] = 0x03;
+    }
+    else if (step_detect_int_cfg->step_detector_mode == BMI160_STEP_DETECT_SENSITIVE)
+    {
+        /* Sensitive mode setting */
+        data_array[0] = 0x2D;
+        data_array[1] = 0x00;
+    }
+    else if (step_detect_int_cfg->step_detector_mode == BMI160_STEP_DETECT_ROBUST)
+    {
+        /* Robust mode setting */
+        data_array[0] = 0x1D;
+        data_array[1] = 0x07;
+    }
+    else if (step_detect_int_cfg->step_detector_mode == BMI160_STEP_DETECT_USER_DEFINE)
+    {
+        /* Non recommended User defined setting */
+        /* Configuring STEP_CONFIG register */
+        rslt = bmi160_get_regs(BMI160_INT_STEP_CONFIG_0_ADDR, &data_array[0], 2, dev);
+        if (rslt == BMI160_OK)
+        {
+            temp = data_array[0] & ~BMI160_STEP_DETECT_MIN_THRES_MASK;
+
+            /* Adding min_threshold */
+            data_array[0] = temp | ((step_detect_int_cfg->min_threshold << 3) & BMI160_STEP_DETECT_MIN_THRES_MASK);
+            temp = data_array[0] & ~BMI160_STEP_DETECT_STEPTIME_MIN_MASK;
+
+            /* Adding steptime_min */
+            data_array[0] = temp | ((step_detect_int_cfg->steptime_min) & BMI160_STEP_DETECT_STEPTIME_MIN_MASK);
+            temp = data_array[1] & ~BMI160_STEP_MIN_BUF_MASK;
+
+            /* Adding steptime_min */
+            data_array[1] = temp | ((step_detect_int_cfg->step_min_buf) & BMI160_STEP_MIN_BUF_MASK);
+        }
+    }
+
+    /* Write data to STEP_CONFIG register */
+    rslt = bmi160_set_regs(BMI160_INT_STEP_CONFIG_0_ADDR, data_array, 2, dev);
+
+    return rslt;
+}
+
+/*!
+ * @brief This API enables the single/double tap interrupt.
+ */
+static int8_t enable_tap_int(const struct bmi160_int_settg *int_config,
+                             const struct bmi160_acc_tap_int_cfg *tap_int_cfg,
+                             const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Enable single tap or double tap interrupt in Int Enable 0 register */
+    rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        if (int_config->int_type == BMI160_ACC_SINGLE_TAP_INT)
+        {
+            temp = data & ~BMI160_SINGLE_TAP_INT_EN_MASK;
+            data = temp | ((tap_int_cfg->tap_en << 5) & BMI160_SINGLE_TAP_INT_EN_MASK);
+        }
+        else
+        {
+            temp = data & ~BMI160_DOUBLE_TAP_INT_EN_MASK;
+            data = temp | ((tap_int_cfg->tap_en << 4) & BMI160_DOUBLE_TAP_INT_EN_MASK);
+        }
+
+        /* Write to Enable 0 Address */
+        rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the interrupt PIN setting for
+ * tap interrupt.
+ */
+static int8_t config_tap_int_settg(const struct bmi160_int_settg *int_config,
+                                   const struct bmi160_acc_tap_int_cfg *tap_int_cfg,
+                                   const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Configure Interrupt pins */
+    rslt = set_intr_pin_config(int_config, dev);
+    if (rslt == BMI160_OK)
+    {
+        rslt = map_feature_interrupt(int_config, dev);
+        if (rslt == BMI160_OK)
+        {
+            rslt = config_tap_data_src(tap_int_cfg, dev);
+            if (rslt == BMI160_OK)
+            {
+                rslt = config_tap_param(int_config, tap_int_cfg, dev);
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the source of data(filter & pre-filter)
+ * for tap interrupt.
+ */
+static int8_t config_tap_data_src(const struct bmi160_acc_tap_int_cfg *tap_int_cfg, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Configure Int data 0 register to add source of interrupt */
+    rslt = bmi160_get_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data & ~BMI160_TAP_SRC_INT_MASK;
+        data = temp | ((tap_int_cfg->tap_data_src << 3) & BMI160_TAP_SRC_INT_MASK);
+
+        /* Write data to Data 0 address */
+        rslt = bmi160_set_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the  parameters of tap interrupt.
+ * Threshold, quite, shock, and duration.
+ */
+static int8_t config_tap_param(const struct bmi160_int_settg *int_config,
+                               const struct bmi160_acc_tap_int_cfg *tap_int_cfg,
+                               const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t temp = 0;
+    uint8_t data = 0;
+    uint8_t data_array[2] = { 0 };
+    uint8_t count = 0;
+    uint8_t dur, shock, quiet, thres;
+
+    /* Configure tap 0 register for tap shock,tap quiet duration
+     * in case of single tap interrupt */
+    rslt = bmi160_get_regs(BMI160_INT_TAP_0_ADDR, data_array, 2, dev);
+    if (rslt == BMI160_OK)
+    {
+        data = data_array[count];
+        if (int_config->int_type == BMI160_ACC_DOUBLE_TAP_INT)
+        {
+            dur = (uint8_t)tap_int_cfg->tap_dur;
+            temp = (data & ~BMI160_TAP_DUR_MASK);
+
+            /* Add tap duration data in case of
+             * double tap interrupt */
+            data = temp | (dur & BMI160_TAP_DUR_MASK);
+        }
+
+        shock = (uint8_t)tap_int_cfg->tap_shock;
+        temp = data & ~BMI160_TAP_SHOCK_DUR_MASK;
+        data = temp | ((shock << 6) & BMI160_TAP_SHOCK_DUR_MASK);
+        quiet = (uint8_t)tap_int_cfg->tap_quiet;
+        temp = data & ~BMI160_TAP_QUIET_DUR_MASK;
+        data = temp | ((quiet << 7) & BMI160_TAP_QUIET_DUR_MASK);
+        data_array[count++] = data;
+        data = data_array[count];
+        thres = (uint8_t)tap_int_cfg->tap_thr;
+        temp = data & ~BMI160_TAP_THRES_MASK;
+        data = temp | (thres & BMI160_TAP_THRES_MASK);
+        data_array[count++] = data;
+
+        /* TAP 0 and TAP 1 address lie consecutively,
+         * hence writing data to respective registers at one go */
+
+        /* Writing to Tap 0 and Tap 1 Address simultaneously */
+        rslt = bmi160_set_regs(BMI160_INT_TAP_0_ADDR, data_array, count, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the secondary interface.
+ */
+static int8_t config_sec_if(const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t if_conf = 0;
+    uint8_t cmd = BMI160_AUX_NORMAL_MODE;
+
+    /* set the aux power mode to normal*/
+    rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &cmd, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* 0.5ms delay - refer datasheet table 24*/
+        dev->delay_ms(1);
+        rslt = bmi160_get_regs(BMI160_IF_CONF_ADDR, &if_conf, 1, dev);
+        if_conf |= (uint8_t)(1 << 5);
+        if (rslt == BMI160_OK)
+        {
+            /*enable the secondary interface also*/
+            rslt = bmi160_set_regs(BMI160_IF_CONF_ADDR, &if_conf, 1, dev);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the ODR of the auxiliary sensor.
+ */
+static int8_t config_aux_odr(const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t aux_odr;
+
+    rslt = bmi160_get_regs(BMI160_AUX_ODR_ADDR, &aux_odr, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        aux_odr = (uint8_t)(dev->aux_cfg.aux_odr);
+
+        /* Set the secondary interface ODR
+         * i.e polling rate of secondary sensor */
+        rslt = bmi160_set_regs(BMI160_AUX_ODR_ADDR, &aux_odr, 1, dev);
+        dev->delay_ms(BMI160_AUX_COM_DELAY);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API maps the actual burst read length set by user.
+ */
+static int8_t map_read_len(uint16_t *len, const struct bmi160_dev *dev)
+{
+    int8_t rslt = BMI160_OK;
+
+    switch (dev->aux_cfg.aux_rd_burst_len)
+    {
+        case BMI160_AUX_READ_LEN_0:
+            *len = 1;
+            break;
+        case BMI160_AUX_READ_LEN_1:
+            *len = 2;
+            break;
+        case BMI160_AUX_READ_LEN_2:
+            *len = 6;
+            break;
+        case BMI160_AUX_READ_LEN_3:
+            *len = 8;
+            break;
+        default:
+            rslt = BMI160_E_INVALID_INPUT;
+            break;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the settings of auxiliary sensor.
+ */
+static int8_t config_aux_settg(const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    rslt = config_sec_if(dev);
+    if (rslt == BMI160_OK)
+    {
+        /* Configures the auxiliary interface settings */
+        rslt = bmi160_config_aux_mode(dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API extract the read data from auxiliary sensor.
+ */
+static int8_t extract_aux_read(uint16_t map_len,
+                               uint8_t reg_addr,
+                               uint8_t *aux_data,
+                               uint16_t len,
+                               const struct bmi160_dev *dev)
+{
+    int8_t rslt = BMI160_OK;
+    uint8_t data[8] = { 0, };
+    uint8_t read_addr = BMI160_AUX_DATA_ADDR;
+    uint8_t count = 0;
+    uint8_t read_count;
+    uint8_t read_len = (uint8_t)map_len;
+
+    for (; count < len;)
+    {
+        /* set address to read */
+        rslt = bmi160_set_regs(BMI160_AUX_IF_2_ADDR, &reg_addr, 1, dev);
+        dev->delay_ms(BMI160_AUX_COM_DELAY);
+        if (rslt == BMI160_OK)
+        {
+            rslt = bmi160_get_regs(read_addr, data, map_len, dev);
+            if (rslt == BMI160_OK)
+            {
+                read_count = 0;
+
+                /* if read len is less the burst read len
+                 * mention by user*/
+                if (len < map_len)
+                {
+                    read_len = (uint8_t)len;
+                }
+                else if ((len - count) < map_len)
+                {
+                    read_len = (uint8_t)(len - count);
+                }
+
+                for (; read_count < read_len; read_count++)
+                {
+                    aux_data[count + read_count] = data[read_count];
+                }
+
+                reg_addr += (uint8_t)map_len;
+                count += (uint8_t)map_len;
+            }
+            else
+            {
+                rslt = BMI160_E_COM_FAIL;
+                break;
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API enables the orient interrupt.
+ */
+static int8_t enable_orient_int(const struct bmi160_acc_orient_int_cfg *orient_int_cfg, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Enable data ready interrupt in Int Enable 0 register */
+    rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data & ~BMI160_ORIENT_INT_EN_MASK;
+        data = temp | ((orient_int_cfg->orient_en << 6) & BMI160_ORIENT_INT_EN_MASK);
+
+        /* write data to Int Enable 0 register */
+        rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the necessary setting of orientation interrupt.
+ */
+static int8_t config_orient_int_settg(const struct bmi160_acc_orient_int_cfg *orient_int_cfg,
+                                      const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+    uint8_t data_array[2] = { 0, 0 };
+
+    /* Configuring INT_ORIENT registers */
+    rslt = bmi160_get_regs(BMI160_INT_ORIENT_0_ADDR, data_array, 2, dev);
+    if (rslt == BMI160_OK)
+    {
+        data = data_array[0];
+        temp = data & ~BMI160_ORIENT_MODE_MASK;
+
+        /* Adding Orientation mode */
+        data = temp | ((orient_int_cfg->orient_mode) & BMI160_ORIENT_MODE_MASK);
+        temp = data & ~BMI160_ORIENT_BLOCK_MASK;
+
+        /* Adding Orientation blocking */
+        data = temp | ((orient_int_cfg->orient_blocking << 2) & BMI160_ORIENT_BLOCK_MASK);
+        temp = data & ~BMI160_ORIENT_HYST_MASK;
+
+        /* Adding Orientation hysteresis */
+        data = temp | ((orient_int_cfg->orient_hyst << 4) & BMI160_ORIENT_HYST_MASK);
+        data_array[0] = data;
+        data = data_array[1];
+        temp = data & ~BMI160_ORIENT_THETA_MASK;
+
+        /* Adding Orientation threshold */
+        data = temp | ((orient_int_cfg->orient_theta) & BMI160_ORIENT_THETA_MASK);
+        temp = data & ~BMI160_ORIENT_UD_ENABLE;
+
+        /* Adding Orient_ud_en */
+        data = temp | ((orient_int_cfg->orient_ud_en << 6) & BMI160_ORIENT_UD_ENABLE);
+        temp = data & ~BMI160_AXES_EN_MASK;
+
+        /* Adding axes_en */
+        data = temp | ((orient_int_cfg->axes_ex << 7) & BMI160_AXES_EN_MASK);
+        data_array[1] = data;
+
+        /* Writing data to INT_ORIENT 0 and INT_ORIENT 1
+         * registers simultaneously */
+        rslt = bmi160_set_regs(BMI160_INT_ORIENT_0_ADDR, data_array, 2, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API enables the flat interrupt.
+ */
+static int8_t enable_flat_int(const struct bmi160_acc_flat_detect_int_cfg *flat_int, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Enable flat interrupt in Int Enable 0 register */
+    rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data & ~BMI160_FLAT_INT_EN_MASK;
+        data = temp | ((flat_int->flat_en << 7) & BMI160_FLAT_INT_EN_MASK);
+
+        /* write data to Int Enable 0 register */
+        rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the necessary setting of flat interrupt.
+ */
+static int8_t config_flat_int_settg(const struct bmi160_acc_flat_detect_int_cfg *flat_int, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+    uint8_t data_array[2] = { 0, 0 };
+
+    /* Configuring INT_FLAT register */
+    rslt = bmi160_get_regs(BMI160_INT_FLAT_0_ADDR, data_array, 2, dev);
+    if (rslt == BMI160_OK)
+    {
+        data = data_array[0];
+        temp = data & ~BMI160_FLAT_THRES_MASK;
+
+        /* Adding flat theta */
+        data = temp | ((flat_int->flat_theta) & BMI160_FLAT_THRES_MASK);
+        data_array[0] = data;
+        data = data_array[1];
+        temp = data & ~BMI160_FLAT_HOLD_TIME_MASK;
+
+        /* Adding flat hold time */
+        data = temp | ((flat_int->flat_hold_time << 4) & BMI160_FLAT_HOLD_TIME_MASK);
+        temp = data & ~BMI160_FLAT_HYST_MASK;
+
+        /* Adding flat hysteresis */
+        data = temp | ((flat_int->flat_hy) & BMI160_FLAT_HYST_MASK);
+        data_array[1] = data;
+
+        /* Writing data to INT_FLAT 0 and INT_FLAT 1
+         * registers simultaneously */
+        rslt = bmi160_set_regs(BMI160_INT_FLAT_0_ADDR, data_array, 2, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API enables the Low-g interrupt.
+ */
+static int8_t enable_low_g_int(const struct bmi160_acc_low_g_int_cfg *low_g_int, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Enable low-g interrupt in Int Enable 1 register */
+    rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data & ~BMI160_LOW_G_INT_EN_MASK;
+        data = temp | ((low_g_int->low_en << 3) & BMI160_LOW_G_INT_EN_MASK);
+
+        /* write data to Int Enable 0 register */
+        rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the source of data(filter & pre-filter)
+ * for low-g interrupt.
+ */
+static int8_t config_low_g_data_src(const struct bmi160_acc_low_g_int_cfg *low_g_int, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Configure Int data 0 register to add source of interrupt */
+    rslt = bmi160_get_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data & ~BMI160_LOW_HIGH_SRC_INT_MASK;
+        data = temp | ((low_g_int->low_data_src << 7) & BMI160_LOW_HIGH_SRC_INT_MASK);
+
+        /* Write data to Data 0 address */
+        rslt = bmi160_set_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the necessary setting of low-g interrupt.
+ */
+static int8_t config_low_g_int_settg(const struct bmi160_acc_low_g_int_cfg *low_g_int, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t temp = 0;
+    uint8_t data_array[3] = { 0, 0, 0 };
+
+    /* Configuring INT_LOWHIGH register for low-g interrupt */
+    rslt = bmi160_get_regs(BMI160_INT_LOWHIGH_2_ADDR, &data_array[2], 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data_array[2] & ~BMI160_LOW_G_HYST_MASK;
+
+        /* Adding low-g hysteresis */
+        data_array[2] = temp | (low_g_int->low_hyst & BMI160_LOW_G_HYST_MASK);
+        temp = data_array[2] & ~BMI160_LOW_G_LOW_MODE_MASK;
+
+        /* Adding low-mode */
+        data_array[2] = temp | ((low_g_int->low_mode << 2) & BMI160_LOW_G_LOW_MODE_MASK);
+
+        /* Adding low-g threshold */
+        data_array[1] = low_g_int->low_thres;
+
+        /* Adding low-g interrupt delay */
+        data_array[0] = low_g_int->low_dur;
+
+        /* Writing data to INT_LOWHIGH 0,1,2 registers simultaneously*/
+        rslt = bmi160_set_regs(BMI160_INT_LOWHIGH_0_ADDR, data_array, 3, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API enables the high-g interrupt.
+ */
+static int8_t enable_high_g_int(const struct bmi160_acc_high_g_int_cfg *high_g_int_cfg, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Enable low-g interrupt in Int Enable 1 register */
+    rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* Adding high-g X-axis */
+        temp = data & ~BMI160_HIGH_G_X_INT_EN_MASK;
+        data = temp | (high_g_int_cfg->high_g_x & BMI160_HIGH_G_X_INT_EN_MASK);
+
+        /* Adding high-g Y-axis */
+        temp = data & ~BMI160_HIGH_G_Y_INT_EN_MASK;
+        data = temp | ((high_g_int_cfg->high_g_y << 1) & BMI160_HIGH_G_Y_INT_EN_MASK);
+
+        /* Adding high-g Z-axis */
+        temp = data & ~BMI160_HIGH_G_Z_INT_EN_MASK;
+        data = temp | ((high_g_int_cfg->high_g_z << 2) & BMI160_HIGH_G_Z_INT_EN_MASK);
+
+        /* write data to Int Enable 0 register */
+        rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the source of data(filter & pre-filter)
+ * for high-g interrupt.
+ */
+static int8_t config_high_g_data_src(const struct bmi160_acc_high_g_int_cfg *high_g_int_cfg,
+                                     const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+    uint8_t temp = 0;
+
+    /* Configure Int data 0 register to add source of interrupt */
+    rslt = bmi160_get_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data & ~BMI160_LOW_HIGH_SRC_INT_MASK;
+        data = temp | ((high_g_int_cfg->high_data_src << 7) & BMI160_LOW_HIGH_SRC_INT_MASK);
+
+        /* Write data to Data 0 address */
+        rslt = bmi160_set_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the necessary setting of high-g interrupt.
+ */
+static int8_t config_high_g_int_settg(const struct bmi160_acc_high_g_int_cfg *high_g_int_cfg,
+                                      const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t temp = 0;
+    uint8_t data_array[3] = { 0, 0, 0 };
+
+    rslt = bmi160_get_regs(BMI160_INT_LOWHIGH_2_ADDR, &data_array[0], 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        temp = data_array[0] & ~BMI160_HIGH_G_HYST_MASK;
+
+        /* Adding high-g hysteresis */
+        data_array[0] = temp | ((high_g_int_cfg->high_hy << 6) & BMI160_HIGH_G_HYST_MASK);
+
+        /* Adding high-g duration */
+        data_array[1] = high_g_int_cfg->high_dur;
+
+        /* Adding high-g threshold */
+        data_array[2] = high_g_int_cfg->high_thres;
+        rslt = bmi160_set_regs(BMI160_INT_LOWHIGH_2_ADDR, data_array, 3, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the behavioural setting of interrupt pin.
+ */
+static int8_t config_int_out_ctrl(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t temp = 0;
+    uint8_t data = 0;
+
+    /* Configuration of output interrupt signals on pins INT1 and INT2 are
+     * done in BMI160_INT_OUT_CTRL_ADDR register*/
+    rslt = bmi160_get_regs(BMI160_INT_OUT_CTRL_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* updating the interrupt pin structure to local structure */
+        const struct bmi160_int_pin_settg *intr_pin_sett = &(int_config->int_pin_settg);
+
+        /* Configuring channel 1 */
+        if (int_config->int_channel == BMI160_INT_CHANNEL_1)
+        {
+            /* Output enable */
+            temp = data & ~BMI160_INT1_OUTPUT_EN_MASK;
+            data = temp | ((intr_pin_sett->output_en << 3) & BMI160_INT1_OUTPUT_EN_MASK);
+
+            /* Output mode */
+            temp = data & ~BMI160_INT1_OUTPUT_MODE_MASK;
+            data = temp | ((intr_pin_sett->output_mode << 2) & BMI160_INT1_OUTPUT_MODE_MASK);
+
+            /* Output type */
+            temp = data & ~BMI160_INT1_OUTPUT_TYPE_MASK;
+            data = temp | ((intr_pin_sett->output_type << 1) & BMI160_INT1_OUTPUT_TYPE_MASK);
+
+            /* edge control */
+            temp = data & ~BMI160_INT1_EDGE_CTRL_MASK;
+            data = temp | ((intr_pin_sett->edge_ctrl) & BMI160_INT1_EDGE_CTRL_MASK);
+        }
+        else
+        {
+            /* Configuring channel 2 */
+            /* Output enable */
+            temp = data & ~BMI160_INT2_OUTPUT_EN_MASK;
+            data = temp | ((intr_pin_sett->output_en << 7) & BMI160_INT2_OUTPUT_EN_MASK);
+
+            /* Output mode */
+            temp = data & ~BMI160_INT2_OUTPUT_MODE_MASK;
+            data = temp | ((intr_pin_sett->output_mode << 6) & BMI160_INT2_OUTPUT_MODE_MASK);
+
+            /* Output type */
+            temp = data & ~BMI160_INT2_OUTPUT_TYPE_MASK;
+            data = temp | ((intr_pin_sett->output_type << 5) & BMI160_INT2_OUTPUT_TYPE_MASK);
+
+            /* edge control */
+            temp = data & ~BMI160_INT2_EDGE_CTRL_MASK;
+            data = temp | ((intr_pin_sett->edge_ctrl << 4) & BMI160_INT2_EDGE_CTRL_MASK);
+        }
+
+        rslt = bmi160_set_regs(BMI160_INT_OUT_CTRL_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API configure the mode(input enable, latch or non-latch) of interrupt pin.
+ */
+static int8_t config_int_latch(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t temp = 0;
+    uint8_t data = 0;
+
+    /* Configuration of latch on pins INT1 and INT2 are done in
+     * BMI160_INT_LATCH_ADDR register*/
+    rslt = bmi160_get_regs(BMI160_INT_LATCH_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* updating the interrupt pin structure to local structure */
+        const struct bmi160_int_pin_settg *intr_pin_sett = &(int_config->int_pin_settg);
+        if (int_config->int_channel == BMI160_INT_CHANNEL_1)
+        {
+            /* Configuring channel 1 */
+            /* Input enable */
+            temp = data & ~BMI160_INT1_INPUT_EN_MASK;
+            data = temp | ((intr_pin_sett->input_en << 4) & BMI160_INT1_INPUT_EN_MASK);
+        }
+        else
+        {
+            /* Configuring channel 2 */
+            /* Input enable */
+            temp = data & ~BMI160_INT2_INPUT_EN_MASK;
+            data = temp | ((intr_pin_sett->input_en << 5) & BMI160_INT2_INPUT_EN_MASK);
+        }
+
+        /* In case of latch interrupt,update the latch duration */
+
+        /* Latching holds the interrupt for the amount of latch
+         * duration time */
+        temp = data & ~BMI160_INT_LATCH_MASK;
+        data = temp | (intr_pin_sett->latch_dur & BMI160_INT_LATCH_MASK);
+
+        /* OUT_CTRL_INT and LATCH_INT address lie consecutively,
+         * hence writing data to respective registers at one go */
+        rslt = bmi160_set_regs(BMI160_INT_LATCH_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API performs the self test for accelerometer of BMI160
+ */
+static int8_t perform_accel_self_test(struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    struct bmi160_sensor_data accel_pos, accel_neg;
+
+    /* Enable Gyro self test bit */
+    rslt = enable_accel_self_test(dev);
+    if (rslt == BMI160_OK)
+    {
+        /* Perform accel self test with positive excitation */
+        rslt = accel_self_test_positive_excitation(&accel_pos, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Perform accel self test with negative excitation */
+            rslt = accel_self_test_negative_excitation(&accel_neg, dev);
+            if (rslt == BMI160_OK)
+            {
+                /* Validate the self test result */
+                rslt = validate_accel_self_test(&accel_pos, &accel_neg);
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API enables to perform the accel self test by setting proper
+ * configurations to facilitate accel self test
+ */
+static int8_t enable_accel_self_test(struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t reg_data;
+
+    /* Set the Accel power mode as normal mode */
+    dev->accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
+
+    /* Set the sensor range configuration as 8G */
+    dev->accel_cfg.range = BMI160_ACCEL_RANGE_8G;
+    rslt = bmi160_set_sens_conf(dev);
+    if (rslt == BMI160_OK)
+    {
+        /* Accel configurations are set to facilitate self test
+         * acc_odr - 1600Hz ; acc_bwp = 2 ; acc_us = 0 */
+        reg_data = BMI160_ACCEL_SELF_TEST_CONFIG;
+        rslt = bmi160_set_regs(BMI160_ACCEL_CONFIG_ADDR, &reg_data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API performs accel self test with positive excitation
+ */
+static int8_t accel_self_test_positive_excitation(struct bmi160_sensor_data *accel_pos, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t reg_data;
+
+    /* Enable accel self test with positive self-test excitation
+     * and with amplitude of deflection set as high */
+    reg_data = BMI160_ACCEL_SELF_TEST_POSITIVE_EN;
+    rslt = bmi160_set_regs(BMI160_SELF_TEST_ADDR, &reg_data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* Read the data after a delay of 50ms - refer datasheet  2.8.1 accel self test*/
+        dev->delay_ms(BMI160_ACCEL_SELF_TEST_DELAY);
+        rslt = bmi160_get_sensor_data(BMI160_ACCEL_ONLY, accel_pos, NULL, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API performs accel self test with negative excitation
+ */
+static int8_t accel_self_test_negative_excitation(struct bmi160_sensor_data *accel_neg, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t reg_data;
+
+    /* Enable accel self test with negative self-test excitation
+     * and with amplitude of deflection set as high */
+    reg_data = BMI160_ACCEL_SELF_TEST_NEGATIVE_EN;
+    rslt = bmi160_set_regs(BMI160_SELF_TEST_ADDR, &reg_data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* Read the data after a delay of 50ms */
+        dev->delay_ms(BMI160_ACCEL_SELF_TEST_DELAY);
+        rslt = bmi160_get_sensor_data(BMI160_ACCEL_ONLY, accel_neg, NULL, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API validates the accel self test results
+ */
+static int8_t validate_accel_self_test(const struct bmi160_sensor_data *accel_pos,
+                                       const struct bmi160_sensor_data *accel_neg)
+{
+    int8_t rslt;
+
+    /* Validate the results of self test */
+    if (((accel_neg->x - accel_pos->x) > BMI160_ACCEL_SELF_TEST_LIMIT) &&
+        ((accel_neg->y - accel_pos->y) > BMI160_ACCEL_SELF_TEST_LIMIT) &&
+        ((accel_neg->z - accel_pos->z) > BMI160_ACCEL_SELF_TEST_LIMIT))
+    {
+        /* Self test pass condition */
+        rslt = BMI160_OK;
+    }
+    else
+    {
+        rslt = BMI160_W_ACCEl_SELF_TEST_FAIL;
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API performs the self test for gyroscope of BMI160
+ */
+static int8_t perform_gyro_self_test(const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+
+    /* Enable Gyro self test bit */
+    rslt = enable_gyro_self_test(dev);
+    if (rslt == BMI160_OK)
+    {
+        /* Validate the gyro self test a delay of 50ms */
+        dev->delay_ms(50);
+
+        /* Validate the gyro self test results */
+        rslt = validate_gyro_self_test(dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API enables the self test bit to trigger self test for Gyro
+ */
+static int8_t enable_gyro_self_test(const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t reg_data;
+
+    /* Enable the Gyro self test bit to trigger the self test */
+    rslt = bmi160_get_regs(BMI160_SELF_TEST_ADDR, &reg_data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        reg_data = BMI160_SET_BITS(reg_data, BMI160_GYRO_SELF_TEST, 1);
+        rslt = bmi160_set_regs(BMI160_SELF_TEST_ADDR, &reg_data, 1, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Delay to enable gyro self test */
+            dev->delay_ms(15);
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This API validates the self test results of Gyro
+ */
+static int8_t validate_gyro_self_test(const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t reg_data;
+
+    /* Validate the Gyro self test result */
+    rslt = bmi160_get_regs(BMI160_STATUS_ADDR, &reg_data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+
+        reg_data = BMI160_GET_BITS(reg_data, BMI160_GYRO_SELF_TEST_STATUS);
+        if (reg_data == BMI160_ENABLE)
+        {
+            /* Gyro self test success case */
+            rslt = BMI160_OK;
+        }
+        else
+        {
+            rslt = BMI160_W_GYRO_SELF_TEST_FAIL;
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API sets FIFO full interrupt of the sensor.This interrupt
+ *  occurs when the FIFO is full and the next full data sample would cause
+ *  a FIFO overflow, which may delete the old samples.
+ */
+static int8_t set_fifo_full_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt = BMI160_OK;
+
+    /* Null-pointer check */
+    if ((dev == NULL) || (dev->delay_ms == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /*enable the fifo full interrupt */
+        rslt = enable_fifo_full_int(int_config, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Configure Interrupt pins */
+            rslt = set_intr_pin_config(int_config, dev);
+            if (rslt == BMI160_OK)
+            {
+                rslt = map_hardware_interrupt(int_config, dev);
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This enable the FIFO full interrupt engine.
+ */
+static int8_t enable_fifo_full_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+
+    rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        data = BMI160_SET_BITS(data, BMI160_FIFO_FULL_INT, int_config->fifo_full_int_en);
+
+        /* Writing data to INT ENABLE 1 Address */
+        rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API sets FIFO watermark interrupt of the sensor.The FIFO
+ *  watermark interrupt is fired, when the FIFO fill level is above a fifo
+ *  watermark.
+ */
+static int8_t set_fifo_watermark_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt = BMI160_OK;
+
+    if ((dev == NULL) || (dev->delay_ms == NULL))
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* Enable fifo-watermark interrupt in Int Enable 1 register */
+        rslt = enable_fifo_wtm_int(int_config, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Configure Interrupt pins */
+            rslt = set_intr_pin_config(int_config, dev);
+            if (rslt == BMI160_OK)
+            {
+                rslt = map_hardware_interrupt(int_config, dev);
+            }
+        }
+    }
+
+    return rslt;
+}
+
+/*!
+ * @brief This enable the FIFO watermark interrupt engine.
+ */
+static int8_t enable_fifo_wtm_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev)
+{
+    int8_t rslt;
+    uint8_t data = 0;
+
+    rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        data = BMI160_SET_BITS(data, BMI160_FIFO_WTM_INT, int_config->fifo_wtm_int_en);
+
+        /* Writing data to INT ENABLE 1 Address */
+        rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev);
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API is used to reset the FIFO related configurations
+ *  in the fifo_frame structure.
+ */
+static void reset_fifo_data_structure(const struct bmi160_dev *dev)
+{
+    /*Prepare for next FIFO read by resetting FIFO's
+     * internal data structures*/
+    dev->fifo->accel_byte_start_idx = 0;
+    dev->fifo->gyro_byte_start_idx = 0;
+    dev->fifo->aux_byte_start_idx = 0;
+    dev->fifo->sensor_time = 0;
+    dev->fifo->skipped_frame_count = 0;
+}
+
+/*!
+ *  @brief This API is used to read fifo_byte_counter value (i.e)
+ *  current fill-level in Fifo buffer.
+ */
+static int8_t get_fifo_byte_counter(uint16_t *bytes_to_read, struct bmi160_dev const *dev)
+{
+    int8_t rslt = 0;
+    uint8_t data[2];
+    uint8_t addr = BMI160_FIFO_LENGTH_ADDR;
+
+    rslt |= bmi160_get_regs(addr, data, 2, dev);
+    data[1] = data[1] & BMI160_FIFO_BYTE_COUNTER_MASK;
+
+    /* Available data in FIFO is stored in bytes_to_read*/
+    *bytes_to_read = (((uint16_t)data[1] << 8) | ((uint16_t)data[0]));
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API is used to compute the number of bytes of accel FIFO data
+ *  which is to be parsed in header-less mode
+ */
+static void get_accel_len_to_parse(uint16_t *data_index,
+                                   uint16_t *data_read_length,
+                                   const uint8_t *acc_frame_count,
+                                   const struct bmi160_dev *dev)
+{
+    /* Data start index */
+    *data_index = dev->fifo->accel_byte_start_idx;
+    if (dev->fifo->fifo_data_enable == BMI160_FIFO_A_ENABLE)
+    {
+        *data_read_length = (*acc_frame_count) * BMI160_FIFO_A_LENGTH;
+    }
+    else if (dev->fifo->fifo_data_enable == BMI160_FIFO_G_A_ENABLE)
+    {
+        *data_read_length = (*acc_frame_count) * BMI160_FIFO_GA_LENGTH;
+    }
+    else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_A_ENABLE)
+    {
+        *data_read_length = (*acc_frame_count) * BMI160_FIFO_MA_LENGTH;
+    }
+    else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_A_ENABLE)
+    {
+        *data_read_length = (*acc_frame_count) * BMI160_FIFO_MGA_LENGTH;
+    }
+    else
+    {
+        /* When accel is not enabled ,there will be no accel data.
+         * so we update the data index as complete */
+        *data_index = dev->fifo->length;
+    }
+
+    if (*data_read_length > dev->fifo->length)
+    {
+        /* Handling the case where more data is requested
+         * than that is available*/
+        *data_read_length = dev->fifo->length;
+    }
+}
+
+/*!
+ *  @brief This API is used to parse the accelerometer data from the
+ *  FIFO data in both header mode and header-less mode.
+ *  It updates the idx value which is used to store the index of
+ *  the current data byte which is parsed.
+ */
+static void unpack_accel_frame(struct bmi160_sensor_data *acc,
+                               uint16_t *idx,
+                               uint8_t *acc_idx,
+                               uint8_t frame_info,
+                               const struct bmi160_dev *dev)
+{
+    switch (frame_info)
+    {
+        case BMI160_FIFO_HEAD_A:
+        case BMI160_FIFO_A_ENABLE:
+
+            /*Partial read, then skip the data*/
+            if ((*idx + BMI160_FIFO_A_LENGTH) > dev->fifo->length)
+            {
+                /*Update the data index as complete*/
+                *idx = dev->fifo->length;
+                break;
+            }
+
+            /*Unpack the data array into the structure instance "acc" */
+            unpack_accel_data(&acc[*acc_idx], *idx, dev);
+
+            /*Move the data index*/
+            *idx = *idx + BMI160_FIFO_A_LENGTH;
+            (*acc_idx)++;
+            break;
+        case BMI160_FIFO_HEAD_G_A:
+        case BMI160_FIFO_G_A_ENABLE:
+
+            /*Partial read, then skip the data*/
+            if ((*idx + BMI160_FIFO_GA_LENGTH) > dev->fifo->length)
+            {
+                /*Update the data index as complete*/
+                *idx = dev->fifo->length;
+                break;
+            }
+
+            /*Unpack the data array into structure instance "acc"*/
+            unpack_accel_data(&acc[*acc_idx], *idx + BMI160_FIFO_G_LENGTH, dev);
+
+            /*Move the data index*/
+            *idx = *idx + BMI160_FIFO_GA_LENGTH;
+            (*acc_idx)++;
+            break;
+        case BMI160_FIFO_HEAD_M_A:
+        case BMI160_FIFO_M_A_ENABLE:
+
+            /*Partial read, then skip the data*/
+            if ((*idx + BMI160_FIFO_MA_LENGTH) > dev->fifo->length)
+            {
+                /*Update the data index as complete*/
+                *idx = dev->fifo->length;
+                break;
+            }
+
+            /*Unpack the data array into structure instance "acc"*/
+            unpack_accel_data(&acc[*acc_idx], *idx + BMI160_FIFO_M_LENGTH, dev);
+
+            /*Move the data index*/
+            *idx = *idx + BMI160_FIFO_MA_LENGTH;
+            (*acc_idx)++;
+            break;
+        case BMI160_FIFO_HEAD_M_G_A:
+        case BMI160_FIFO_M_G_A_ENABLE:
+
+            /*Partial read, then skip the data*/
+            if ((*idx + BMI160_FIFO_MGA_LENGTH) > dev->fifo->length)
+            {
+                /*Update the data index as complete*/
+                *idx = dev->fifo->length;
+                break;
+            }
+
+            /*Unpack the data array into structure instance "acc"*/
+            unpack_accel_data(&acc[*acc_idx], *idx + BMI160_FIFO_MG_LENGTH, dev);
+
+            /*Move the data index*/
+            *idx = *idx + BMI160_FIFO_MGA_LENGTH;
+            (*acc_idx)++;
+            break;
+        case BMI160_FIFO_HEAD_M:
+        case BMI160_FIFO_M_ENABLE:
+            (*idx) = (*idx) + BMI160_FIFO_M_LENGTH;
+            break;
+        case BMI160_FIFO_HEAD_G:
+        case BMI160_FIFO_G_ENABLE:
+            (*idx) = (*idx) + BMI160_FIFO_G_LENGTH;
+            break;
+        case BMI160_FIFO_HEAD_M_G:
+        case BMI160_FIFO_M_G_ENABLE:
+            (*idx) = (*idx) + BMI160_FIFO_MG_LENGTH;
+            break;
+        default:
+            break;
+    }
+}
+
+/*!
+ *  @brief This API is used to parse the accelerometer data from the
+ *  FIFO data and store it in the instance of the structure bmi160_sensor_data.
+ */
+static void unpack_accel_data(struct bmi160_sensor_data *accel_data,
+                              uint16_t data_start_index,
+                              const struct bmi160_dev *dev)
+{
+    uint16_t data_lsb;
+    uint16_t data_msb;
+
+    /* Accel raw x data */
+    data_lsb = dev->fifo->data[data_start_index++];
+    data_msb = dev->fifo->data[data_start_index++];
+    accel_data->x = (int16_t)((data_msb << 8) | data_lsb);
+
+    /* Accel raw y data */
+    data_lsb = dev->fifo->data[data_start_index++];
+    data_msb = dev->fifo->data[data_start_index++];
+    accel_data->y = (int16_t)((data_msb << 8) | data_lsb);
+
+    /* Accel raw z data */
+    data_lsb = dev->fifo->data[data_start_index++];
+    data_msb = dev->fifo->data[data_start_index++];
+    accel_data->z = (int16_t)((data_msb << 8) | data_lsb);
+}
+
+/*!
+ *  @brief This API is used to parse the accelerometer data from the
+ *  FIFO data in header mode.
+ */
+static void extract_accel_header_mode(struct bmi160_sensor_data *accel_data,
+                                      uint8_t *accel_length,
+                                      const struct bmi160_dev *dev)
+{
+    uint8_t frame_header = 0;
+    uint16_t data_index;
+    uint8_t accel_index = 0;
+
+    for (data_index = dev->fifo->accel_byte_start_idx; data_index < dev->fifo->length;)
+    {
+        /* extracting Frame header */
+        frame_header = (dev->fifo->data[data_index] & BMI160_FIFO_TAG_INTR_MASK);
+
+        /*Index is moved to next byte where the data is starting*/
+        data_index++;
+        switch (frame_header)
+        {
+            /* Accel frame */
+            case BMI160_FIFO_HEAD_A:
+            case BMI160_FIFO_HEAD_M_A:
+            case BMI160_FIFO_HEAD_G_A:
+            case BMI160_FIFO_HEAD_M_G_A:
+                unpack_accel_frame(accel_data, &data_index, &accel_index, frame_header, dev);
+                break;
+            case BMI160_FIFO_HEAD_M:
+                move_next_frame(&data_index, BMI160_FIFO_M_LENGTH, dev);
+                break;
+            case BMI160_FIFO_HEAD_G:
+                move_next_frame(&data_index, BMI160_FIFO_G_LENGTH, dev);
+                break;
+            case BMI160_FIFO_HEAD_M_G:
+                move_next_frame(&data_index, BMI160_FIFO_MG_LENGTH, dev);
+                break;
+
+            /* Sensor time frame */
+            case BMI160_FIFO_HEAD_SENSOR_TIME:
+                unpack_sensortime_frame(&data_index, dev);
+                break;
+
+            /* Skip frame */
+            case BMI160_FIFO_HEAD_SKIP_FRAME:
+                unpack_skipped_frame(&data_index, dev);
+                break;
+
+            /* Input config frame */
+            case BMI160_FIFO_HEAD_INPUT_CONFIG:
+                move_next_frame(&data_index, 1, dev);
+                break;
+            case BMI160_FIFO_HEAD_OVER_READ:
+
+                /* Update the data index as complete in case of Over read */
+                data_index = dev->fifo->length;
+                break;
+            default:
+                break;
+        }
+        if (*accel_length == accel_index)
+        {
+            /* Number of frames to read completed */
+            break;
+        }
+    }
+
+    /*Update number of accel data read*/
+    *accel_length = accel_index;
+
+    /*Update the accel frame index*/
+    dev->fifo->accel_byte_start_idx = data_index;
+}
+
+/*!
+ *  @brief This API computes the number of bytes of gyro FIFO data
+ *  which is to be parsed in header-less mode
+ */
+static void get_gyro_len_to_parse(uint16_t *data_index,
+                                  uint16_t *data_read_length,
+                                  const uint8_t *gyro_frame_count,
+                                  const struct bmi160_dev *dev)
+{
+    /* Data start index */
+    *data_index = dev->fifo->gyro_byte_start_idx;
+    if (dev->fifo->fifo_data_enable == BMI160_FIFO_G_ENABLE)
+    {
+        *data_read_length = (*gyro_frame_count) * BMI160_FIFO_G_LENGTH;
+    }
+    else if (dev->fifo->fifo_data_enable == BMI160_FIFO_G_A_ENABLE)
+    {
+        *data_read_length = (*gyro_frame_count) * BMI160_FIFO_GA_LENGTH;
+    }
+    else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_ENABLE)
+    {
+        *data_read_length = (*gyro_frame_count) * BMI160_FIFO_MG_LENGTH;
+    }
+    else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_A_ENABLE)
+    {
+        *data_read_length = (*gyro_frame_count) * BMI160_FIFO_MGA_LENGTH;
+    }
+    else
+    {
+        /* When gyro is not enabled ,there will be no gyro data.
+         * so we update the data index as complete */
+        *data_index = dev->fifo->length;
+    }
+
+    if (*data_read_length > dev->fifo->length)
+    {
+        /* Handling the case where more data is requested
+         * than that is available*/
+        *data_read_length = dev->fifo->length;
+    }
+}
+
+/*!
+ *  @brief This API is used to parse the gyroscope's data from the
+ *  FIFO data in both header mode and header-less mode.
+ *  It updates the idx value which is used to store the index of
+ *  the current data byte which is parsed.
+ */
+static void unpack_gyro_frame(struct bmi160_sensor_data *gyro,
+                              uint16_t *idx,
+                              uint8_t *gyro_idx,
+                              uint8_t frame_info,
+                              const struct bmi160_dev *dev)
+{
+    switch (frame_info)
+    {
+        case BMI160_FIFO_HEAD_G:
+        case BMI160_FIFO_G_ENABLE:
+
+            /*Partial read, then skip the data*/
+            if ((*idx + BMI160_FIFO_G_LENGTH) > dev->fifo->length)
+            {
+                /*Update the data index as complete*/
+                *idx = dev->fifo->length;
+                break;
+            }
+
+            /*Unpack the data array into structure instance "gyro"*/
+            unpack_gyro_data(&gyro[*gyro_idx], *idx, dev);
+
+            /*Move the data index*/
+            (*idx) = (*idx) + BMI160_FIFO_G_LENGTH;
+            (*gyro_idx)++;
+            break;
+        case BMI160_FIFO_HEAD_G_A:
+        case BMI160_FIFO_G_A_ENABLE:
+
+            /*Partial read, then skip the data*/
+            if ((*idx + BMI160_FIFO_GA_LENGTH) > dev->fifo->length)
+            {
+                /*Update the data index as complete*/
+                *idx = dev->fifo->length;
+                break;
+            }
+
+            /* Unpack the data array into structure instance "gyro" */
+            unpack_gyro_data(&gyro[*gyro_idx], *idx, dev);
+
+            /* Move the data index */
+            *idx = *idx + BMI160_FIFO_GA_LENGTH;
+            (*gyro_idx)++;
+            break;
+        case BMI160_FIFO_HEAD_M_G_A:
+        case BMI160_FIFO_M_G_A_ENABLE:
+
+            /*Partial read, then skip the data*/
+            if ((*idx + BMI160_FIFO_MGA_LENGTH) > dev->fifo->length)
+            {
+                /*Update the data index as complete*/
+                *idx = dev->fifo->length;
+                break;
+            }
+
+            /*Unpack the data array into structure instance "gyro"*/
+            unpack_gyro_data(&gyro[*gyro_idx], *idx + BMI160_FIFO_M_LENGTH, dev);
+
+            /*Move the data index*/
+            *idx = *idx + BMI160_FIFO_MGA_LENGTH;
+            (*gyro_idx)++;
+            break;
+        case BMI160_FIFO_HEAD_M_A:
+        case BMI160_FIFO_M_A_ENABLE:
+
+            /* Move the data index */
+            *idx = *idx + BMI160_FIFO_MA_LENGTH;
+            break;
+        case BMI160_FIFO_HEAD_M:
+        case BMI160_FIFO_M_ENABLE:
+            (*idx) = (*idx) + BMI160_FIFO_M_LENGTH;
+            break;
+        case BMI160_FIFO_HEAD_M_G:
+        case BMI160_FIFO_M_G_ENABLE:
+
+            /*Partial read, then skip the data*/
+            if ((*idx + BMI160_FIFO_MG_LENGTH) > dev->fifo->length)
+            {
+                /*Update the data index as complete*/
+                *idx = dev->fifo->length;
+                break;
+            }
+
+            /*Unpack the data array into structure instance "gyro"*/
+            unpack_gyro_data(&gyro[*gyro_idx], *idx + BMI160_FIFO_M_LENGTH, dev);
+
+            /*Move the data index*/
+            (*idx) = (*idx) + BMI160_FIFO_MG_LENGTH;
+            (*gyro_idx)++;
+            break;
+        case BMI160_FIFO_HEAD_A:
+        case BMI160_FIFO_A_ENABLE:
+
+            /*Move the data index*/
+            *idx = *idx + BMI160_FIFO_A_LENGTH;
+            break;
+        default:
+            break;
+    }
+}
+
+/*!
+ *  @brief This API is used to parse the gyro data from the
+ *  FIFO data and store it in the instance of the structure bmi160_sensor_data.
+ */
+static void unpack_gyro_data(struct bmi160_sensor_data *gyro_data,
+                             uint16_t data_start_index,
+                             const struct bmi160_dev *dev)
+{
+    uint16_t data_lsb;
+    uint16_t data_msb;
+
+    /* Gyro raw x data */
+    data_lsb = dev->fifo->data[data_start_index++];
+    data_msb = dev->fifo->data[data_start_index++];
+    gyro_data->x = (int16_t)((data_msb << 8) | data_lsb);
+
+    /* Gyro raw y data */
+    data_lsb = dev->fifo->data[data_start_index++];
+    data_msb = dev->fifo->data[data_start_index++];
+    gyro_data->y = (int16_t)((data_msb << 8) | data_lsb);
+
+    /* Gyro raw z data */
+    data_lsb = dev->fifo->data[data_start_index++];
+    data_msb = dev->fifo->data[data_start_index++];
+    gyro_data->z = (int16_t)((data_msb << 8) | data_lsb);
+}
+
+/*!
+ *  @brief This API is used to parse the gyro data from the
+ *  FIFO data in header mode.
+ */
+static void extract_gyro_header_mode(struct bmi160_sensor_data *gyro_data,
+                                     uint8_t *gyro_length,
+                                     const struct bmi160_dev *dev)
+{
+    uint8_t frame_header = 0;
+    uint16_t data_index;
+    uint8_t gyro_index = 0;
+
+    for (data_index = dev->fifo->gyro_byte_start_idx; data_index < dev->fifo->length;)
+    {
+        /* extracting Frame header */
+        frame_header = (dev->fifo->data[data_index] & BMI160_FIFO_TAG_INTR_MASK);
+
+        /*Index is moved to next byte where the data is starting*/
+        data_index++;
+        switch (frame_header)
+        {
+            /* GYRO frame */
+            case BMI160_FIFO_HEAD_G:
+            case BMI160_FIFO_HEAD_G_A:
+            case BMI160_FIFO_HEAD_M_G:
+            case BMI160_FIFO_HEAD_M_G_A:
+                unpack_gyro_frame(gyro_data, &data_index, &gyro_index, frame_header, dev);
+                break;
+            case BMI160_FIFO_HEAD_A:
+                move_next_frame(&data_index, BMI160_FIFO_A_LENGTH, dev);
+                break;
+            case BMI160_FIFO_HEAD_M:
+                move_next_frame(&data_index, BMI160_FIFO_M_LENGTH, dev);
+                break;
+            case BMI160_FIFO_HEAD_M_A:
+                move_next_frame(&data_index, BMI160_FIFO_M_LENGTH, dev);
+                break;
+
+            /* Sensor time frame */
+            case BMI160_FIFO_HEAD_SENSOR_TIME:
+                unpack_sensortime_frame(&data_index, dev);
+                break;
+
+            /* Skip frame */
+            case BMI160_FIFO_HEAD_SKIP_FRAME:
+                unpack_skipped_frame(&data_index, dev);
+                break;
+
+            /* Input config frame */
+            case BMI160_FIFO_HEAD_INPUT_CONFIG:
+                move_next_frame(&data_index, 1, dev);
+                break;
+            case BMI160_FIFO_HEAD_OVER_READ:
+
+                /* Update the data index as complete in case of over read */
+                data_index = dev->fifo->length;
+                break;
+            default:
+                break;
+        }
+        if (*gyro_length == gyro_index)
+        {
+            /*Number of frames to read completed*/
+            break;
+        }
+    }
+
+    /*Update number of gyro data read*/
+    *gyro_length = gyro_index;
+
+    /*Update the gyro frame index*/
+    dev->fifo->gyro_byte_start_idx = data_index;
+}
+
+/*!
+ *  @brief This API computes the number of bytes of aux FIFO data
+ *  which is to be parsed in header-less mode
+ */
+static void get_aux_len_to_parse(uint16_t *data_index,
+                                 uint16_t *data_read_length,
+                                 const uint8_t *aux_frame_count,
+                                 const struct bmi160_dev *dev)
+{
+    /* Data start index */
+    *data_index = dev->fifo->gyro_byte_start_idx;
+    if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_ENABLE)
+    {
+        *data_read_length = (*aux_frame_count) * BMI160_FIFO_M_LENGTH;
+    }
+    else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_A_ENABLE)
+    {
+        *data_read_length = (*aux_frame_count) * BMI160_FIFO_MA_LENGTH;
+    }
+    else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_ENABLE)
+    {
+        *data_read_length = (*aux_frame_count) * BMI160_FIFO_MG_LENGTH;
+    }
+    else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_A_ENABLE)
+    {
+        *data_read_length = (*aux_frame_count) * BMI160_FIFO_MGA_LENGTH;
+    }
+    else
+    {
+        /* When aux is not enabled ,there will be no aux data.
+         * so we update the data index as complete */
+        *data_index = dev->fifo->length;
+    }
+
+    if (*data_read_length > dev->fifo->length)
+    {
+        /* Handling the case where more data is requested
+         * than that is available */
+        *data_read_length = dev->fifo->length;
+    }
+}
+
+/*!
+ *  @brief This API is used to parse the aux's data from the
+ *  FIFO data in both header mode and header-less mode.
+ *  It updates the idx value which is used to store the index of
+ *  the current data byte which is parsed
+ */
+static void unpack_aux_frame(struct bmi160_aux_data *aux_data,
+                             uint16_t *idx,
+                             uint8_t *aux_index,
+                             uint8_t frame_info,
+                             const struct bmi160_dev *dev)
+{
+    switch (frame_info)
+    {
+        case BMI160_FIFO_HEAD_M:
+        case BMI160_FIFO_M_ENABLE:
+
+            /* Partial read, then skip the data */
+            if ((*idx + BMI160_FIFO_M_LENGTH) > dev->fifo->length)
+            {
+                /* Update the data index as complete */
+                *idx = dev->fifo->length;
+                break;
+            }
+
+            /* Unpack the data array into structure instance */
+            unpack_aux_data(&aux_data[*aux_index], *idx, dev);
+
+            /* Move the data index */
+            *idx = *idx + BMI160_FIFO_M_LENGTH;
+            (*aux_index)++;
+            break;
+        case BMI160_FIFO_HEAD_M_A:
+        case BMI160_FIFO_M_A_ENABLE:
+
+            /* Partial read, then skip the data */
+            if ((*idx + BMI160_FIFO_MA_LENGTH) > dev->fifo->length)
+            {
+                /* Update the data index as complete */
+                *idx = dev->fifo->length;
+                break;
+            }
+
+            /* Unpack the data array into structure instance */
+            unpack_aux_data(&aux_data[*aux_index], *idx, dev);
+
+            /* Move the data index */
+            *idx = *idx + BMI160_FIFO_MA_LENGTH;
+            (*aux_index)++;
+            break;
+        case BMI160_FIFO_HEAD_M_G:
+        case BMI160_FIFO_M_G_ENABLE:
+
+            /* Partial read, then skip the data */
+            if ((*idx + BMI160_FIFO_MG_LENGTH) > dev->fifo->length)
+            {
+                /* Update the data index as complete */
+                *idx = dev->fifo->length;
+                break;
+            }
+
+            /* Unpack the data array into structure instance */
+            unpack_aux_data(&aux_data[*aux_index], *idx, dev);
+
+            /* Move the data index */
+            (*idx) = (*idx) + BMI160_FIFO_MG_LENGTH;
+            (*aux_index)++;
+            break;
+        case BMI160_FIFO_HEAD_M_G_A:
+        case BMI160_FIFO_M_G_A_ENABLE:
+
+            /*Partial read, then skip the data*/
+            if ((*idx + BMI160_FIFO_MGA_LENGTH) > dev->fifo->length)
+            {
+                /* Update the data index as complete */
+                *idx = dev->fifo->length;
+                break;
+            }
+
+            /* Unpack the data array into structure instance */
+            unpack_aux_data(&aux_data[*aux_index], *idx, dev);
+
+            /*Move the data index*/
+            *idx = *idx + BMI160_FIFO_MGA_LENGTH;
+            (*aux_index)++;
+            break;
+        case BMI160_FIFO_HEAD_G:
+        case BMI160_FIFO_G_ENABLE:
+
+            /* Move the data index */
+            (*idx) = (*idx) + BMI160_FIFO_G_LENGTH;
+            break;
+        case BMI160_FIFO_HEAD_G_A:
+        case BMI160_FIFO_G_A_ENABLE:
+
+            /* Move the data index */
+            *idx = *idx + BMI160_FIFO_GA_LENGTH;
+            break;
+        case BMI160_FIFO_HEAD_A:
+        case BMI160_FIFO_A_ENABLE:
+
+            /* Move the data index */
+            *idx = *idx + BMI160_FIFO_A_LENGTH;
+            break;
+        default:
+            break;
+    }
+}
+
+/*!
+ *  @brief This API is used to parse the aux data from the
+ *  FIFO data and store it in the instance of the structure bmi160_aux_data.
+ */
+static void unpack_aux_data(struct bmi160_aux_data *aux_data, uint16_t data_start_index, const struct bmi160_dev *dev)
+{
+    /* Aux data bytes */
+    aux_data->data[0] = dev->fifo->data[data_start_index++];
+    aux_data->data[1] = dev->fifo->data[data_start_index++];
+    aux_data->data[2] = dev->fifo->data[data_start_index++];
+    aux_data->data[3] = dev->fifo->data[data_start_index++];
+    aux_data->data[4] = dev->fifo->data[data_start_index++];
+    aux_data->data[5] = dev->fifo->data[data_start_index++];
+    aux_data->data[6] = dev->fifo->data[data_start_index++];
+    aux_data->data[7] = dev->fifo->data[data_start_index++];
+}
+
+/*!
+ *  @brief This API is used to parse the aux data from the
+ *  FIFO data in header mode.
+ */
+static void extract_aux_header_mode(struct bmi160_aux_data *aux_data, uint8_t *aux_length, const struct bmi160_dev *dev)
+{
+    uint8_t frame_header = 0;
+    uint16_t data_index;
+    uint8_t aux_index = 0;
+
+    for (data_index = dev->fifo->aux_byte_start_idx; data_index < dev->fifo->length;)
+    {
+        /* extracting Frame header */
+        frame_header = (dev->fifo->data[data_index] & BMI160_FIFO_TAG_INTR_MASK);
+
+        /*Index is moved to next byte where the data is starting*/
+        data_index++;
+        switch (frame_header)
+        {
+            /* Aux frame */
+            case BMI160_FIFO_HEAD_M:
+            case BMI160_FIFO_HEAD_M_A:
+            case BMI160_FIFO_HEAD_M_G:
+            case BMI160_FIFO_HEAD_M_G_A:
+                unpack_aux_frame(aux_data, &data_index, &aux_index, frame_header, dev);
+                break;
+            case BMI160_FIFO_HEAD_G:
+                move_next_frame(&data_index, BMI160_FIFO_G_LENGTH, dev);
+                break;
+            case BMI160_FIFO_HEAD_G_A:
+                move_next_frame(&data_index, BMI160_FIFO_GA_LENGTH, dev);
+                break;
+            case BMI160_FIFO_HEAD_A:
+                move_next_frame(&data_index, BMI160_FIFO_A_LENGTH, dev);
+                break;
+
+            /* Sensor time frame */
+            case BMI160_FIFO_HEAD_SENSOR_TIME:
+                unpack_sensortime_frame(&data_index, dev);
+                break;
+
+            /* Skip frame */
+            case BMI160_FIFO_HEAD_SKIP_FRAME:
+                unpack_skipped_frame(&data_index, dev);
+                break;
+
+            /* Input config frame */
+            case BMI160_FIFO_HEAD_INPUT_CONFIG:
+                move_next_frame(&data_index, 1, dev);
+                break;
+            case BMI160_FIFO_HEAD_OVER_READ:
+
+                /* Update the data index as complete in case
+                 * of over read */
+                data_index = dev->fifo->length;
+                break;
+            default:
+
+                /* Update the data index as complete in case of
+                 * getting other headers like 0x00 */
+                data_index = dev->fifo->length;
+                break;
+        }
+        if (*aux_length == aux_index)
+        {
+            /*Number of frames to read completed*/
+            break;
+        }
+    }
+
+    /* Update number of aux data read */
+    *aux_length = aux_index;
+
+    /* Update the aux frame index */
+    dev->fifo->aux_byte_start_idx = data_index;
+}
+
+/*!
+ *  @brief This API checks the presence of non-valid frames in the read fifo data.
+ */
+static void check_frame_validity(uint16_t *data_index, const struct bmi160_dev *dev)
+{
+    if ((*data_index + 2) < dev->fifo->length)
+    {
+        /* Check if FIFO is empty */
+        if ((dev->fifo->data[*data_index] == FIFO_CONFIG_MSB_CHECK) &&
+            (dev->fifo->data[*data_index + 1] == FIFO_CONFIG_LSB_CHECK))
+        {
+            /*Update the data index as complete*/
+            *data_index = dev->fifo->length;
+        }
+    }
+}
+
+/*!
+ *  @brief This API is used to move the data index ahead of the
+ *  current_frame_length parameter when unnecessary FIFO data appears while
+ *  extracting the user specified data.
+ */
+static void move_next_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bmi160_dev *dev)
+{
+    /*Partial read, then move the data index to last data*/
+    if ((*data_index + current_frame_length) > dev->fifo->length)
+    {
+        /*Update the data index as complete*/
+        *data_index = dev->fifo->length;
+    }
+    else
+    {
+        /*Move the data index to next frame*/
+        *data_index = *data_index + current_frame_length;
+    }
+}
+
+/*!
+ *  @brief This API is used to parse and store the sensor time from the
+ *  FIFO data in the structure instance dev.
+ */
+static void unpack_sensortime_frame(uint16_t *data_index, const struct bmi160_dev *dev)
+{
+    uint32_t sensor_time_byte3 = 0;
+    uint16_t sensor_time_byte2 = 0;
+    uint8_t sensor_time_byte1 = 0;
+
+    /*Partial read, then move the data index to last data*/
+    if ((*data_index + BMI160_SENSOR_TIME_LENGTH) > dev->fifo->length)
+    {
+        /*Update the data index as complete*/
+        *data_index = dev->fifo->length;
+    }
+    else
+    {
+        sensor_time_byte3 = dev->fifo->data[(*data_index) + BMI160_SENSOR_TIME_MSB_BYTE] << 16;
+        sensor_time_byte2 = dev->fifo->data[(*data_index) + BMI160_SENSOR_TIME_XLSB_BYTE] << 8;
+        sensor_time_byte1 = dev->fifo->data[(*data_index)];
+
+        /* Sensor time */
+        dev->fifo->sensor_time = (uint32_t)(sensor_time_byte3 | sensor_time_byte2 | sensor_time_byte1);
+        *data_index = (*data_index) + BMI160_SENSOR_TIME_LENGTH;
+    }
+}
+
+/*!
+ *  @brief This API is used to parse and store the skipped_frame_count from
+ *  the FIFO data in the structure instance dev.
+ */
+static void unpack_skipped_frame(uint16_t *data_index, const struct bmi160_dev *dev)
+{
+    /*Partial read, then move the data index to last data*/
+    if (*data_index >= dev->fifo->length)
+    {
+        /*Update the data index as complete*/
+        *data_index = dev->fifo->length;
+    }
+    else
+    {
+        dev->fifo->skipped_frame_count = dev->fifo->data[*data_index];
+
+        /*Move the data index*/
+        *data_index = (*data_index) + 1;
+    }
+}
+
+/*!
+ *  @brief This API is used to get the FOC status from the sensor
+ */
+static int8_t get_foc_status(uint8_t *foc_status, struct bmi160_dev const *dev)
+{
+    int8_t rslt;
+    uint8_t data;
+
+    /* Read the FOC status from sensor */
+    rslt = bmi160_get_regs(BMI160_STATUS_ADDR, &data, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* Get the foc_status bit */
+        *foc_status = BMI160_GET_BITS(data, BMI160_FOC_STATUS);
+    }
+
+    return rslt;
+}
+
+/*!
+ *  @brief This API is used to configure the offset enable bits in the sensor
+ */
+static int8_t configure_offset_enable(const struct bmi160_foc_conf *foc_conf, struct bmi160_dev const *dev)
+{
+    int8_t rslt;
+    uint8_t data;
+
+    /* Null-pointer check */
+    rslt = null_ptr_check(dev);
+    if (rslt != BMI160_OK)
+    {
+        rslt = BMI160_E_NULL_PTR;
+    }
+    else
+    {
+        /* Read the FOC config from the sensor */
+        rslt = bmi160_get_regs(BMI160_OFFSET_CONF_ADDR, &data, 1, dev);
+        if (rslt == BMI160_OK)
+        {
+            /* Set the offset enable/disable for gyro */
+            data = BMI160_SET_BITS(data, BMI160_GYRO_OFFSET_EN, foc_conf->gyro_off_en);
+
+            /* Set the offset enable/disable for accel */
+            data = BMI160_SET_BITS(data, BMI160_ACCEL_OFFSET_EN, foc_conf->acc_off_en);
+
+            /* Set the offset config in the sensor */
+            rslt = bmi160_set_regs(BMI160_OFFSET_CONF_ADDR, &data, 1, dev);
+        }
+    }
+
+    return rslt;
+}
+
+static int8_t trigger_foc(struct bmi160_offsets *offset, struct bmi160_dev const *dev)
+{
+    int8_t rslt;
+    uint8_t foc_status = BMI160_ENABLE;
+    uint8_t cmd = BMI160_START_FOC_CMD;
+    uint8_t timeout = 0;
+    uint8_t data_array[20];
+
+    /* Start the FOC process */
+    rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &cmd, 1, dev);
+    if (rslt == BMI160_OK)
+    {
+        /* Check the FOC status*/
+        rslt = get_foc_status(&foc_status, dev);
+
+        if ((rslt != BMI160_OK) || (foc_status != BMI160_ENABLE))
+        {
+            while ((foc_status != BMI160_ENABLE) && (timeout < 11))
+            {
+                /* Maximum time of 250ms is given in 10
+                 * steps of 25ms each - 250ms refer datasheet 2.9.1 */
+                dev->delay_ms(25);
+
+                /* Check the FOC status*/
+                rslt = get_foc_status(&foc_status, dev);
+                timeout++;
+            }
+
+            if ((rslt == BMI160_OK) && (foc_status == BMI160_ENABLE))
+            {
+                /* Get offset values from sensor */
+                rslt = bmi160_get_offsets(offset, dev);
+            }
+            else
+            {
+                /* FOC failure case */
+                rslt = BMI160_E_FOC_FAILURE;
+            }
+        }
+
+        if (rslt == BMI160_OK)
+        {
+            /* Read registers 0x04-0x17 */
+            rslt = bmi160_get_regs(BMI160_GYRO_DATA_ADDR, data_array, 20, dev);
+        }
+    }
+
+    return rslt;
+}

+ 969 - 0
tracking/imu/bmi160.h

@@ -0,0 +1,969 @@
+/**
+* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved.
+*
+* BSD-3-Clause
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+* 2. Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+* 3. Neither the name of the copyright holder nor the names of its
+*    contributors may be used to endorse or promote products derived from
+*    this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+* @file       bmi160.h
+* @date       2021-10-05
+* @version    v3.9.2
+*
+*/
+
+/*!
+ * @defgroup bmi160 BMI160
+ */
+
+#ifndef BMI160_H_
+#define BMI160_H_
+
+/*************************** C++ guard macro *****************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "bmi160_defs.h"
+#ifdef __KERNEL__
+#include <bmi160_math.h>
+#else
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#endif
+
+/*********************** User function prototypes ************************/
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiInit Initialization
+ * @brief Initialize the sensor and device structure
+ */
+
+/*!
+ * \ingroup bmi160ApiInit
+ * \page bmi160_api_bmi160_init bmi160_init
+ * \code
+ * int8_t bmi160_init(struct bmi160_dev *dev);
+ * \endcode
+ * @details This API is the entry point for sensor.It performs
+ *  the selection of I2C/SPI read mechanism according to the
+ *  selected interface and reads the chip-id of bmi160 sensor.
+ *
+ *  @param[in,out] dev : Structure instance of bmi160_dev
+ *  @note : Refer user guide for detailed info.
+ *
+ *  @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_init(struct bmi160_dev *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiRegs Registers
+ * @brief Read data from the given register address of sensor
+ */
+
+/*!
+ * \ingroup bmi160ApiRegs
+ * \page bmi160_api_bmi160_get_regs bmi160_get_regs
+ * \code
+ * int8_t bmi160_get_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_dev *dev);
+ * \endcode
+ * @details This API reads the data from the given register address of sensor.
+ *
+ * @param[in] reg_addr  : Register address from where the data to be read
+ * @param[out] data     : Pointer to data buffer to store the read data.
+ * @param[in] len       : No of bytes of data to be read.
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @note For most of the registers auto address increment applies, with the
+ * exception of a few special registers, which trap the address. For e.g.,
+ * Register address - 0x24(BMI160_FIFO_DATA_ADDR)
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_get_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_dev *dev);
+
+/*!
+ * \ingroup bmi160ApiRegs
+ * \page bmi160_api_bmi160_set_regs bmi160_set_regs
+ * \code
+ * int8_t bmi160_set_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_dev *dev);
+ * \endcode
+ * @details This API writes the given data to the register address
+ * of sensor.
+ *
+ * @param[in] reg_addr  : Register address from where the data to be written.
+ * @param[in] data      : Pointer to data buffer which is to be written
+ * in the sensor.
+ * @param[in] len       : No of bytes of data to write..
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_set_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_dev *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiSoftreset Soft reset
+ * @brief Perform soft reset of the sensor
+ */
+
+/*!
+ * \ingroup bmi160ApiSoftreset
+ * \page bmi160_api_bmi160_soft_reset bmi160_soft_reset
+ * \code
+ * int8_t bmi160_soft_reset(struct bmi160_dev *dev);
+ * \endcode
+ * @details This API resets and restarts the device.
+ * All register values are overwritten with default parameters.
+ *
+ * @param[in] dev  : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_soft_reset(struct bmi160_dev *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiConfig Configuration
+ * @brief Configuration of the sensor
+ */
+
+/*!
+ * \ingroup bmi160ApiConfig
+ * \page bmi160_api_bmi160_set_sens_conf bmi160_set_sens_conf
+ * \code
+ * int8_t bmi160_set_sens_conf(struct bmi160_dev *dev);
+ * \endcode
+ * @details This API configures the power mode, range and bandwidth
+ * of sensor.
+ *
+ * @param[in] dev    : Structure instance of bmi160_dev.
+ * @note : Refer user guide for detailed info.
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_set_sens_conf(struct bmi160_dev *dev);
+
+/*!
+ * \ingroup bmi160ApiConfig
+ * \page bmi160_api_bmi160_get_sens_conf bmi160_get_sens_conf
+ * \code
+ * int8_t bmi160_get_sens_conf(struct bmi160_dev *dev);
+ * \endcode
+ * @details This API gets accel and gyro configurations.
+ *
+ * @param[out] dev    : Structure instance of bmi160_dev.
+ * @note : Refer user guide for detailed info.
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_get_sens_conf(struct bmi160_dev *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiPowermode Power mode
+ * @brief Set / Get power mode of the sensor
+ */
+
+/*!
+ * \ingroup bmi160ApiPowermode
+ * \page bmi160_api_bmi160_set_power_mode bmi160_set_power_mode
+ * \code
+ * int8_t bmi160_set_power_mode(struct bmi160_dev *dev);
+ * \endcode
+ * @details This API sets the power mode of the sensor.
+ *
+ * @param[in] dev  : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_set_power_mode(struct bmi160_dev *dev);
+
+/*!
+ * \ingroup bmi160ApiPowermode
+ * \page bmi160_api_bmi160_get_power_mode bmi160_get_power_mode
+ * \code
+ * int8_t bmi160_get_power_mode(struct bmi160_dev *dev);
+ * \endcode
+ * @details This API gets the power mode of the sensor.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_get_power_mode(struct bmi160_dev *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiData Sensor Data
+ * @brief Read sensor data
+ */
+
+/*!
+ * \ingroup bmi160ApiData
+ * \page bmi160_api_bmi160_get_sensor_data bmi160_get_sensor_data
+ * \code
+ * int8_t bmi160_get_sensor_data(uint8_t select_sensor,
+ *                             struct bmi160_sensor_data *accel,
+ *                             struct bmi160_sensor_data *gyro,
+ *                             const struct bmi160_dev *dev);
+ *
+ * \endcode
+ * @details This API reads sensor data, stores it in
+ * the bmi160_sensor_data structure pointer passed by the user.
+ * The user can ask for accel data ,gyro data or both sensor
+ * data using bmi160_select_sensor enum
+ *
+ * @param[in] select_sensor    : enum to choose accel,gyro or both sensor data
+ * @param[out] accel    : Structure pointer to store accel data
+ * @param[out] gyro     : Structure pointer to store gyro data
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ * @note : Refer user guide for detailed info.
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_get_sensor_data(uint8_t select_sensor,
+                              struct bmi160_sensor_data *accel,
+                              struct bmi160_sensor_data *gyro,
+                              const struct bmi160_dev *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiInt Interrupt configuration
+ * @brief Set interrupt configuration of the sensor
+ */
+
+/*!
+ * \ingroup bmi160ApiInt
+ * \page bmi160_api_bmi160_set_int_config bmi160_set_int_config
+ * \code
+ * int8_t bmi160_set_int_config(struct bmi160_int_settg *int_config, struct bmi160_dev *dev);
+ * \endcode
+ * @details This API configures the necessary interrupt based on
+ *  the user settings in the bmi160_int_settg structure instance.
+ *
+ * @param[in] int_config  : Structure instance of bmi160_int_settg.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ * @note : Refer user guide for detailed info.
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_set_int_config(struct bmi160_int_settg *int_config, struct bmi160_dev *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiStepC Step counter
+ * @brief Step counter operations
+ */
+
+/*!
+ * \ingroup bmi160ApiStepC
+ * \page bmi160_api_bmi160_set_step_counter bmi160_set_step_counter
+ * \code
+ * int8_t bmi160_set_step_counter(uint8_t step_cnt_enable, const struct bmi160_dev *dev);
+ * \endcode
+ * @details This API enables the step counter feature.
+ *
+ * @param[in] step_cnt_enable   : value to enable or disable
+ * @param[in] dev       : Structure instance of bmi160_dev.
+ * @note : Refer user guide for detailed info.
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_set_step_counter(uint8_t step_cnt_enable, const struct bmi160_dev *dev);
+
+/*!
+ * \ingroup bmi160ApiStepC
+ * \page bmi160_api_bmi160_read_step_counter bmi160_read_step_counter
+ * \code
+ * int8_t bmi160_read_step_counter(uint16_t *step_val, const struct bmi160_dev *dev);
+ * \endcode
+ * @details This API reads the step counter value.
+ *
+ * @param[in] step_val    : Pointer to store the step counter value.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ * @note : Refer user guide for detailed info.
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_read_step_counter(uint16_t *step_val, const struct bmi160_dev *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiAux Auxiliary sensor
+ * @brief Auxiliary sensor operations
+ */
+
+/*!
+ * \ingroup bmi160ApiAux
+ * \page bmi160_api_bmi160_aux_read bmi160_aux_read
+ * \code
+ * int8_t bmi160_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev);
+ * \endcode
+ * @details This API reads the mention no of byte of data from the given
+ * register address of auxiliary sensor.
+ *
+ * @param[in] reg_addr    : Address of register to read.
+ * @param[in] aux_data    : Pointer to store the read data.
+ * @param[in] len     : No of bytes to read.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ * @note : Refer user guide for detailed info.
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev);
+
+/*!
+ * \ingroup bmi160ApiAux
+ * \page bmi160_api_bmi160_aux_write bmi160_aux_write
+ * \code
+ * int8_t bmi160_aux_write(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev);
+ * \endcode
+ * @details This API writes the mention no of byte of data to the given
+ * register address of auxiliary sensor.
+ *
+ * @param[in] reg_addr    : Address of register to write.
+ * @param[in] aux_data    : Pointer to write data.
+ * @param[in] len     : No of bytes to write.
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ * @note : Refer user guide for detailed info.
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_aux_write(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev);
+
+/*!
+ * \ingroup bmi160ApiAux
+ * \page bmi160_api_bmi160_aux_init bmi160_aux_init
+ * \code
+ * int8_t bmi160_aux_init(const struct bmi160_dev *dev);
+ * \endcode
+ * @details This API initialize the auxiliary sensor
+ * in order to access it.
+ *
+ * @param[in] dev         : Structure instance of bmi160_dev.
+ * @note : Refer user guide for detailed info.
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_aux_init(const struct bmi160_dev *dev);
+
+/*!
+ * \ingroup bmi160ApiAux
+ * \page bmi160_api_bmi160_set_aux_auto_mode bmi160_set_aux_auto_mode
+ * \code
+ * int8_t bmi160_set_aux_auto_mode(uint8_t *data_addr, struct bmi160_dev *dev);
+ * \endcode
+ * @details This API is used to setup the auxiliary sensor of bmi160 in auto mode
+ * Thus enabling the auto update of 8 bytes of data from auxiliary sensor
+ * to BMI160 register address 0x04 to 0x0B
+ *
+ * @param[in] data_addr    : Starting address of aux. sensor's data register
+ *                           (BMI160 registers 0x04 to 0x0B will be updated
+ *                           with 8 bytes of data from auxiliary sensor
+ *                           starting from this register address.)
+ * @param[in] dev      : Structure instance of bmi160_dev.
+ *
+ * @note : Set the value of auxiliary polling rate by setting
+ *         dev->aux_cfg.aux_odr to the required value from the table
+ *         before calling this API
+ *
+ *@verbatim
+ *   dev->aux_cfg.aux_odr  |   Auxiliary ODR (Hz)
+ *  -----------------------|-----------------------
+ *  BMI160_AUX_ODR_0_78HZ  |        25/32
+ *  BMI160_AUX_ODR_1_56HZ  |        25/16
+ *  BMI160_AUX_ODR_3_12HZ  |        25/8
+ *  BMI160_AUX_ODR_6_25HZ  |        25/4
+ *  BMI160_AUX_ODR_12_5HZ  |        25/2
+ *  BMI160_AUX_ODR_25HZ    |        25
+ *  BMI160_AUX_ODR_50HZ    |        50
+ *  BMI160_AUX_ODR_100HZ   |        100
+ *  BMI160_AUX_ODR_200HZ   |        200
+ *  BMI160_AUX_ODR_400HZ   |        400
+ *  BMI160_AUX_ODR_800HZ   |        800
+ *@endverbatim
+ *
+ * @note : Other values of  dev->aux_cfg.aux_odr are reserved and not for use
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_set_aux_auto_mode(uint8_t *data_addr, struct bmi160_dev *dev);
+
+/*!
+ * \ingroup bmi160ApiAux
+ * \page bmi160_api_bmi160_config_aux_mode bmi160_config_aux_mode
+ * \code
+ * int8_t bmi160_config_aux_mode(const struct bmi160_dev *dev);
+ * \endcode
+ * @details This API configures the 0x4C register and settings like
+ * Auxiliary sensor manual enable/ disable and aux burst read length.
+ *
+ * @param[in] dev    : Structure instance of bmi160_dev.
+ *
+ * @return Result of API execution status
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_config_aux_mode(const struct bmi160_dev *dev);
+
+/*!
+ * \ingroup bmi160ApiAux
+ * \page bmi160_api_bmi160_read_aux_data_auto_mode bmi160_read_aux_data_auto_mode
+ * \code
+ * int8_t bmi160_read_aux_data_auto_mode(uint8_t *aux_data, const struct bmi160_dev *dev);
+ * \endcode
+ * @details This API is used to read the raw uncompensated auxiliary sensor
+ * data of 8 bytes from BMI160 register address 0x04 to 0x0B
+ *
+ * @param[in] aux_data       : Pointer to user array of length 8 bytes
+ *                             Ensure that the aux_data array is of
+ *                             length 8 bytes
+ * @param[in] dev        : Structure instance of bmi160_dev
+ *
+ * @retval zero -> Success  / -ve value -> Error
+ * @retval Zero Success
+ * @retval Negative Error
+ */
+int8_t bmi160_read_aux_data_auto_mode(uint8_t *aux_data, const struct bmi160_dev *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiSelfTest Self test
+ * @brief Perform self test of the sensor
+ */
+
+/*!
+ * \ingroup bmi160ApiSelfTest
+ * \page bmi160_api_bmi160_perform_self_test bmi160_perform_self_test
+ * \code
+ * int8_t bmi160_perform_self_test(uint8_t select_sensor, struct bmi160_dev *dev);
+ * \endcode
+ * @details This is used to perform self test of accel/gyro of the BMI160 sensor
+ *
+ * @param[in] select_sensor  : enum to choose accel or gyro for self test
+ * @param[in] dev            : Structure instance of bmi160_dev
+ *
+ * @note self test can be performed either for accel/gyro at any instant.
+ *
+ *@verbatim
+ *     value of select_sensor       |  Inference
+ *----------------------------------|--------------------------------
+ *   BMI160_ACCEL_ONLY              | Accel self test enabled
+ *   BMI160_GYRO_ONLY               | Gyro self test enabled
+ *   BMI160_BOTH_ACCEL_AND_GYRO     | NOT TO BE USED
+ *@endverbatim
+ *
+ * @note The return value of this API gives us the result of self test.
+ *
+ * @note Performing self test does soft reset of the sensor, User can
+ * set the desired settings after performing the self test.
+ *
+ * @return Result of API execution status
+ * @retval  BMI160_OK                       Self test success
+ * @retval  BMI160_W_GYRO_SELF_TEST_FAIL    Gyro self test fail
+ * @retval  BMI160_W_ACCEl_SELF_TEST_FAIL   Accel self test fail
+ */
+int8_t bmi160_perform_self_test(uint8_t select_sensor, struct bmi160_dev *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiFIFO FIFO
+ * @brief FIFO operations of the sensor
+ */
+
+/*!
+ * \ingroup bmi160ApiFIFO
+ * \page bmi160_api_bmi160_get_fifo_data bmi160_get_fifo_data
+ * \code
+ * int8_t bmi160_get_fifo_data(struct bmi160_dev const *dev);
+ * \endcode
+ * @details This API reads data from the fifo buffer.
+ *
+ *  @note User has to allocate the FIFO buffer along with
+ *  corresponding fifo length from his side before calling this API
+ *  as mentioned in the readme.md
+ *
+ *  @note User must specify the number of bytes to read from the FIFO in
+ *  dev->fifo->length , It will be updated by the number of bytes actually
+ *  read from FIFO after calling this API
+ *
+ *  @param[in] dev     : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval Zero Success
+ *  @retval Negative Error
+ */
+int8_t bmi160_get_fifo_data(struct bmi160_dev const *dev);
+
+/*!
+ * \ingroup bmi160ApiFIFO
+ * \page bmi160_api_bmi160_set_fifo_flush bmi160_set_fifo_flush
+ * \code
+ * int8_t bmi160_set_fifo_flush(const struct bmi160_dev *dev);
+ * \endcode
+ * @details This API writes fifo_flush command to command register.This
+ *  action clears all data in the Fifo without changing fifo configuration
+ *  settings.
+ *
+ *  @param[in] dev     : Structure instance of bmi160_dev
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ *
+ */
+int8_t bmi160_set_fifo_flush(const struct bmi160_dev *dev);
+
+/*!
+ * \ingroup bmi160ApiFIFO
+ * \page bmi160_api_bmi160_set_fifo_config bmi160_set_fifo_config
+ * \code
+ * int8_t bmi160_set_fifo_config(uint8_t config, uint8_t enable, struct bmi160_dev const *dev);
+ * \endcode
+ * @details This API sets the FIFO configuration in the sensor.
+ *
+ *  @param[in] config : variable used to specify the FIFO
+ *  configurations which are to be enabled or disabled in the sensor.
+ *
+ *  @note : User can set either set one or more or all FIFO configurations
+ *  by ORing the below mentioned macros.
+ *
+ *@verbatim
+ *      config                  |   Value
+ *      ------------------------|---------------------------
+ *      BMI160_FIFO_TIME        |   0x02
+ *      BMI160_FIFO_TAG_INT2    |   0x04
+ *      BMI160_FIFO_TAG_INT1    |   0x08
+ *      BMI160_FIFO_HEADER      |   0x10
+ *      BMI160_FIFO_AUX         |   0x20
+ *      BMI160_FIFO_ACCEL       |   0x40
+ *      BMI160_FIFO_GYRO        |   0x80
+ *@endverbatim
+ *
+ *  @param[in] enable : Parameter used to enable or disable the above
+ *  FIFO configuration
+ *  @param[in] dev : Structure instance of bmi160_dev.
+ *
+ *  @return status of bus communication result
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ *
+ */
+int8_t bmi160_set_fifo_config(uint8_t config, uint8_t enable, struct bmi160_dev const *dev);
+
+/*!
+ * \ingroup bmi160ApiFIFO
+ * \page bmi160_api_bmi160_set_fifo_down bmi160_set_fifo_down
+ * \code
+ * int8_t bmi160_set_fifo_down(uint8_t fifo_down, const struct bmi160_dev *dev);
+ * \endcode
+ * @details This API is used to configure the down sampling ratios of
+ *  the accel and gyro data for FIFO.Also, it configures filtered or
+ *  pre-filtered data for the fifo for accel and gyro.
+ *
+ *  @param[in] fifo_down : variable used to specify the FIFO down
+ *  configurations which are to be enabled or disabled in the sensor.
+ *
+ *  @note The user must select one among the following macros to
+ *  select down-sampling ratio for accel
+ *
+ *@verbatim
+ *      config                               |   Value
+ *      -------------------------------------|---------------------------
+ *      BMI160_ACCEL_FIFO_DOWN_ZERO          |   0x00
+ *      BMI160_ACCEL_FIFO_DOWN_ONE           |   0x10
+ *      BMI160_ACCEL_FIFO_DOWN_TWO           |   0x20
+ *      BMI160_ACCEL_FIFO_DOWN_THREE         |   0x30
+ *      BMI160_ACCEL_FIFO_DOWN_FOUR          |   0x40
+ *      BMI160_ACCEL_FIFO_DOWN_FIVE          |   0x50
+ *      BMI160_ACCEL_FIFO_DOWN_SIX           |   0x60
+ *      BMI160_ACCEL_FIFO_DOWN_SEVEN         |   0x70
+ *@endverbatim
+ *
+ *  @note The user must select one among the following macros to
+ *  select down-sampling ratio for gyro
+ *
+ *@verbatim
+ *      config                               |   Value
+ *      -------------------------------------|---------------------------
+ *      BMI160_GYRO_FIFO_DOWN_ZERO           |   0x00
+ *      BMI160_GYRO_FIFO_DOWN_ONE            |   0x01
+ *      BMI160_GYRO_FIFO_DOWN_TWO            |   0x02
+ *      BMI160_GYRO_FIFO_DOWN_THREE          |   0x03
+ *      BMI160_GYRO_FIFO_DOWN_FOUR           |   0x04
+ *      BMI160_GYRO_FIFO_DOWN_FIVE           |   0x05
+ *      BMI160_GYRO_FIFO_DOWN_SIX            |   0x06
+ *      BMI160_GYRO_FIFO_DOWN_SEVEN          |   0x07
+ *@endverbatim
+ *
+ *  @note The user can enable filtered accel data by the following macro
+ *
+ *@verbatim
+ *      config                               |   Value
+ *      -------------------------------------|---------------------------
+ *      BMI160_ACCEL_FIFO_FILT_EN            |   0x80
+ *@endverbatim
+ *
+ *  @note The user can enable filtered gyro data by the following macro
+ *
+ *@verbatim
+ *      config                               |   Value
+ *      -------------------------------------|---------------------------
+ *      BMI160_GYRO_FIFO_FILT_EN             |   0x08
+ *@endverbatim
+ *
+ *  @note : By ORing the above mentioned macros, the user can select
+ *  the required FIFO down config settings
+ *
+ *  @param[in] dev : Structure instance of bmi160_dev.
+ *
+ *  @return status of bus communication result
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ *
+ */
+int8_t bmi160_set_fifo_down(uint8_t fifo_down, const struct bmi160_dev *dev);
+
+/*!
+ * \ingroup bmi160ApiFIFO
+ * \page bmi160_api_bmi160_set_fifo_wm bmi160_set_fifo_wm
+ * \code
+ * int8_t bmi160_set_fifo_wm(uint8_t fifo_wm, const struct bmi160_dev *dev);
+ * \endcode
+ * @details This API sets the FIFO watermark level in the sensor.
+ *
+ *  @note The FIFO watermark is issued when the FIFO fill level is
+ *  equal or above the watermark level and units of watermark is 4 bytes.
+ *
+ *  @param[in]  fifo_wm        : Variable used to set the FIFO water mark level
+ *  @param[in]  dev            : Structure instance of bmi160_dev
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ *
+ */
+int8_t bmi160_set_fifo_wm(uint8_t fifo_wm, const struct bmi160_dev *dev);
+
+/*!
+ * \ingroup bmi160ApiFIFO
+ * \page bmi160_api_bmi160_extract_accel bmi160_extract_accel
+ * \code
+ * int8_t bmi160_extract_accel(struct bmi160_sensor_data *accel_data, uint8_t *accel_length, struct bmi160_dev const
+ **dev);
+ * \endcode
+ * @details This API parses and extracts the accelerometer frames from
+ *  FIFO data read by the "bmi160_get_fifo_data" API and stores it in
+ *  the "accel_data" structure instance.
+ *
+ *  @note The bmi160_extract_accel API should be called only after
+ *  reading the FIFO data by calling the bmi160_get_fifo_data() API.
+ *
+ *  @param[out] accel_data    : Structure instance of bmi160_sensor_data
+ *                              where the accelerometer data in FIFO is stored.
+ *  @param[in,out] accel_length  : Number of valid accelerometer frames
+ *                              (x,y,z axes data) read out from fifo.
+ *  @param[in] dev            : Structure instance of bmi160_dev.
+ *
+ *  @note accel_length is updated with the number of valid accelerometer
+ *  frames extracted from fifo (1 accel frame   = 6 bytes) at the end of
+ *  execution of this API.
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ *
+ */
+int8_t bmi160_extract_accel(struct bmi160_sensor_data *accel_data, uint8_t *accel_length, struct bmi160_dev const *dev);
+
+/*!
+ * \ingroup bmi160ApiFIFO
+ * \page bmi160_api_bmi160_extract_gyro bmi160_extract_gyro
+ * \code
+ * int8_t bmi160_extract_gyro(struct bmi160_sensor_data *gyro_data, uint8_t *gyro_length, struct bmi160_dev const *dev);
+ * \endcode
+ * @details This API parses and extracts the gyro frames from
+ *  FIFO data read by the "bmi160_get_fifo_data" API and stores it in
+ *  the "gyro_data" structure instance.
+ *
+ *  @note The bmi160_extract_gyro API should be called only after
+ *  reading the FIFO data by calling the bmi160_get_fifo_data() API.
+ *
+ *  @param[out] gyro_data    : Structure instance of bmi160_sensor_data
+ *                             where the gyro data in FIFO is stored.
+ *  @param[in,out] gyro_length  : Number of valid gyro frames
+ *                             (x,y,z axes data) read out from fifo.
+ *  @param[in] dev           : Structure instance of bmi160_dev.
+ *
+ *  @note gyro_length is updated with the number of valid gyro
+ *  frames extracted from fifo (1 gyro frame   = 6 bytes) at the end of
+ *  execution of this API.
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ *
+ */
+int8_t bmi160_extract_gyro(struct bmi160_sensor_data *gyro_data, uint8_t *gyro_length, struct bmi160_dev const *dev);
+
+/*!
+ * \ingroup bmi160ApiFIFO
+ * \page bmi160_api_bmi160_extract_aux bmi160_extract_aux
+ * \code
+ * int8_t bmi160_extract_aux(struct bmi160_aux_data *aux_data, uint8_t *aux_len, struct bmi160_dev const *dev);
+ * \endcode
+ * @details This API parses and extracts the aux frames from
+ *  FIFO data read by the "bmi160_get_fifo_data" API and stores it in
+ *  the bmi160_aux_data structure instance.
+ *
+ *  @note The bmi160_extract_aux API should be called only after
+ *  reading the FIFO data by calling the bmi160_get_fifo_data() API.
+ *
+ *  @param[out] aux_data    : Structure instance of bmi160_aux_data
+ *                            where the aux data in FIFO is stored.
+ *  @param[in,out] aux_len  : Number of valid aux frames (8bytes)
+ *                            read out from FIFO.
+ *  @param[in] dev          : Structure instance of bmi160_dev.
+ *
+ *  @note aux_len is updated with the number of valid aux
+ *  frames extracted from fifo (1 aux frame = 8 bytes) at the end of
+ *  execution of this API.
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ *
+ */
+int8_t bmi160_extract_aux(struct bmi160_aux_data *aux_data, uint8_t *aux_len, struct bmi160_dev const *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiFOC FOC
+ * @brief Start FOC of accel and gyro sensors
+ */
+
+/*!
+ * \ingroup bmi160ApiFOC
+ * \page bmi160_api_bmi160_start_foc bmi160_start_foc
+ * \code
+ * int8_t bmi160_start_foc(const struct bmi160_foc_conf *foc_conf,
+ * \endcode
+ * @details This API starts the FOC of accel and gyro
+ *
+ *  @note FOC should not be used in low-power mode of sensor
+ *
+ *  @note Accel FOC targets values of +1g , 0g , -1g
+ *  Gyro FOC always targets value of 0 dps
+ *
+ *  @param[in] foc_conf    : Structure instance of bmi160_foc_conf which
+ *                                   has the FOC configuration
+ *  @param[in,out] offset  : Structure instance to store Offset
+ *                                   values read from sensor
+ *  @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ *  @note Pre-requisites for triggering FOC in accel , Set the following,
+ *   Enable the acc_off_en
+ *       Ex :  foc_conf.acc_off_en = BMI160_ENABLE;
+ *
+ *   Set the desired target values of FOC to each axes (x,y,z) by using the
+ *   following macros
+ *       - BMI160_FOC_ACCEL_DISABLED
+ *       - BMI160_FOC_ACCEL_POSITIVE_G
+ *       - BMI160_FOC_ACCEL_NEGATIVE_G
+ *       - BMI160_FOC_ACCEL_0G
+ *
+ *   Ex : foc_conf.foc_acc_x  = BMI160_FOC_ACCEL_0G;
+ *        foc_conf.foc_acc_y  = BMI160_FOC_ACCEL_0G;
+ *        foc_conf.foc_acc_z  = BMI160_FOC_ACCEL_POSITIVE_G;
+ *
+ *  @note Pre-requisites for triggering FOC in gyro ,
+ *  Set the following parameters,
+ *
+ *   Ex : foc_conf.foc_gyr_en = BMI160_ENABLE;
+ *        foc_conf.gyro_off_en = BMI160_ENABLE;
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ */
+int8_t bmi160_start_foc(const struct bmi160_foc_conf *foc_conf,
+                        struct bmi160_offsets *offset,
+                        struct bmi160_dev const *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiOffsets Offsets
+ * @brief Set / Get offset values of accel and gyro sensors
+ */
+
+/*!
+ * \ingroup bmi160ApiOffsets
+ * \page bmi160_api_bmi160_get_offsets bmi160_get_offsets
+ * \code
+ * int8_t bmi160_get_offsets(struct bmi160_offsets *offset, const struct bmi160_dev *dev);
+ * \endcode
+ * @details This API reads and stores the offset values of accel and gyro
+ *
+ *  @param[in,out] offset : Structure instance of bmi160_offsets in which
+ *                          the offset values are read and stored
+ *  @param[in] dev        : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ */
+int8_t bmi160_get_offsets(struct bmi160_offsets *offset, const struct bmi160_dev *dev);
+
+/*!
+ * \ingroup bmi160ApiOffsets
+ * \page bmi160_api_bmi160_set_offsets bmi160_set_offsets
+ * \code
+ * int8_t bmi160_set_offsets(const struct bmi160_foc_conf *foc_conf,
+ *                         const struct bmi160_offsets *offset,
+ *                         struct bmi160_dev const *dev);
+ * \endcode
+ * @details This API writes the offset values of accel and gyro to
+ *  the sensor but these values will be reset on POR or soft reset.
+ *
+ *  @param[in] foc_conf    : Structure instance of bmi160_foc_conf which
+ *                                   has the FOC configuration
+ *  @param[in] offset      : Structure instance in which user updates offset
+ *                            values which are to be written in the sensor
+ *  @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ *  @note Offsets can be set by user like offset->off_acc_x = 10;
+ *  where 1LSB = 3.9mg and for gyro 1LSB = 0.061degrees/second
+ *
+ * @note BMI160 offset values for xyz axes of accel should be within range of
+ *  BMI160_ACCEL_MIN_OFFSET (-128) to BMI160_ACCEL_MAX_OFFSET (127)
+ *
+ * @note BMI160 offset values for xyz axes of gyro should be within range of
+ *  BMI160_GYRO_MIN_OFFSET (-512) to BMI160_GYRO_MAX_OFFSET (511)
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ */
+int8_t bmi160_set_offsets(const struct bmi160_foc_conf *foc_conf,
+                          const struct bmi160_offsets *offset,
+                          struct bmi160_dev const *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiNVM NVM
+ * @brief Write image registers values to NVM
+ */
+
+/*!
+ * \ingroup bmi160ApiNVM
+ * \page bmi160_api_bmi160_update_nvm bmi160_update_nvm
+ * \code
+ * int8_t bmi160_update_nvm(struct bmi160_dev const *dev);
+ * \endcode
+ * @details This API writes the image registers values to NVM which is
+ *  stored even after POR or soft reset
+ *
+ *  @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ */
+int8_t bmi160_update_nvm(struct bmi160_dev const *dev);
+
+/**
+ * \ingroup bmi160
+ * \defgroup bmi160ApiInts Interrupt status
+ * @brief Read interrupt status from the sensor
+ */
+
+/*!
+ * \ingroup bmi160ApiInts
+ * \page bmi160_api_bmi160_get_int_status bmi160_get_int_status
+ * \code
+ * int8_t bmi160_get_int_status(enum bmi160_int_status_sel int_status_sel,
+ *                            union bmi160_int_status *int_status,
+ *                            struct bmi160_dev const *dev);
+ * \endcode
+ * @details This API gets the interrupt status from the sensor.
+ *
+ *  @param[in] int_status_sel       : Enum variable to select either individual or all the
+ *  interrupt status bits.
+ *  @param[in] int_status           : pointer variable to get the interrupt status
+ *  from the sensor.
+ *  param[in] dev                   : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ */
+int8_t bmi160_get_int_status(enum bmi160_int_status_sel int_status_sel,
+                             union bmi160_int_status *int_status,
+                             struct bmi160_dev const *dev);
+
+/*************************** C++ guard macro *****************************/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BMI160_H_ */

+ 1647 - 0
tracking/imu/bmi160_defs.h

@@ -0,0 +1,1647 @@
+/**
+* Copyright (c) 2021 Bosch Sensortec GmbH. All rights reserved.
+*
+* BSD-3-Clause
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+* 2. Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+* 3. Neither the name of the copyright holder nor the names of its
+*    contributors may be used to endorse or promote products derived from
+*    this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*
+* @file       bmi160_defs.h
+* @date       2021-10-05
+* @version    v3.9.2
+*
+*/
+
+#ifndef BMI160_DEFS_H_
+#define BMI160_DEFS_H_
+
+/*************************** C types headers *****************************/
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/kernel.h>
+#else
+#include <stdint.h>
+#include <stddef.h>
+#endif
+
+/*************************** Common macros   *****************************/
+
+#if !defined(UINT8_C) && !defined(INT8_C)
+#define INT8_C(x)                                 S8_C(x)
+#define UINT8_C(x)                                U8_C(x)
+#endif
+
+#if !defined(UINT16_C) && !defined(INT16_C)
+#define INT16_C(x)                                S16_C(x)
+#define UINT16_C(x)                               U16_C(x)
+#endif
+
+#if !defined(INT32_C) && !defined(UINT32_C)
+#define INT32_C(x)                                S32_C(x)
+#define UINT32_C(x)                               U32_C(x)
+#endif
+
+#if !defined(INT64_C) && !defined(UINT64_C)
+#define INT64_C(x)                                S64_C(x)
+#define UINT64_C(x)                               U64_C(x)
+#endif
+
+/**@}*/
+/**\name C standard macros */
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL                                      0
+#else
+#define NULL                                      ((void *) 0)
+#endif
+#endif
+
+/*************************** Sensor macros   *****************************/
+/* Test for an endian machine */
+#ifndef __ORDER_LITTLE_ENDIAN__
+#define __ORDER_LITTLE_ENDIAN__                   0
+#endif
+
+#ifndef __BYTE_ORDER__
+#define __BYTE_ORDER__                            __ORDER_LITTLE_ENDIAN__
+#endif
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN                             1
+#endif
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN                                1
+#endif
+#else
+#error "Code does not support Endian format of the processor"
+#endif
+
+/** Mask definitions */
+#define BMI160_ACCEL_BW_MASK                      UINT8_C(0x70)
+#define BMI160_ACCEL_ODR_MASK                     UINT8_C(0x0F)
+#define BMI160_ACCEL_UNDERSAMPLING_MASK           UINT8_C(0x80)
+#define BMI160_ACCEL_RANGE_MASK                   UINT8_C(0x0F)
+#define BMI160_GYRO_BW_MASK                       UINT8_C(0x30)
+#define BMI160_GYRO_ODR_MASK                      UINT8_C(0x0F)
+#define BMI160_GYRO_RANGE_MASK                    UINT8_C(0x07)
+
+#define BMI160_ACCEL_BW_POS                       UINT8_C(4)
+#define BMI160_GYRO_BW_POS                        UINT8_C(4)
+
+/** Mask definitions for INT_EN registers */
+#define BMI160_ANY_MOTION_X_INT_EN_MASK           UINT8_C(0x01)
+#define BMI160_HIGH_G_X_INT_EN_MASK               UINT8_C(0x01)
+#define BMI160_NO_MOTION_X_INT_EN_MASK            UINT8_C(0x01)
+#define BMI160_ANY_MOTION_Y_INT_EN_MASK           UINT8_C(0x02)
+#define BMI160_HIGH_G_Y_INT_EN_MASK               UINT8_C(0x02)
+#define BMI160_NO_MOTION_Y_INT_EN_MASK            UINT8_C(0x02)
+#define BMI160_ANY_MOTION_Z_INT_EN_MASK           UINT8_C(0x04)
+#define BMI160_HIGH_G_Z_INT_EN_MASK               UINT8_C(0x04)
+#define BMI160_NO_MOTION_Z_INT_EN_MASK            UINT8_C(0x04)
+#define BMI160_SIG_MOTION_INT_EN_MASK             UINT8_C(0x07)
+#define BMI160_ANY_MOTION_ALL_INT_EN_MASK         UINT8_C(0x07)
+#define BMI160_STEP_DETECT_INT_EN_MASK            UINT8_C(0x08)
+#define BMI160_DOUBLE_TAP_INT_EN_MASK             UINT8_C(0x10)
+#define BMI160_SINGLE_TAP_INT_EN_MASK             UINT8_C(0x20)
+#define BMI160_FIFO_FULL_INT_EN_MASK              UINT8_C(0x20)
+#define BMI160_ORIENT_INT_EN_MASK                 UINT8_C(0x40)
+#define BMI160_FIFO_WATERMARK_INT_EN_MASK         UINT8_C(0x40)
+#define BMI160_LOW_G_INT_EN_MASK                  UINT8_C(0x08)
+#define BMI160_STEP_DETECT_EN_MASK                UINT8_C(0x08)
+#define BMI160_FLAT_INT_EN_MASK                   UINT8_C(0x80)
+#define BMI160_DATA_RDY_INT_EN_MASK               UINT8_C(0x10)
+
+/** PMU status Macros */
+#define BMI160_AUX_PMU_SUSPEND                    UINT8_C(0x00)
+#define BMI160_AUX_PMU_NORMAL                     UINT8_C(0x01)
+#define BMI160_AUX_PMU_LOW_POWER                  UINT8_C(0x02)
+
+#define BMI160_GYRO_PMU_SUSPEND                   UINT8_C(0x00)
+#define BMI160_GYRO_PMU_NORMAL                    UINT8_C(0x01)
+#define BMI160_GYRO_PMU_FSU                       UINT8_C(0x03)
+
+#define BMI160_ACCEL_PMU_SUSPEND                  UINT8_C(0x00)
+#define BMI160_ACCEL_PMU_NORMAL                   UINT8_C(0x01)
+#define BMI160_ACCEL_PMU_LOW_POWER                UINT8_C(0x02)
+
+/** Mask definitions for INT_OUT_CTRL register */
+#define BMI160_INT1_EDGE_CTRL_MASK                UINT8_C(0x01)
+#define BMI160_INT1_OUTPUT_MODE_MASK              UINT8_C(0x04)
+#define BMI160_INT1_OUTPUT_TYPE_MASK              UINT8_C(0x02)
+#define BMI160_INT1_OUTPUT_EN_MASK                UINT8_C(0x08)
+#define BMI160_INT2_EDGE_CTRL_MASK                UINT8_C(0x10)
+#define BMI160_INT2_OUTPUT_MODE_MASK              UINT8_C(0x40)
+#define BMI160_INT2_OUTPUT_TYPE_MASK              UINT8_C(0x20)
+#define BMI160_INT2_OUTPUT_EN_MASK                UINT8_C(0x80)
+
+/** Mask definitions for INT_LATCH register */
+#define BMI160_INT1_INPUT_EN_MASK                 UINT8_C(0x10)
+#define BMI160_INT2_INPUT_EN_MASK                 UINT8_C(0x20)
+#define BMI160_INT_LATCH_MASK                     UINT8_C(0x0F)
+
+/** Mask definitions for INT_MAP register */
+#define BMI160_INT1_LOW_G_MASK                    UINT8_C(0x01)
+#define BMI160_INT1_HIGH_G_MASK                   UINT8_C(0x02)
+#define BMI160_INT1_SLOPE_MASK                    UINT8_C(0x04)
+#define BMI160_INT1_NO_MOTION_MASK                UINT8_C(0x08)
+#define BMI160_INT1_DOUBLE_TAP_MASK               UINT8_C(0x10)
+#define BMI160_INT1_SINGLE_TAP_MASK               UINT8_C(0x20)
+#define BMI160_INT1_FIFO_FULL_MASK                UINT8_C(0x20)
+#define BMI160_INT1_FIFO_WM_MASK                  UINT8_C(0x40)
+#define BMI160_INT1_ORIENT_MASK                   UINT8_C(0x40)
+#define BMI160_INT1_FLAT_MASK                     UINT8_C(0x80)
+#define BMI160_INT1_DATA_READY_MASK               UINT8_C(0x80)
+#define BMI160_INT2_LOW_G_MASK                    UINT8_C(0x01)
+#define BMI160_INT1_LOW_STEP_DETECT_MASK          UINT8_C(0x01)
+#define BMI160_INT2_LOW_STEP_DETECT_MASK          UINT8_C(0x01)
+#define BMI160_INT2_HIGH_G_MASK                   UINT8_C(0x02)
+#define BMI160_INT2_FIFO_FULL_MASK                UINT8_C(0x02)
+#define BMI160_INT2_FIFO_WM_MASK                  UINT8_C(0x04)
+#define BMI160_INT2_SLOPE_MASK                    UINT8_C(0x04)
+#define BMI160_INT2_DATA_READY_MASK               UINT8_C(0x08)
+#define BMI160_INT2_NO_MOTION_MASK                UINT8_C(0x08)
+#define BMI160_INT2_DOUBLE_TAP_MASK               UINT8_C(0x10)
+#define BMI160_INT2_SINGLE_TAP_MASK               UINT8_C(0x20)
+#define BMI160_INT2_ORIENT_MASK                   UINT8_C(0x40)
+#define BMI160_INT2_FLAT_MASK                     UINT8_C(0x80)
+
+/** Mask definitions for INT_DATA register */
+#define BMI160_TAP_SRC_INT_MASK                   UINT8_C(0x08)
+#define BMI160_LOW_HIGH_SRC_INT_MASK              UINT8_C(0x80)
+#define BMI160_MOTION_SRC_INT_MASK                UINT8_C(0x80)
+
+/** Mask definitions for INT_MOTION register */
+#define BMI160_SLOPE_INT_DUR_MASK                 UINT8_C(0x03)
+#define BMI160_NO_MOTION_INT_DUR_MASK             UINT8_C(0xFC)
+#define BMI160_NO_MOTION_SEL_BIT_MASK             UINT8_C(0x01)
+
+/** Mask definitions for INT_TAP register */
+#define BMI160_TAP_DUR_MASK                       UINT8_C(0x07)
+#define BMI160_TAP_SHOCK_DUR_MASK                 UINT8_C(0x40)
+#define BMI160_TAP_QUIET_DUR_MASK                 UINT8_C(0x80)
+#define BMI160_TAP_THRES_MASK                     UINT8_C(0x1F)
+
+/** Mask definitions for INT_FLAT register */
+#define BMI160_FLAT_THRES_MASK                    UINT8_C(0x3F)
+#define BMI160_FLAT_HOLD_TIME_MASK                UINT8_C(0x30)
+#define BMI160_FLAT_HYST_MASK                     UINT8_C(0x07)
+
+/** Mask definitions for INT_LOWHIGH register */
+#define BMI160_LOW_G_HYST_MASK                    UINT8_C(0x03)
+#define BMI160_LOW_G_LOW_MODE_MASK                UINT8_C(0x04)
+#define BMI160_HIGH_G_HYST_MASK                   UINT8_C(0xC0)
+
+/** Mask definitions for INT_SIG_MOTION register */
+#define BMI160_SIG_MOTION_SEL_MASK                UINT8_C(0x02)
+#define BMI160_SIG_MOTION_SKIP_MASK               UINT8_C(0x0C)
+#define BMI160_SIG_MOTION_PROOF_MASK              UINT8_C(0x30)
+
+/** Mask definitions for INT_ORIENT register */
+#define BMI160_ORIENT_MODE_MASK                   UINT8_C(0x03)
+#define BMI160_ORIENT_BLOCK_MASK                  UINT8_C(0x0C)
+#define BMI160_ORIENT_HYST_MASK                   UINT8_C(0xF0)
+#define BMI160_ORIENT_THETA_MASK                  UINT8_C(0x3F)
+#define BMI160_ORIENT_UD_ENABLE                   UINT8_C(0x40)
+#define BMI160_AXES_EN_MASK                       UINT8_C(0x80)
+
+/** Mask definitions for FIFO_CONFIG register */
+#define BMI160_FIFO_GYRO                          UINT8_C(0x80)
+#define BMI160_FIFO_ACCEL                         UINT8_C(0x40)
+#define BMI160_FIFO_AUX                           UINT8_C(0x20)
+#define BMI160_FIFO_TAG_INT1                      UINT8_C(0x08)
+#define BMI160_FIFO_TAG_INT2                      UINT8_C(0x04)
+#define BMI160_FIFO_TIME                          UINT8_C(0x02)
+#define BMI160_FIFO_HEADER                        UINT8_C(0x10)
+#define BMI160_FIFO_CONFIG_1_MASK                 UINT8_C(0xFE)
+
+/** Mask definitions for STEP_CONF register */
+#define BMI160_STEP_COUNT_EN_BIT_MASK             UINT8_C(0x08)
+#define BMI160_STEP_DETECT_MIN_THRES_MASK         UINT8_C(0x18)
+#define BMI160_STEP_DETECT_STEPTIME_MIN_MASK      UINT8_C(0x07)
+#define BMI160_STEP_MIN_BUF_MASK                  UINT8_C(0x07)
+
+/** Mask definition for FIFO Header Data Tag */
+#define BMI160_FIFO_TAG_INTR_MASK                 UINT8_C(0xFC)
+
+/** Fifo byte counter mask definitions */
+#define BMI160_FIFO_BYTE_COUNTER_MASK             UINT8_C(0x07)
+
+/** Enable/disable bit value */
+#define BMI160_ENABLE                             UINT8_C(0x01)
+#define BMI160_DISABLE                            UINT8_C(0x00)
+
+/** Latch Duration */
+#define BMI160_LATCH_DUR_NONE                     UINT8_C(0x00)
+#define BMI160_LATCH_DUR_312_5_MICRO_SEC          UINT8_C(0x01)
+#define BMI160_LATCH_DUR_625_MICRO_SEC            UINT8_C(0x02)
+#define BMI160_LATCH_DUR_1_25_MILLI_SEC           UINT8_C(0x03)
+#define BMI160_LATCH_DUR_2_5_MILLI_SEC            UINT8_C(0x04)
+#define BMI160_LATCH_DUR_5_MILLI_SEC              UINT8_C(0x05)
+#define BMI160_LATCH_DUR_10_MILLI_SEC             UINT8_C(0x06)
+#define BMI160_LATCH_DUR_20_MILLI_SEC             UINT8_C(0x07)
+#define BMI160_LATCH_DUR_40_MILLI_SEC             UINT8_C(0x08)
+#define BMI160_LATCH_DUR_80_MILLI_SEC             UINT8_C(0x09)
+#define BMI160_LATCH_DUR_160_MILLI_SEC            UINT8_C(0x0A)
+#define BMI160_LATCH_DUR_320_MILLI_SEC            UINT8_C(0x0B)
+#define BMI160_LATCH_DUR_640_MILLI_SEC            UINT8_C(0x0C)
+#define BMI160_LATCH_DUR_1_28_SEC                 UINT8_C(0x0D)
+#define BMI160_LATCH_DUR_2_56_SEC                 UINT8_C(0x0E)
+#define BMI160_LATCHED                            UINT8_C(0x0F)
+
+/** BMI160 Register map */
+#define BMI160_CHIP_ID_ADDR                       UINT8_C(0x00)
+#define BMI160_ERROR_REG_ADDR                     UINT8_C(0x02)
+#define BMI160_PMU_STATUS_ADDR                    UINT8_C(0x03)
+#define BMI160_AUX_DATA_ADDR                      UINT8_C(0x04)
+#define BMI160_GYRO_DATA_ADDR                     UINT8_C(0x0C)
+#define BMI160_ACCEL_DATA_ADDR                    UINT8_C(0x12)
+#define BMI160_STATUS_ADDR                        UINT8_C(0x1B)
+#define BMI160_INT_STATUS_ADDR                    UINT8_C(0x1C)
+#define BMI160_FIFO_LENGTH_ADDR                   UINT8_C(0x22)
+#define BMI160_FIFO_DATA_ADDR                     UINT8_C(0x24)
+#define BMI160_ACCEL_CONFIG_ADDR                  UINT8_C(0x40)
+#define BMI160_ACCEL_RANGE_ADDR                   UINT8_C(0x41)
+#define BMI160_GYRO_CONFIG_ADDR                   UINT8_C(0x42)
+#define BMI160_GYRO_RANGE_ADDR                    UINT8_C(0x43)
+#define BMI160_AUX_ODR_ADDR                       UINT8_C(0x44)
+#define BMI160_FIFO_DOWN_ADDR                     UINT8_C(0x45)
+#define BMI160_FIFO_CONFIG_0_ADDR                 UINT8_C(0x46)
+#define BMI160_FIFO_CONFIG_1_ADDR                 UINT8_C(0x47)
+#define BMI160_AUX_IF_0_ADDR                      UINT8_C(0x4B)
+#define BMI160_AUX_IF_1_ADDR                      UINT8_C(0x4C)
+#define BMI160_AUX_IF_2_ADDR                      UINT8_C(0x4D)
+#define BMI160_AUX_IF_3_ADDR                      UINT8_C(0x4E)
+#define BMI160_AUX_IF_4_ADDR                      UINT8_C(0x4F)
+#define BMI160_INT_ENABLE_0_ADDR                  UINT8_C(0x50)
+#define BMI160_INT_ENABLE_1_ADDR                  UINT8_C(0x51)
+#define BMI160_INT_ENABLE_2_ADDR                  UINT8_C(0x52)
+#define BMI160_INT_OUT_CTRL_ADDR                  UINT8_C(0x53)
+#define BMI160_INT_LATCH_ADDR                     UINT8_C(0x54)
+#define BMI160_INT_MAP_0_ADDR                     UINT8_C(0x55)
+#define BMI160_INT_MAP_1_ADDR                     UINT8_C(0x56)
+#define BMI160_INT_MAP_2_ADDR                     UINT8_C(0x57)
+#define BMI160_INT_DATA_0_ADDR                    UINT8_C(0x58)
+#define BMI160_INT_DATA_1_ADDR                    UINT8_C(0x59)
+#define BMI160_INT_LOWHIGH_0_ADDR                 UINT8_C(0x5A)
+#define BMI160_INT_LOWHIGH_1_ADDR                 UINT8_C(0x5B)
+#define BMI160_INT_LOWHIGH_2_ADDR                 UINT8_C(0x5C)
+#define BMI160_INT_LOWHIGH_3_ADDR                 UINT8_C(0x5D)
+#define BMI160_INT_LOWHIGH_4_ADDR                 UINT8_C(0x5E)
+#define BMI160_INT_MOTION_0_ADDR                  UINT8_C(0x5F)
+#define BMI160_INT_MOTION_1_ADDR                  UINT8_C(0x60)
+#define BMI160_INT_MOTION_2_ADDR                  UINT8_C(0x61)
+#define BMI160_INT_MOTION_3_ADDR                  UINT8_C(0x62)
+#define BMI160_INT_TAP_0_ADDR                     UINT8_C(0x63)
+#define BMI160_INT_TAP_1_ADDR                     UINT8_C(0x64)
+#define BMI160_INT_ORIENT_0_ADDR                  UINT8_C(0x65)
+#define BMI160_INT_ORIENT_1_ADDR                  UINT8_C(0x66)
+#define BMI160_INT_FLAT_0_ADDR                    UINT8_C(0x67)
+#define BMI160_INT_FLAT_1_ADDR                    UINT8_C(0x68)
+#define BMI160_FOC_CONF_ADDR                      UINT8_C(0x69)
+#define BMI160_CONF_ADDR                          UINT8_C(0x6A)
+
+#define BMI160_IF_CONF_ADDR                       UINT8_C(0x6B)
+#define BMI160_SELF_TEST_ADDR                     UINT8_C(0x6D)
+#define BMI160_OFFSET_ADDR                        UINT8_C(0x71)
+#define BMI160_OFFSET_CONF_ADDR                   UINT8_C(0x77)
+#define BMI160_INT_STEP_CNT_0_ADDR                UINT8_C(0x78)
+#define BMI160_INT_STEP_CONFIG_0_ADDR             UINT8_C(0x7A)
+#define BMI160_INT_STEP_CONFIG_1_ADDR             UINT8_C(0x7B)
+#define BMI160_COMMAND_REG_ADDR                   UINT8_C(0x7E)
+#define BMI160_SPI_COMM_TEST_ADDR                 UINT8_C(0x7F)
+#define BMI160_INTL_PULLUP_CONF_ADDR              UINT8_C(0x85)
+
+/** Error code definitions */
+#define BMI160_OK                                 INT8_C(0)
+#define BMI160_E_NULL_PTR                         INT8_C(-1)
+#define BMI160_E_COM_FAIL                         INT8_C(-2)
+#define BMI160_E_DEV_NOT_FOUND                    INT8_C(-3)
+#define BMI160_E_OUT_OF_RANGE                     INT8_C(-4)
+#define BMI160_E_INVALID_INPUT                    INT8_C(-5)
+#define BMI160_E_ACCEL_ODR_BW_INVALID             INT8_C(-6)
+#define BMI160_E_GYRO_ODR_BW_INVALID              INT8_C(-7)
+#define BMI160_E_LWP_PRE_FLTR_INT_INVALID         INT8_C(-8)
+#define BMI160_E_LWP_PRE_FLTR_INVALID             INT8_C(-9)
+#define BMI160_E_AUX_NOT_FOUND                    INT8_C(-10)
+#define BMI160_E_FOC_FAILURE                      INT8_C(-11)
+#define BMI160_E_READ_WRITE_LENGTH_INVALID        INT8_C(-12)
+#define BMI160_E_INVALID_CONFIG                   INT8_C(-13)
+
+/**\name API warning codes */
+#define BMI160_W_GYRO_SELF_TEST_FAIL              INT8_C(1)
+#define BMI160_W_ACCEl_SELF_TEST_FAIL             INT8_C(2)
+
+/** BMI160 unique chip identifier */
+#define BMI160_CHIP_ID                            UINT8_C(0xD3)
+
+/** Soft reset command */
+#define BMI160_SOFT_RESET_CMD                     UINT8_C(0xb6)
+#define BMI160_SOFT_RESET_DELAY_MS                UINT8_C(1)
+
+/** Start FOC command */
+#define BMI160_START_FOC_CMD                      UINT8_C(0x03)
+
+/** NVM backup enabling command */
+#define BMI160_NVM_BACKUP_EN                      UINT8_C(0xA0)
+
+/* Delay in ms settings */
+#define BMI160_ACCEL_DELAY_MS                     UINT8_C(5)
+#define BMI160_GYRO_DELAY_MS                      UINT8_C(80)
+#define BMI160_ONE_MS_DELAY                       UINT8_C(1)
+#define BMI160_AUX_COM_DELAY                      UINT8_C(10)
+#define BMI160_GYRO_SELF_TEST_DELAY               UINT8_C(20)
+#define BMI160_ACCEL_SELF_TEST_DELAY              UINT8_C(50)
+
+/** Self test configurations */
+#define BMI160_ACCEL_SELF_TEST_CONFIG             UINT8_C(0x2C)
+#define BMI160_ACCEL_SELF_TEST_POSITIVE_EN        UINT8_C(0x0D)
+#define BMI160_ACCEL_SELF_TEST_NEGATIVE_EN        UINT8_C(0x09)
+#define BMI160_ACCEL_SELF_TEST_LIMIT              UINT16_C(8192)
+
+/** Power mode settings */
+/* Accel power mode */
+#define BMI160_ACCEL_NORMAL_MODE                  UINT8_C(0x11)
+#define BMI160_ACCEL_LOWPOWER_MODE                UINT8_C(0x12)
+#define BMI160_ACCEL_SUSPEND_MODE                 UINT8_C(0x10)
+
+/* Gyro power mode */
+#define BMI160_GYRO_SUSPEND_MODE                  UINT8_C(0x14)
+#define BMI160_GYRO_NORMAL_MODE                   UINT8_C(0x15)
+#define BMI160_GYRO_FASTSTARTUP_MODE              UINT8_C(0x17)
+
+/* Aux power mode */
+#define BMI160_AUX_SUSPEND_MODE                   UINT8_C(0x18)
+#define BMI160_AUX_NORMAL_MODE                    UINT8_C(0x19)
+#define BMI160_AUX_LOWPOWER_MODE                  UINT8_C(0x1A)
+
+/** Range settings */
+/* Accel Range */
+#define BMI160_ACCEL_RANGE_2G                     UINT8_C(0x03)
+#define BMI160_ACCEL_RANGE_4G                     UINT8_C(0x05)
+#define BMI160_ACCEL_RANGE_8G                     UINT8_C(0x08)
+#define BMI160_ACCEL_RANGE_16G                    UINT8_C(0x0C)
+
+/* Gyro Range */
+#define BMI160_GYRO_RANGE_2000_DPS                UINT8_C(0x00)
+#define BMI160_GYRO_RANGE_1000_DPS                UINT8_C(0x01)
+#define BMI160_GYRO_RANGE_500_DPS                 UINT8_C(0x02)
+#define BMI160_GYRO_RANGE_250_DPS                 UINT8_C(0x03)
+#define BMI160_GYRO_RANGE_125_DPS                 UINT8_C(0x04)
+
+/** Bandwidth settings */
+/* Accel Bandwidth */
+#define BMI160_ACCEL_BW_OSR4_AVG1                 UINT8_C(0x00)
+#define BMI160_ACCEL_BW_OSR2_AVG2                 UINT8_C(0x01)
+#define BMI160_ACCEL_BW_NORMAL_AVG4               UINT8_C(0x02)
+#define BMI160_ACCEL_BW_RES_AVG8                  UINT8_C(0x03)
+#define BMI160_ACCEL_BW_RES_AVG16                 UINT8_C(0x04)
+#define BMI160_ACCEL_BW_RES_AVG32                 UINT8_C(0x05)
+#define BMI160_ACCEL_BW_RES_AVG64                 UINT8_C(0x06)
+#define BMI160_ACCEL_BW_RES_AVG128                UINT8_C(0x07)
+
+#define BMI160_GYRO_BW_OSR4_MODE                  UINT8_C(0x00)
+#define BMI160_GYRO_BW_OSR2_MODE                  UINT8_C(0x01)
+#define BMI160_GYRO_BW_NORMAL_MODE                UINT8_C(0x02)
+
+/* Output Data Rate settings */
+/* Accel Output data rate */
+#define BMI160_ACCEL_ODR_RESERVED                 UINT8_C(0x00)
+#define BMI160_ACCEL_ODR_0_78HZ                   UINT8_C(0x01)
+#define BMI160_ACCEL_ODR_1_56HZ                   UINT8_C(0x02)
+#define BMI160_ACCEL_ODR_3_12HZ                   UINT8_C(0x03)
+#define BMI160_ACCEL_ODR_6_25HZ                   UINT8_C(0x04)
+#define BMI160_ACCEL_ODR_12_5HZ                   UINT8_C(0x05)
+#define BMI160_ACCEL_ODR_25HZ                     UINT8_C(0x06)
+#define BMI160_ACCEL_ODR_50HZ                     UINT8_C(0x07)
+#define BMI160_ACCEL_ODR_100HZ                    UINT8_C(0x08)
+#define BMI160_ACCEL_ODR_200HZ                    UINT8_C(0x09)
+#define BMI160_ACCEL_ODR_400HZ                    UINT8_C(0x0A)
+#define BMI160_ACCEL_ODR_800HZ                    UINT8_C(0x0B)
+#define BMI160_ACCEL_ODR_1600HZ                   UINT8_C(0x0C)
+#define BMI160_ACCEL_ODR_RESERVED0                UINT8_C(0x0D)
+#define BMI160_ACCEL_ODR_RESERVED1                UINT8_C(0x0E)
+#define BMI160_ACCEL_ODR_RESERVED2                UINT8_C(0x0F)
+
+/* Gyro Output data rate */
+#define BMI160_GYRO_ODR_RESERVED                  UINT8_C(0x00)
+#define BMI160_GYRO_ODR_25HZ                      UINT8_C(0x06)
+#define BMI160_GYRO_ODR_50HZ                      UINT8_C(0x07)
+#define BMI160_GYRO_ODR_100HZ                     UINT8_C(0x08)
+#define BMI160_GYRO_ODR_200HZ                     UINT8_C(0x09)
+#define BMI160_GYRO_ODR_400HZ                     UINT8_C(0x0A)
+#define BMI160_GYRO_ODR_800HZ                     UINT8_C(0x0B)
+#define BMI160_GYRO_ODR_1600HZ                    UINT8_C(0x0C)
+#define BMI160_GYRO_ODR_3200HZ                    UINT8_C(0x0D)
+
+/* Auxiliary sensor Output data rate */
+#define BMI160_AUX_ODR_RESERVED                   UINT8_C(0x00)
+#define BMI160_AUX_ODR_0_78HZ                     UINT8_C(0x01)
+#define BMI160_AUX_ODR_1_56HZ                     UINT8_C(0x02)
+#define BMI160_AUX_ODR_3_12HZ                     UINT8_C(0x03)
+#define BMI160_AUX_ODR_6_25HZ                     UINT8_C(0x04)
+#define BMI160_AUX_ODR_12_5HZ                     UINT8_C(0x05)
+#define BMI160_AUX_ODR_25HZ                       UINT8_C(0x06)
+#define BMI160_AUX_ODR_50HZ                       UINT8_C(0x07)
+#define BMI160_AUX_ODR_100HZ                      UINT8_C(0x08)
+#define BMI160_AUX_ODR_200HZ                      UINT8_C(0x09)
+#define BMI160_AUX_ODR_400HZ                      UINT8_C(0x0A)
+#define BMI160_AUX_ODR_800HZ                      UINT8_C(0x0B)
+
+/** FIFO_CONFIG Definitions */
+#define BMI160_FIFO_TIME_ENABLE                   UINT8_C(0x02)
+#define BMI160_FIFO_TAG_INT2_ENABLE               UINT8_C(0x04)
+#define BMI160_FIFO_TAG_INT1_ENABLE               UINT8_C(0x08)
+#define BMI160_FIFO_HEAD_ENABLE                   UINT8_C(0x10)
+#define BMI160_FIFO_M_ENABLE                      UINT8_C(0x20)
+#define BMI160_FIFO_A_ENABLE                      UINT8_C(0x40)
+#define BMI160_FIFO_M_A_ENABLE                    UINT8_C(0x60)
+#define BMI160_FIFO_G_ENABLE                      UINT8_C(0x80)
+#define BMI160_FIFO_M_G_ENABLE                    UINT8_C(0xA0)
+#define BMI160_FIFO_G_A_ENABLE                    UINT8_C(0xC0)
+#define BMI160_FIFO_M_G_A_ENABLE                  UINT8_C(0xE0)
+
+/* Macro to specify the number of bytes over-read from the
+ * FIFO in order to get the sensor time at the end of FIFO */
+#ifndef BMI160_FIFO_BYTES_OVERREAD
+#define BMI160_FIFO_BYTES_OVERREAD                UINT8_C(25)
+#endif
+
+/* Accel, gyro and aux. sensor length and also their combined
+ * length definitions in FIFO */
+#define BMI160_FIFO_G_LENGTH                      UINT8_C(6)
+#define BMI160_FIFO_A_LENGTH                      UINT8_C(6)
+#define BMI160_FIFO_M_LENGTH                      UINT8_C(8)
+#define BMI160_FIFO_GA_LENGTH                     UINT8_C(12)
+#define BMI160_FIFO_MA_LENGTH                     UINT8_C(14)
+#define BMI160_FIFO_MG_LENGTH                     UINT8_C(14)
+#define BMI160_FIFO_MGA_LENGTH                    UINT8_C(20)
+
+/** FIFO Header Data definitions */
+#define BMI160_FIFO_HEAD_SKIP_FRAME               UINT8_C(0x40)
+#define BMI160_FIFO_HEAD_SENSOR_TIME              UINT8_C(0x44)
+#define BMI160_FIFO_HEAD_INPUT_CONFIG             UINT8_C(0x48)
+#define BMI160_FIFO_HEAD_OVER_READ                UINT8_C(0x80)
+#define BMI160_FIFO_HEAD_A                        UINT8_C(0x84)
+#define BMI160_FIFO_HEAD_G                        UINT8_C(0x88)
+#define BMI160_FIFO_HEAD_G_A                      UINT8_C(0x8C)
+#define BMI160_FIFO_HEAD_M                        UINT8_C(0x90)
+#define BMI160_FIFO_HEAD_M_A                      UINT8_C(0x94)
+#define BMI160_FIFO_HEAD_M_G                      UINT8_C(0x98)
+#define BMI160_FIFO_HEAD_M_G_A                    UINT8_C(0x9C)
+
+/** FIFO sensor time length definitions */
+#define BMI160_SENSOR_TIME_LENGTH                 UINT8_C(3)
+
+/** FIFO DOWN selection */
+/* Accel fifo down-sampling values*/
+#define  BMI160_ACCEL_FIFO_DOWN_ZERO              UINT8_C(0x00)
+#define  BMI160_ACCEL_FIFO_DOWN_ONE               UINT8_C(0x10)
+#define  BMI160_ACCEL_FIFO_DOWN_TWO               UINT8_C(0x20)
+#define  BMI160_ACCEL_FIFO_DOWN_THREE             UINT8_C(0x30)
+#define  BMI160_ACCEL_FIFO_DOWN_FOUR              UINT8_C(0x40)
+#define  BMI160_ACCEL_FIFO_DOWN_FIVE              UINT8_C(0x50)
+#define  BMI160_ACCEL_FIFO_DOWN_SIX               UINT8_C(0x60)
+#define  BMI160_ACCEL_FIFO_DOWN_SEVEN             UINT8_C(0x70)
+
+/* Gyro fifo down-smapling values*/
+#define  BMI160_GYRO_FIFO_DOWN_ZERO               UINT8_C(0x00)
+#define  BMI160_GYRO_FIFO_DOWN_ONE                UINT8_C(0x01)
+#define  BMI160_GYRO_FIFO_DOWN_TWO                UINT8_C(0x02)
+#define  BMI160_GYRO_FIFO_DOWN_THREE              UINT8_C(0x03)
+#define  BMI160_GYRO_FIFO_DOWN_FOUR               UINT8_C(0x04)
+#define  BMI160_GYRO_FIFO_DOWN_FIVE               UINT8_C(0x05)
+#define  BMI160_GYRO_FIFO_DOWN_SIX                UINT8_C(0x06)
+#define  BMI160_GYRO_FIFO_DOWN_SEVEN              UINT8_C(0x07)
+
+/* Accel Fifo filter enable*/
+#define  BMI160_ACCEL_FIFO_FILT_EN                UINT8_C(0x80)
+
+/* Gyro Fifo filter enable*/
+#define  BMI160_GYRO_FIFO_FILT_EN                 UINT8_C(0x08)
+
+/** Definitions to check validity of FIFO frames */
+#define FIFO_CONFIG_MSB_CHECK                     UINT8_C(0x80)
+#define FIFO_CONFIG_LSB_CHECK                     UINT8_C(0x00)
+
+/*! BMI160 accel FOC configurations */
+#define BMI160_FOC_ACCEL_DISABLED                 UINT8_C(0x00)
+#define BMI160_FOC_ACCEL_POSITIVE_G               UINT8_C(0x01)
+#define BMI160_FOC_ACCEL_NEGATIVE_G               UINT8_C(0x02)
+#define BMI160_FOC_ACCEL_0G                       UINT8_C(0x03)
+
+/** Array Parameter DefinItions */
+#define BMI160_SENSOR_TIME_LSB_BYTE               UINT8_C(0)
+#define BMI160_SENSOR_TIME_XLSB_BYTE              UINT8_C(1)
+#define BMI160_SENSOR_TIME_MSB_BYTE               UINT8_C(2)
+
+/** Interface settings */
+#define BMI160_SPI_INTF                           UINT8_C(1)
+#define BMI160_I2C_INTF                           UINT8_C(0)
+#define BMI160_SPI_RD_MASK                        UINT8_C(0x80)
+#define BMI160_SPI_WR_MASK                        UINT8_C(0x7F)
+
+/* Sensor & time select definition*/
+#define BMI160_ACCEL_SEL                          UINT8_C(0x01)
+#define BMI160_GYRO_SEL                           UINT8_C(0x02)
+#define BMI160_TIME_SEL                           UINT8_C(0x04)
+
+/* Sensor select mask*/
+#define BMI160_SEN_SEL_MASK                       UINT8_C(0x07)
+
+/* Error code mask */
+#define BMI160_ERR_REG_MASK                       UINT8_C(0x0F)
+
+/* BMI160 I2C address */
+#define BMI160_I2C_ADDR                           UINT8_C(0x68)
+
+/* BMI160 secondary IF address */
+#define BMI160_AUX_BMM150_I2C_ADDR                UINT8_C(0x10)
+
+/** BMI160 Length definitions */
+#define BMI160_ONE                                UINT8_C(1)
+#define BMI160_TWO                                UINT8_C(2)
+#define BMI160_THREE                              UINT8_C(3)
+#define BMI160_FOUR                               UINT8_C(4)
+#define BMI160_FIVE                               UINT8_C(5)
+
+/** BMI160 fifo level Margin */
+#define BMI160_FIFO_LEVEL_MARGIN                  UINT8_C(16)
+
+/** BMI160 fifo flush Command */
+#define BMI160_FIFO_FLUSH_VALUE                   UINT8_C(0xB0)
+
+/** BMI160 offset values for xyz axes of accel */
+#define BMI160_ACCEL_MIN_OFFSET                   INT8_C(-128)
+#define BMI160_ACCEL_MAX_OFFSET                   INT8_C(127)
+
+/** BMI160 offset values for xyz axes of gyro */
+#define BMI160_GYRO_MIN_OFFSET                    INT16_C(-512)
+#define BMI160_GYRO_MAX_OFFSET                    INT16_C(511)
+
+/** BMI160 fifo full interrupt position and mask */
+#define BMI160_FIFO_FULL_INT_POS                  UINT8_C(5)
+#define BMI160_FIFO_FULL_INT_MSK                  UINT8_C(0x20)
+#define BMI160_FIFO_WTM_INT_POS                   UINT8_C(6)
+#define BMI160_FIFO_WTM_INT_MSK                   UINT8_C(0x40)
+
+#define BMI160_FIFO_FULL_INT_PIN1_POS             UINT8_C(5)
+#define BMI160_FIFO_FULL_INT_PIN1_MSK             UINT8_C(0x20)
+#define BMI160_FIFO_FULL_INT_PIN2_POS             UINT8_C(1)
+#define BMI160_FIFO_FULL_INT_PIN2_MSK             UINT8_C(0x02)
+
+#define BMI160_FIFO_WTM_INT_PIN1_POS              UINT8_C(6)
+#define BMI160_FIFO_WTM_INT_PIN1_MSK              UINT8_C(0x40)
+#define BMI160_FIFO_WTM_INT_PIN2_POS              UINT8_C(2)
+#define BMI160_FIFO_WTM_INT_PIN2_MSK              UINT8_C(0x04)
+
+#define BMI160_MANUAL_MODE_EN_POS                 UINT8_C(7)
+#define BMI160_MANUAL_MODE_EN_MSK                 UINT8_C(0x80)
+#define BMI160_AUX_READ_BURST_POS                 UINT8_C(0)
+#define BMI160_AUX_READ_BURST_MSK                 UINT8_C(0x03)
+
+#define BMI160_GYRO_SELF_TEST_POS                 UINT8_C(4)
+#define BMI160_GYRO_SELF_TEST_MSK                 UINT8_C(0x10)
+#define BMI160_GYRO_SELF_TEST_STATUS_POS          UINT8_C(1)
+#define BMI160_GYRO_SELF_TEST_STATUS_MSK          UINT8_C(0x02)
+
+#define BMI160_GYRO_FOC_EN_POS                    UINT8_C(6)
+#define BMI160_GYRO_FOC_EN_MSK                    UINT8_C(0x40)
+
+#define BMI160_ACCEL_FOC_X_CONF_POS               UINT8_C(4)
+#define BMI160_ACCEL_FOC_X_CONF_MSK               UINT8_C(0x30)
+
+#define BMI160_ACCEL_FOC_Y_CONF_POS               UINT8_C(2)
+#define BMI160_ACCEL_FOC_Y_CONF_MSK               UINT8_C(0x0C)
+
+#define BMI160_ACCEL_FOC_Z_CONF_MSK               UINT8_C(0x03)
+
+#define BMI160_FOC_STATUS_POS                     UINT8_C(3)
+#define BMI160_FOC_STATUS_MSK                     UINT8_C(0x08)
+
+#define BMI160_GYRO_OFFSET_X_MSK                  UINT8_C(0x03)
+
+#define BMI160_GYRO_OFFSET_Y_POS                  UINT8_C(2)
+#define BMI160_GYRO_OFFSET_Y_MSK                  UINT8_C(0x0C)
+
+#define BMI160_GYRO_OFFSET_Z_POS                  UINT8_C(4)
+#define BMI160_GYRO_OFFSET_Z_MSK                  UINT8_C(0x30)
+
+#define BMI160_GYRO_OFFSET_EN_POS                 UINT8_C(7)
+#define BMI160_GYRO_OFFSET_EN_MSK                 UINT8_C(0x80)
+
+#define BMI160_ACCEL_OFFSET_EN_POS                UINT8_C(6)
+#define BMI160_ACCEL_OFFSET_EN_MSK                UINT8_C(0x40)
+
+#define BMI160_GYRO_OFFSET_POS                    UINT16_C(8)
+#define BMI160_GYRO_OFFSET_MSK                    UINT16_C(0x0300)
+
+#define BMI160_NVM_UPDATE_POS                     UINT8_C(1)
+#define BMI160_NVM_UPDATE_MSK                     UINT8_C(0x02)
+
+#define BMI160_NVM_STATUS_POS                     UINT8_C(4)
+#define BMI160_NVM_STATUS_MSK                     UINT8_C(0x10)
+
+#define BMI160_MAG_POWER_MODE_MSK                 UINT8_C(0x03)
+
+#define BMI160_ACCEL_POWER_MODE_MSK               UINT8_C(0x30)
+#define BMI160_ACCEL_POWER_MODE_POS               UINT8_C(4)
+
+#define BMI160_GYRO_POWER_MODE_MSK                UINT8_C(0x0C)
+#define BMI160_GYRO_POWER_MODE_POS                UINT8_C(2)
+
+/* BIT SLICE GET AND SET FUNCTIONS */
+#define BMI160_GET_BITS(regvar, bitname) \
+    ((regvar & bitname##_MSK) >> bitname##_POS)
+#define BMI160_SET_BITS(regvar, bitname, val) \
+    ((regvar & ~bitname##_MSK) | \
+     ((val << bitname##_POS) & bitname##_MSK))
+
+#define BMI160_SET_BITS_POS_0(reg_data, bitname, data) \
+    ((reg_data & ~(bitname##_MSK)) | \
+     (data & bitname##_MSK))
+
+#define BMI160_GET_BITS_POS_0(reg_data, bitname)  (reg_data & (bitname##_MSK))
+
+/**\name UTILITY MACROS */
+#define BMI160_SET_LOW_BYTE                       UINT16_C(0x00FF)
+#define BMI160_SET_HIGH_BYTE                      UINT16_C(0xFF00)
+
+#define BMI160_GET_LSB(var)                       (uint8_t)(var & BMI160_SET_LOW_BYTE)
+#define BMI160_GET_MSB(var)                       (uint8_t)((var & BMI160_SET_HIGH_BYTE) >> 8)
+
+/*****************************************************************************/
+/* type definitions */
+
+/*!
+ * @brief Bus communication function pointer which should be mapped to
+ * the platform specific read functions of the user
+ */
+typedef int8_t (*bmi160_read_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t len);
+
+/*!
+ * @brief Bus communication function pointer which should be mapped to
+ * the platform specific write functions of the user
+ */
+typedef int8_t (*bmi160_write_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_data, uint16_t len);
+typedef void (*bmi160_delay_fptr_t)(uint32_t period);
+
+/*************************** Data structures *********************************/
+
+/*!
+ * @brief bmi160 interrupt status selection enum.
+ */
+enum bmi160_int_status_sel {
+    BMI160_INT_STATUS_0 = 1,
+    BMI160_INT_STATUS_1 = 2,
+    BMI160_INT_STATUS_2 = 4,
+    BMI160_INT_STATUS_3 = 8,
+    BMI160_INT_STATUS_ALL = 15
+};
+
+/*!
+ * @brief bmi160 interrupt status bits structure
+ */
+struct bmi160_int_status_bits
+{
+#ifdef LITTLE_ENDIAN
+
+    uint32_t step : 1;
+    uint32_t sigmot : 1;
+    uint32_t anym : 1;
+
+    /* pmu trigger will be handled later */
+    uint32_t pmu_trigger_reserved : 1;
+    uint32_t d_tap : 1;
+    uint32_t s_tap : 1;
+    uint32_t orient : 1;
+    uint32_t flat_int : 1;
+    uint32_t reserved : 2;
+    uint32_t high_g : 1;
+    uint32_t low_g : 1;
+    uint32_t drdy : 1;
+    uint32_t ffull : 1;
+    uint32_t fwm : 1;
+    uint32_t nomo : 1;
+    uint32_t anym_first_x : 1;
+    uint32_t anym_first_y : 1;
+    uint32_t anym_first_z : 1;
+    uint32_t anym_sign : 1;
+    uint32_t tap_first_x : 1;
+    uint32_t tap_first_y : 1;
+    uint32_t tap_first_z : 1;
+    uint32_t tap_sign : 1;
+    uint32_t high_first_x : 1;
+    uint32_t high_first_y : 1;
+    uint32_t high_first_z : 1;
+    uint32_t high_sign : 1;
+    uint32_t orient_1_0 : 2;
+    uint32_t orient_2 : 1;
+    uint32_t flat : 1;
+#else
+    uint32_t high_first_x : 1;
+    uint32_t high_first_y : 1;
+    uint32_t high_first_z : 1;
+    uint32_t high_sign : 1;
+    uint32_t orient_1_0 : 2;
+    uint32_t orient_2 : 1;
+    uint32_t flat : 1;
+    uint32_t anym_first_x : 1;
+    uint32_t anym_first_y : 1;
+    uint32_t anym_first_z : 1;
+    uint32_t anym_sign : 1;
+    uint32_t tap_first_x : 1;
+    uint32_t tap_first_y : 1;
+    uint32_t tap_first_z : 1;
+    uint32_t tap_sign : 1;
+    uint32_t reserved : 2;
+    uint32_t high_g : 1;
+    uint32_t low_g : 1;
+    uint32_t drdy : 1;
+    uint32_t ffull : 1;
+    uint32_t fwm : 1;
+    uint32_t nomo : 1;
+    uint32_t step : 1;
+    uint32_t sigmot : 1;
+    uint32_t anym : 1;
+
+    /* pmu trigger will be handled later */
+    uint32_t pmu_trigger_reserved : 1;
+    uint32_t d_tap : 1;
+    uint32_t s_tap : 1;
+    uint32_t orient : 1;
+    uint32_t flat_int : 1;
+#endif
+};
+
+/*!
+ * @brief bmi160 interrupt status structure
+ */
+union bmi160_int_status
+{
+    uint8_t data[4];
+    struct bmi160_int_status_bits bit;
+};
+
+/*!
+ * @brief bmi160 sensor data structure which comprises of accel data
+ */
+struct bmi160_sensor_data
+{
+    /*! X-axis sensor data */
+    int16_t x;
+
+    /*! Y-axis sensor data */
+    int16_t y;
+
+    /*! Z-axis sensor data */
+    int16_t z;
+
+    /*! sensor time */
+    uint32_t sensortime;
+};
+
+/*!
+ * @brief bmi160 aux data structure which comprises of 8 bytes of accel data
+ */
+struct bmi160_aux_data
+{
+    /*! Auxiliary data */
+    uint8_t data[8];
+};
+
+/*!
+ * @brief bmi160 FOC configuration structure
+ */
+struct bmi160_foc_conf
+{
+    /*! Enabling FOC in gyro
+     * Assignable macros :
+     *  - BMI160_ENABLE
+     *  - BMI160_DISABLE
+     */
+    uint8_t foc_gyr_en;
+
+    /*! Accel FOC configurations
+     * Assignable macros :
+     *  - BMI160_FOC_ACCEL_DISABLED
+     *  - BMI160_FOC_ACCEL_POSITIVE_G
+     *  - BMI160_FOC_ACCEL_NEGATIVE_G
+     *  - BMI160_FOC_ACCEL_0G
+     */
+    uint8_t foc_acc_x;
+    uint8_t foc_acc_y;
+    uint8_t foc_acc_z;
+
+    /*! Enabling offset compensation for accel in data registers
+     * Assignable macros :
+     *  - BMI160_ENABLE
+     *  - BMI160_DISABLE
+     */
+    uint8_t acc_off_en;
+
+    /*! Enabling offset compensation for gyro in data registers
+     * Assignable macros :
+     *  - BMI160_ENABLE
+     *  - BMI160_DISABLE
+     */
+    uint8_t gyro_off_en;
+};
+
+/*!
+ * @brief bmi160 accel gyro offsets
+ */
+struct bmi160_offsets
+{
+    /*! Accel offset for x axis */
+    int8_t off_acc_x;
+
+    /*! Accel offset for y axis */
+    int8_t off_acc_y;
+
+    /*! Accel offset for z axis */
+    int8_t off_acc_z;
+
+    /*! Gyro offset for x axis */
+    int16_t off_gyro_x;
+
+    /*! Gyro offset for y axis */
+    int16_t off_gyro_y;
+
+    /*! Gyro offset for z axis */
+    int16_t off_gyro_z;
+};
+
+/*!
+ * @brief FIFO aux. sensor data structure
+ */
+struct bmi160_aux_fifo_data
+{
+    /*! The value of aux. sensor x LSB data */
+    uint8_t aux_x_lsb;
+
+    /*! The value of aux. sensor x MSB data */
+    uint8_t aux_x_msb;
+
+    /*! The value of aux. sensor y LSB data */
+    uint8_t aux_y_lsb;
+
+    /*! The value of aux. sensor y MSB data */
+    uint8_t aux_y_msb;
+
+    /*! The value of aux. sensor z LSB data */
+    uint8_t aux_z_lsb;
+
+    /*! The value of aux. sensor z MSB data */
+    uint8_t aux_z_msb;
+
+    /*! The value of aux. sensor r for BMM150 LSB data */
+    uint8_t aux_r_y2_lsb;
+
+    /*! The value of aux. sensor r for BMM150 MSB data */
+    uint8_t aux_r_y2_msb;
+};
+
+/*!
+ * @brief bmi160 sensor select structure
+ */
+enum bmi160_select_sensor {
+    BMI160_ACCEL_ONLY = 1,
+    BMI160_GYRO_ONLY,
+    BMI160_BOTH_ACCEL_AND_GYRO
+};
+
+/*!
+ * @brief bmi160 sensor step detector mode structure
+ */
+enum bmi160_step_detect_mode {
+    BMI160_STEP_DETECT_NORMAL,
+    BMI160_STEP_DETECT_SENSITIVE,
+    BMI160_STEP_DETECT_ROBUST,
+
+    /*! Non recommended User defined setting */
+    BMI160_STEP_DETECT_USER_DEFINE
+};
+
+/*!
+ * @brief enum for auxiliary burst read selection
+ */
+enum bmi160_aux_read_len {
+    BMI160_AUX_READ_LEN_0,
+    BMI160_AUX_READ_LEN_1,
+    BMI160_AUX_READ_LEN_2,
+    BMI160_AUX_READ_LEN_3
+};
+
+/*!
+ * @brief bmi160 sensor configuration structure
+ */
+struct bmi160_cfg
+{
+    /*! power mode */
+    uint8_t power;
+
+    /*! output data rate */
+    uint8_t odr;
+
+    /*! range */
+    uint8_t range;
+
+    /*! bandwidth */
+    uint8_t bw;
+};
+
+/*!
+ * @brief Aux sensor configuration structure
+ */
+struct bmi160_aux_cfg
+{
+    /*! Aux sensor, 1 - enable 0 - disable */
+    uint8_t aux_sensor_enable : 1;
+
+    /*! Aux manual/auto mode status */
+    uint8_t manual_enable : 1;
+
+    /*! Aux read burst length */
+    uint8_t aux_rd_burst_len : 2;
+
+    /*! output data rate */
+    uint8_t aux_odr : 4;
+
+    /*! i2c addr of auxiliary sensor */
+    uint8_t aux_i2c_addr;
+};
+
+/*!
+ * @brief bmi160 interrupt channel selection structure
+ */
+enum bmi160_int_channel {
+    /*! Un-map both channels */
+    BMI160_INT_CHANNEL_NONE,
+
+    /*! interrupt Channel 1 */
+    BMI160_INT_CHANNEL_1,
+
+    /*! interrupt Channel 2 */
+    BMI160_INT_CHANNEL_2,
+
+    /*! Map both channels */
+    BMI160_INT_CHANNEL_BOTH
+};
+enum bmi160_int_types {
+    /*! Slope/Any-motion interrupt */
+    BMI160_ACC_ANY_MOTION_INT,
+
+    /*! Significant motion interrupt */
+    BMI160_ACC_SIG_MOTION_INT,
+
+    /*! Step detector interrupt */
+    BMI160_STEP_DETECT_INT,
+
+    /*! double tap interrupt */
+    BMI160_ACC_DOUBLE_TAP_INT,
+
+    /*! single tap interrupt */
+    BMI160_ACC_SINGLE_TAP_INT,
+
+    /*! orientation interrupt */
+    BMI160_ACC_ORIENT_INT,
+
+    /*! flat interrupt */
+    BMI160_ACC_FLAT_INT,
+
+    /*! high-g interrupt */
+    BMI160_ACC_HIGH_G_INT,
+
+    /*! low-g interrupt */
+    BMI160_ACC_LOW_G_INT,
+
+    /*! slow/no-motion interrupt */
+    BMI160_ACC_SLOW_NO_MOTION_INT,
+
+    /*! data ready interrupt  */
+    BMI160_ACC_GYRO_DATA_RDY_INT,
+
+    /*! fifo full interrupt */
+    BMI160_ACC_GYRO_FIFO_FULL_INT,
+
+    /*! fifo watermark interrupt */
+    BMI160_ACC_GYRO_FIFO_WATERMARK_INT,
+
+    /*! fifo tagging feature support */
+    BMI160_FIFO_TAG_INT_PIN
+};
+
+/*!
+ * @brief bmi160 active state of any & sig motion interrupt.
+ */
+enum bmi160_any_sig_motion_active_interrupt_state {
+    /*! Both any & sig motion are disabled */
+    BMI160_BOTH_ANY_SIG_MOTION_DISABLED = -1,
+
+    /*! Any-motion selected */
+    BMI160_ANY_MOTION_ENABLED,
+
+    /*! Sig-motion selected */
+    BMI160_SIG_MOTION_ENABLED
+};
+struct bmi160_acc_tap_int_cfg
+{
+#ifdef LITTLE_ENDIAN
+
+    /*! tap threshold */
+    uint16_t tap_thr : 5;
+
+    /*! tap shock */
+    uint16_t tap_shock : 1;
+
+    /*! tap quiet */
+    uint16_t tap_quiet : 1;
+
+    /*! tap duration */
+    uint16_t tap_dur : 3;
+
+    /*! data source 0- filter & 1 pre-filter*/
+    uint16_t tap_data_src : 1;
+
+    /*! tap enable, 1 - enable, 0 - disable */
+    uint16_t tap_en : 1;
+#else
+
+    /*! tap enable, 1 - enable, 0 - disable */
+    uint16_t tap_en : 1;
+
+    /*! data source 0- filter & 1 pre-filter*/
+    uint16_t tap_data_src : 1;
+
+    /*! tap duration */
+    uint16_t tap_dur : 3;
+
+    /*! tap quiet */
+    uint16_t tap_quiet : 1;
+
+    /*! tap shock */
+    uint16_t tap_shock : 1;
+
+    /*! tap threshold */
+    uint16_t tap_thr : 5;
+#endif
+};
+struct bmi160_acc_any_mot_int_cfg
+{
+#ifdef LITTLE_ENDIAN
+
+    /*! 1 any-motion enable, 0 - any-motion disable */
+    uint8_t anymotion_en : 1;
+
+    /*! slope interrupt x, 1 - enable, 0 - disable */
+    uint8_t anymotion_x : 1;
+
+    /*! slope interrupt y, 1 - enable, 0 - disable */
+    uint8_t anymotion_y : 1;
+
+    /*! slope interrupt z, 1 - enable, 0 - disable */
+    uint8_t anymotion_z : 1;
+
+    /*! slope duration */
+    uint8_t anymotion_dur : 2;
+
+    /*! data source 0- filter & 1 pre-filter*/
+    uint8_t anymotion_data_src : 1;
+
+    /*! slope threshold */
+    uint8_t anymotion_thr;
+#else
+
+    /*! slope threshold */
+    uint8_t anymotion_thr;
+
+    /*! data source 0- filter & 1 pre-filter*/
+    uint8_t anymotion_data_src : 1;
+
+    /*! slope duration */
+    uint8_t anymotion_dur : 2;
+
+    /*! slope interrupt z, 1 - enable, 0 - disable */
+    uint8_t anymotion_z : 1;
+
+    /*! slope interrupt y, 1 - enable, 0 - disable */
+    uint8_t anymotion_y : 1;
+
+    /*! slope interrupt x, 1 - enable, 0 - disable */
+    uint8_t anymotion_x : 1;
+
+    /*! 1 any-motion enable, 0 - any-motion disable */
+    uint8_t anymotion_en : 1;
+#endif
+};
+struct bmi160_acc_sig_mot_int_cfg
+{
+#ifdef LITTLE_ENDIAN
+
+    /*! skip time of sig-motion interrupt */
+    uint8_t sig_mot_skip : 2;
+
+    /*! proof time of sig-motion interrupt */
+    uint8_t sig_mot_proof : 2;
+
+    /*! data source 0- filter & 1 pre-filter*/
+    uint8_t sig_data_src : 1;
+
+    /*! 1 - enable sig, 0 - disable sig & enable anymotion */
+    uint8_t sig_en : 1;
+
+    /*! sig-motion threshold */
+    uint8_t sig_mot_thres;
+#else
+
+    /*! sig-motion threshold */
+    uint8_t sig_mot_thres;
+
+    /*! 1 - enable sig, 0 - disable sig & enable anymotion */
+    uint8_t sig_en : 1;
+
+    /*! data source 0- filter & 1 pre-filter*/
+    uint8_t sig_data_src : 1;
+
+    /*! proof time of sig-motion interrupt */
+    uint8_t sig_mot_proof : 2;
+
+    /*! skip time of sig-motion interrupt */
+    uint8_t sig_mot_skip : 2;
+#endif
+};
+struct bmi160_acc_step_detect_int_cfg
+{
+#ifdef LITTLE_ENDIAN
+
+    /*! 1- step detector enable, 0- step detector disable */
+    uint16_t step_detector_en : 1;
+
+    /*! minimum threshold */
+    uint16_t min_threshold : 2;
+
+    /*! minimal detectable step time */
+    uint16_t steptime_min : 3;
+
+    /*! enable step counter mode setting */
+    uint16_t step_detector_mode : 2;
+
+    /*! minimum step buffer size*/
+    uint16_t step_min_buf : 3;
+#else
+
+    /*! minimum step buffer size*/
+    uint16_t step_min_buf : 3;
+
+    /*! enable step counter mode setting */
+    uint16_t step_detector_mode : 2;
+
+    /*! minimal detectable step time */
+    uint16_t steptime_min : 3;
+
+    /*! minimum threshold */
+    uint16_t min_threshold : 2;
+
+    /*! 1- step detector enable, 0- step detector disable */
+    uint16_t step_detector_en : 1;
+#endif
+};
+struct bmi160_acc_no_motion_int_cfg
+{
+#ifdef LITTLE_ENDIAN
+
+    /*! no motion interrupt x */
+    uint16_t no_motion_x : 1;
+
+    /*! no motion interrupt y */
+    uint16_t no_motion_y : 1;
+
+    /*! no motion interrupt z */
+    uint16_t no_motion_z : 1;
+
+    /*! no motion duration */
+    uint16_t no_motion_dur : 6;
+
+    /*! no motion sel , 1 - enable no-motion ,0- enable slow-motion */
+    uint16_t no_motion_sel : 1;
+
+    /*! data source 0- filter & 1 pre-filter*/
+    uint16_t no_motion_src : 1;
+
+    /*! no motion threshold */
+    uint8_t no_motion_thres;
+#else
+
+    /*! no motion threshold */
+    uint8_t no_motion_thres;
+
+    /*! data source 0- filter & 1 pre-filter*/
+    uint16_t no_motion_src : 1;
+
+    /*! no motion sel , 1 - enable no-motion ,0- enable slow-motion */
+    uint16_t no_motion_sel : 1;
+
+    /*! no motion duration */
+    uint16_t no_motion_dur : 6;
+
+    /* no motion interrupt z */
+    uint16_t no_motion_z : 1;
+
+    /*! no motion interrupt y */
+    uint16_t no_motion_y : 1;
+
+    /*! no motion interrupt x */
+    uint16_t no_motion_x : 1;
+#endif
+};
+struct bmi160_acc_orient_int_cfg
+{
+#ifdef LITTLE_ENDIAN
+
+    /*! thresholds for switching between the different orientations */
+    uint16_t orient_mode : 2;
+
+    /*! blocking_mode */
+    uint16_t orient_blocking : 2;
+
+    /*! Orientation interrupt hysteresis */
+    uint16_t orient_hyst : 4;
+
+    /*! Orientation interrupt theta */
+    uint16_t orient_theta : 6;
+
+    /*! Enable/disable Orientation interrupt */
+    uint16_t orient_ud_en : 1;
+
+    /*! exchange x- and z-axis in algorithm ,0 - z, 1 - x */
+    uint16_t axes_ex : 1;
+
+    /*! 1 - orient enable, 0 - orient disable */
+    uint8_t orient_en : 1;
+#else
+
+    /*! 1 - orient enable, 0 - orient disable */
+    uint8_t orient_en : 1;
+
+    /*! exchange x- and z-axis in algorithm ,0 - z, 1 - x */
+    uint16_t axes_ex : 1;
+
+    /*! Enable/disable Orientation interrupt */
+    uint16_t orient_ud_en : 1;
+
+    /*! Orientation interrupt theta */
+    uint16_t orient_theta : 6;
+
+    /*! Orientation interrupt hysteresis */
+    uint16_t orient_hyst : 4;
+
+    /*! blocking_mode */
+    uint16_t orient_blocking : 2;
+
+    /*! thresholds for switching between the different orientations */
+    uint16_t orient_mode : 2;
+#endif
+};
+struct bmi160_acc_flat_detect_int_cfg
+{
+#ifdef LITTLE_ENDIAN
+
+    /*! flat threshold */
+    uint16_t flat_theta : 6;
+
+    /*! flat interrupt hysteresis */
+    uint16_t flat_hy : 3;
+
+    /*! delay time for which the flat value must remain stable for the
+     * flat interrupt to be generated */
+    uint16_t flat_hold_time : 2;
+
+    /*! 1 - flat enable, 0 - flat disable */
+    uint16_t flat_en : 1;
+#else
+
+    /*! 1 - flat enable, 0 - flat disable */
+    uint16_t flat_en : 1;
+
+    /*! delay time for which the flat value must remain stable for the
+     * flat interrupt to be generated */
+    uint16_t flat_hold_time : 2;
+
+    /*! flat interrupt hysteresis */
+    uint16_t flat_hy : 3;
+
+    /*! flat threshold */
+    uint16_t flat_theta : 6;
+#endif
+};
+struct bmi160_acc_low_g_int_cfg
+{
+#ifdef LITTLE_ENDIAN
+
+    /*! low-g interrupt trigger delay */
+    uint8_t low_dur;
+
+    /*! low-g interrupt trigger threshold */
+    uint8_t low_thres;
+
+    /*! hysteresis of low-g interrupt */
+    uint8_t low_hyst : 2;
+
+    /*! 0 - single-axis mode ,1 - axis-summing mode */
+    uint8_t low_mode : 1;
+
+    /*! data source 0- filter & 1 pre-filter */
+    uint8_t low_data_src : 1;
+
+    /*! 1 - enable low-g, 0 - disable low-g */
+    uint8_t low_en : 1;
+#else
+
+    /*! 1 - enable low-g, 0 - disable low-g */
+    uint8_t low_en : 1;
+
+    /*! data source 0- filter & 1 pre-filter */
+    uint8_t low_data_src : 1;
+
+    /*! 0 - single-axis mode ,1 - axis-summing mode */
+    uint8_t low_mode : 1;
+
+    /*! hysteresis of low-g interrupt */
+    uint8_t low_hyst : 2;
+
+    /*! low-g interrupt trigger threshold */
+    uint8_t low_thres;
+
+    /*! low-g interrupt trigger delay */
+    uint8_t low_dur;
+#endif
+};
+struct bmi160_acc_high_g_int_cfg
+{
+#ifdef LITTLE_ENDIAN
+
+    /*! High-g interrupt x, 1 - enable, 0 - disable */
+    uint8_t high_g_x : 1;
+
+    /*! High-g interrupt y, 1 - enable, 0 - disable */
+    uint8_t high_g_y : 1;
+
+    /*! High-g interrupt z, 1 - enable, 0 - disable */
+    uint8_t high_g_z : 1;
+
+    /*! High-g hysteresis  */
+    uint8_t high_hy : 2;
+
+    /*! data source 0- filter & 1 pre-filter */
+    uint8_t high_data_src : 1;
+
+    /*! High-g threshold */
+    uint8_t high_thres;
+
+    /*! High-g duration */
+    uint8_t high_dur;
+#else
+
+    /*! High-g duration */
+    uint8_t high_dur;
+
+    /*! High-g threshold */
+    uint8_t high_thres;
+
+    /*! data source 0- filter & 1 pre-filter */
+    uint8_t high_data_src : 1;
+
+    /*! High-g hysteresis  */
+    uint8_t high_hy : 2;
+
+    /*! High-g interrupt z, 1 - enable, 0 - disable */
+    uint8_t high_g_z : 1;
+
+    /*! High-g interrupt y, 1 - enable, 0 - disable */
+    uint8_t high_g_y : 1;
+
+    /*! High-g interrupt x, 1 - enable, 0 - disable */
+    uint8_t high_g_x : 1;
+#endif
+};
+struct bmi160_int_pin_settg
+{
+#ifdef LITTLE_ENDIAN
+
+    /*! To enable either INT1 or INT2 pin as output.
+     * 0- output disabled ,1- output enabled */
+    uint16_t output_en : 1;
+
+    /*! 0 - push-pull 1- open drain,only valid if output_en is set 1 */
+    uint16_t output_mode : 1;
+
+    /*! 0 - active low , 1 - active high level.
+     * if output_en is 1,this applies to interrupts,else PMU_trigger */
+    uint16_t output_type : 1;
+
+    /*! 0 - level trigger , 1 - edge trigger  */
+    uint16_t edge_ctrl : 1;
+
+    /*! To enable either INT1 or INT2 pin as input.
+     * 0 - input disabled ,1 - input enabled */
+    uint16_t input_en : 1;
+
+    /*! latch duration*/
+    uint16_t latch_dur : 4;
+#else
+
+    /*! latch duration*/
+    uint16_t latch_dur : 4;
+
+    /*! Latched,non-latched or temporary interrupt modes */
+    uint16_t input_en : 1;
+
+    /*! 1 - edge trigger, 0 - level trigger */
+    uint16_t edge_ctrl : 1;
+
+    /*! 0 - active low , 1 - active high level.
+     * if output_en is 1,this applies to interrupts,else PMU_trigger */
+    uint16_t output_type : 1;
+
+    /*! 0 - push-pull , 1 - open drain,only valid if output_en is set 1 */
+    uint16_t output_mode : 1;
+
+    /*! To enable either INT1 or INT2 pin as output.
+     * 0 - output disabled , 1 - output enabled */
+    uint16_t output_en : 1;
+#endif
+};
+union bmi160_int_type_cfg
+{
+    /*! Tap interrupt structure */
+    struct bmi160_acc_tap_int_cfg acc_tap_int;
+
+    /*! Slope interrupt structure */
+    struct bmi160_acc_any_mot_int_cfg acc_any_motion_int;
+
+    /*! Significant motion interrupt structure */
+    struct bmi160_acc_sig_mot_int_cfg acc_sig_motion_int;
+
+    /*! Step detector interrupt structure */
+    struct bmi160_acc_step_detect_int_cfg acc_step_detect_int;
+
+    /*! No motion interrupt structure */
+    struct bmi160_acc_no_motion_int_cfg acc_no_motion_int;
+
+    /*! Orientation interrupt structure */
+    struct bmi160_acc_orient_int_cfg acc_orient_int;
+
+    /*! Flat interrupt structure */
+    struct bmi160_acc_flat_detect_int_cfg acc_flat_int;
+
+    /*! Low-g interrupt structure */
+    struct bmi160_acc_low_g_int_cfg acc_low_g_int;
+
+    /*! High-g interrupt structure */
+    struct bmi160_acc_high_g_int_cfg acc_high_g_int;
+};
+struct bmi160_int_settg
+{
+    /*! Interrupt channel */
+    enum bmi160_int_channel int_channel;
+
+    /*! Select Interrupt */
+    enum bmi160_int_types int_type;
+
+    /*! Structure configuring Interrupt pins */
+    struct bmi160_int_pin_settg int_pin_settg;
+
+    /*! Union configures required interrupt */
+    union bmi160_int_type_cfg int_type_cfg;
+
+    /*! FIFO FULL INT 1-enable, 0-disable */
+    uint8_t fifo_full_int_en : 1;
+
+    /*! FIFO WTM INT 1-enable, 0-disable */
+    uint8_t fifo_wtm_int_en : 1;
+};
+
+/*!
+ *  @brief This structure holds the information for usage of
+ *  FIFO by the user.
+ */
+struct bmi160_fifo_frame
+{
+    /*! Data buffer of user defined length is to be mapped here */
+    uint8_t *data;
+
+    /*! While calling the API  "bmi160_get_fifo_data" , length stores
+     *  number of bytes in FIFO to be read (specified by user as input)
+     *  and after execution of the API ,number of FIFO data bytes
+     *  available is provided as an output to user
+     */
+    uint16_t length;
+
+    /*! FIFO time enable */
+    uint8_t fifo_time_enable;
+
+    /*! Enabling of the FIFO header to stream in header mode */
+    uint8_t fifo_header_enable;
+
+    /*! Streaming of the Accelerometer, Gyroscope
+     * sensor data or both in FIFO */
+    uint8_t fifo_data_enable;
+
+    /*! Will be equal to length when no more frames are there to parse */
+    uint16_t accel_byte_start_idx;
+
+    /*! Will be equal to length when no more frames are there to parse */
+    uint16_t gyro_byte_start_idx;
+
+    /*! Will be equal to length when no more frames are there to parse */
+    uint16_t aux_byte_start_idx;
+
+    /*! Value of FIFO sensor time time */
+    uint32_t sensor_time;
+
+    /*! Value of Skipped frame counts */
+    uint8_t skipped_frame_count;
+};
+struct bmi160_dev
+{
+    /*! Chip Id */
+    uint8_t chip_id;
+
+    /*! Device Id */
+    uint8_t id;
+
+    /*! 0 - I2C , 1 - SPI Interface */
+    uint8_t intf;
+
+    /*! Hold active interrupts status for any and sig motion
+     *  0 - Any-motion enable, 1 - Sig-motion enable,
+     *  -1 neither any-motion nor sig-motion selected */
+    enum bmi160_any_sig_motion_active_interrupt_state any_sig_sel;
+
+    /*! Structure to configure Accel sensor */
+    struct bmi160_cfg accel_cfg;
+
+    /*! Structure to hold previous/old accel config parameters.
+     * This is used at driver level to prevent overwriting of same
+     * data, hence user does not change it in the code */
+    struct bmi160_cfg prev_accel_cfg;
+
+    /*! Structure to configure Gyro sensor */
+    struct bmi160_cfg gyro_cfg;
+
+    /*! Structure to hold previous/old gyro config parameters.
+     * This is used at driver level to prevent overwriting of same
+     * data, hence user does not change it in the code */
+    struct bmi160_cfg prev_gyro_cfg;
+
+    /*! Structure to configure the auxiliary sensor */
+    struct bmi160_aux_cfg aux_cfg;
+
+    /*! Structure to hold previous/old aux config parameters.
+     * This is used at driver level to prevent overwriting of same
+     * data, hence user does not change it in the code */
+    struct bmi160_aux_cfg prev_aux_cfg;
+
+    /*! FIFO related configurations */
+    struct bmi160_fifo_frame *fifo;
+
+    /*! Read function pointer */
+    bmi160_read_fptr_t read;
+
+    /*! Write function pointer */
+    bmi160_write_fptr_t write;
+
+    /*!  Delay function pointer */
+    bmi160_delay_fptr_t delay_ms;
+
+    /*! User set read/write length */
+    uint16_t read_write_len;
+};
+
+#endif /* BMI160_DEFS_H_ */

+ 29 - 0
tracking/imu/imu.c

@@ -0,0 +1,29 @@
+#include "imu.h"
+#include <furi_hal.h>
+
+bool bmi160_begin();
+int bmi160_read(double* vec);
+
+bool lsm6ds3trc_begin();
+void lsm6ds3trc_end();
+int lsm6ds3trc_read(double* vec);
+
+bool imu_begin() {
+    furi_hal_i2c_acquire(&furi_hal_i2c_handle_external);
+    bool ret = lsm6ds3trc_begin(); // bmi160_begin();
+    furi_hal_i2c_release(&furi_hal_i2c_handle_external);
+    return ret;
+}
+
+void imu_end() {
+    furi_hal_i2c_acquire(&furi_hal_i2c_handle_external);
+    lsm6ds3trc_end(); // 
+    furi_hal_i2c_release(&furi_hal_i2c_handle_external);
+}
+
+int imu_read(double* vec) {
+    furi_hal_i2c_acquire(&furi_hal_i2c_handle_external);
+    int ret = lsm6ds3trc_read(vec); // bmi160_read(vec);
+    furi_hal_i2c_release(&furi_hal_i2c_handle_external);
+    return ret;
+}

+ 18 - 0
tracking/imu/imu.h

@@ -0,0 +1,18 @@
+#pragma once
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ACC_DATA_READY (1 << 0)
+#define GYR_DATA_READY (1 << 1)
+
+bool imu_begin();
+void imu_end();
+int imu_read(double* vec);
+
+#ifdef __cplusplus
+}
+#endif

+ 86 - 0
tracking/imu/imu_bmi160.c

@@ -0,0 +1,86 @@
+#include "bmi160.h"
+
+#include <furi_hal.h>
+
+#include "imu.h"
+
+#define TAG "BMI160"
+
+#define BMI160_DEV_ADDR       (0x69 << 1)
+
+static const double DEG_TO_RAD = 0.017453292519943295769236907684886;
+static const double G = 9.81;
+
+struct bmi160_dev bmi160dev;
+struct bmi160_sensor_data bmi160_accel;
+struct bmi160_sensor_data bmi160_gyro;
+
+int8_t bmi160_write_i2c(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t len) {
+    if (furi_hal_i2c_write_mem(&furi_hal_i2c_handle_external, dev_addr, reg_addr, data, len, 50))
+        return BMI160_OK;
+    return BMI160_E_COM_FAIL;
+}
+
+int8_t bmi160_read_i2c(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_data, uint16_t len) {
+    if (furi_hal_i2c_read_mem(&furi_hal_i2c_handle_external, dev_addr, reg_addr, read_data, len, 50))
+        return BMI160_OK;
+    return BMI160_E_COM_FAIL;
+}
+
+bool bmi160_begin() {
+    FURI_LOG_I(TAG, "Init BMI160");
+
+    if (!furi_hal_i2c_is_device_ready(&furi_hal_i2c_handle_external, BMI160_DEV_ADDR, 50)) {
+        FURI_LOG_E(TAG, "Device not ready!");
+        return false;
+    }
+
+    FURI_LOG_I(TAG, "Device ready!");
+
+    bmi160dev.id = BMI160_DEV_ADDR;
+    bmi160dev.intf = BMI160_I2C_INTF;
+    bmi160dev.read = bmi160_read_i2c;
+    bmi160dev.write = bmi160_write_i2c;
+    bmi160dev.delay_ms = furi_delay_ms;
+
+    if (bmi160_init(&bmi160dev) != BMI160_OK) {
+        FURI_LOG_E(TAG, "Initialization failure!");
+        FURI_LOG_E(TAG, "Chip ID 0x%X", bmi160dev.chip_id);
+        return false;
+    }
+
+    bmi160dev.accel_cfg.odr = BMI160_ACCEL_ODR_400HZ;
+    bmi160dev.accel_cfg.range = BMI160_ACCEL_RANGE_4G;
+    bmi160dev.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4;
+    bmi160dev.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
+    bmi160dev.gyro_cfg.odr = BMI160_GYRO_ODR_400HZ;
+    bmi160dev.gyro_cfg.range = BMI160_GYRO_RANGE_2000_DPS;
+    bmi160dev.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE;
+    bmi160dev.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE;
+
+    if (bmi160_set_sens_conf(&bmi160dev) != BMI160_OK) {
+        FURI_LOG_E(TAG, "Initialization failure!");
+        FURI_LOG_E(TAG, "Chip ID 0x%X", bmi160dev.chip_id);
+        return false;
+    }
+
+    FURI_LOG_I(TAG, "Initialization success!");
+    FURI_LOG_I(TAG, "Chip ID 0x%X", bmi160dev.chip_id);
+
+    return true;
+}
+
+int bmi160_read(float* vec) {
+    if (bmi160_get_sensor_data((BMI160_ACCEL_SEL | BMI160_GYRO_SEL), &bmi160_accel, &bmi160_gyro, &bmi160dev) != BMI160_OK) {
+        return 0;
+    }
+
+    vec[0] = ((double)bmi160_accel.x * 4 / 32768) * G;
+    vec[1] = ((double)bmi160_accel.y * 4 / 32768) * G;
+    vec[2] = ((double)bmi160_accel.z * 4 / 32768) * G;
+    vec[3] = ((double)bmi160_gyro.x * 2000 / 32768) * DEG_TO_RAD;
+    vec[4] = ((double)bmi160_gyro.y * 2000 / 32768) * DEG_TO_RAD;
+    vec[5] = ((double)bmi160_gyro.z * 2000 / 32768) * DEG_TO_RAD;
+
+    return ACC_DATA_READY | GYR_DATA_READY;
+}

+ 96 - 0
tracking/imu/imu_lsm6ds3trc.c

@@ -0,0 +1,96 @@
+#include "lsm6ds3tr-c_reg.h"
+
+#include <furi_hal.h>
+
+#include "imu.h"
+
+#define TAG "LSM6DS3TR-C"
+
+#define LSM6DS3_ADDRESS            (0x6A << 1)
+
+static const double DEG_TO_RAD = 0.017453292519943295769236907684886;
+
+stmdev_ctx_t lsm6ds3trc_ctx;
+
+int32_t lsm6ds3trc_write_i2c(void *handle, uint8_t reg_addr, const uint8_t *data, uint16_t len) {
+    if (furi_hal_i2c_write_mem(handle, LSM6DS3_ADDRESS, reg_addr, (uint8_t *)data, len, 50))
+        return 0;
+    return -1;
+}
+
+int32_t lsm6ds3trc_read_i2c(void *handle, uint8_t reg_addr, uint8_t *read_data, uint16_t len) {
+    if (furi_hal_i2c_read_mem(handle, LSM6DS3_ADDRESS, reg_addr, read_data, len, 50))
+        return 0;
+    return -1;
+}
+
+bool lsm6ds3trc_begin() {
+    FURI_LOG_I(TAG, "Init LSM6DS3TR-C");
+
+    if (!furi_hal_i2c_is_device_ready(&furi_hal_i2c_handle_external, LSM6DS3_ADDRESS, 50)) {
+        FURI_LOG_E(TAG, "Not ready");
+        return false;
+    }
+
+    lsm6ds3trc_ctx.write_reg = lsm6ds3trc_write_i2c;
+    lsm6ds3trc_ctx.read_reg = lsm6ds3trc_read_i2c;
+    lsm6ds3trc_ctx.mdelay = furi_delay_ms;
+    lsm6ds3trc_ctx.handle = &furi_hal_i2c_handle_external;
+
+    uint8_t whoami;
+    lsm6ds3tr_c_device_id_get(&lsm6ds3trc_ctx, &whoami);
+    if (whoami != LSM6DS3TR_C_ID) {
+        FURI_LOG_I(TAG, "Unknown model: %x", (int)whoami);
+        return false;
+    }
+
+    lsm6ds3tr_c_reset_set(&lsm6ds3trc_ctx, PROPERTY_ENABLE);
+    uint8_t rst = PROPERTY_ENABLE;
+    while (rst)
+        lsm6ds3tr_c_reset_get(&lsm6ds3trc_ctx, &rst);
+
+    lsm6ds3tr_c_block_data_update_set(&lsm6ds3trc_ctx, PROPERTY_ENABLE);
+    lsm6ds3tr_c_fifo_mode_set(&lsm6ds3trc_ctx, LSM6DS3TR_C_BYPASS_MODE);
+
+    lsm6ds3tr_c_xl_data_rate_set(&lsm6ds3trc_ctx, LSM6DS3TR_C_XL_ODR_104Hz);
+    lsm6ds3tr_c_xl_full_scale_set(&lsm6ds3trc_ctx, LSM6DS3TR_C_4g);
+    lsm6ds3tr_c_xl_lp1_bandwidth_set(&lsm6ds3trc_ctx, LSM6DS3TR_C_XL_LP1_ODR_DIV_4);
+
+    lsm6ds3tr_c_gy_data_rate_set(&lsm6ds3trc_ctx, LSM6DS3TR_C_GY_ODR_104Hz);
+    lsm6ds3tr_c_gy_full_scale_set(&lsm6ds3trc_ctx, LSM6DS3TR_C_2000dps);
+    lsm6ds3tr_c_gy_power_mode_set(&lsm6ds3trc_ctx, LSM6DS3TR_C_GY_HIGH_PERFORMANCE);
+    lsm6ds3tr_c_gy_band_pass_set(&lsm6ds3trc_ctx, LSM6DS3TR_C_LP2_ONLY);
+
+    FURI_LOG_I(TAG, "Init OK");
+    return true;
+}
+
+void lsm6ds3trc_end() {
+    lsm6ds3tr_c_xl_data_rate_set(&lsm6ds3trc_ctx, LSM6DS3TR_C_XL_ODR_OFF);
+    lsm6ds3tr_c_gy_data_rate_set(&lsm6ds3trc_ctx, LSM6DS3TR_C_GY_ODR_OFF);
+}
+
+int lsm6ds3trc_read(double* vec) {
+    int ret = 0;
+    int16_t data[3];
+    lsm6ds3tr_c_reg_t reg;
+    lsm6ds3tr_c_status_reg_get(&lsm6ds3trc_ctx, &reg.status_reg);
+
+    if (reg.status_reg.xlda) {
+        lsm6ds3tr_c_acceleration_raw_get(&lsm6ds3trc_ctx, data);
+        vec[0] = (double)lsm6ds3tr_c_from_fs2g_to_mg(data[0]) / 1000;
+        vec[1] = (double)lsm6ds3tr_c_from_fs2g_to_mg(data[1]) / 1000;
+        vec[2] = (double)lsm6ds3tr_c_from_fs2g_to_mg(data[2]) / 1000;
+        ret |= ACC_DATA_READY;
+    }
+
+    if (reg.status_reg.gda) {
+        lsm6ds3tr_c_angular_rate_raw_get(&lsm6ds3trc_ctx, data);
+        vec[3] = (double)lsm6ds3tr_c_from_fs2000dps_to_mdps(data[0]) * DEG_TO_RAD / 1000;
+        vec[4] = (double)lsm6ds3tr_c_from_fs2000dps_to_mdps(data[1]) * DEG_TO_RAD / 1000;
+        vec[5] = (double)lsm6ds3tr_c_from_fs2000dps_to_mdps(data[2]) * DEG_TO_RAD / 1000;
+        ret |= GYR_DATA_READY;
+    }
+
+    return ret;
+}

+ 8209 - 0
tracking/imu/lsm6ds3tr-c_reg.c

@@ -0,0 +1,8209 @@
+/**
+  ******************************************************************************
+  * @file    lsm6ds3tr_c_reg.c
+  * @author  Sensors Software Solution Team
+  * @brief   LSM6DS3TR_C driver file
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
+  * All rights reserved.</center></h2>
+  *
+  * This software component is licensed by ST under BSD 3-Clause license,
+  * the "License"; You may not use this file except in compliance with the
+  * License. You may obtain a copy of the License at:
+  *                        opensource.org/licenses/BSD-3-Clause
+  *
+  ******************************************************************************
+  */
+
+#include "lsm6ds3tr-c_reg.h"
+
+/**
+  * @defgroup    LSM6DS3TR_C
+  * @brief       This file provides a set of functions needed to drive the
+  *              lsm6ds3tr_c enanced inertial module.
+  * @{
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_interfaces_functions
+  * @brief       This section provide a set of functions used to read and
+  *              write a generic register of the device.
+  *              MANDATORY: return 0 -> no Error.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Read generic device register
+  *
+  * @param  ctx   read / write interface definitions(ptr)
+  * @param  reg   register to read
+  * @param  data  pointer to buffer that store the data read(ptr)
+  * @param  len   number of consecutive register to read
+  * @retval       interface status (MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lsm6ds3tr_c_read_reg(stmdev_ctx_t *ctx, uint8_t reg,
+                             uint8_t *data,
+                             uint16_t len)
+{
+  int32_t ret;
+
+  ret = ctx->read_reg(ctx->handle, reg, data, len);
+
+  return ret;
+}
+
+/**
+  * @brief  Write generic device register
+  *
+  * @param  ctx   read / write interface definitions(ptr)
+  * @param  reg   register to write
+  * @param  data  pointer to data to write in register reg(ptr)
+  * @param  len   number of consecutive register to write
+  * @retval       interface status (MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lsm6ds3tr_c_write_reg(stmdev_ctx_t *ctx, uint8_t reg,
+                              uint8_t *data,
+                              uint16_t len)
+{
+  int32_t ret;
+
+  ret = ctx->write_reg(ctx->handle, reg, data, len);
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_Sensitivity
+  * @brief       These functions convert raw-data into engineering units.
+  * @{
+  *
+  */
+
+float_t lsm6ds3tr_c_from_fs2g_to_mg(int16_t lsb)
+{
+  return ((float_t)lsb * 0.061f);
+}
+
+float_t lsm6ds3tr_c_from_fs4g_to_mg(int16_t lsb)
+{
+  return ((float_t)lsb * 0.122f);
+}
+
+float_t lsm6ds3tr_c_from_fs8g_to_mg(int16_t lsb)
+{
+  return ((float_t)lsb * 0.244f);
+}
+
+float_t lsm6ds3tr_c_from_fs16g_to_mg(int16_t lsb)
+{
+  return ((float_t)lsb * 0.488f);
+}
+
+float_t lsm6ds3tr_c_from_fs125dps_to_mdps(int16_t lsb)
+{
+  return ((float_t)lsb * 4.375f);
+}
+
+float_t lsm6ds3tr_c_from_fs250dps_to_mdps(int16_t lsb)
+{
+  return ((float_t)lsb * 8.750f);
+}
+
+float_t lsm6ds3tr_c_from_fs500dps_to_mdps(int16_t lsb)
+{
+  return ((float_t)lsb * 17.50f);
+}
+
+float_t lsm6ds3tr_c_from_fs1000dps_to_mdps(int16_t lsb)
+{
+  return ((float_t)lsb * 35.0f);
+}
+
+float_t lsm6ds3tr_c_from_fs2000dps_to_mdps(int16_t lsb)
+{
+  return ((float_t)lsb * 70.0f);
+}
+
+float_t lsm6ds3tr_c_from_lsb_to_celsius(int16_t lsb)
+{
+  return (((float_t)lsb / 256.0f) + 25.0f);
+}
+
+/**
+  * @}
+  *
+  */
+
+
+/**
+  * @defgroup    LSM6DS3TR_C_data_generation
+  * @brief       This section groups all the functions concerning data
+  *              generation
+  * @{
+  *
+  */
+
+/**
+  * @brief  Accelerometer full-scale selection.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of fs_xl in reg CTRL1_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_full_scale_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_fs_xl_t val)
+{
+  lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL,
+                             (uint8_t *)&ctrl1_xl, 1);
+
+  if (ret == 0)
+  {
+    ctrl1_xl.fs_xl = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL1_XL,
+                                (uint8_t *)&ctrl1_xl, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Accelerometer full-scale selection.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of fs_xl in reg CTRL1_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_full_scale_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_fs_xl_t *val)
+{
+  lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL,
+                             (uint8_t *)&ctrl1_xl, 1);
+
+  switch (ctrl1_xl.fs_xl)
+  {
+    case LSM6DS3TR_C_2g:
+      *val = LSM6DS3TR_C_2g;
+      break;
+
+    case LSM6DS3TR_C_16g:
+      *val = LSM6DS3TR_C_16g;
+      break;
+
+    case LSM6DS3TR_C_4g:
+      *val = LSM6DS3TR_C_4g;
+      break;
+
+    case LSM6DS3TR_C_8g:
+      *val = LSM6DS3TR_C_8g;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_XL_FS_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Accelerometer data rate selection.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of odr_xl in reg CTRL1_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_data_rate_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_odr_xl_t val)
+{
+  lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL,
+                             (uint8_t *)&ctrl1_xl, 1);
+
+  if (ret == 0)
+  {
+    ctrl1_xl.odr_xl = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL1_XL,
+                                (uint8_t *)&ctrl1_xl, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Accelerometer data rate selection.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of odr_xl in reg CTRL1_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_data_rate_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_odr_xl_t *val)
+{
+  lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL,
+                             (uint8_t *)&ctrl1_xl, 1);
+
+  switch (ctrl1_xl.odr_xl)
+  {
+    case LSM6DS3TR_C_XL_ODR_OFF:
+      *val = LSM6DS3TR_C_XL_ODR_OFF;
+      break;
+
+    case LSM6DS3TR_C_XL_ODR_12Hz5:
+      *val = LSM6DS3TR_C_XL_ODR_12Hz5;
+      break;
+
+    case LSM6DS3TR_C_XL_ODR_26Hz:
+      *val = LSM6DS3TR_C_XL_ODR_26Hz;
+      break;
+
+    case LSM6DS3TR_C_XL_ODR_52Hz:
+      *val = LSM6DS3TR_C_XL_ODR_52Hz;
+      break;
+
+    case LSM6DS3TR_C_XL_ODR_104Hz:
+      *val = LSM6DS3TR_C_XL_ODR_104Hz;
+      break;
+
+    case LSM6DS3TR_C_XL_ODR_208Hz:
+      *val = LSM6DS3TR_C_XL_ODR_208Hz;
+      break;
+
+    case LSM6DS3TR_C_XL_ODR_416Hz:
+      *val = LSM6DS3TR_C_XL_ODR_416Hz;
+      break;
+
+    case LSM6DS3TR_C_XL_ODR_833Hz:
+      *val = LSM6DS3TR_C_XL_ODR_833Hz;
+      break;
+
+    case LSM6DS3TR_C_XL_ODR_1k66Hz:
+      *val = LSM6DS3TR_C_XL_ODR_1k66Hz;
+      break;
+
+    case LSM6DS3TR_C_XL_ODR_3k33Hz:
+      *val = LSM6DS3TR_C_XL_ODR_3k33Hz;
+      break;
+
+    case LSM6DS3TR_C_XL_ODR_6k66Hz:
+      *val = LSM6DS3TR_C_XL_ODR_6k66Hz;
+      break;
+
+    case LSM6DS3TR_C_XL_ODR_1Hz6:
+      *val = LSM6DS3TR_C_XL_ODR_1Hz6;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_XL_ODR_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Gyroscope chain full-scale selection.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of fs_g in reg CTRL2_G
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_gy_full_scale_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_fs_g_t val)
+{
+  lsm6ds3tr_c_ctrl2_g_t ctrl2_g;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL2_G,
+                             (uint8_t *)&ctrl2_g, 1);
+
+  if (ret == 0)
+  {
+    ctrl2_g.fs_g = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL2_G,
+                                (uint8_t *)&ctrl2_g, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Gyroscope chain full-scale selection.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of fs_g in reg CTRL2_G
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_gy_full_scale_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_fs_g_t *val)
+{
+  lsm6ds3tr_c_ctrl2_g_t ctrl2_g;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL2_G,
+                             (uint8_t *)&ctrl2_g, 1);
+
+  switch (ctrl2_g.fs_g)
+  {
+    case LSM6DS3TR_C_250dps:
+      *val = LSM6DS3TR_C_250dps;
+      break;
+
+    case LSM6DS3TR_C_125dps:
+      *val = LSM6DS3TR_C_125dps;
+      break;
+
+    case LSM6DS3TR_C_500dps:
+      *val = LSM6DS3TR_C_500dps;
+      break;
+
+    case LSM6DS3TR_C_1000dps:
+      *val = LSM6DS3TR_C_1000dps;
+      break;
+
+    case LSM6DS3TR_C_2000dps:
+      *val = LSM6DS3TR_C_2000dps;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_GY_FS_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Gyroscope data rate selection.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of odr_g in reg CTRL2_G
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_gy_data_rate_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_odr_g_t val)
+{
+  lsm6ds3tr_c_ctrl2_g_t ctrl2_g;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL2_G,
+                             (uint8_t *)&ctrl2_g, 1);
+
+  if (ret == 0)
+  {
+    ctrl2_g.odr_g = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL2_G,
+                                (uint8_t *)&ctrl2_g, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Gyroscope data rate selection.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of odr_g in reg CTRL2_G
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_gy_data_rate_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_odr_g_t *val)
+{
+  lsm6ds3tr_c_ctrl2_g_t ctrl2_g;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL2_G,
+                             (uint8_t *)&ctrl2_g, 1);
+
+  switch (ctrl2_g.odr_g)
+  {
+    case LSM6DS3TR_C_GY_ODR_OFF:
+      *val = LSM6DS3TR_C_GY_ODR_OFF;
+      break;
+
+    case LSM6DS3TR_C_GY_ODR_12Hz5:
+      *val = LSM6DS3TR_C_GY_ODR_12Hz5;
+      break;
+
+    case LSM6DS3TR_C_GY_ODR_26Hz:
+      *val = LSM6DS3TR_C_GY_ODR_26Hz;
+      break;
+
+    case LSM6DS3TR_C_GY_ODR_52Hz:
+      *val = LSM6DS3TR_C_GY_ODR_52Hz;
+      break;
+
+    case LSM6DS3TR_C_GY_ODR_104Hz:
+      *val = LSM6DS3TR_C_GY_ODR_104Hz;
+      break;
+
+    case LSM6DS3TR_C_GY_ODR_208Hz:
+      *val = LSM6DS3TR_C_GY_ODR_208Hz;
+      break;
+
+    case LSM6DS3TR_C_GY_ODR_416Hz:
+      *val = LSM6DS3TR_C_GY_ODR_416Hz;
+      break;
+
+    case LSM6DS3TR_C_GY_ODR_833Hz:
+      *val = LSM6DS3TR_C_GY_ODR_833Hz;
+      break;
+
+    case LSM6DS3TR_C_GY_ODR_1k66Hz:
+      *val = LSM6DS3TR_C_GY_ODR_1k66Hz;
+      break;
+
+    case LSM6DS3TR_C_GY_ODR_3k33Hz:
+      *val = LSM6DS3TR_C_GY_ODR_3k33Hz;
+      break;
+
+    case LSM6DS3TR_C_GY_ODR_6k66Hz:
+      *val = LSM6DS3TR_C_GY_ODR_6k66Hz;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_GY_ODR_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Block data update.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of bdu in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_block_data_update_set(stmdev_ctx_t *ctx,
+                                          uint8_t val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl3_c.bdu = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                                (uint8_t *)&ctrl3_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Block data update.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of bdu in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_block_data_update_get(stmdev_ctx_t *ctx,
+                                          uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+  *val = ctrl3_c.bdu;
+
+  return ret;
+}
+
+/**
+  * @brief  Weight of XL user offset bits of registers
+  *         X_OFS_USR(73h), Y_OFS_USR(74h), Z_OFS_USR(75h).[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of usr_off_w in reg CTRL6_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_offset_weight_set(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_usr_off_w_t val)
+{
+  lsm6ds3tr_c_ctrl6_c_t ctrl6_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C,
+                             (uint8_t *)&ctrl6_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl6_c.usr_off_w = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL6_C,
+                                (uint8_t *)&ctrl6_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Weight of XL user offset bits of registers
+  *         X_OFS_USR(73h), Y_OFS_USR(74h), Z_OFS_USR(75h).[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of usr_off_w in reg CTRL6_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_offset_weight_get(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_usr_off_w_t *val)
+{
+  lsm6ds3tr_c_ctrl6_c_t ctrl6_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C,
+                             (uint8_t *)&ctrl6_c, 1);
+
+  switch (ctrl6_c.usr_off_w)
+  {
+    case LSM6DS3TR_C_LSb_1mg:
+      *val = LSM6DS3TR_C_LSb_1mg;
+      break;
+
+    case LSM6DS3TR_C_LSb_16mg:
+      *val = LSM6DS3TR_C_LSb_16mg;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_WEIGHT_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  High-performance operating mode for accelerometer[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of xl_hm_mode in reg CTRL6_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_power_mode_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_xl_hm_mode_t val)
+{
+  lsm6ds3tr_c_ctrl6_c_t ctrl6_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C,
+                             (uint8_t *)&ctrl6_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl6_c.xl_hm_mode = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL6_C,
+                                (uint8_t *)&ctrl6_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  High-performance operating mode for accelerometer.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of xl_hm_mode in reg CTRL6_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_power_mode_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_xl_hm_mode_t *val)
+{
+  lsm6ds3tr_c_ctrl6_c_t ctrl6_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C,
+                             (uint8_t *)&ctrl6_c, 1);
+
+  switch (ctrl6_c.xl_hm_mode)
+  {
+    case LSM6DS3TR_C_XL_HIGH_PERFORMANCE:
+      *val = LSM6DS3TR_C_XL_HIGH_PERFORMANCE;
+      break;
+
+    case LSM6DS3TR_C_XL_NORMAL:
+      *val = LSM6DS3TR_C_XL_NORMAL;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_XL_PW_MODE_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Source register rounding function on WAKE_UP_SRC (1Bh),
+  *         TAP_SRC (1Ch), D6D_SRC (1Dh), STATUS_REG (1Eh) and
+  *         FUNC_SRC1 (53h) registers in the primary interface.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of rounding_status in reg CTRL7_G
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_rounding_on_status_set(stmdev_ctx_t *ctx,
+                                           lsm6ds3tr_c_rounding_status_t val)
+{
+  lsm6ds3tr_c_ctrl7_g_t ctrl7_g;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G,
+                             (uint8_t *)&ctrl7_g, 1);
+
+  if (ret == 0)
+  {
+    ctrl7_g.rounding_status = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL7_G,
+                                (uint8_t *)&ctrl7_g, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Source register rounding function on WAKE_UP_SRC (1Bh),
+  *         TAP_SRC (1Ch), D6D_SRC (1Dh), STATUS_REG (1Eh) and
+  *         FUNC_SRC1 (53h) registers in the primary interface.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of rounding_status in reg CTRL7_G
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_rounding_on_status_get(stmdev_ctx_t *ctx,
+                                           lsm6ds3tr_c_rounding_status_t *val)
+{
+  lsm6ds3tr_c_ctrl7_g_t ctrl7_g;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G,
+                             (uint8_t *)&ctrl7_g, 1);
+
+  switch (ctrl7_g.rounding_status)
+  {
+    case LSM6DS3TR_C_STAT_RND_DISABLE:
+      *val = LSM6DS3TR_C_STAT_RND_DISABLE;
+      break;
+
+    case LSM6DS3TR_C_STAT_RND_ENABLE:
+      *val = LSM6DS3TR_C_STAT_RND_ENABLE;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_STAT_RND_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  High-performance operating mode disable for gyroscope.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of g_hm_mode in reg CTRL7_G
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_gy_power_mode_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_g_hm_mode_t val)
+{
+  lsm6ds3tr_c_ctrl7_g_t ctrl7_g;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G,
+                             (uint8_t *)&ctrl7_g, 1);
+
+  if (ret == 0)
+  {
+    ctrl7_g.g_hm_mode = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL7_G,
+                                (uint8_t *)&ctrl7_g, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  High-performance operating mode disable for gyroscope.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of g_hm_mode in reg CTRL7_G
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_gy_power_mode_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_g_hm_mode_t *val)
+{
+  lsm6ds3tr_c_ctrl7_g_t ctrl7_g;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G,
+                             (uint8_t *)&ctrl7_g, 1);
+
+  switch (ctrl7_g.g_hm_mode)
+  {
+    case LSM6DS3TR_C_GY_HIGH_PERFORMANCE:
+      *val = LSM6DS3TR_C_GY_HIGH_PERFORMANCE;
+      break;
+
+    case LSM6DS3TR_C_GY_NORMAL:
+      *val = LSM6DS3TR_C_GY_NORMAL;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_GY_PW_MODE_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Read all the interrupt/status flag of the device.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    WAKE_UP_SRC, TAP_SRC, D6D_SRC, STATUS_REG,
+  *                FUNC_SRC1, FUNC_SRC2, WRIST_TILT_IA, A_WRIST_TILT_Mask
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_all_sources_get(stmdev_ctx_t *ctx,
+                                    lsm6ds3tr_c_all_sources_t *val)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_SRC,
+                             (uint8_t *) & (val->wake_up_src), 1);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_SRC,
+                               (uint8_t *) & (val->tap_src), 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_D6D_SRC,
+                               (uint8_t *) & (val->d6d_src), 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG,
+                               (uint8_t *) & (val->status_reg), 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FUNC_SRC1,
+                               (uint8_t *) & (val->func_src1), 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FUNC_SRC2,
+                               (uint8_t *) & (val->func_src2), 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WRIST_TILT_IA,
+                               (uint8_t *) & (val->wrist_tilt_ia), 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_MASK,
+                               (uint8_t *) & (val->a_wrist_tilt_mask), 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+  }
+
+  return ret;
+}
+/**
+  * @brief  The STATUS_REG register is read by the primary interface[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Registers STATUS_REG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_status_reg_get(stmdev_ctx_t *ctx,
+                                   lsm6ds3tr_c_status_reg_t *val)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG,
+                             (uint8_t *) val, 1);
+
+  return ret;
+}
+
+/**
+  * @brief  Accelerometer new data available.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of xlda in reg STATUS_REG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_flag_data_ready_get(stmdev_ctx_t *ctx,
+                                           uint8_t *val)
+{
+  lsm6ds3tr_c_status_reg_t status_reg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG,
+                             (uint8_t *)&status_reg, 1);
+  *val = status_reg.xlda;
+
+  return ret;
+}
+
+/**
+  * @brief  Gyroscope new data available.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of gda in reg STATUS_REG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_gy_flag_data_ready_get(stmdev_ctx_t *ctx,
+                                           uint8_t *val)
+{
+  lsm6ds3tr_c_status_reg_t status_reg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG,
+                             (uint8_t *)&status_reg, 1);
+  *val = status_reg.gda;
+
+  return ret;
+}
+
+/**
+  * @brief  Temperature new data available.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tda in reg STATUS_REG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_temp_flag_data_ready_get(stmdev_ctx_t *ctx,
+                                             uint8_t *val)
+{
+  lsm6ds3tr_c_status_reg_t status_reg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG,
+                             (uint8_t *)&status_reg, 1);
+  *val = status_reg.tda;
+
+  return ret;
+}
+
+/**
+  * @brief  Accelerometer axis user offset correction expressed in two’s
+  *         complement, weight depends on USR_OFF_W in CTRL6_C.
+  *         The value must be in the range [-127 127].[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that contains data to write
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_usr_offset_set(stmdev_ctx_t *ctx,
+                                      uint8_t *buff)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_X_OFS_USR, buff, 3);
+
+  return ret;
+}
+
+/**
+  * @brief  Accelerometer axis user offset correction xpressed in two’s
+  *         complement, weight depends on USR_OFF_W in CTRL6_C.
+  *         The value must be in the range [-127 127].[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that stores data read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_usr_offset_get(stmdev_ctx_t *ctx,
+                                      uint8_t *buff)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_X_OFS_USR, buff, 3);
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_Timestamp
+  * @brief       This section groups all the functions that manage the
+  *              timestamp generation.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Enable timestamp count. The count is saved in TIMESTAMP0_REG (40h),
+  *         TIMESTAMP1_REG (41h) and TIMESTAMP2_REG (42h).[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of timer_en in reg CTRL10_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_timestamp_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                             (uint8_t *)&ctrl10_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl10_c.timer_en = val;
+
+    if (val != 0x00U)
+    {
+      ctrl10_c.func_en = val;
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                                  (uint8_t *)&ctrl10_c, 1);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable timestamp count. The count is saved in TIMESTAMP0_REG (40h),
+  *         TIMESTAMP1_REG (41h) and TIMESTAMP2_REG (42h).[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of timer_en in reg CTRL10_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_timestamp_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                             (uint8_t *)&ctrl10_c, 1);
+  *val = ctrl10_c.timer_en;
+
+  return ret;
+}
+
+/**
+  * @brief  Timestamp register resolution setting.
+  *         Configuration of this bit affects
+  *         TIMESTAMP0_REG(40h), TIMESTAMP1_REG(41h),
+  *         TIMESTAMP2_REG(42h), STEP_TIMESTAMP_L(49h),
+  *         STEP_TIMESTAMP_H(4Ah) and
+  *         STEP_COUNT_DELTA(15h) registers.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of timer_hr in reg WAKE_UP_DUR
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_timestamp_res_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_timer_hr_t val)
+{
+  lsm6ds3tr_c_wake_up_dur_t wake_up_dur;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR,
+                             (uint8_t *)&wake_up_dur, 1);
+
+  if (ret == 0)
+  {
+    wake_up_dur.timer_hr = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR,
+                                (uint8_t *)&wake_up_dur, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Timestamp register resolution setting.
+  *         Configuration of this bit affects
+  *         TIMESTAMP0_REG(40h), TIMESTAMP1_REG(41h),
+  *         TIMESTAMP2_REG(42h), STEP_TIMESTAMP_L(49h),
+  *         STEP_TIMESTAMP_H(4Ah) and
+  *         STEP_COUNT_DELTA(15h) registers.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of timer_hr in reg WAKE_UP_DUR
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_timestamp_res_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_timer_hr_t *val)
+{
+  lsm6ds3tr_c_wake_up_dur_t wake_up_dur;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR,
+                             (uint8_t *)&wake_up_dur, 1);
+
+  switch (wake_up_dur.timer_hr)
+  {
+    case LSM6DS3TR_C_LSB_6ms4:
+      *val = LSM6DS3TR_C_LSB_6ms4;
+      break;
+
+    case LSM6DS3TR_C_LSB_25us:
+      *val = LSM6DS3TR_C_LSB_25us;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_TS_RES_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_Dataoutput
+  * @brief       This section groups all the data output functions.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Circular burst-mode (rounding) read from output registers
+  *         through the primary interface.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of rounding in reg CTRL5_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_rounding_mode_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_rounding_t val)
+{
+  lsm6ds3tr_c_ctrl5_c_t ctrl5_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C,
+                             (uint8_t *)&ctrl5_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl5_c.rounding = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL5_C,
+                                (uint8_t *)&ctrl5_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Circular burst-mode (rounding) read from output registers
+  *         through the primary interface.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of rounding in reg CTRL5_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_rounding_mode_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_rounding_t *val)
+{
+  lsm6ds3tr_c_ctrl5_c_t ctrl5_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C,
+                             (uint8_t *)&ctrl5_c, 1);
+
+  switch (ctrl5_c.rounding)
+  {
+    case LSM6DS3TR_C_ROUND_DISABLE:
+      *val = LSM6DS3TR_C_ROUND_DISABLE;
+      break;
+
+    case LSM6DS3TR_C_ROUND_XL:
+      *val = LSM6DS3TR_C_ROUND_XL;
+      break;
+
+    case LSM6DS3TR_C_ROUND_GY:
+      *val = LSM6DS3TR_C_ROUND_GY;
+      break;
+
+    case LSM6DS3TR_C_ROUND_GY_XL:
+      *val = LSM6DS3TR_C_ROUND_GY_XL;
+      break;
+
+    case LSM6DS3TR_C_ROUND_SH1_TO_SH6:
+      *val = LSM6DS3TR_C_ROUND_SH1_TO_SH6;
+      break;
+
+    case LSM6DS3TR_C_ROUND_XL_SH1_TO_SH6:
+      *val = LSM6DS3TR_C_ROUND_XL_SH1_TO_SH6;
+      break;
+
+    case LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH12:
+      *val = LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH12;
+      break;
+
+    case LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH6:
+      *val = LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH6;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_ROUND_OUT_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Temperature data output register (r). L and H registers together
+  *         express a 16-bit word in two’s complement.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that stores data read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_temperature_raw_get(stmdev_ctx_t *ctx,
+                                        int16_t *val)
+{
+  uint8_t buff[2];
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_OUT_TEMP_L, buff, 2);
+  *val = (int16_t)buff[1];
+  *val = (*val * 256) + (int16_t)buff[0];
+
+  return ret;
+}
+
+/**
+  * @brief  Angular rate sensor. The value is expressed as a 16-bit word in
+  *         two’s complement.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that stores data read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_angular_rate_raw_get(stmdev_ctx_t *ctx,
+                                         int16_t *val)
+{
+  uint8_t buff[6];
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_OUTX_L_G, buff, 6);
+  val[0] = (int16_t)buff[1];
+  val[0] = (val[0] * 256) + (int16_t)buff[0];
+  val[1] = (int16_t)buff[3];
+  val[1] = (val[1] * 256) + (int16_t)buff[2];
+  val[2] = (int16_t)buff[5];
+  val[2] = (val[2] * 256) + (int16_t)buff[4];
+
+  return ret;
+}
+
+/**
+  * @brief  Linear acceleration output register. The value is expressed
+  *         as a 16-bit word in two’s complement.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that stores data read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_acceleration_raw_get(stmdev_ctx_t *ctx,
+                                         int16_t *val)
+{
+  uint8_t buff[6];
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_OUTX_L_XL, buff, 6);
+  val[0] = (int16_t)buff[1];
+  val[0] = (val[0] * 256) + (int16_t)buff[0];
+  val[1] = (int16_t)buff[3];
+  val[1] = (val[1] * 256) + (int16_t)buff[2];
+  val[2] = (int16_t)buff[5];
+  val[2] = (val[2] * 256) + (int16_t)buff[4];
+
+  return ret;
+}
+
+/**
+  * @brief  External magnetometer raw data.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that stores data read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_mag_calibrated_raw_get(stmdev_ctx_t *ctx,
+                                           int16_t *val)
+{
+  uint8_t buff[6];
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_OUT_MAG_RAW_X_L, buff, 6);
+  val[0] = (int16_t)buff[1];
+  val[0] = (val[0] * 256) + (int16_t)buff[0];
+  val[1] = (int16_t)buff[3];
+  val[1] = (val[1] * 256) + (int16_t)buff[2];
+  val[2] = (int16_t)buff[5];
+  val[2] = (val[2] * 256) + (int16_t)buff[4];
+
+  return ret;
+}
+
+/**
+  * @brief  Read data in FIFO.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buffer Data buffer to store FIFO data.
+  * @param  len    Number of data to read from FIFO.
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_raw_data_get(stmdev_ctx_t *ctx,
+                                      uint8_t *buffer,
+                                      uint8_t len)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_DATA_OUT_L, buffer,
+                             len);
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_common
+  * @brief       This section groups common useful functions.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Enable access to the embedded functions/sensor hub
+  *         configuration registers[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of func_cfg_en in reg FUNC_CFG_ACCESS
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_mem_bank_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_func_cfg_en_t val)
+{
+  lsm6ds3tr_c_func_cfg_access_t func_cfg_access;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FUNC_CFG_ACCESS,
+                             (uint8_t *)&func_cfg_access, 1);
+
+  if (ret == 0)
+  {
+    func_cfg_access.func_cfg_en = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FUNC_CFG_ACCESS,
+                                (uint8_t *)&func_cfg_access, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable access to the embedded functions/sensor hub configuration
+  *         registers[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of func_cfg_en in reg FUNC_CFG_ACCESS
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_mem_bank_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_func_cfg_en_t *val)
+{
+  lsm6ds3tr_c_func_cfg_access_t func_cfg_access;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FUNC_CFG_ACCESS,
+                             (uint8_t *)&func_cfg_access, 1);
+
+  switch (func_cfg_access.func_cfg_en)
+  {
+    case LSM6DS3TR_C_USER_BANK:
+      *val = LSM6DS3TR_C_USER_BANK;
+      break;
+
+    case LSM6DS3TR_C_BANK_B:
+      *val = LSM6DS3TR_C_BANK_B;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_BANK_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Data-ready pulsed / letched mode[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of drdy_pulsed in reg DRDY_PULSE_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_data_ready_mode_set(stmdev_ctx_t *ctx,
+                                        lsm6ds3tr_c_drdy_pulsed_g_t val)
+{
+  lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G,
+                             (uint8_t *)&drdy_pulse_cfg_g, 1);
+
+  if (ret == 0)
+  {
+    drdy_pulse_cfg_g.drdy_pulsed = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G,
+                                (uint8_t *)&drdy_pulse_cfg_g, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Data-ready pulsed / letched mode[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of drdy_pulsed in reg DRDY_PULSE_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_data_ready_mode_get(stmdev_ctx_t *ctx,
+                                        lsm6ds3tr_c_drdy_pulsed_g_t *val)
+{
+  lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G,
+                             (uint8_t *)&drdy_pulse_cfg_g, 1);
+
+  switch (drdy_pulse_cfg_g.drdy_pulsed)
+  {
+    case LSM6DS3TR_C_DRDY_LATCHED:
+      *val = LSM6DS3TR_C_DRDY_LATCHED;
+      break;
+
+    case LSM6DS3TR_C_DRDY_PULSED:
+      *val = LSM6DS3TR_C_DRDY_PULSED;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_DRDY_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  DeviceWhoamI.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that stores data read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_device_id_get(stmdev_ctx_t *ctx, uint8_t *buff)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WHO_AM_I, buff, 1);
+
+  return ret;
+}
+
+/**
+  * @brief  Software reset. Restore the default values in user registers[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of sw_reset in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_reset_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl3_c.sw_reset = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                                (uint8_t *)&ctrl3_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Software reset. Restore the default values in user registers[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of sw_reset in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_reset_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+  *val = ctrl3_c.sw_reset;
+
+  return ret;
+}
+
+/**
+  * @brief  Big/Little Endian Data selection.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of ble in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_data_format_set(stmdev_ctx_t *ctx,
+                                    lsm6ds3tr_c_ble_t val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl3_c.ble = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                                (uint8_t *)&ctrl3_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Big/Little Endian Data selection.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of ble in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_data_format_get(stmdev_ctx_t *ctx,
+                                    lsm6ds3tr_c_ble_t *val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+
+  switch (ctrl3_c.ble)
+  {
+    case LSM6DS3TR_C_LSB_AT_LOW_ADD:
+      *val = LSM6DS3TR_C_LSB_AT_LOW_ADD;
+      break;
+
+    case LSM6DS3TR_C_MSB_AT_LOW_ADD:
+      *val = LSM6DS3TR_C_MSB_AT_LOW_ADD;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_DATA_FMT_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Register address automatically incremented during a multiple byte
+  *         access with a serial interface.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of if_inc in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_auto_increment_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl3_c.if_inc = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                                (uint8_t *)&ctrl3_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Register address automatically incremented during a multiple byte
+  *         access with a serial interface.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of if_inc in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_auto_increment_get(stmdev_ctx_t *ctx,
+                                       uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+  *val = ctrl3_c.if_inc;
+
+  return ret;
+}
+
+/**
+  * @brief  Reboot memory content. Reload the calibration parameters.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of boot in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_boot_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl3_c.boot = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                                (uint8_t *)&ctrl3_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Reboot memory content. Reload the calibration parameters.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of boot in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_boot_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+  *val = ctrl3_c.boot;
+
+  return ret;
+}
+
+/**
+  * @brief  Linear acceleration sensor self-test enable.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of st_xl in reg CTRL5_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_self_test_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_st_xl_t val)
+{
+  lsm6ds3tr_c_ctrl5_c_t ctrl5_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C,
+                             (uint8_t *)&ctrl5_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl5_c.st_xl = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL5_C,
+                                (uint8_t *)&ctrl5_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Linear acceleration sensor self-test enable.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of st_xl in reg CTRL5_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_self_test_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_st_xl_t *val)
+{
+  lsm6ds3tr_c_ctrl5_c_t ctrl5_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C,
+                             (uint8_t *)&ctrl5_c, 1);
+
+  switch (ctrl5_c.st_xl)
+  {
+    case LSM6DS3TR_C_XL_ST_DISABLE:
+      *val = LSM6DS3TR_C_XL_ST_DISABLE;
+      break;
+
+    case LSM6DS3TR_C_XL_ST_POSITIVE:
+      *val = LSM6DS3TR_C_XL_ST_POSITIVE;
+      break;
+
+    case LSM6DS3TR_C_XL_ST_NEGATIVE:
+      *val = LSM6DS3TR_C_XL_ST_NEGATIVE;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_XL_ST_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Angular rate sensor self-test enable.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of st_g in reg CTRL5_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_gy_self_test_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_st_g_t val)
+{
+  lsm6ds3tr_c_ctrl5_c_t ctrl5_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C,
+                             (uint8_t *)&ctrl5_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl5_c.st_g = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL5_C,
+                                (uint8_t *)&ctrl5_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Angular rate sensor self-test enable.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of st_g in reg CTRL5_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_gy_self_test_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_st_g_t *val)
+{
+  lsm6ds3tr_c_ctrl5_c_t ctrl5_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C,
+                             (uint8_t *)&ctrl5_c, 1);
+
+  switch (ctrl5_c.st_g)
+  {
+    case LSM6DS3TR_C_GY_ST_DISABLE:
+      *val = LSM6DS3TR_C_GY_ST_DISABLE;
+      break;
+
+    case LSM6DS3TR_C_GY_ST_POSITIVE:
+      *val = LSM6DS3TR_C_GY_ST_POSITIVE;
+      break;
+
+    case LSM6DS3TR_C_GY_ST_NEGATIVE:
+      *val = LSM6DS3TR_C_GY_ST_NEGATIVE;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_GY_ST_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_filters
+  * @brief       This section group all the functions concerning the filters
+  *              configuration that impact both accelerometer and gyro.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Mask DRDY on pin (both XL & Gyro) until filter settling ends
+  *         (XL and Gyro independently masked).[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of drdy_mask in reg CTRL4_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_filter_settling_mask_set(stmdev_ctx_t *ctx,
+                                             uint8_t val)
+{
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                             (uint8_t *)&ctrl4_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl4_c.drdy_mask = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                                (uint8_t *)&ctrl4_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Mask DRDY on pin (both XL & Gyro) until filter settling ends
+  *         (XL and Gyro independently masked).[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of drdy_mask in reg CTRL4_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_filter_settling_mask_get(stmdev_ctx_t *ctx,
+                                             uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                             (uint8_t *)&ctrl4_c, 1);
+  *val = ctrl4_c.drdy_mask;
+
+  return ret;
+}
+
+/**
+  * @brief  HPF or SLOPE filter selection on wake-up and Activity/Inactivity
+  *         functions.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of slope_fds in reg TAP_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_hp_path_internal_set(stmdev_ctx_t *ctx,
+                                            lsm6ds3tr_c_slope_fds_t val)
+{
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                             (uint8_t *)&tap_cfg, 1);
+
+  if (ret == 0)
+  {
+    tap_cfg.slope_fds = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                                (uint8_t *)&tap_cfg, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  HPF or SLOPE filter selection on wake-up and Activity/Inactivity
+  *         functions.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of slope_fds in reg TAP_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_hp_path_internal_get(stmdev_ctx_t *ctx,
+                                            lsm6ds3tr_c_slope_fds_t *val)
+{
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                             (uint8_t *)&tap_cfg, 1);
+
+  switch (tap_cfg.slope_fds)
+  {
+    case LSM6DS3TR_C_USE_SLOPE:
+      *val = LSM6DS3TR_C_USE_SLOPE;
+      break;
+
+    case LSM6DS3TR_C_USE_HPF:
+      *val = LSM6DS3TR_C_USE_HPF;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_HP_PATH_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_accelerometer_filters
+  * @brief       This section group all the functions concerning the filters
+  *              configuration that impact accelerometer in every mode.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Accelerometer analog chain bandwidth selection (only for
+  *         accelerometer ODR ≥ 1.67 kHz).[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of bw0_xl in reg CTRL1_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_filter_analog_set(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_bw0_xl_t val)
+{
+  lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL,
+                             (uint8_t *)&ctrl1_xl, 1);
+
+  if (ret == 0)
+  {
+    ctrl1_xl.bw0_xl = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL1_XL,
+                                (uint8_t *)&ctrl1_xl, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Accelerometer analog chain bandwidth selection (only for
+  *         accelerometer ODR ≥ 1.67 kHz).[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of bw0_xl in reg CTRL1_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_filter_analog_get(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_bw0_xl_t *val)
+{
+  lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL,
+                             (uint8_t *)&ctrl1_xl, 1);
+
+  switch (ctrl1_xl.bw0_xl)
+  {
+    case LSM6DS3TR_C_XL_ANA_BW_1k5Hz:
+      *val = LSM6DS3TR_C_XL_ANA_BW_1k5Hz;
+      break;
+
+    case LSM6DS3TR_C_XL_ANA_BW_400Hz:
+      *val = LSM6DS3TR_C_XL_ANA_BW_400Hz;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_XL_ANA_BW_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_accelerometer_filters
+  * @brief       This section group all the functions concerning the filters
+  *              configuration that impact accelerometer.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Accelerometer digital LPF (LPF1) bandwidth selection LPF2 is
+  *         not used.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of lpf1_bw_sel in reg CTRL1_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_lp1_bandwidth_set(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_lpf1_bw_sel_t val)
+{
+  lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl;
+  lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL,
+                             (uint8_t *)&ctrl1_xl, 1);
+
+  if (ret == 0)
+  {
+    ctrl1_xl.lpf1_bw_sel = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL1_XL,
+                                (uint8_t *)&ctrl1_xl, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                                 (uint8_t *)&ctrl8_xl, 1);
+
+      if (ret == 0)
+      {
+        ctrl8_xl.lpf2_xl_en = 0;
+        ctrl8_xl.hp_slope_xl_en = 0;
+        ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                                    (uint8_t *)&ctrl8_xl, 1);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Accelerometer digital LPF (LPF1) bandwidth selection LPF2
+  *         is not used.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of lpf1_bw_sel in reg CTRL1_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_lp1_bandwidth_get(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_lpf1_bw_sel_t *val)
+{
+  lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl;
+  lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                             (uint8_t *)&ctrl8_xl, 1);
+
+  if (ret == 0)
+  {
+    if ((ctrl8_xl.lpf2_xl_en != 0x00U) ||
+        (ctrl8_xl.hp_slope_xl_en != 0x00U))
+    {
+      *val = LSM6DS3TR_C_XL_LP1_NA;
+    }
+
+    else
+    {
+      ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL,
+                                 (uint8_t *)&ctrl1_xl, 1);
+
+      switch (ctrl1_xl.lpf1_bw_sel)
+      {
+        case LSM6DS3TR_C_XL_LP1_ODR_DIV_2:
+          *val = LSM6DS3TR_C_XL_LP1_ODR_DIV_2;
+          break;
+
+        case LSM6DS3TR_C_XL_LP1_ODR_DIV_4:
+          *val = LSM6DS3TR_C_XL_LP1_ODR_DIV_4;
+          break;
+
+        default:
+          *val = LSM6DS3TR_C_XL_LP1_NA;
+          break;
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  LPF2 on outputs[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of input_composite in reg CTRL8_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_lp2_bandwidth_set(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_input_composite_t val)
+{
+  lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                             (uint8_t *)&ctrl8_xl, 1);
+
+  if (ret == 0)
+  {
+    ctrl8_xl.input_composite = ((uint8_t) val & 0x10U) >> 4;
+    ctrl8_xl.hpcf_xl = (uint8_t) val & 0x03U;
+    ctrl8_xl.lpf2_xl_en = 1;
+    ctrl8_xl.hp_slope_xl_en = 0;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                                (uint8_t *)&ctrl8_xl, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  LPF2 on outputs[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of input_composite in reg CTRL8_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_lp2_bandwidth_get(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_input_composite_t *val)
+{
+  lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                             (uint8_t *)&ctrl8_xl, 1);
+
+  if (ret == 0)
+  {
+    if ((ctrl8_xl.lpf2_xl_en == 0x00U) ||
+        (ctrl8_xl.hp_slope_xl_en != 0x00U))
+    {
+      *val = LSM6DS3TR_C_XL_LP_NA;
+    }
+
+    else
+    {
+      switch ((ctrl8_xl.input_composite << 4) + ctrl8_xl.hpcf_xl)
+      {
+        case LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_50:
+          *val = LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_50;
+          break;
+
+        case LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_100:
+          *val = LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_100;
+          break;
+
+        case LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_9:
+          *val = LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_9;
+          break;
+
+        case LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_400:
+          *val = LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_400;
+          break;
+
+        case LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_50:
+          *val = LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_50;
+          break;
+
+        case LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_100:
+          *val = LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_100;
+          break;
+
+        case LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_9:
+          *val = LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_9;
+          break;
+
+        case LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_400:
+          *val = LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_400;
+          break;
+
+        default:
+          *val = LSM6DS3TR_C_XL_LP_NA;
+          break;
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable HP filter reference mode.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of hp_ref_mode in reg CTRL8_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_reference_mode_set(stmdev_ctx_t *ctx,
+                                          uint8_t val)
+{
+  lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                             (uint8_t *)&ctrl8_xl, 1);
+
+  if (ret == 0)
+  {
+    ctrl8_xl.hp_ref_mode = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                                (uint8_t *)&ctrl8_xl, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable HP filter reference mode.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of hp_ref_mode in reg CTRL8_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_reference_mode_get(stmdev_ctx_t *ctx,
+                                          uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                             (uint8_t *)&ctrl8_xl, 1);
+  *val = ctrl8_xl.hp_ref_mode;
+
+  return ret;
+}
+
+/**
+  * @brief  High pass/Slope on outputs.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of hpcf_xl in reg CTRL8_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_hp_bandwidth_set(stmdev_ctx_t *ctx,
+                                        lsm6ds3tr_c_hpcf_xl_t val)
+{
+  lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                             (uint8_t *)&ctrl8_xl, 1);
+
+  if (ret == 0)
+  {
+    ctrl8_xl.input_composite = 0;
+    ctrl8_xl.hpcf_xl = (uint8_t)val & 0x03U;
+    ctrl8_xl.hp_slope_xl_en = 1;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                                (uint8_t *)&ctrl8_xl, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  High pass/Slope on outputs.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of hpcf_xl in reg CTRL8_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_xl_hp_bandwidth_get(stmdev_ctx_t *ctx,
+                                        lsm6ds3tr_c_hpcf_xl_t *val)
+{
+  lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                             (uint8_t *)&ctrl8_xl, 1);
+
+  if (ctrl8_xl.hp_slope_xl_en == 0x00U)
+  {
+    *val = LSM6DS3TR_C_XL_HP_NA;
+  }
+
+  switch (ctrl8_xl.hpcf_xl)
+  {
+    case LSM6DS3TR_C_XL_HP_ODR_DIV_4:
+      *val = LSM6DS3TR_C_XL_HP_ODR_DIV_4;
+      break;
+
+    case LSM6DS3TR_C_XL_HP_ODR_DIV_100:
+      *val = LSM6DS3TR_C_XL_HP_ODR_DIV_100;
+      break;
+
+    case LSM6DS3TR_C_XL_HP_ODR_DIV_9:
+      *val = LSM6DS3TR_C_XL_HP_ODR_DIV_9;
+      break;
+
+    case LSM6DS3TR_C_XL_HP_ODR_DIV_400:
+      *val = LSM6DS3TR_C_XL_HP_ODR_DIV_400;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_XL_HP_NA;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_gyroscope_filters
+  * @brief       This section group all the functions concerning the filters
+  *              configuration that impact gyroscope.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Gyroscope low pass path bandwidth.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    gyroscope filtering chain configuration.
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_gy_band_pass_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_lpf1_sel_g_t val)
+{
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  lsm6ds3tr_c_ctrl6_c_t ctrl6_c;
+  lsm6ds3tr_c_ctrl7_g_t ctrl7_g;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G,
+                             (uint8_t *)&ctrl7_g, 1);
+
+  if (ret == 0)
+  {
+    ctrl7_g.hpm_g  = ((uint8_t)val & 0x30U) >> 4;
+    ctrl7_g.hp_en_g = ((uint8_t)val & 0x80U) >> 7;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL7_G,
+                                (uint8_t *)&ctrl7_g, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C,
+                                 (uint8_t *)&ctrl6_c, 1);
+
+      if (ret == 0)
+      {
+        ctrl6_c.ftype = (uint8_t)val & 0x03U;
+        ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL6_C,
+                                    (uint8_t *)&ctrl6_c, 1);
+
+        if (ret == 0)
+        {
+          ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                                     (uint8_t *)&ctrl4_c, 1);
+
+          if (ret == 0)
+          {
+            ctrl4_c.lpf1_sel_g = ((uint8_t)val & 0x08U) >> 3;
+            ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                                        (uint8_t *)&ctrl4_c, 1);
+          }
+        }
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Gyroscope low pass path bandwidth.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    gyroscope filtering chain
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_gy_band_pass_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_lpf1_sel_g_t *val)
+{
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  lsm6ds3tr_c_ctrl6_c_t ctrl6_c;
+  lsm6ds3tr_c_ctrl7_g_t ctrl7_g;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C,
+                             (uint8_t *)&ctrl6_c, 1);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                               (uint8_t *)&ctrl4_c, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G,
+                                 (uint8_t *)&ctrl7_g, 1);
+
+      switch ((ctrl7_g.hp_en_g << 7) + (ctrl7_g.hpm_g << 4) +
+              (ctrl4_c.lpf1_sel_g << 3) + ctrl6_c.ftype)
+      {
+        case LSM6DS3TR_C_HP_16mHz_LP2:
+          *val = LSM6DS3TR_C_HP_16mHz_LP2;
+          break;
+
+        case LSM6DS3TR_C_HP_65mHz_LP2:
+          *val = LSM6DS3TR_C_HP_65mHz_LP2;
+          break;
+
+        case LSM6DS3TR_C_HP_260mHz_LP2:
+          *val = LSM6DS3TR_C_HP_260mHz_LP2;
+          break;
+
+        case LSM6DS3TR_C_HP_1Hz04_LP2:
+          *val = LSM6DS3TR_C_HP_1Hz04_LP2;
+          break;
+
+        case LSM6DS3TR_C_HP_DISABLE_LP1_LIGHT:
+          *val = LSM6DS3TR_C_HP_DISABLE_LP1_LIGHT;
+          break;
+
+        case LSM6DS3TR_C_HP_DISABLE_LP1_NORMAL:
+          *val = LSM6DS3TR_C_HP_DISABLE_LP1_NORMAL;
+          break;
+
+        case LSM6DS3TR_C_HP_DISABLE_LP_STRONG:
+          *val = LSM6DS3TR_C_HP_DISABLE_LP_STRONG;
+          break;
+
+        case LSM6DS3TR_C_HP_DISABLE_LP1_AGGRESSIVE:
+          *val = LSM6DS3TR_C_HP_DISABLE_LP1_AGGRESSIVE;
+          break;
+
+        case LSM6DS3TR_C_HP_16mHz_LP1_LIGHT:
+          *val = LSM6DS3TR_C_HP_16mHz_LP1_LIGHT;
+          break;
+
+        case LSM6DS3TR_C_HP_65mHz_LP1_NORMAL:
+          *val = LSM6DS3TR_C_HP_65mHz_LP1_NORMAL;
+          break;
+
+        case LSM6DS3TR_C_HP_260mHz_LP1_STRONG:
+          *val = LSM6DS3TR_C_HP_260mHz_LP1_STRONG;
+          break;
+
+        case LSM6DS3TR_C_HP_1Hz04_LP1_AGGRESSIVE:
+          *val = LSM6DS3TR_C_HP_1Hz04_LP1_AGGRESSIVE;
+          break;
+
+        default:
+          *val = LSM6DS3TR_C_HP_GY_BAND_NA;
+          break;
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_serial_interface
+  * @brief       This section groups all the functions concerning serial
+  *              interface management
+  * @{
+  *
+  */
+
+/**
+  * @brief  SPI Serial Interface Mode selection.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of sim in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_spi_mode_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_sim_t val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl3_c.sim = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                                (uint8_t *)&ctrl3_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  SPI Serial Interface Mode selection.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of sim in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_spi_mode_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_sim_t *val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+
+  switch (ctrl3_c.sim)
+  {
+    case LSM6DS3TR_C_SPI_4_WIRE:
+      *val = LSM6DS3TR_C_SPI_4_WIRE;
+      break;
+
+    case LSM6DS3TR_C_SPI_3_WIRE:
+      *val = LSM6DS3TR_C_SPI_3_WIRE;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_SPI_MODE_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Disable / Enable I2C interface.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of i2c_disable in reg CTRL4_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_i2c_interface_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_i2c_disable_t val)
+{
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                             (uint8_t *)&ctrl4_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl4_c.i2c_disable = (uint8_t)val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                                (uint8_t *)&ctrl4_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Disable / Enable I2C interface.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of i2c_disable in reg CTRL4_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_i2c_interface_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_i2c_disable_t *val)
+{
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                             (uint8_t *)&ctrl4_c, 1);
+
+  switch (ctrl4_c.i2c_disable)
+  {
+    case LSM6DS3TR_C_I2C_ENABLE:
+      *val = LSM6DS3TR_C_I2C_ENABLE;
+      break;
+
+    case LSM6DS3TR_C_I2C_DISABLE:
+      *val = LSM6DS3TR_C_I2C_DISABLE;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_I2C_MODE_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_interrupt_pins
+  * @brief       This section groups all the functions that manage
+  *              interrupt pins
+  * @{
+  *
+  */
+
+/**
+  * @brief  Select the signal that need to route on int1 pad[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    configure INT1_CTRL, MD1_CFG, CTRL4_C(den_drdy_int1),
+  *                MASTER_CONFIG(drdy_on_int1)
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pin_int1_route_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_int1_route_t val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  lsm6ds3tr_c_int1_ctrl_t int1_ctrl;
+  lsm6ds3tr_c_md1_cfg_t md1_cfg;
+  lsm6ds3tr_c_md2_cfg_t md2_cfg;
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT1_CTRL,
+                             (uint8_t *)&int1_ctrl, 1);
+
+  if (ret == 0)
+  {
+    int1_ctrl.int1_drdy_xl        = val.int1_drdy_xl;
+    int1_ctrl.int1_drdy_g         = val.int1_drdy_g;
+    int1_ctrl.int1_boot           = val.int1_boot;
+    int1_ctrl.int1_fth            = val.int1_fth;
+    int1_ctrl.int1_fifo_ovr       = val.int1_fifo_ovr;
+    int1_ctrl.int1_full_flag      = val.int1_full_flag;
+    int1_ctrl.int1_sign_mot       = val.int1_sign_mot;
+    int1_ctrl.int1_step_detector  = val.int1_step_detector;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT1_CTRL,
+                                (uint8_t *)&int1_ctrl, 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD1_CFG,
+                               (uint8_t *)&md1_cfg, 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD2_CFG,
+                               (uint8_t *)&md2_cfg, 1);
+  }
+
+  if (ret == 0)
+  {
+    md1_cfg.int1_timer           = val.int1_timer;
+    md1_cfg.int1_tilt            = val.int1_tilt;
+    md1_cfg.int1_6d              = val.int1_6d;
+    md1_cfg.int1_double_tap      = val.int1_double_tap;
+    md1_cfg.int1_ff              = val.int1_ff;
+    md1_cfg.int1_wu              = val.int1_wu;
+    md1_cfg.int1_single_tap      = val.int1_single_tap;
+    md1_cfg.int1_inact_state     = val.int1_inact_state;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MD1_CFG,
+                                (uint8_t *)&md1_cfg, 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                               (uint8_t *)&ctrl4_c, 1);
+  }
+
+  if (ret == 0)
+  {
+    ctrl4_c.den_drdy_int1 = val.den_drdy_int1;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                                (uint8_t *)&ctrl4_c, 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                               (uint8_t *)&master_config, 1);
+  }
+
+  if (ret == 0)
+  {
+    master_config.drdy_on_int1   = val.den_drdy_int1;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                                (uint8_t *)&master_config, 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                               (uint8_t *)&tap_cfg, 1);
+
+    if ((val.int1_6d != 0x00U) ||
+        (val.int1_ff != 0x00U) ||
+        (val.int1_wu != 0x00U) ||
+        (val.int1_single_tap != 0x00U) ||
+        (val.int1_double_tap != 0x00U) ||
+        (val.int1_inact_state != 0x00U) ||
+        (md2_cfg.int2_6d != 0x00U) ||
+        (md2_cfg.int2_ff != 0x00U) ||
+        (md2_cfg.int2_wu != 0x00U) ||
+        (md2_cfg.int2_single_tap != 0x00U) ||
+        (md2_cfg.int2_double_tap != 0x00U) ||
+        (md2_cfg.int2_inact_state != 0x00U))
+    {
+      tap_cfg.interrupts_enable = PROPERTY_ENABLE;
+    }
+
+    else
+    {
+      tap_cfg.interrupts_enable = PROPERTY_DISABLE;
+    }
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                                (uint8_t *)&tap_cfg, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Select the signal that need to route on int1 pad[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    read INT1_CTRL, MD1_CFG, CTRL4_C(den_drdy_int1),
+  *                MASTER_CONFIG(drdy_on_int1)
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pin_int1_route_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_int1_route_t *val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  lsm6ds3tr_c_int1_ctrl_t int1_ctrl;
+  lsm6ds3tr_c_md1_cfg_t md1_cfg;
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT1_CTRL,
+                             (uint8_t *)&int1_ctrl, 1);
+
+  if (ret == 0)
+  {
+    val->int1_drdy_xl       = int1_ctrl.int1_drdy_xl;
+    val->int1_drdy_g        = int1_ctrl.int1_drdy_g;
+    val->int1_boot          = int1_ctrl.int1_boot;
+    val->int1_fth           = int1_ctrl.int1_fth;
+    val->int1_fifo_ovr      = int1_ctrl.int1_fifo_ovr;
+    val->int1_full_flag     = int1_ctrl.int1_full_flag;
+    val->int1_sign_mot      = int1_ctrl.int1_sign_mot;
+    val->int1_step_detector = int1_ctrl.int1_step_detector ;
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD1_CFG,
+                               (uint8_t *)&md1_cfg, 1);
+
+    if (ret == 0)
+    {
+      val->int1_timer       = md1_cfg.int1_timer;
+      val->int1_tilt        = md1_cfg.int1_tilt;
+      val->int1_6d          = md1_cfg.int1_6d;
+      val->int1_double_tap  = md1_cfg.int1_double_tap;
+      val->int1_ff          = md1_cfg.int1_ff;
+      val->int1_wu          = md1_cfg.int1_wu;
+      val->int1_single_tap  = md1_cfg.int1_single_tap;
+      val->int1_inact_state = md1_cfg.int1_inact_state;
+      ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                                 (uint8_t *)&ctrl4_c, 1);
+
+      if (ret == 0)
+      {
+        val->den_drdy_int1 = ctrl4_c.den_drdy_int1;
+        ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                                   (uint8_t *)&master_config, 1);
+        val->den_drdy_int1 = master_config.drdy_on_int1;
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Select the signal that need to route on int2 pad[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    INT2_CTRL, DRDY_PULSE_CFG(int2_wrist_tilt), MD2_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pin_int2_route_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_int2_route_t val)
+{
+  lsm6ds3tr_c_int2_ctrl_t int2_ctrl;
+  lsm6ds3tr_c_md1_cfg_t md1_cfg;
+  lsm6ds3tr_c_md2_cfg_t md2_cfg;
+  lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g;
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT2_CTRL,
+                             (uint8_t *)&int2_ctrl, 1);
+
+  if (ret == 0)
+  {
+    int2_ctrl.int2_drdy_xl        = val.int2_drdy_xl;
+    int2_ctrl.int2_drdy_g         = val.int2_drdy_g;
+    int2_ctrl.int2_drdy_temp      = val.int2_drdy_temp;
+    int2_ctrl.int2_fth            = val.int2_fth;
+    int2_ctrl.int2_fifo_ovr       = val.int2_fifo_ovr;
+    int2_ctrl.int2_full_flag      = val.int2_full_flag;
+    int2_ctrl.int2_step_count_ov  = val.int2_step_count_ov;
+    int2_ctrl.int2_step_delta     = val.int2_step_delta;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT2_CTRL,
+                                (uint8_t *)&int2_ctrl, 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD1_CFG,
+                               (uint8_t *)&md1_cfg, 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD2_CFG,
+                               (uint8_t *)&md2_cfg, 1);
+  }
+
+  if (ret == 0)
+  {
+    md2_cfg.int2_iron              = val.int2_iron;
+    md2_cfg.int2_tilt              = val.int2_tilt;
+    md2_cfg.int2_6d                = val.int2_6d;
+    md2_cfg.int2_double_tap        = val.int2_double_tap;
+    md2_cfg.int2_ff                = val.int2_ff;
+    md2_cfg.int2_wu                = val.int2_wu;
+    md2_cfg.int2_single_tap        = val.int2_single_tap;
+    md2_cfg.int2_inact_state       = val.int2_inact_state;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MD2_CFG,
+                                (uint8_t *)&md2_cfg, 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G,
+                               (uint8_t *)&drdy_pulse_cfg_g, 1);
+  }
+
+  if (ret == 0)
+  {
+    drdy_pulse_cfg_g.int2_wrist_tilt = val.int2_wrist_tilt;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G,
+                                (uint8_t *)&drdy_pulse_cfg_g, 1);
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                               (uint8_t *)&tap_cfg, 1);
+
+    if ((md1_cfg.int1_6d != 0x00U) ||
+        (md1_cfg.int1_ff != 0x00U) ||
+        (md1_cfg.int1_wu != 0x00U) ||
+        (md1_cfg.int1_single_tap != 0x00U) ||
+        (md1_cfg.int1_double_tap != 0x00U) ||
+        (md1_cfg.int1_inact_state != 0x00U) ||
+        (val.int2_6d != 0x00U) ||
+        (val.int2_ff != 0x00U) ||
+        (val.int2_wu != 0x00U) ||
+        (val.int2_single_tap != 0x00U) ||
+        (val.int2_double_tap != 0x00U) ||
+        (val.int2_inact_state != 0x00U))
+    {
+      tap_cfg.interrupts_enable = PROPERTY_ENABLE;
+    }
+
+    else
+    {
+      tap_cfg.interrupts_enable = PROPERTY_DISABLE;
+    }
+  }
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                                (uint8_t *)&tap_cfg, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Select the signal that need to route on int2 pad[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    INT2_CTRL, DRDY_PULSE_CFG(int2_wrist_tilt), MD2_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pin_int2_route_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_int2_route_t *val)
+{
+  lsm6ds3tr_c_int2_ctrl_t int2_ctrl;
+  lsm6ds3tr_c_md2_cfg_t md2_cfg;
+  lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT2_CTRL,
+                             (uint8_t *)&int2_ctrl, 1);
+
+  if (ret == 0)
+  {
+    val->int2_drdy_xl         = int2_ctrl.int2_drdy_xl;
+    val->int2_drdy_g          = int2_ctrl.int2_drdy_g;
+    val->int2_drdy_temp       = int2_ctrl.int2_drdy_temp;
+    val->int2_fth             = int2_ctrl.int2_fth;
+    val->int2_fifo_ovr        = int2_ctrl.int2_fifo_ovr;
+    val->int2_full_flag       = int2_ctrl.int2_full_flag;
+    val->int2_step_count_ov   = int2_ctrl.int2_step_count_ov;
+    val->int2_step_delta      = int2_ctrl.int2_step_delta;
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD2_CFG,
+                               (uint8_t *)&md2_cfg, 1);
+
+    if (ret == 0)
+    {
+      val->int2_iron           = md2_cfg.int2_iron;
+      val->int2_tilt           = md2_cfg.int2_tilt;
+      val->int2_6d             = md2_cfg.int2_6d;
+      val->int2_double_tap     = md2_cfg.int2_double_tap;
+      val->int2_ff             = md2_cfg.int2_ff;
+      val->int2_wu             = md2_cfg.int2_wu;
+      val->int2_single_tap     = md2_cfg.int2_single_tap;
+      val->int2_inact_state    = md2_cfg.int2_inact_state;
+      ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G,
+                                 (uint8_t *)&drdy_pulse_cfg_g, 1);
+      val->int2_wrist_tilt = drdy_pulse_cfg_g.int2_wrist_tilt;
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Push-pull/open drain selection on interrupt pads.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of pp_od in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pin_mode_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_pp_od_t val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl3_c.pp_od = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                                (uint8_t *)&ctrl3_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Push-pull/open drain selection on interrupt pads.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of pp_od in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pin_mode_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_pp_od_t *val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+
+  switch (ctrl3_c.pp_od)
+  {
+    case LSM6DS3TR_C_PUSH_PULL:
+      *val = LSM6DS3TR_C_PUSH_PULL;
+      break;
+
+    case LSM6DS3TR_C_OPEN_DRAIN:
+      *val = LSM6DS3TR_C_OPEN_DRAIN;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_PIN_MODE_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Interrupt active-high/low.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of h_lactive in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pin_polarity_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_h_lactive_t val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl3_c.h_lactive = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                                (uint8_t *)&ctrl3_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Interrupt active-high/low.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of h_lactive in reg CTRL3_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pin_polarity_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_h_lactive_t *val)
+{
+  lsm6ds3tr_c_ctrl3_c_t ctrl3_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C,
+                             (uint8_t *)&ctrl3_c, 1);
+
+  switch (ctrl3_c.h_lactive)
+  {
+    case LSM6DS3TR_C_ACTIVE_HIGH:
+      *val = LSM6DS3TR_C_ACTIVE_HIGH;
+      break;
+
+    case LSM6DS3TR_C_ACTIVE_LOW:
+      *val = LSM6DS3TR_C_ACTIVE_LOW;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_POLARITY_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  All interrupt signals become available on INT1 pin.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of int2_on_int1 in reg CTRL4_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_all_on_int1_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                             (uint8_t *)&ctrl4_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl4_c.int2_on_int1 = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                                (uint8_t *)&ctrl4_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  All interrupt signals become available on INT1 pin.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of int2_on_int1 in reg CTRL4_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_all_on_int1_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                             (uint8_t *)&ctrl4_c, 1);
+  *val = ctrl4_c.int2_on_int1;
+
+  return ret;
+}
+
+/**
+  * @brief  Latched/pulsed interrupt.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of lir in reg TAP_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_int_notification_set(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_lir_t val)
+{
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                             (uint8_t *)&tap_cfg, 1);
+
+  if (ret == 0)
+  {
+    tap_cfg.lir = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                                (uint8_t *)&tap_cfg, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Latched/pulsed interrupt.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of lir in reg TAP_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_int_notification_get(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_lir_t *val)
+{
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                             (uint8_t *)&tap_cfg, 1);
+
+  switch (tap_cfg.lir)
+  {
+    case LSM6DS3TR_C_INT_PULSED:
+      *val = LSM6DS3TR_C_INT_PULSED;
+      break;
+
+    case LSM6DS3TR_C_INT_LATCHED:
+      *val = LSM6DS3TR_C_INT_LATCHED;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_INT_MODE;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_Wake_Up_event
+  * @brief       This section groups all the functions that manage the
+  *              Wake Up event generation.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Threshold for wakeup.1 LSB = FS_XL / 64.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of wk_ths in reg WAKE_UP_THS
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_wkup_threshold_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_wake_up_ths_t wake_up_ths;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS,
+                             (uint8_t *)&wake_up_ths, 1);
+
+  if (ret == 0)
+  {
+    wake_up_ths.wk_ths = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS,
+                                (uint8_t *)&wake_up_ths, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Threshold for wakeup.1 LSB = FS_XL / 64.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of wk_ths in reg WAKE_UP_THS
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_wkup_threshold_get(stmdev_ctx_t *ctx,
+                                       uint8_t *val)
+{
+  lsm6ds3tr_c_wake_up_ths_t wake_up_ths;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS,
+                             (uint8_t *)&wake_up_ths, 1);
+  *val = wake_up_ths.wk_ths;
+
+  return ret;
+}
+
+/**
+  * @brief  Wake up duration event.1LSb = 1 / ODR[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of wake_dur in reg WAKE_UP_DUR
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_wkup_dur_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_wake_up_dur_t wake_up_dur;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR,
+                             (uint8_t *)&wake_up_dur, 1);
+
+  if (ret == 0)
+  {
+    wake_up_dur.wake_dur = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR,
+                                (uint8_t *)&wake_up_dur, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Wake up duration event.1LSb = 1 / ODR[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of wake_dur in reg WAKE_UP_DUR
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_wkup_dur_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_wake_up_dur_t wake_up_dur;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR,
+                             (uint8_t *)&wake_up_dur, 1);
+  *val = wake_up_dur.wake_dur;
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_Activity/Inactivity_detection
+  * @brief       This section groups all the functions concerning
+  *              activity/inactivity detection.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Enables gyroscope Sleep mode.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of sleep in reg CTRL4_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_gy_sleep_mode_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                             (uint8_t *)&ctrl4_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl4_c.sleep = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                                (uint8_t *)&ctrl4_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enables gyroscope Sleep mode.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of sleep in reg CTRL4_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_gy_sleep_mode_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                             (uint8_t *)&ctrl4_c, 1);
+  *val = ctrl4_c.sleep;
+
+  return ret;
+}
+
+/**
+  * @brief  Enable inactivity function.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of inact_en in reg TAP_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_act_mode_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_inact_en_t val)
+{
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                             (uint8_t *)&tap_cfg, 1);
+
+  if (ret == 0)
+  {
+    tap_cfg.inact_en = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                                (uint8_t *)&tap_cfg, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable inactivity function.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of inact_en in reg TAP_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_act_mode_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_inact_en_t *val)
+{
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                             (uint8_t *)&tap_cfg, 1);
+
+  switch (tap_cfg.inact_en)
+  {
+    case LSM6DS3TR_C_PROPERTY_DISABLE:
+      *val = LSM6DS3TR_C_PROPERTY_DISABLE;
+      break;
+
+    case LSM6DS3TR_C_XL_12Hz5_GY_NOT_AFFECTED:
+      *val = LSM6DS3TR_C_XL_12Hz5_GY_NOT_AFFECTED;
+      break;
+
+    case LSM6DS3TR_C_XL_12Hz5_GY_SLEEP:
+      *val = LSM6DS3TR_C_XL_12Hz5_GY_SLEEP;
+      break;
+
+    case LSM6DS3TR_C_XL_12Hz5_GY_PD:
+      *val = LSM6DS3TR_C_XL_12Hz5_GY_PD;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_ACT_MODE_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Duration to go in sleep mode.1 LSb = 512 / ODR[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of sleep_dur in reg WAKE_UP_DUR
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_act_sleep_dur_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_wake_up_dur_t wake_up_dur;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR,
+                             (uint8_t *)&wake_up_dur, 1);
+
+  if (ret == 0)
+  {
+    wake_up_dur.sleep_dur = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR,
+                                (uint8_t *)&wake_up_dur, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Duration to go in sleep mode. 1 LSb = 512 / ODR[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of sleep_dur in reg WAKE_UP_DUR
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_act_sleep_dur_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_wake_up_dur_t wake_up_dur;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR,
+                             (uint8_t *)&wake_up_dur, 1);
+  *val = wake_up_dur.sleep_dur;
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_tap_generator
+  * @brief       This section groups all the functions that manage the
+  *              tap and double tap event generation.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Read the tap / double tap source register.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Structure of registers from TAP_SRC
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_src_get(stmdev_ctx_t *ctx,
+                                lsm6ds3tr_c_tap_src_t *val)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_SRC, (uint8_t *) val, 1);
+
+  return ret;
+}
+
+/**
+  * @brief  Enable Z direction in tap recognition.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tap_z_en in reg TAP_CFG
+  *
+  */
+int32_t lsm6ds3tr_c_tap_detection_on_z_set(stmdev_ctx_t *ctx,
+                                           uint8_t val)
+{
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                             (uint8_t *)&tap_cfg, 1);
+
+  if (ret == 0)
+  {
+    tap_cfg.tap_z_en = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                                (uint8_t *)&tap_cfg, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable Z direction in tap recognition.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tap_z_en in reg TAP_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_detection_on_z_get(stmdev_ctx_t *ctx,
+                                           uint8_t *val)
+{
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                             (uint8_t *)&tap_cfg, 1);
+  *val = tap_cfg.tap_z_en;
+
+  return ret;
+}
+
+/**
+  * @brief  Enable Y direction in tap recognition.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tap_y_en in reg TAP_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_detection_on_y_set(stmdev_ctx_t *ctx,
+                                           uint8_t val)
+{
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                             (uint8_t *)&tap_cfg, 1);
+
+  if (ret == 0)
+  {
+    tap_cfg.tap_y_en = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                                (uint8_t *)&tap_cfg, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable Y direction in tap recognition.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tap_y_en in reg TAP_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_detection_on_y_get(stmdev_ctx_t *ctx,
+                                           uint8_t *val)
+{
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                             (uint8_t *)&tap_cfg, 1);
+  *val = tap_cfg.tap_y_en;
+
+  return ret;
+}
+
+/**
+  * @brief  Enable X direction in tap recognition.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tap_x_en in reg TAP_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_detection_on_x_set(stmdev_ctx_t *ctx,
+                                           uint8_t val)
+{
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                             (uint8_t *)&tap_cfg, 1);
+
+  if (ret == 0)
+  {
+    tap_cfg.tap_x_en = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                                (uint8_t *)&tap_cfg, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable X direction in tap recognition.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tap_x_en in reg TAP_CFG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_detection_on_x_get(stmdev_ctx_t *ctx,
+                                           uint8_t *val)
+{
+  lsm6ds3tr_c_tap_cfg_t tap_cfg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG,
+                             (uint8_t *)&tap_cfg, 1);
+  *val = tap_cfg.tap_x_en;
+
+  return ret;
+}
+
+/**
+  * @brief  Threshold for tap recognition.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tap_ths in reg TAP_THS_6D
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_threshold_x_set(stmdev_ctx_t *ctx,
+                                        uint8_t val)
+{
+  lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D,
+                             (uint8_t *)&tap_ths_6d, 1);
+
+  if (ret == 0)
+  {
+    tap_ths_6d.tap_ths = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_THS_6D,
+                                (uint8_t *)&tap_ths_6d, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Threshold for tap recognition.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tap_ths in reg TAP_THS_6D
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_threshold_x_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val)
+{
+  lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D,
+                             (uint8_t *)&tap_ths_6d, 1);
+  *val = tap_ths_6d.tap_ths;
+
+  return ret;
+}
+
+/**
+  * @brief  Maximum duration is the maximum time of an overthreshold signal
+  *         detection to be recognized as a tap event.
+  *         The default value of these bits is 00b which corresponds to
+  *         4*ODR_XL time.
+  *         If the SHOCK[1:0] bits are set to a different
+  *         value, 1LSB corresponds to 8*ODR_XL time.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of shock in reg INT_DUR2
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_shock_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_int_dur2_t int_dur2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2,
+                             (uint8_t *)&int_dur2, 1);
+
+  if (ret == 0)
+  {
+    int_dur2.shock = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT_DUR2,
+                                (uint8_t *)&int_dur2, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Maximum duration is the maximum time of an overthreshold signal
+  *         detection to be recognized as a tap event.
+  *         The default value of these bits is 00b which corresponds to
+  *         4*ODR_XL time.
+  *         If the SHOCK[1:0] bits are set to a different value, 1LSB
+  *         corresponds to 8*ODR_XL time.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of shock in reg INT_DUR2
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_shock_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_int_dur2_t int_dur2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2,
+                             (uint8_t *)&int_dur2, 1);
+  *val = int_dur2.shock;
+
+  return ret;
+}
+
+/**
+  * @brief  Quiet time is the time after the first detected tap in which there
+  *         must not be any overthreshold event.
+  *         The default value of these bits is 00b which corresponds to
+  *         2*ODR_XL time.
+  *         If the QUIET[1:0] bits are set to a different value, 1LSB
+  *         corresponds to 4*ODR_XL time.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of quiet in reg INT_DUR2
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_quiet_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_int_dur2_t int_dur2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2,
+                             (uint8_t *)&int_dur2, 1);
+
+  if (ret == 0)
+  {
+    int_dur2.quiet = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT_DUR2,
+                                (uint8_t *)&int_dur2, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Quiet time is the time after the first detected tap in which there
+  *         must not be any overthreshold event.
+  *         The default value of these bits is 00b which corresponds to
+  *         2*ODR_XL time.
+  *         If the QUIET[1:0] bits are set to a different value, 1LSB
+  *         corresponds to 4*ODR_XL time.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of quiet in reg INT_DUR2
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_quiet_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_int_dur2_t int_dur2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2,
+                             (uint8_t *)&int_dur2, 1);
+  *val = int_dur2.quiet;
+
+  return ret;
+}
+
+/**
+  * @brief  When double tap recognition is enabled, this register expresses the
+  *         maximum time between two consecutive detected taps to determine a
+  *         double tap event.
+  *         The default value of these bits is 0000b which corresponds to
+  *         16*ODR_XL time.
+  *         If the DUR[3:0] bits are set to a different value,1LSB corresponds
+  *         to 32*ODR_XL time.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of dur in reg INT_DUR2
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_dur_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_int_dur2_t int_dur2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2,
+                             (uint8_t *)&int_dur2, 1);
+
+  if (ret == 0)
+  {
+    int_dur2.dur = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT_DUR2,
+                                (uint8_t *)&int_dur2, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  When double tap recognition is enabled, this register expresses the
+  *         maximum time between two consecutive detected taps to determine a
+  *         double tap event.
+  *         The default value of these bits is 0000b which corresponds to
+  *         16*ODR_XL time.
+  *         If the DUR[3:0] bits are set to a different value,1LSB corresponds
+  *         to 32*ODR_XL time.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of dur in reg INT_DUR2
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_dur_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_int_dur2_t int_dur2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2,
+                             (uint8_t *)&int_dur2, 1);
+  *val = int_dur2.dur;
+
+  return ret;
+}
+
+/**
+  * @brief  Single/double-tap event enable/disable.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of
+  *                                      single_double_tap in reg WAKE_UP_THS
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_mode_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_single_double_tap_t val)
+{
+  lsm6ds3tr_c_wake_up_ths_t wake_up_ths;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS,
+                             (uint8_t *)&wake_up_ths, 1);
+
+  if (ret == 0)
+  {
+    wake_up_ths.single_double_tap = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS,
+                                (uint8_t *)&wake_up_ths, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Single/double-tap event enable/disable.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of single_double_tap
+  *                                      in reg WAKE_UP_THS
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tap_mode_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_single_double_tap_t *val)
+{
+  lsm6ds3tr_c_wake_up_ths_t wake_up_ths;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS,
+                             (uint8_t *)&wake_up_ths, 1);
+
+  switch (wake_up_ths.single_double_tap)
+  {
+    case LSM6DS3TR_C_ONLY_SINGLE:
+      *val = LSM6DS3TR_C_ONLY_SINGLE;
+      break;
+
+    case LSM6DS3TR_C_BOTH_SINGLE_DOUBLE:
+      *val = LSM6DS3TR_C_BOTH_SINGLE_DOUBLE;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_TAP_MODE_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_ Six_position_detection(6D/4D)
+  * @brief       This section groups all the functions concerning six
+  *              position detection (6D).
+  * @{
+  *
+  */
+
+/**
+  * @brief  LPF2 feed 6D function selection.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of low_pass_on_6d in
+  *                                   reg CTRL8_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_6d_feed_data_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_low_pass_on_6d_t val)
+{
+  lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                             (uint8_t *)&ctrl8_xl, 1);
+
+  if (ret == 0)
+  {
+    ctrl8_xl.low_pass_on_6d = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                                (uint8_t *)&ctrl8_xl, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  LPF2 feed 6D function selection.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of low_pass_on_6d in reg CTRL8_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_6d_feed_data_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_low_pass_on_6d_t *val)
+{
+  lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL,
+                             (uint8_t *)&ctrl8_xl, 1);
+
+  switch (ctrl8_xl.low_pass_on_6d)
+  {
+    case LSM6DS3TR_C_ODR_DIV_2_FEED:
+      *val = LSM6DS3TR_C_ODR_DIV_2_FEED;
+      break;
+
+    case LSM6DS3TR_C_LPF2_FEED:
+      *val = LSM6DS3TR_C_LPF2_FEED;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_6D_FEED_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Threshold for 4D/6D function.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of sixd_ths in reg TAP_THS_6D
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_6d_threshold_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_sixd_ths_t val)
+{
+  lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D,
+                             (uint8_t *)&tap_ths_6d, 1);
+
+  if (ret == 0)
+  {
+    tap_ths_6d.sixd_ths = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_THS_6D,
+                                (uint8_t *)&tap_ths_6d, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Threshold for 4D/6D function.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of sixd_ths in reg TAP_THS_6D
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_6d_threshold_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_sixd_ths_t *val)
+{
+  lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D,
+                             (uint8_t *)&tap_ths_6d, 1);
+
+  switch (tap_ths_6d.sixd_ths)
+  {
+    case LSM6DS3TR_C_DEG_80:
+      *val = LSM6DS3TR_C_DEG_80;
+      break;
+
+    case LSM6DS3TR_C_DEG_70:
+      *val = LSM6DS3TR_C_DEG_70;
+      break;
+
+    case LSM6DS3TR_C_DEG_60:
+      *val = LSM6DS3TR_C_DEG_60;
+      break;
+
+    case LSM6DS3TR_C_DEG_50:
+      *val = LSM6DS3TR_C_DEG_50;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_6D_TH_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  4D orientation detection enable.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of d4d_en in reg TAP_THS_6D
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_4d_mode_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D,
+                             (uint8_t *)&tap_ths_6d, 1);
+
+  if (ret == 0)
+  {
+    tap_ths_6d.d4d_en = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_THS_6D,
+                                (uint8_t *)&tap_ths_6d, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  4D orientation detection enable.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of d4d_en in reg TAP_THS_6D
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_4d_mode_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D,
+                             (uint8_t *)&tap_ths_6d, 1);
+  *val = tap_ths_6d.d4d_en;
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_free_fall
+  * @brief       This section group all the functions concerning the free
+  *              fall detection.
+  * @{
+  *
+  */
+
+/**
+  * @brief Free-fall duration event. 1LSb = 1 / ODR[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of ff_dur in reg WAKE_UP_DUR
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_ff_dur_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_wake_up_dur_t wake_up_dur;
+  lsm6ds3tr_c_free_fall_t free_fall;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FREE_FALL,
+                             (uint8_t *)&free_fall, 1);
+
+  if (ret == 0)
+  {
+    free_fall.ff_dur = (val & 0x1FU);
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FREE_FALL,
+                                (uint8_t *)&free_fall, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR,
+                                 (uint8_t *)&wake_up_dur, 1);
+
+      if (ret == 0)
+      {
+        wake_up_dur.ff_dur = (val & 0x20U) >> 5;
+        ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR,
+                                    (uint8_t *)&wake_up_dur, 1);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Free-fall duration event. 1LSb = 1 / ODR[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of ff_dur in reg WAKE_UP_DUR
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_ff_dur_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_wake_up_dur_t wake_up_dur;
+  lsm6ds3tr_c_free_fall_t free_fall;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR,
+                             (uint8_t *)&wake_up_dur, 1);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FREE_FALL,
+                               (uint8_t *)&free_fall, 1);
+  }
+
+  *val = (wake_up_dur.ff_dur << 5) + free_fall.ff_dur;
+
+  return ret;
+}
+
+/**
+  * @brief  Free fall threshold setting.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of ff_ths in reg FREE_FALL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_ff_threshold_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_ff_ths_t val)
+{
+  lsm6ds3tr_c_free_fall_t free_fall;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FREE_FALL,
+                             (uint8_t *)&free_fall, 1);
+
+  if (ret == 0)
+  {
+    free_fall.ff_ths = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FREE_FALL,
+                                (uint8_t *)&free_fall, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Free fall threshold setting.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of ff_ths in reg FREE_FALL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_ff_threshold_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_ff_ths_t *val)
+{
+  lsm6ds3tr_c_free_fall_t free_fall;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FREE_FALL,
+                             (uint8_t *)&free_fall, 1);
+
+  switch (free_fall.ff_ths)
+  {
+    case LSM6DS3TR_C_FF_TSH_156mg:
+      *val = LSM6DS3TR_C_FF_TSH_156mg;
+      break;
+
+    case LSM6DS3TR_C_FF_TSH_219mg:
+      *val = LSM6DS3TR_C_FF_TSH_219mg;
+      break;
+
+    case LSM6DS3TR_C_FF_TSH_250mg:
+      *val = LSM6DS3TR_C_FF_TSH_250mg;
+      break;
+
+    case LSM6DS3TR_C_FF_TSH_312mg:
+      *val = LSM6DS3TR_C_FF_TSH_312mg;
+      break;
+
+    case LSM6DS3TR_C_FF_TSH_344mg:
+      *val = LSM6DS3TR_C_FF_TSH_344mg;
+      break;
+
+    case LSM6DS3TR_C_FF_TSH_406mg:
+      *val = LSM6DS3TR_C_FF_TSH_406mg;
+      break;
+
+    case LSM6DS3TR_C_FF_TSH_469mg:
+      *val = LSM6DS3TR_C_FF_TSH_469mg;
+      break;
+
+    case LSM6DS3TR_C_FF_TSH_500mg:
+      *val = LSM6DS3TR_C_FF_TSH_500mg;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_FF_TSH_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_fifo
+  * @brief       This section group all the functions concerning the
+  *              fifo usage
+  * @{
+  *
+  */
+
+/**
+  * @brief  FIFO watermark level selection.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of fth in reg FIFO_CTRL1
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_watermark_set(stmdev_ctx_t *ctx,
+                                       uint16_t val)
+{
+  lsm6ds3tr_c_fifo_ctrl1_t fifo_ctrl1;
+  lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2,
+                             (uint8_t *)&fifo_ctrl2, 1);
+
+  if (ret == 0)
+  {
+    fifo_ctrl1.fth = (uint8_t)(0x00FFU & val);
+    fifo_ctrl2.fth = (uint8_t)((0x0700U & val) >> 8);
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL1,
+                                (uint8_t *)&fifo_ctrl1, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2,
+                                  (uint8_t *)&fifo_ctrl2, 1);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  FIFO watermark level selection.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of fth in reg FIFO_CTRL1
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_watermark_get(stmdev_ctx_t *ctx,
+                                       uint16_t *val)
+{
+  lsm6ds3tr_c_fifo_ctrl1_t fifo_ctrl1;
+  lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL1,
+                             (uint8_t *)&fifo_ctrl1, 1);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2,
+                               (uint8_t *)&fifo_ctrl2, 1);
+  }
+
+  *val = ((uint16_t)fifo_ctrl2.fth << 8) + (uint16_t)fifo_ctrl1.fth;
+
+  return ret;
+}
+
+/**
+  * @brief  FIFO data level.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    get the values of diff_fifo in reg  FIFO_STATUS1 and
+  *                FIFO_STATUS2(diff_fifo), it is recommended to set the
+  *                BDU bit.
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_data_level_get(stmdev_ctx_t *ctx,
+                                        uint16_t *val)
+{
+  lsm6ds3tr_c_fifo_status1_t fifo_status1;
+  lsm6ds3tr_c_fifo_status2_t fifo_status2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS1,
+                             (uint8_t *)&fifo_status1, 1);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS2,
+                               (uint8_t *)&fifo_status2, 1);
+    *val = ((uint16_t) fifo_status2.diff_fifo << 8) +
+           (uint16_t) fifo_status1.diff_fifo;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  FIFO watermark.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    get the values of watermark in reg  FIFO_STATUS2 and
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_wtm_flag_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_fifo_status2_t fifo_status2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS2,
+                             (uint8_t *)&fifo_status2, 1);
+  *val = fifo_status2.waterm;
+
+  return ret;
+}
+
+/**
+  * @brief  FIFO pattern.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    get the values of fifo_pattern in reg  FIFO_STATUS3 and
+  *                FIFO_STATUS4, it is recommended to set the BDU bit
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_pattern_get(stmdev_ctx_t *ctx, uint16_t *val)
+{
+  lsm6ds3tr_c_fifo_status3_t fifo_status3;
+  lsm6ds3tr_c_fifo_status4_t fifo_status4;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS3,
+                             (uint8_t *)&fifo_status3, 1);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS4,
+                               (uint8_t *)&fifo_status4, 1);
+    *val = ((uint16_t)fifo_status4.fifo_pattern << 8) +
+           fifo_status3.fifo_pattern;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Batching of temperature data[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of fifo_temp_en in reg FIFO_CTRL2
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_temp_batch_set(stmdev_ctx_t *ctx,
+                                        uint8_t val)
+{
+  lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2,
+                             (uint8_t *)&fifo_ctrl2, 1);
+
+  if (ret == 0)
+  {
+    fifo_ctrl2.fifo_temp_en = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2,
+                                (uint8_t *)&fifo_ctrl2, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Batching of temperature data[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of fifo_temp_en in reg FIFO_CTRL2
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_temp_batch_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val)
+{
+  lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2,
+                             (uint8_t *)&fifo_ctrl2, 1);
+  *val = fifo_ctrl2.fifo_temp_en;
+
+  return ret;
+}
+
+/**
+  * @brief  Trigger signal for FIFO write operation.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    act on FIFO_CTRL2(timer_pedo_fifo_drdy)
+  *                and MASTER_CONFIG(data_valid_sel_fifo)
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_write_trigger_set(stmdev_ctx_t *ctx,
+                                           lsm6ds3tr_c_trigger_fifo_t val)
+{
+  lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2;
+  lsm6ds3tr_c_master_config_t master_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2,
+                             (uint8_t *)&fifo_ctrl2, 1);
+
+  if (ret == 0)
+  {
+    fifo_ctrl2.timer_pedo_fifo_drdy = (uint8_t)val & 0x01U;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2,
+                                (uint8_t *)&fifo_ctrl2, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                                 (uint8_t *)&master_config, 1);
+
+      if (ret == 0)
+      {
+        master_config.data_valid_sel_fifo = (((uint8_t)val & 0x02U) >> 1);
+        ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                                    (uint8_t *)&master_config, 1);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Trigger signal for FIFO write operation.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    act on FIFO_CTRL2(timer_pedo_fifo_drdy)
+  *                and MASTER_CONFIG(data_valid_sel_fifo)
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_write_trigger_get(stmdev_ctx_t *ctx,
+                                           lsm6ds3tr_c_trigger_fifo_t *val)
+{
+  lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2;
+  lsm6ds3tr_c_master_config_t master_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2,
+                             (uint8_t *)&fifo_ctrl2, 1);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                               (uint8_t *)&master_config, 1);
+
+    switch ((fifo_ctrl2.timer_pedo_fifo_drdy << 1) +
+            fifo_ctrl2. timer_pedo_fifo_drdy)
+    {
+      case LSM6DS3TR_C_TRG_XL_GY_DRDY:
+        *val = LSM6DS3TR_C_TRG_XL_GY_DRDY;
+        break;
+
+      case LSM6DS3TR_C_TRG_STEP_DETECT:
+        *val = LSM6DS3TR_C_TRG_STEP_DETECT;
+        break;
+
+      case LSM6DS3TR_C_TRG_SH_DRDY:
+        *val = LSM6DS3TR_C_TRG_SH_DRDY;
+        break;
+
+      default:
+        *val = LSM6DS3TR_C_TRG_SH_ND;
+        break;
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief   Enable pedometer step counter and timestamp as 4th
+  *          FIFO data set.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of timer_pedo_fifo_en in reg FIFO_CTRL2
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_pedo_and_timestamp_batch_set(
+  stmdev_ctx_t *ctx,
+  uint8_t val)
+{
+  lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2,
+                             (uint8_t *)&fifo_ctrl2, 1);
+
+  if (ret == 0)
+  {
+    fifo_ctrl2.timer_pedo_fifo_en = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2,
+                                (uint8_t *)&fifo_ctrl2, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable pedometer step counter and timestamp as 4th
+  *         FIFO data set.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of timer_pedo_fifo_en in reg FIFO_CTRL2
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_pedo_and_timestamp_batch_get(
+  stmdev_ctx_t *ctx,
+  uint8_t *val)
+{
+  lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2,
+                             (uint8_t *)&fifo_ctrl2, 1);
+  *val = fifo_ctrl2.timer_pedo_fifo_en;
+
+  return ret;
+}
+
+/**
+  * @brief  Selects Batching Data Rate (writing frequency in FIFO) for
+  *         accelerometer data.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of dec_fifo_xl in reg FIFO_CTRL3
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_xl_batch_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_dec_fifo_xl_t val)
+{
+  lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3,
+                             (uint8_t *)&fifo_ctrl3, 1);
+
+  if (ret == 0)
+  {
+    fifo_ctrl3.dec_fifo_xl = (uint8_t)val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3,
+                                (uint8_t *)&fifo_ctrl3, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Selects Batching Data Rate (writing frequency in FIFO) for
+  *         accelerometer data.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of dec_fifo_xl in reg FIFO_CTRL3
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_xl_batch_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_dec_fifo_xl_t *val)
+{
+  lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3,
+                             (uint8_t *)&fifo_ctrl3, 1);
+
+  switch (fifo_ctrl3.dec_fifo_xl)
+  {
+    case LSM6DS3TR_C_FIFO_XL_DISABLE:
+      *val = LSM6DS3TR_C_FIFO_XL_DISABLE;
+      break;
+
+    case LSM6DS3TR_C_FIFO_XL_NO_DEC:
+      *val = LSM6DS3TR_C_FIFO_XL_NO_DEC;
+      break;
+
+    case LSM6DS3TR_C_FIFO_XL_DEC_2:
+      *val = LSM6DS3TR_C_FIFO_XL_DEC_2;
+      break;
+
+    case LSM6DS3TR_C_FIFO_XL_DEC_3:
+      *val = LSM6DS3TR_C_FIFO_XL_DEC_3;
+      break;
+
+    case LSM6DS3TR_C_FIFO_XL_DEC_4:
+      *val = LSM6DS3TR_C_FIFO_XL_DEC_4;
+      break;
+
+    case LSM6DS3TR_C_FIFO_XL_DEC_8:
+      *val = LSM6DS3TR_C_FIFO_XL_DEC_8;
+      break;
+
+    case LSM6DS3TR_C_FIFO_XL_DEC_16:
+      *val = LSM6DS3TR_C_FIFO_XL_DEC_16;
+      break;
+
+    case LSM6DS3TR_C_FIFO_XL_DEC_32:
+      *val = LSM6DS3TR_C_FIFO_XL_DEC_32;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_FIFO_XL_DEC_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Selects Batching Data Rate (writing frequency in FIFO)
+  *         for gyroscope data.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of dec_fifo_gyro in reg FIFO_CTRL3
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_gy_batch_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_dec_fifo_gyro_t val)
+{
+  lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3,
+                             (uint8_t *)&fifo_ctrl3, 1);
+
+  if (ret == 0)
+  {
+    fifo_ctrl3.dec_fifo_gyro = (uint8_t)val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3,
+                                (uint8_t *)&fifo_ctrl3, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Selects Batching Data Rate (writing frequency in FIFO)
+  *         for gyroscope data.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of dec_fifo_gyro in reg FIFO_CTRL3
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_gy_batch_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_dec_fifo_gyro_t *val)
+{
+  lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3,
+                             (uint8_t *)&fifo_ctrl3, 1);
+
+  switch (fifo_ctrl3.dec_fifo_gyro)
+  {
+    case LSM6DS3TR_C_FIFO_GY_DISABLE:
+      *val = LSM6DS3TR_C_FIFO_GY_DISABLE;
+      break;
+
+    case LSM6DS3TR_C_FIFO_GY_NO_DEC:
+      *val = LSM6DS3TR_C_FIFO_GY_NO_DEC;
+      break;
+
+    case LSM6DS3TR_C_FIFO_GY_DEC_2:
+      *val = LSM6DS3TR_C_FIFO_GY_DEC_2;
+      break;
+
+    case LSM6DS3TR_C_FIFO_GY_DEC_3:
+      *val = LSM6DS3TR_C_FIFO_GY_DEC_3;
+      break;
+
+    case LSM6DS3TR_C_FIFO_GY_DEC_4:
+      *val = LSM6DS3TR_C_FIFO_GY_DEC_4;
+      break;
+
+    case LSM6DS3TR_C_FIFO_GY_DEC_8:
+      *val = LSM6DS3TR_C_FIFO_GY_DEC_8;
+      break;
+
+    case LSM6DS3TR_C_FIFO_GY_DEC_16:
+      *val = LSM6DS3TR_C_FIFO_GY_DEC_16;
+      break;
+
+    case LSM6DS3TR_C_FIFO_GY_DEC_32:
+      *val = LSM6DS3TR_C_FIFO_GY_DEC_32;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_FIFO_GY_DEC_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief   Selects Batching Data Rate (writing frequency in FIFO)
+  *          for third data set.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of dec_ds3_fifo in reg FIFO_CTRL4
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_dataset_3_batch_set(stmdev_ctx_t *ctx,
+                                             lsm6ds3tr_c_dec_ds3_fifo_t val)
+{
+  lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4,
+                             (uint8_t *)&fifo_ctrl4, 1);
+
+  if (ret == 0)
+  {
+    fifo_ctrl4.dec_ds3_fifo = (uint8_t)val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4,
+                                (uint8_t *)&fifo_ctrl4, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief   Selects Batching Data Rate (writing frequency in FIFO)
+  *          for third data set.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of dec_ds3_fifo in reg FIFO_CTRL4
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_dataset_3_batch_get(stmdev_ctx_t *ctx,
+                                             lsm6ds3tr_c_dec_ds3_fifo_t *val)
+{
+  lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4,
+                             (uint8_t *)&fifo_ctrl4, 1);
+
+  switch (fifo_ctrl4.dec_ds3_fifo)
+  {
+    case LSM6DS3TR_C_FIFO_DS3_DISABLE:
+      *val = LSM6DS3TR_C_FIFO_DS3_DISABLE;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS3_NO_DEC:
+      *val = LSM6DS3TR_C_FIFO_DS3_NO_DEC;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS3_DEC_2:
+      *val = LSM6DS3TR_C_FIFO_DS3_DEC_2;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS3_DEC_3:
+      *val = LSM6DS3TR_C_FIFO_DS3_DEC_3;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS3_DEC_4:
+      *val = LSM6DS3TR_C_FIFO_DS3_DEC_4;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS3_DEC_8:
+      *val = LSM6DS3TR_C_FIFO_DS3_DEC_8;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS3_DEC_16:
+      *val = LSM6DS3TR_C_FIFO_DS3_DEC_16;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS3_DEC_32:
+      *val = LSM6DS3TR_C_FIFO_DS3_DEC_32;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_FIFO_DS3_DEC_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief   Selects Batching Data Rate (writing frequency in FIFO)
+  *          for fourth data set.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of dec_ds4_fifo in reg FIFO_CTRL4
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_dataset_4_batch_set(stmdev_ctx_t *ctx,
+                                             lsm6ds3tr_c_dec_ds4_fifo_t val)
+{
+  lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4,
+                             (uint8_t *)&fifo_ctrl4, 1);
+
+  if (ret == 0)
+  {
+    fifo_ctrl4.dec_ds4_fifo = (uint8_t)val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4,
+                                (uint8_t *)&fifo_ctrl4, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief   Selects Batching Data Rate (writing frequency in FIFO) for
+  *          fourth data set.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of dec_ds4_fifo in reg FIFO_CTRL4
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_dataset_4_batch_get(stmdev_ctx_t *ctx,
+                                             lsm6ds3tr_c_dec_ds4_fifo_t *val)
+{
+  lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4,
+                             (uint8_t *)&fifo_ctrl4, 1);
+
+  switch (fifo_ctrl4.dec_ds4_fifo)
+  {
+    case LSM6DS3TR_C_FIFO_DS4_DISABLE:
+      *val = LSM6DS3TR_C_FIFO_DS4_DISABLE;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS4_NO_DEC:
+      *val = LSM6DS3TR_C_FIFO_DS4_NO_DEC;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS4_DEC_2:
+      *val = LSM6DS3TR_C_FIFO_DS4_DEC_2;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS4_DEC_3:
+      *val = LSM6DS3TR_C_FIFO_DS4_DEC_3;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS4_DEC_4:
+      *val = LSM6DS3TR_C_FIFO_DS4_DEC_4;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS4_DEC_8:
+      *val = LSM6DS3TR_C_FIFO_DS4_DEC_8;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS4_DEC_16:
+      *val = LSM6DS3TR_C_FIFO_DS4_DEC_16;
+      break;
+
+    case LSM6DS3TR_C_FIFO_DS4_DEC_32:
+      *val = LSM6DS3TR_C_FIFO_DS4_DEC_32;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_FIFO_DS4_DEC_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief   8-bit data storage in FIFO.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of only_high_data in reg FIFO_CTRL4
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_xl_gy_8bit_format_set(stmdev_ctx_t *ctx,
+                                               uint8_t val)
+{
+  lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4,
+                             (uint8_t *)&fifo_ctrl4, 1);
+
+  if (ret == 0)
+  {
+    fifo_ctrl4.only_high_data = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4,
+                                (uint8_t *)&fifo_ctrl4, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  8-bit data storage in FIFO.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of only_high_data in reg FIFO_CTRL4
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_xl_gy_8bit_format_get(stmdev_ctx_t *ctx,
+                                               uint8_t *val)
+{
+  lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4,
+                             (uint8_t *)&fifo_ctrl4, 1);
+  *val = fifo_ctrl4.only_high_data;
+
+  return ret;
+}
+
+/**
+  * @brief  Sensing chain FIFO stop values memorization at threshold
+  *         level.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of stop_on_fth in reg FIFO_CTRL4
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_stop_on_wtm_set(stmdev_ctx_t *ctx,
+                                         uint8_t val)
+{
+  lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4,
+                             (uint8_t *)&fifo_ctrl4, 1);
+
+  if (ret == 0)
+  {
+    fifo_ctrl4.stop_on_fth = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4,
+                                (uint8_t *)&fifo_ctrl4, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Sensing chain FIFO stop values memorization at threshold
+  *         level.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of stop_on_fth in reg FIFO_CTRL4
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_stop_on_wtm_get(stmdev_ctx_t *ctx,
+                                         uint8_t *val)
+{
+  lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4,
+                             (uint8_t *)&fifo_ctrl4, 1);
+  *val = fifo_ctrl4.stop_on_fth;
+
+  return ret;
+}
+
+/**
+  * @brief  FIFO mode selection.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of fifo_mode in reg FIFO_CTRL5
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_mode_set(stmdev_ctx_t *ctx,
+                                  lsm6ds3tr_c_fifo_mode_t val)
+{
+  lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5,
+                             (uint8_t *)&fifo_ctrl5, 1);
+
+  if (ret == 0)
+  {
+    fifo_ctrl5.fifo_mode = (uint8_t)val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5,
+                                (uint8_t *)&fifo_ctrl5, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  FIFO mode selection.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of fifo_mode in reg FIFO_CTRL5
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_mode_get(stmdev_ctx_t *ctx,
+                                  lsm6ds3tr_c_fifo_mode_t *val)
+{
+  lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5,
+                             (uint8_t *)&fifo_ctrl5, 1);
+
+  switch (fifo_ctrl5.fifo_mode)
+  {
+    case LSM6DS3TR_C_BYPASS_MODE:
+      *val = LSM6DS3TR_C_BYPASS_MODE;
+      break;
+
+    case LSM6DS3TR_C_FIFO_MODE:
+      *val = LSM6DS3TR_C_FIFO_MODE;
+      break;
+
+    case LSM6DS3TR_C_STREAM_TO_FIFO_MODE:
+      *val = LSM6DS3TR_C_STREAM_TO_FIFO_MODE;
+      break;
+
+    case LSM6DS3TR_C_BYPASS_TO_STREAM_MODE:
+      *val = LSM6DS3TR_C_BYPASS_TO_STREAM_MODE;
+      break;
+
+    case LSM6DS3TR_C_STREAM_MODE:
+      *val = LSM6DS3TR_C_STREAM_MODE;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_FIFO_MODE_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  FIFO ODR selection, setting FIFO_MODE also.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of odr_fifo in reg FIFO_CTRL5
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_data_rate_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_odr_fifo_t val)
+{
+  lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5,
+                             (uint8_t *)&fifo_ctrl5, 1);
+
+  if (ret == 0)
+  {
+    fifo_ctrl5.odr_fifo = (uint8_t)val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5,
+                                (uint8_t *)&fifo_ctrl5, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  FIFO ODR selection, setting FIFO_MODE also.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of odr_fifo in reg FIFO_CTRL5
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_fifo_data_rate_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_odr_fifo_t *val)
+{
+  lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5,
+                             (uint8_t *)&fifo_ctrl5, 1);
+
+  switch (fifo_ctrl5.odr_fifo)
+  {
+    case LSM6DS3TR_C_FIFO_DISABLE:
+      *val = LSM6DS3TR_C_FIFO_DISABLE;
+      break;
+
+    case LSM6DS3TR_C_FIFO_12Hz5:
+      *val = LSM6DS3TR_C_FIFO_12Hz5;
+      break;
+
+    case LSM6DS3TR_C_FIFO_26Hz:
+      *val = LSM6DS3TR_C_FIFO_26Hz;
+      break;
+
+    case LSM6DS3TR_C_FIFO_52Hz:
+      *val = LSM6DS3TR_C_FIFO_52Hz;
+      break;
+
+    case LSM6DS3TR_C_FIFO_104Hz:
+      *val = LSM6DS3TR_C_FIFO_104Hz;
+      break;
+
+    case LSM6DS3TR_C_FIFO_208Hz:
+      *val = LSM6DS3TR_C_FIFO_208Hz;
+      break;
+
+    case LSM6DS3TR_C_FIFO_416Hz:
+      *val = LSM6DS3TR_C_FIFO_416Hz;
+      break;
+
+    case LSM6DS3TR_C_FIFO_833Hz:
+      *val = LSM6DS3TR_C_FIFO_833Hz;
+      break;
+
+    case LSM6DS3TR_C_FIFO_1k66Hz:
+      *val = LSM6DS3TR_C_FIFO_1k66Hz;
+      break;
+
+    case LSM6DS3TR_C_FIFO_3k33Hz:
+      *val = LSM6DS3TR_C_FIFO_3k33Hz;
+      break;
+
+    case LSM6DS3TR_C_FIFO_6k66Hz:
+      *val = LSM6DS3TR_C_FIFO_6k66Hz;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_FIFO_RATE_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_DEN_functionality
+  * @brief       This section groups all the functions concerning DEN
+  *              functionality.
+  * @{
+  *
+  */
+
+/**
+  * @brief  DEN active level configuration.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of den_lh in reg CTRL5_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_den_polarity_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_den_lh_t val)
+{
+  lsm6ds3tr_c_ctrl5_c_t ctrl5_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C,
+                             (uint8_t *)&ctrl5_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl5_c.den_lh = (uint8_t)val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL5_C,
+                                (uint8_t *)&ctrl5_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  DEN active level configuration.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of den_lh in reg CTRL5_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_den_polarity_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_den_lh_t *val)
+{
+  lsm6ds3tr_c_ctrl5_c_t ctrl5_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C,
+                             (uint8_t *)&ctrl5_c, 1);
+
+  switch (ctrl5_c.den_lh)
+  {
+    case LSM6DS3TR_C_DEN_ACT_LOW:
+      *val = LSM6DS3TR_C_DEN_ACT_LOW;
+      break;
+
+    case LSM6DS3TR_C_DEN_ACT_HIGH:
+      *val = LSM6DS3TR_C_DEN_ACT_HIGH;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_DEN_POL_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  DEN functionality marking mode[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of den_mode in reg CTRL6_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_den_mode_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_den_mode_t val)
+{
+  lsm6ds3tr_c_ctrl6_c_t ctrl6_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C,
+                             (uint8_t *)&ctrl6_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl6_c.den_mode = (uint8_t)val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL6_C,
+                                (uint8_t *)&ctrl6_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  DEN functionality marking mode[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of den_mode in reg CTRL6_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_den_mode_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_den_mode_t *val)
+{
+  lsm6ds3tr_c_ctrl6_c_t ctrl6_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C,
+                             (uint8_t *)&ctrl6_c, 1);
+
+  switch (ctrl6_c.den_mode)
+  {
+    case LSM6DS3TR_C_DEN_DISABLE:
+      *val = LSM6DS3TR_C_DEN_DISABLE;
+      break;
+
+    case LSM6DS3TR_C_LEVEL_LETCHED:
+      *val = LSM6DS3TR_C_LEVEL_LETCHED;
+      break;
+
+    case LSM6DS3TR_C_LEVEL_TRIGGER:
+      *val = LSM6DS3TR_C_LEVEL_TRIGGER;
+      break;
+
+    case LSM6DS3TR_C_EDGE_TRIGGER:
+      *val = LSM6DS3TR_C_EDGE_TRIGGER;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_DEN_MODE_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Extend DEN functionality to accelerometer sensor.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of den_xl_g in reg CTRL9_XL
+  *                             and den_xl_en in CTRL4_C.
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_den_enable_set(stmdev_ctx_t *ctx,
+                                   lsm6ds3tr_c_den_xl_en_t val)
+{
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                             (uint8_t *)&ctrl9_xl, 1);
+
+  if (ret == 0)
+  {
+    ctrl9_xl.den_xl_g = (uint8_t)val & 0x01U;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                                (uint8_t *)&ctrl9_xl, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                                 (uint8_t *)&ctrl4_c, 1);
+
+      if (ret == 0)
+      {
+        ctrl4_c.den_xl_en = (uint8_t)val & 0x02U;
+        ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                                    (uint8_t *)&ctrl4_c, 1);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Extend DEN functionality to accelerometer sensor. [get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of den_xl_g in reg CTRL9_XL
+  *                             and den_xl_en in CTRL4_C.
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_den_enable_get(stmdev_ctx_t *ctx,
+                                   lsm6ds3tr_c_den_xl_en_t *val)
+{
+  lsm6ds3tr_c_ctrl4_c_t ctrl4_c;
+  lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C,
+                             (uint8_t *)&ctrl4_c, 1);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                               (uint8_t *)&ctrl9_xl, 1);
+
+    switch ((ctrl4_c.den_xl_en << 1) + ctrl9_xl.den_xl_g)
+    {
+      case LSM6DS3TR_C_STAMP_IN_GY_DATA:
+        *val = LSM6DS3TR_C_STAMP_IN_GY_DATA;
+        break;
+
+      case LSM6DS3TR_C_STAMP_IN_XL_DATA:
+        *val = LSM6DS3TR_C_STAMP_IN_XL_DATA;
+        break;
+
+      case LSM6DS3TR_C_STAMP_IN_GY_XL_DATA:
+        *val = LSM6DS3TR_C_STAMP_IN_GY_XL_DATA;
+        break;
+
+      default:
+        *val = LSM6DS3TR_C_DEN_STAMP_ND;
+        break;
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  DEN value stored in LSB of Z-axis.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of den_z in reg CTRL9_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_den_mark_axis_z_set(stmdev_ctx_t *ctx,
+                                        uint8_t val)
+{
+  lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                             (uint8_t *)&ctrl9_xl, 1);
+
+  if (ret == 0)
+  {
+    ctrl9_xl.den_z = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                                (uint8_t *)&ctrl9_xl, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  DEN value stored in LSB of Z-axis.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of den_z in reg CTRL9_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_den_mark_axis_z_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                             (uint8_t *)&ctrl9_xl, 1);
+  *val = ctrl9_xl.den_z;
+
+  return ret;
+}
+
+/**
+  * @brief  DEN value stored in LSB of Y-axis.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of den_y in reg CTRL9_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_den_mark_axis_y_set(stmdev_ctx_t *ctx,
+                                        uint8_t val)
+{
+  lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                             (uint8_t *)&ctrl9_xl, 1);
+
+  if (ret == 0)
+  {
+    ctrl9_xl.den_y = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                                (uint8_t *)&ctrl9_xl, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  DEN value stored in LSB of Y-axis.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of den_y in reg CTRL9_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_den_mark_axis_y_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                             (uint8_t *)&ctrl9_xl, 1);
+  *val = ctrl9_xl.den_y;
+
+  return ret;
+}
+
+/**
+  * @brief  DEN value stored in LSB of X-axis.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of den_x in reg CTRL9_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_den_mark_axis_x_set(stmdev_ctx_t *ctx,
+                                        uint8_t val)
+{
+  lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                             (uint8_t *)&ctrl9_xl, 1);
+
+  if (ret == 0)
+  {
+    ctrl9_xl.den_x = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                                (uint8_t *)&ctrl9_xl, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  DEN value stored in LSB of X-axis.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of den_x in reg CTRL9_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_den_mark_axis_x_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                             (uint8_t *)&ctrl9_xl, 1);
+  *val = ctrl9_xl.den_x;
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_Pedometer
+  * @brief       This section groups all the functions that manage pedometer.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Reset pedometer step counter.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of pedo_rst_step in reg CTRL10_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_step_reset_set(stmdev_ctx_t *ctx,
+                                        uint8_t val)
+{
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                             (uint8_t *)&ctrl10_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl10_c.pedo_rst_step = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                                (uint8_t *)&ctrl10_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Reset pedometer step counter.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of pedo_rst_step in reg CTRL10_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_step_reset_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                             (uint8_t *)&ctrl10_c, 1);
+  *val = ctrl10_c.pedo_rst_step;
+
+  return ret;
+}
+
+/**
+  * @brief  Enable pedometer algorithm.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of pedo_en in reg CTRL10_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_sens_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                             (uint8_t *)&ctrl10_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl10_c.pedo_en = val;
+
+    if (val != 0x00U)
+    {
+      ctrl10_c.func_en = val;
+    }
+
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                                (uint8_t *)&ctrl10_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  pedo_sens:   Enable pedometer algorithm.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of pedo_en in reg CTRL10_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_sens_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                             (uint8_t *)&ctrl10_c, 1);
+  *val = ctrl10_c.pedo_en;
+
+  return ret;
+}
+
+/**
+  * @brief  Minimum threshold to detect a peak. Default is 10h.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of ths_min in reg
+  *                      CONFIG_PEDO_THS_MIN
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_threshold_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN,
+                               (uint8_t *)&config_pedo_ths_min, 1);
+
+    if (ret == 0)
+    {
+      config_pedo_ths_min.ths_min = val;
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN,
+                                  (uint8_t *)&config_pedo_ths_min, 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Minimum threshold to detect a peak. Default is 10h.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of ths_min in reg  CONFIG_PEDO_THS_MIN
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_threshold_get(stmdev_ctx_t *ctx,
+                                       uint8_t *val)
+{
+  lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN,
+                               (uint8_t *)&config_pedo_ths_min, 1);
+
+    if (ret == 0)
+    {
+      *val =  config_pedo_ths_min.ths_min;
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  pedo_full_scale:   Pedometer data range.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of pedo_fs in
+  *                            reg CONFIG_PEDO_THS_MIN
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_full_scale_set(stmdev_ctx_t *ctx,
+                                        lsm6ds3tr_c_pedo_fs_t val)
+{
+  lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN,
+                               (uint8_t *)&config_pedo_ths_min, 1);
+
+    if (ret == 0)
+    {
+      config_pedo_ths_min.pedo_fs = (uint8_t) val;
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN,
+                                  (uint8_t *)&config_pedo_ths_min, 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Pedometer data range.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of pedo_fs in
+  *                            reg CONFIG_PEDO_THS_MIN
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_full_scale_get(stmdev_ctx_t *ctx,
+                                        lsm6ds3tr_c_pedo_fs_t *val)
+{
+  lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN,
+                               (uint8_t *)&config_pedo_ths_min, 1);
+
+    if (ret == 0)
+    {
+      switch (config_pedo_ths_min.pedo_fs)
+      {
+        case LSM6DS3TR_C_PEDO_AT_2g:
+          *val = LSM6DS3TR_C_PEDO_AT_2g;
+          break;
+
+        case LSM6DS3TR_C_PEDO_AT_4g:
+          *val = LSM6DS3TR_C_PEDO_AT_4g;
+          break;
+
+        default:
+          *val = LSM6DS3TR_C_PEDO_FS_ND;
+          break;
+      }
+
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Pedometer debounce configuration register (r/w).[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of deb_step in reg PEDO_DEB_REG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_debounce_steps_set(stmdev_ctx_t *ctx,
+                                            uint8_t val)
+{
+  lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG,
+                               (uint8_t *)&pedo_deb_reg, 1);
+
+    if (ret == 0)
+    {
+      pedo_deb_reg.deb_step = val;
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG,
+                                  (uint8_t *)&pedo_deb_reg, 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Pedometer debounce configuration register (r/w).[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of deb_step in reg PEDO_DEB_REG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_debounce_steps_get(stmdev_ctx_t *ctx,
+                                            uint8_t *val)
+{
+  lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG,
+                               (uint8_t *)&pedo_deb_reg, 1);
+
+    if (ret == 0)
+    {
+      *val = pedo_deb_reg.deb_step;
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Debounce time. If the time between two consecutive steps is
+  *         greater than  DEB_TIME*80ms, the debouncer is reactivated.
+  *         Default value: 01101[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of deb_time in reg PEDO_DEB_REG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_timeout_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG,
+                               (uint8_t *)&pedo_deb_reg, 1);
+
+    if (ret == 0)
+    {
+      pedo_deb_reg.deb_time = val;
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG,
+                                  (uint8_t *)&pedo_deb_reg, 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Debounce time. If the time between two consecutive steps is
+  *         greater than  DEB_TIME*80ms, the debouncer is reactivated.
+  *         Default value: 01101[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of deb_time in reg PEDO_DEB_REG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_timeout_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG,
+                               (uint8_t *)&pedo_deb_reg, 1);
+
+    if (ret == 0)
+    {
+      *val = pedo_deb_reg.deb_time;
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Time period register for step detection on delta time (r/w).[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that contains data to write
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_steps_period_set(stmdev_ctx_t *ctx,
+                                          uint8_t *buff)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_STEP_COUNT_DELTA, buff, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Time period register for step detection on delta time (r/w).[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that stores data read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_pedo_steps_period_get(stmdev_ctx_t *ctx,
+                                          uint8_t *buff)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STEP_COUNT_DELTA, buff, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_significant_motion
+  * @brief       This section groups all the functions that manage the
+  *              significant motion detection.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Enable significant motion detection function.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of sign_motion_en in reg CTRL10_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_motion_sens_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                             (uint8_t *)&ctrl10_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl10_c.sign_motion_en = val;
+
+    if (val != 0x00U)
+    {
+      ctrl10_c.func_en = val;
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                                  (uint8_t *)&ctrl10_c, 1);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable significant motion detection function.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of sign_motion_en in reg CTRL10_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_motion_sens_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                             (uint8_t *)&ctrl10_c, 1);
+  *val = ctrl10_c.sign_motion_en;
+
+  return ret;
+}
+
+/**
+  * @brief  Significant motion threshold.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that store significant motion threshold.
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_motion_threshold_set(stmdev_ctx_t *ctx,
+                                         uint8_t *buff)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SM_THS, buff, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Significant motion threshold.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that store significant motion threshold.
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_motion_threshold_get(stmdev_ctx_t *ctx,
+                                         uint8_t *buff)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SM_THS, buff, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_tilt_detection
+  * @brief       This section groups all the functions that manage the tilt
+  *              event detection.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Enable tilt calculation.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tilt_en in reg CTRL10_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tilt_sens_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                             (uint8_t *)&ctrl10_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl10_c.tilt_en = val;
+
+    if (val != 0x00U)
+    {
+      ctrl10_c.func_en = val;
+    }
+
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                                (uint8_t *)&ctrl10_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable tilt calculation.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tilt_en in reg CTRL10_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tilt_sens_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                             (uint8_t *)&ctrl10_c, 1);
+  *val = ctrl10_c.tilt_en;
+
+  return ret;
+}
+
+/**
+  * @brief  Enable tilt calculation.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tilt_en in reg CTRL10_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_wrist_tilt_sens_set(stmdev_ctx_t *ctx,
+                                        uint8_t val)
+{
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                             (uint8_t *)&ctrl10_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl10_c.wrist_tilt_en = val;
+
+    if (val != 0x00U)
+    {
+      ctrl10_c.func_en = val;
+    }
+
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                                (uint8_t *)&ctrl10_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable tilt calculation.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tilt_en in reg CTRL10_C
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_wrist_tilt_sens_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                             (uint8_t *)&ctrl10_c, 1);
+  *val = ctrl10_c.wrist_tilt_en;
+
+  return ret;
+}
+
+/**
+  * @brief  Absolute Wrist Tilt latency register (r/w).
+  *         Absolute wrist tilt latency parameters.
+  *         1 LSB = 40 ms. Default value: 0Fh (600 ms).[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that contains data to write
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tilt_latency_set(stmdev_ctx_t *ctx, uint8_t *buff)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_LAT, buff, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Absolute Wrist Tilt latency register (r/w).
+  *         Absolute wrist tilt latency parameters.
+  *         1 LSB = 40 ms. Default value: 0Fh (600 ms).[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that stores data read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tilt_latency_get(stmdev_ctx_t *ctx, uint8_t *buff)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_LAT, buff, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Absolute Wrist Tilt threshold register(r/w).
+  *         Absolute wrist tilt threshold parameters.
+  *         1 LSB = 15.625 mg.Default value: 20h (500 mg).[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that contains data to write
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tilt_threshold_set(stmdev_ctx_t *ctx,
+                                       uint8_t *buff)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_THS, buff, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Absolute Wrist Tilt threshold register(r/w).
+  *         Absolute wrist tilt threshold parameters.
+  *         1 LSB = 15.625 mg.Default value: 20h (500 mg).[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that stores data read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tilt_threshold_get(stmdev_ctx_t *ctx,
+                                       uint8_t *buff)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_THS, buff, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Absolute Wrist Tilt mask register (r/w).[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Registers A_WRIST_TILT_MASK
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tilt_src_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_a_wrist_tilt_mask_t *val)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_MASK,
+                               (uint8_t *) val, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Absolute Wrist Tilt mask register (r/w).[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Registers A_WRIST_TILT_MASK
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_tilt_src_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_a_wrist_tilt_mask_t *val)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_MASK,
+                               (uint8_t *) val, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_ magnetometer_sensor
+  * @brief       This section groups all the functions that manage additional
+  *              magnetometer sensor.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Enable soft-iron correction algorithm for magnetometer.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of soft_en in reg CTRL9_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_mag_soft_iron_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                             (uint8_t *)&ctrl9_xl, 1);
+
+  if (ret == 0)
+  {
+    ctrl9_xl.soft_en = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                                (uint8_t *)&ctrl9_xl, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable soft-iron correction algorithm for magnetometer.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of soft_en in reg CTRL9_XL
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_mag_soft_iron_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL,
+                             (uint8_t *)&ctrl9_xl, 1);
+  *val = ctrl9_xl.soft_en;
+
+  return ret;
+}
+
+/**
+  * @brief  Enable hard-iron correction algorithm for magnetometer.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of iron_en in reg MASTER_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_mag_hard_iron_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                             (uint8_t *)&master_config, 1);
+
+  if (ret == 0)
+  {
+    master_config.iron_en = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                                (uint8_t *)&master_config, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                                 (uint8_t *)&ctrl10_c, 1);
+
+      if (ret == 0)
+      {
+        if (val != 0x00U)
+        {
+          ctrl10_c.func_en = val;
+        }
+
+        ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                                    (uint8_t *)&ctrl10_c, 1);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Enable hard-iron correction algorithm for magnetometer.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of iron_en in reg MASTER_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_mag_hard_iron_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                             (uint8_t *)&master_config, 1);
+  *val = master_config.iron_en;
+
+  return ret;
+}
+
+/**
+  * @brief  Soft iron 3x3 matrix. Value are expressed in sign-module format.
+  *         (Es. SVVVVVVVb where S is the sign 0/+1/- and V is the value).[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that contains data to write
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_mag_soft_iron_mat_set(stmdev_ctx_t *ctx,
+                                          uint8_t *buff)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MAG_SI_XX, buff, 9);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Soft iron 3x3 matrix. Value are expressed in sign-module format.
+  *         (Es. SVVVVVVVb where S is the sign 0/+1/- and V is the value).[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that stores data read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_mag_soft_iron_mat_get(stmdev_ctx_t *ctx,
+                                          uint8_t *buff)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MAG_SI_XX, buff, 9);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Offset for hard-iron compensation register (r/w). The value is
+  *         expressed as a 16-bit word in two’s complement.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that contains data to write
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_mag_offset_set(stmdev_ctx_t *ctx, int16_t *val)
+{
+  uint8_t buff[6];
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    buff[1] = (uint8_t)((uint16_t)val[0] / 256U);
+    buff[0] = (uint8_t)((uint16_t)val[0] - (buff[1] * 256U));
+    buff[3] = (uint8_t)((uint16_t)val[1] / 256U);
+    buff[2] = (uint8_t)((uint16_t)val[1] - (buff[3] * 256U));
+    buff[5] = (uint8_t)((uint16_t)val[2] / 256U);
+    buff[4] = (uint8_t)((uint16_t)val[2] - (buff[5] * 256U));
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MAG_OFFX_L, buff, 6);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Offset for hard-iron compensation register(r/w).
+  *         The value is expressed as a 16-bit word in two’s complement.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  buff   Buffer that stores data read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_mag_offset_get(stmdev_ctx_t *ctx, int16_t *val)
+{
+  uint8_t buff[6];
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MAG_OFFX_L, buff, 6);
+
+    if (ret == 0)
+    {
+      val[0] = (int16_t)buff[1];
+      val[0] = (val[0] * 256) + (int16_t)buff[0];
+      val[1] = (int16_t)buff[3];
+      val[1] = (val[1] * 256) + (int16_t)buff[2];
+      val[2] = (int16_t)buff[5];
+      val[2] = (val[2] * 256) + (int16_t)buff[4];
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LSM6DS3TR_C_Sensor_hub
+  * @brief       This section groups all the functions that manage the sensor
+  *              hub functionality.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Enable function.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values func_en
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_func_en_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_ctrl10_c_t ctrl10_c;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                             (uint8_t *)&ctrl10_c, 1);
+
+  if (ret == 0)
+  {
+    ctrl10_c.func_en = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C,
+                                (uint8_t *)&ctrl10_c, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Sensor synchronization time frame with the step of 500 ms and
+  *         full range of 5s. Unsigned 8-bit.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tph in reg SENSOR_SYNC_TIME_FRAME
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_sync_sens_frame_set(stmdev_ctx_t *ctx,
+                                           uint8_t val)
+{
+  lsm6ds3tr_c_sensor_sync_time_frame_t sensor_sync_time_frame;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENSOR_SYNC_TIME_FRAME,
+                             (uint8_t *)&sensor_sync_time_frame, 1);
+
+  if (ret == 0)
+  {
+    sensor_sync_time_frame.tph = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SENSOR_SYNC_TIME_FRAME,
+                                (uint8_t *)&sensor_sync_time_frame, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Sensor synchronization time frame with the step of 500 ms and
+  *         full range of 5s. Unsigned 8-bit.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of tph in reg  SENSOR_SYNC_TIME_FRAME
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_sync_sens_frame_get(stmdev_ctx_t *ctx,
+                                           uint8_t *val)
+{
+  lsm6ds3tr_c_sensor_sync_time_frame_t sensor_sync_time_frame;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENSOR_SYNC_TIME_FRAME,
+                             (uint8_t *)&sensor_sync_time_frame, 1);
+  *val =  sensor_sync_time_frame.tph;
+
+  return ret;
+}
+
+/**
+  * @brief  Resolution ratio of error code for sensor synchronization.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of rr in reg  SENSOR_SYNC_RES_RATIO
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_sync_sens_ratio_set(stmdev_ctx_t *ctx,
+                                           lsm6ds3tr_c_rr_t val)
+{
+  lsm6ds3tr_c_sensor_sync_res_ratio_t sensor_sync_res_ratio;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENSOR_SYNC_RES_RATIO,
+                             (uint8_t *)&sensor_sync_res_ratio, 1);
+
+  if (ret == 0)
+  {
+    sensor_sync_res_ratio.rr = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SENSOR_SYNC_RES_RATIO,
+                                (uint8_t *)&sensor_sync_res_ratio, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Resolution ratio of error code for sensor synchronization.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of rr in reg  SENSOR_SYNC_RES_RATIO
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_sync_sens_ratio_get(stmdev_ctx_t *ctx,
+                                           lsm6ds3tr_c_rr_t *val)
+{
+  lsm6ds3tr_c_sensor_sync_res_ratio_t sensor_sync_res_ratio;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENSOR_SYNC_RES_RATIO,
+                             (uint8_t *)&sensor_sync_res_ratio, 1);
+
+  switch (sensor_sync_res_ratio.rr)
+  {
+    case LSM6DS3TR_C_RES_RATIO_2_11:
+      *val = LSM6DS3TR_C_RES_RATIO_2_11;
+      break;
+
+    case LSM6DS3TR_C_RES_RATIO_2_12:
+      *val = LSM6DS3TR_C_RES_RATIO_2_12;
+      break;
+
+    case LSM6DS3TR_C_RES_RATIO_2_13:
+      *val = LSM6DS3TR_C_RES_RATIO_2_13;
+      break;
+
+    case LSM6DS3TR_C_RES_RATIO_2_14:
+      *val = LSM6DS3TR_C_RES_RATIO_2_14;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_RES_RATIO_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Sensor hub I2C master enable.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of master_on in reg MASTER_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_master_set(stmdev_ctx_t *ctx, uint8_t val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                             (uint8_t *)&master_config, 1);
+
+  if (ret == 0)
+  {
+    master_config.master_on = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                                (uint8_t *)&master_config, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Sensor hub I2C master enable.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of master_on in reg MASTER_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_master_get(stmdev_ctx_t *ctx, uint8_t *val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                             (uint8_t *)&master_config, 1);
+  *val = master_config.master_on;
+
+  return ret;
+}
+
+/**
+  * @brief  I2C interface pass-through.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of pass_through_mode in reg MASTER_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_pass_through_set(stmdev_ctx_t *ctx,
+                                        uint8_t val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                             (uint8_t *)&master_config, 1);
+
+  if (ret == 0)
+  {
+    master_config.pass_through_mode = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                                (uint8_t *)&master_config, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  I2C interface pass-through.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of pass_through_mode in reg MASTER_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_pass_through_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                             (uint8_t *)&master_config, 1);
+  *val = master_config.pass_through_mode;
+
+  return ret;
+}
+
+/**
+  * @brief  Master I2C pull-up enable/disable.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of pull_up_en in reg MASTER_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_pin_mode_set(stmdev_ctx_t *ctx,
+                                    lsm6ds3tr_c_pull_up_en_t val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                             (uint8_t *)&master_config, 1);
+
+  if (ret == 0)
+  {
+    master_config.pull_up_en = (uint8_t) val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                                (uint8_t *)&master_config, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Master I2C pull-up enable/disable.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of pull_up_en in reg MASTER_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_pin_mode_get(stmdev_ctx_t *ctx,
+                                    lsm6ds3tr_c_pull_up_en_t *val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                             (uint8_t *)&master_config, 1);
+
+  switch (master_config.pull_up_en)
+  {
+    case LSM6DS3TR_C_EXT_PULL_UP:
+      *val = LSM6DS3TR_C_EXT_PULL_UP;
+      break;
+
+    case LSM6DS3TR_C_INTERNAL_PULL_UP:
+      *val = LSM6DS3TR_C_INTERNAL_PULL_UP;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_SH_PIN_MODE;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Sensor hub trigger signal selection.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of start_config in reg MASTER_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_syncro_mode_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_start_config_t val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                             (uint8_t *)&master_config, 1);
+
+  if (ret == 0)
+  {
+    master_config.start_config = (uint8_t)val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                                (uint8_t *)&master_config, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Sensor hub trigger signal selection.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of start_config in reg MASTER_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_syncro_mode_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_start_config_t *val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                             (uint8_t *)&master_config, 1);
+
+  switch (master_config.start_config)
+  {
+    case LSM6DS3TR_C_XL_GY_DRDY:
+      *val = LSM6DS3TR_C_XL_GY_DRDY;
+      break;
+
+    case LSM6DS3TR_C_EXT_ON_INT2_PIN:
+      *val = LSM6DS3TR_C_EXT_ON_INT2_PIN;
+      break;
+
+    default:
+      *val = LSM6DS3TR_C_SH_SYNCRO_ND;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Manage the Master DRDY signal on INT1 pad.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of drdy_on_int1 in reg MASTER_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_drdy_on_int1_set(stmdev_ctx_t *ctx,
+                                        uint8_t val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                             (uint8_t *)&master_config, 1);
+
+  if (ret == 0)
+  {
+    master_config.drdy_on_int1 = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                                (uint8_t *)&master_config, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Manage the Master DRDY signal on INT1 pad.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of drdy_on_int1 in reg MASTER_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_drdy_on_int1_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val)
+{
+  lsm6ds3tr_c_master_config_t master_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG,
+                             (uint8_t *)&master_config, 1);
+  *val = master_config.drdy_on_int1;
+
+  return ret;
+}
+
+/**
+  * @brief  Sensor hub output registers.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Structure of registers from SENSORHUB1_REG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_read_data_raw_get(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_emb_sh_read_t *val)
+{
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENSORHUB1_REG,
+                             (uint8_t *) & (val->sh_byte_1), 12);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENSORHUB13_REG,
+                               (uint8_t *) & (val->sh_byte_13), 6);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Master command code used for stamping for sensor sync.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of master_cmd_code in
+  *                reg MASTER_CMD_CODE
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_cmd_sens_sync_set(stmdev_ctx_t *ctx,
+                                         uint8_t val)
+{
+  lsm6ds3tr_c_master_cmd_code_t master_cmd_code;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CMD_CODE,
+                             (uint8_t *)&master_cmd_code, 1);
+
+  if (ret == 0)
+  {
+    master_cmd_code.master_cmd_code = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CMD_CODE,
+                                (uint8_t *)&master_cmd_code, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Master command code used for stamping for sensor sync.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of master_cmd_code in
+  *                reg MASTER_CMD_CODE
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_cmd_sens_sync_get(stmdev_ctx_t *ctx,
+                                         uint8_t *val)
+{
+  lsm6ds3tr_c_master_cmd_code_t master_cmd_code;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CMD_CODE,
+                             (uint8_t *)&master_cmd_code, 1);
+  *val = master_cmd_code.master_cmd_code;
+
+  return ret;
+}
+
+/**
+  * @brief  Error code used for sensor synchronization.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of error_code in
+  *                reg SENS_SYNC_SPI_ERROR_CODE.
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_spi_sync_error_set(stmdev_ctx_t *ctx,
+                                          uint8_t val)
+{
+  lsm6ds3tr_c_sens_sync_spi_error_code_t sens_sync_spi_error_code;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENS_SYNC_SPI_ERROR_CODE,
+                             (uint8_t *)&sens_sync_spi_error_code, 1);
+
+  if (ret == 0)
+  {
+    sens_sync_spi_error_code.error_code = val;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SENS_SYNC_SPI_ERROR_CODE,
+                                (uint8_t *)&sens_sync_spi_error_code, 1);
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Error code used for sensor synchronization.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of error_code in
+  *                reg SENS_SYNC_SPI_ERROR_CODE.
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_spi_sync_error_get(stmdev_ctx_t *ctx,
+                                          uint8_t *val)
+{
+  lsm6ds3tr_c_sens_sync_spi_error_code_t sens_sync_spi_error_code;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENS_SYNC_SPI_ERROR_CODE,
+                             (uint8_t *)&sens_sync_spi_error_code, 1);
+  *val =  sens_sync_spi_error_code.error_code;
+
+  return ret;
+}
+
+/**
+  * @brief   Number of external sensors to be read by the sensor hub.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of aux_sens_on in reg SLAVE0_CONFIG.
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_num_of_dev_connected_set(stmdev_ctx_t *ctx,
+                                                lsm6ds3tr_c_aux_sens_on_t val)
+{
+  lsm6ds3tr_c_slave0_config_t slave0_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG,
+                               (uint8_t *)&slave0_config, 1);
+
+    if (ret == 0)
+    {
+      slave0_config.aux_sens_on = (uint8_t) val;
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG,
+                                  (uint8_t *)&slave0_config, 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief   Number of external sensors to be read by the sensor hub.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of aux_sens_on in reg SLAVE0_CONFIG.
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_num_of_dev_connected_get(stmdev_ctx_t *ctx,
+                                                lsm6ds3tr_c_aux_sens_on_t *val)
+{
+  lsm6ds3tr_c_slave0_config_t slave0_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG,
+                               (uint8_t *)&slave0_config, 1);
+
+    if (ret == 0)
+    {
+      switch (slave0_config.aux_sens_on)
+      {
+        case LSM6DS3TR_C_SLV_0:
+          *val = LSM6DS3TR_C_SLV_0;
+          break;
+
+        case LSM6DS3TR_C_SLV_0_1:
+          *val = LSM6DS3TR_C_SLV_0_1;
+          break;
+
+        case LSM6DS3TR_C_SLV_0_1_2:
+          *val = LSM6DS3TR_C_SLV_0_1_2;
+          break;
+
+        case LSM6DS3TR_C_SLV_0_1_2_3:
+          *val = LSM6DS3TR_C_SLV_0_1_2_3;
+          break;
+
+        default:
+          *val = LSM6DS3TR_C_SLV_EN_ND;
+          break;
+      }
+
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Configure slave 0 for perform a write.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Structure that contain:
+  *                  - uint8_t slv_add;    8 bit i2c device address
+  *                  - uint8_t slv_subadd; 8 bit register device address
+  *                  - uint8_t slv_data;   8 bit data to write
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_cfg_write(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_sh_cfg_write_t *val)
+{
+  lsm6ds3tr_c_slv0_add_t slv0_add;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    slv0_add.slave0_add = val->slv0_add;
+    slv0_add.rw_0 = 0;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV0_ADD,
+                                (uint8_t *)&slv0_add, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV0_SUBADD,
+                                  &(val->slv0_subadd), 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_write_reg(ctx,
+                                    LSM6DS3TR_C_DATAWRITE_SRC_MODE_SUB_SLV0,
+                                    &(val->slv0_data), 1);
+
+        if (ret == 0)
+        {
+          ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+        }
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Configure slave 0 for perform a read.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Structure that contain:
+  *                  - uint8_t slv_add;    8 bit i2c device address
+  *                  - uint8_t slv_subadd; 8 bit register device address
+  *                  - uint8_t slv_len;    num of bit to read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_slv0_cfg_read(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_sh_cfg_read_t *val)
+{
+  lsm6ds3tr_c_slave0_config_t slave0_config;
+  lsm6ds3tr_c_slv0_add_t slv0_add;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    slv0_add.slave0_add = val->slv_add;
+    slv0_add.rw_0 = 1;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV0_ADD,
+                                (uint8_t *)&slv0_add, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV0_SUBADD,
+                                  &(val->slv_subadd), 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG,
+                                   (uint8_t *)&slave0_config, 1);
+        slave0_config.slave0_numop = val->slv_len;
+
+        if (ret == 0)
+        {
+          ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG,
+                                      (uint8_t *)&slave0_config, 1);
+
+          if (ret == 0)
+          {
+            ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+          }
+        }
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Configure slave 1 for perform a read.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Structure that contain:
+  *                  - uint8_t slv_add;    8 bit i2c device address
+  *                  - uint8_t slv_subadd; 8 bit register device address
+  *                  - uint8_t slv_len;    num of bit to read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_slv1_cfg_read(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_sh_cfg_read_t *val)
+{
+  lsm6ds3tr_c_slave1_config_t slave1_config;
+  lsm6ds3tr_c_slv1_add_t slv1_add;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    slv1_add.slave1_add  = val->slv_add;
+    slv1_add.r_1 = 1;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV1_ADD,
+                                (uint8_t *)&slv1_add, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV1_SUBADD,
+                                  &(val->slv_subadd), 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG,
+                                   (uint8_t *)&slave1_config, 1);
+        slave1_config.slave1_numop = val->slv_len;
+
+        if (ret == 0)
+        {
+          ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG,
+                                      (uint8_t *)&slave1_config, 1);
+
+          if (ret == 0)
+          {
+            ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+          }
+        }
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Configure slave 2 for perform a read.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Structure that contain:
+  *                  - uint8_t slv_add;    8 bit i2c device address
+  *                  - uint8_t slv_subadd; 8 bit register device address
+  *                  - uint8_t slv_len;    num of bit to read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_slv2_cfg_read(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_sh_cfg_read_t *val)
+{
+  lsm6ds3tr_c_slv2_add_t slv2_add;
+  lsm6ds3tr_c_slave2_config_t slave2_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    slv2_add.slave2_add  = val->slv_add;
+    slv2_add.r_2 = 1;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV2_ADD,
+                                (uint8_t *)&slv2_add, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV2_SUBADD,
+                                  &(val->slv_subadd), 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE2_CONFIG,
+                                   (uint8_t *)&slave2_config, 1);
+
+        if (ret == 0)
+        {
+          slave2_config.slave2_numop = val->slv_len;
+          ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE2_CONFIG,
+                                      (uint8_t *)&slave2_config, 1);
+
+          if (ret == 0)
+          {
+            ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+          }
+        }
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Configure slave 3 for perform a read.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Structure that contain:
+  *                  - uint8_t slv_add;    8 bit i2c device address
+  *                  - uint8_t slv_subadd; 8 bit register device address
+  *                  - uint8_t slv_len;    num of bit to read
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_slv3_cfg_read(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_sh_cfg_read_t *val)
+{
+  lsm6ds3tr_c_slave3_config_t slave3_config;
+  lsm6ds3tr_c_slv3_add_t slv3_add;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    slv3_add.slave3_add  = val->slv_add;
+    slv3_add.r_3 = 1;
+    ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV3_ADD,
+                                (uint8_t *)&slv3_add, 1);
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV3_SUBADD,
+                                  (uint8_t *) & (val->slv_subadd), 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE3_CONFIG,
+                                   (uint8_t *)&slave3_config, 1);
+
+        if (ret == 0)
+        {
+          slave3_config.slave3_numop = val->slv_len;
+          ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE3_CONFIG,
+                                      (uint8_t *)&slave3_config, 1);
+
+          if (ret == 0)
+          {
+            ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+          }
+        }
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Decimation of read operation on Slave 0 starting from the
+  *         sensor hub trigger.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of slave0_rate in reg SLAVE0_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_slave_0_dec_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave0_rate_t val)
+{
+  lsm6ds3tr_c_slave0_config_t slave0_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG,
+                               (uint8_t *)&slave0_config, 1);
+
+    if (ret == 0)
+    {
+      slave0_config.slave0_rate = (uint8_t) val;
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG,
+                                  (uint8_t *)&slave0_config, 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Decimation of read operation on Slave 0 starting from the
+  *         sensor hub trigger.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of slave0_rate in reg SLAVE0_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_slave_0_dec_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave0_rate_t *val)
+{
+  lsm6ds3tr_c_slave0_config_t slave0_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG,
+                               (uint8_t *)&slave0_config, 1);
+
+    if (ret == 0)
+    {
+      switch (slave0_config.slave0_rate)
+      {
+        case LSM6DS3TR_C_SL0_NO_DEC:
+          *val = LSM6DS3TR_C_SL0_NO_DEC;
+          break;
+
+        case LSM6DS3TR_C_SL0_DEC_2:
+          *val = LSM6DS3TR_C_SL0_DEC_2;
+          break;
+
+        case LSM6DS3TR_C_SL0_DEC_4:
+          *val = LSM6DS3TR_C_SL0_DEC_4;
+          break;
+
+        case LSM6DS3TR_C_SL0_DEC_8:
+          *val = LSM6DS3TR_C_SL0_DEC_8;
+          break;
+
+        default:
+          *val = LSM6DS3TR_C_SL0_DEC_ND;
+          break;
+      }
+
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Slave 0 write operation is performed only at the first sensor
+  *         hub cycle.
+  *         This is effective if the Aux_sens_on[1:0] field in
+  *         SLAVE0_CONFIG(04h) is set to a value other than 00.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of write_once in reg SLAVE1_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_write_mode_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_write_once_t val)
+{
+  lsm6ds3tr_c_slave1_config_t slave1_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG,
+                               (uint8_t *)&slave1_config, 1);
+    slave1_config.write_once = (uint8_t) val;
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG,
+                                  (uint8_t *)&slave1_config, 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Slave 0 write operation is performed only at the first sensor
+  *         hub cycle.
+  *         This is effective if the Aux_sens_on[1:0] field in
+  *         SLAVE0_CONFIG(04h) is set to a value other than 00.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of write_once in reg SLAVE1_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_write_mode_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_write_once_t *val)
+{
+  lsm6ds3tr_c_slave1_config_t slave1_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG,
+                               (uint8_t *)&slave1_config, 1);
+
+    if (ret == 0)
+    {
+      switch (slave1_config.write_once)
+      {
+        case LSM6DS3TR_C_EACH_SH_CYCLE:
+          *val = LSM6DS3TR_C_EACH_SH_CYCLE;
+          break;
+
+        case LSM6DS3TR_C_ONLY_FIRST_CYCLE:
+          *val = LSM6DS3TR_C_ONLY_FIRST_CYCLE;
+          break;
+
+        default:
+          *val = LSM6DS3TR_C_SH_WR_MODE_ND;
+          break;
+      }
+
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Decimation of read operation on Slave 1 starting from the
+  *         sensor hub trigger.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of slave1_rate in reg SLAVE1_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_slave_1_dec_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave1_rate_t val)
+{
+  lsm6ds3tr_c_slave1_config_t slave1_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG,
+                               (uint8_t *)&slave1_config, 1);
+
+    if (ret == 0)
+    {
+      slave1_config.slave1_rate = (uint8_t) val;
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG,
+                                  (uint8_t *)&slave1_config, 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Decimation of read operation on Slave 1 starting from the
+  *         sensor hub trigger.[get]
+  *
+  * @param  ctx    Read / write interface definitions reg SLAVE1_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_slave_1_dec_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave1_rate_t *val)
+{
+  lsm6ds3tr_c_slave1_config_t slave1_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG,
+                               (uint8_t *)&slave1_config, 1);
+
+    if (ret == 0)
+    {
+      switch (slave1_config.slave1_rate)
+      {
+        case LSM6DS3TR_C_SL1_NO_DEC:
+          *val = LSM6DS3TR_C_SL1_NO_DEC;
+          break;
+
+        case LSM6DS3TR_C_SL1_DEC_2:
+          *val = LSM6DS3TR_C_SL1_DEC_2;
+          break;
+
+        case LSM6DS3TR_C_SL1_DEC_4:
+          *val = LSM6DS3TR_C_SL1_DEC_4;
+          break;
+
+        case LSM6DS3TR_C_SL1_DEC_8:
+          *val = LSM6DS3TR_C_SL1_DEC_8;
+          break;
+
+        default:
+          *val = LSM6DS3TR_C_SL1_DEC_ND;
+          break;
+      }
+
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Decimation of read operation on Slave 2 starting from the
+  *         sensor hub trigger.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of slave2_rate in reg SLAVE2_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_slave_2_dec_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave2_rate_t val)
+{
+  lsm6ds3tr_c_slave2_config_t slave2_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE2_CONFIG,
+                               (uint8_t *)&slave2_config, 1);
+
+    if (ret == 0)
+    {
+      slave2_config.slave2_rate = (uint8_t) val;
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE2_CONFIG,
+                                  (uint8_t *)&slave2_config, 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Decimation of read operation on Slave 2 starting from the
+  *         sensor hub trigger.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of slave2_rate in reg SLAVE2_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_slave_2_dec_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave2_rate_t *val)
+{
+  lsm6ds3tr_c_slave2_config_t slave2_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE2_CONFIG,
+                               (uint8_t *)&slave2_config, 1);
+
+    if (ret == 0)
+    {
+      switch (slave2_config.slave2_rate)
+      {
+        case LSM6DS3TR_C_SL2_NO_DEC:
+          *val = LSM6DS3TR_C_SL2_NO_DEC;
+          break;
+
+        case LSM6DS3TR_C_SL2_DEC_2:
+          *val = LSM6DS3TR_C_SL2_DEC_2;
+          break;
+
+        case LSM6DS3TR_C_SL2_DEC_4:
+          *val = LSM6DS3TR_C_SL2_DEC_4;
+          break;
+
+        case LSM6DS3TR_C_SL2_DEC_8:
+          *val = LSM6DS3TR_C_SL2_DEC_8;
+          break;
+
+        default:
+          *val = LSM6DS3TR_C_SL2_DEC_ND;
+          break;
+      }
+
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Decimation of read operation on Slave 3 starting from the
+  *         sensor hub trigger.[set]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Change the values of slave3_rate in reg SLAVE3_CONFIG
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_slave_3_dec_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave3_rate_t val)
+{
+  lsm6ds3tr_c_slave3_config_t slave3_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE3_CONFIG,
+                               (uint8_t *)&slave3_config, 1);
+    slave3_config.slave3_rate = (uint8_t)val;
+
+    if (ret == 0)
+    {
+      ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE3_CONFIG,
+                                  (uint8_t *)&slave3_config, 1);
+
+      if (ret == 0)
+      {
+        ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+      }
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @brief  Decimation of read operation on Slave 3 starting from the
+  *         sensor hub trigger.[get]
+  *
+  * @param  ctx    Read / write interface definitions
+  * @param  val    Get the values of slave3_rate in reg SLAVE3_CONFIG.
+  * @retval        Interface status (MANDATORY: return 0 -> no Error).
+  *
+  */
+int32_t lsm6ds3tr_c_sh_slave_3_dec_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave3_rate_t *val)
+{
+  lsm6ds3tr_c_slave3_config_t slave3_config;
+  int32_t ret;
+
+  ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A);
+
+  if (ret == 0)
+  {
+    ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE3_CONFIG,
+                               (uint8_t *)&slave3_config, 1);
+
+    if (ret == 0)
+    {
+      switch (slave3_config.slave3_rate)
+      {
+        case LSM6DS3TR_C_SL3_NO_DEC:
+          *val = LSM6DS3TR_C_SL3_NO_DEC;
+          break;
+
+        case LSM6DS3TR_C_SL3_DEC_2:
+          *val = LSM6DS3TR_C_SL3_DEC_2;
+          break;
+
+        case LSM6DS3TR_C_SL3_DEC_4:
+          *val = LSM6DS3TR_C_SL3_DEC_4;
+          break;
+
+        case LSM6DS3TR_C_SL3_DEC_8:
+          *val = LSM6DS3TR_C_SL3_DEC_8;
+          break;
+
+        default:
+          *val = LSM6DS3TR_C_SL3_DEC_ND;
+          break;
+      }
+
+      ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK);
+    }
+  }
+
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @}
+  *
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 2798 - 0
tracking/imu/lsm6ds3tr-c_reg.h

@@ -0,0 +1,2798 @@
+/**
+  ******************************************************************************
+  * @file    lsm6ds3tr_c_reg.h
+  * @author  Sensors Software Solution Team
+  * @brief   This file contains all the functions prototypes for the
+  *          lsm6ds3tr_c_reg.c driver.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
+  * All rights reserved.</center></h2>
+  *
+  * This software component is licensed by ST under BSD 3-Clause license,
+  * the "License"; You may not use this file except in compliance with the
+  * License. You may obtain a copy of the License at:
+  *                        opensource.org/licenses/BSD-3-Clause
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef LSM6DS3TR_C_DRIVER_H
+#define LSM6DS3TR_C_DRIVER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include <stdint.h>
+#include <stddef.h>
+#include <math.h>
+
+/** @addtogroup LSM6DS3TR_C
+  * @{
+  *
+  */
+
+/** @defgroup  Endianness definitions
+  * @{
+  *
+  */
+
+#ifndef DRV_BYTE_ORDER
+#ifndef __BYTE_ORDER__
+
+#define DRV_LITTLE_ENDIAN 1234
+#define DRV_BIG_ENDIAN    4321
+
+/** if _BYTE_ORDER is not defined, choose the endianness of your architecture
+  * by uncommenting the define which fits your platform endianness
+  */
+//#define DRV_BYTE_ORDER    DRV_BIG_ENDIAN
+#define DRV_BYTE_ORDER    DRV_LITTLE_ENDIAN
+
+#else /* defined __BYTE_ORDER__ */
+
+#define DRV_LITTLE_ENDIAN  __ORDER_LITTLE_ENDIAN__
+#define DRV_BIG_ENDIAN     __ORDER_BIG_ENDIAN__
+#define DRV_BYTE_ORDER     __BYTE_ORDER__
+
+#endif /* __BYTE_ORDER__*/
+#endif /* DRV_BYTE_ORDER */
+
+/**
+  * @}
+  *
+  */
+
+/** @defgroup STMicroelectronics sensors common types
+  * @{
+  *
+  */
+
+#ifndef MEMS_SHARED_TYPES
+#define MEMS_SHARED_TYPES
+
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0       : 1;
+  uint8_t bit1       : 1;
+  uint8_t bit2       : 1;
+  uint8_t bit3       : 1;
+  uint8_t bit4       : 1;
+  uint8_t bit5       : 1;
+  uint8_t bit6       : 1;
+  uint8_t bit7       : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7       : 1;
+  uint8_t bit6       : 1;
+  uint8_t bit5       : 1;
+  uint8_t bit4       : 1;
+  uint8_t bit3       : 1;
+  uint8_t bit2       : 1;
+  uint8_t bit1       : 1;
+  uint8_t bit0       : 1;
+#endif /* DRV_BYTE_ORDER */
+} bitwise_t;
+
+#define PROPERTY_DISABLE                (0U)
+#define PROPERTY_ENABLE                 (1U)
+
+/** @addtogroup  Interfaces_Functions
+  * @brief       This section provide a set of functions used to read and
+  *              write a generic register of the device.
+  *              MANDATORY: return 0 -> no Error.
+  * @{
+  *
+  */
+
+typedef int32_t (*stmdev_write_ptr)(void *, uint8_t, const uint8_t *, uint16_t);
+typedef int32_t (*stmdev_read_ptr)(void *, uint8_t, uint8_t *, uint16_t);
+typedef void (*stmdev_mdelay_ptr)(uint32_t millisec);
+
+typedef struct
+{
+  /** Component mandatory fields **/
+  stmdev_write_ptr  write_reg;
+  stmdev_read_ptr   read_reg;
+  /** Component optional fields **/
+  stmdev_mdelay_ptr   mdelay;
+  /** Customizable optional pointer **/
+  void *handle;
+} stmdev_ctx_t;
+
+/**
+  * @}
+  *
+  */
+
+#endif /* MEMS_SHARED_TYPES */
+
+#ifndef MEMS_UCF_SHARED_TYPES
+#define MEMS_UCF_SHARED_TYPES
+
+/** @defgroup    Generic address-data structure definition
+  * @brief       This structure is useful to load a predefined configuration
+  *              of a sensor.
+  *              You can create a sensor configuration by your own or using
+  *              Unico / Unicleo tools available on STMicroelectronics
+  *              web site.
+  *
+  * @{
+  *
+  */
+
+typedef struct
+{
+  uint8_t address;
+  uint8_t data;
+} ucf_line_t;
+
+/**
+  * @}
+  *
+  */
+
+#endif /* MEMS_UCF_SHARED_TYPES */
+
+/**
+  * @}
+  *
+  */
+
+/** @defgroup LSM6DS3TR_C_Infos
+  * @{
+  *
+  */
+
+/** I2C Device Address 8 bit format  if SA0=0 -> D5 if SA0=1 -> D7 **/
+#define LSM6DS3TR_C_I2C_ADD_L     0xD5U
+#define LSM6DS3TR_C_I2C_ADD_H     0xD7U
+
+/** Device Identification (Who am I) **/
+#define LSM6DS3TR_C_ID            0x6AU
+
+/**
+  * @}
+  *
+  */
+
+#define LSM6DS3TR_C_FUNC_CFG_ACCESS              0x01U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t not_used_01              : 5;
+uint8_t func_cfg_en              :
+  3;  /* func_cfg_en + func_cfg_en_b */
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+uint8_t func_cfg_en              :
+  3;  /* func_cfg_en + func_cfg_en_b */
+  uint8_t not_used_01              : 5;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_func_cfg_access_t;
+
+#define LSM6DS3TR_C_SENSOR_SYNC_TIME_FRAME       0x04U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t tph                      : 4;
+  uint8_t not_used_01              : 4;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t not_used_01              : 4;
+  uint8_t tph                      : 4;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensor_sync_time_frame_t;
+
+#define LSM6DS3TR_C_SENSOR_SYNC_RES_RATIO        0x05U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t rr                       : 2;
+  uint8_t not_used_01              : 6;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t not_used_01              : 6;
+  uint8_t rr                       : 2;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensor_sync_res_ratio_t;
+
+#define LSM6DS3TR_C_FIFO_CTRL1                   0x06U
+typedef struct
+{
+  uint8_t fth                      : 8;  /* + FIFO_CTRL2(fth) */
+} lsm6ds3tr_c_fifo_ctrl1_t;
+
+#define LSM6DS3TR_C_FIFO_CTRL2                   0x07U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t fth                      : 3;  /* + FIFO_CTRL1(fth) */
+  uint8_t fifo_temp_en             : 1;
+  uint8_t not_used_01              : 2;
+  uint8_t timer_pedo_fifo_drdy     : 1;
+  uint8_t timer_pedo_fifo_en       : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t timer_pedo_fifo_en       : 1;
+  uint8_t timer_pedo_fifo_drdy     : 1;
+  uint8_t not_used_01              : 2;
+  uint8_t fifo_temp_en             : 1;
+  uint8_t fth                      : 3;  /* + FIFO_CTRL1(fth) */
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_fifo_ctrl2_t;
+
+#define LSM6DS3TR_C_FIFO_CTRL3                   0x08U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t dec_fifo_xl              : 3;
+  uint8_t dec_fifo_gyro            : 3;
+  uint8_t not_used_01              : 2;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t not_used_01              : 2;
+  uint8_t dec_fifo_gyro            : 3;
+  uint8_t dec_fifo_xl              : 3;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_fifo_ctrl3_t;
+
+#define LSM6DS3TR_C_FIFO_CTRL4                   0x09U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t dec_ds3_fifo             : 3;
+  uint8_t dec_ds4_fifo             : 3;
+  uint8_t only_high_data           : 1;
+  uint8_t stop_on_fth              : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t stop_on_fth              : 1;
+  uint8_t only_high_data           : 1;
+  uint8_t dec_ds4_fifo             : 3;
+  uint8_t dec_ds3_fifo             : 3;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_fifo_ctrl4_t;
+
+#define LSM6DS3TR_C_FIFO_CTRL5                   0x0AU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t fifo_mode                : 3;
+  uint8_t odr_fifo                 : 4;
+  uint8_t not_used_01              : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t not_used_01              : 1;
+  uint8_t odr_fifo                 : 4;
+  uint8_t fifo_mode                : 3;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_fifo_ctrl5_t;
+
+#define LSM6DS3TR_C_DRDY_PULSE_CFG_G             0x0BU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t int2_wrist_tilt          : 1;
+  uint8_t not_used_01              : 6;
+  uint8_t drdy_pulsed              : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t drdy_pulsed              : 1;
+  uint8_t not_used_01              : 6;
+  uint8_t int2_wrist_tilt          : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_drdy_pulse_cfg_g_t;
+
+#define LSM6DS3TR_C_INT1_CTRL                    0x0DU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t int1_drdy_xl             : 1;
+  uint8_t int1_drdy_g              : 1;
+  uint8_t int1_boot                : 1;
+  uint8_t int1_fth                 : 1;
+  uint8_t int1_fifo_ovr            : 1;
+  uint8_t int1_full_flag           : 1;
+  uint8_t int1_sign_mot            : 1;
+  uint8_t int1_step_detector       : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t int1_step_detector       : 1;
+  uint8_t int1_sign_mot            : 1;
+  uint8_t int1_full_flag           : 1;
+  uint8_t int1_fifo_ovr            : 1;
+  uint8_t int1_fth                 : 1;
+  uint8_t int1_boot                : 1;
+  uint8_t int1_drdy_g              : 1;
+  uint8_t int1_drdy_xl             : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_int1_ctrl_t;
+
+#define LSM6DS3TR_C_INT2_CTRL                    0x0EU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t int2_drdy_xl             : 1;
+  uint8_t int2_drdy_g              : 1;
+  uint8_t int2_drdy_temp           : 1;
+  uint8_t int2_fth                 : 1;
+  uint8_t int2_fifo_ovr            : 1;
+  uint8_t int2_full_flag           : 1;
+  uint8_t int2_step_count_ov       : 1;
+  uint8_t int2_step_delta          : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t int2_step_delta          : 1;
+  uint8_t int2_step_count_ov       : 1;
+  uint8_t int2_full_flag           : 1;
+  uint8_t int2_fifo_ovr            : 1;
+  uint8_t int2_fth                 : 1;
+  uint8_t int2_drdy_temp           : 1;
+  uint8_t int2_drdy_g              : 1;
+  uint8_t int2_drdy_xl             : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_int2_ctrl_t;
+
+#define LSM6DS3TR_C_WHO_AM_I                     0x0FU
+#define LSM6DS3TR_C_CTRL1_XL                     0x10U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bw0_xl                   : 1;
+  uint8_t lpf1_bw_sel              : 1;
+  uint8_t fs_xl                    : 2;
+  uint8_t odr_xl                   : 4;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t odr_xl                   : 4;
+  uint8_t fs_xl                    : 2;
+  uint8_t lpf1_bw_sel              : 1;
+  uint8_t bw0_xl                   : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_ctrl1_xl_t;
+
+#define LSM6DS3TR_C_CTRL2_G                      0x11U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t not_used_01              : 1;
+  uint8_t fs_g                     : 3;  /* fs_g + fs_125 */
+  uint8_t odr_g                    : 4;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t odr_g                    : 4;
+  uint8_t fs_g                     : 3;  /* fs_g + fs_125 */
+  uint8_t not_used_01              : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_ctrl2_g_t;
+
+#define LSM6DS3TR_C_CTRL3_C                      0x12U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t sw_reset                 : 1;
+  uint8_t ble                      : 1;
+  uint8_t if_inc                   : 1;
+  uint8_t sim                      : 1;
+  uint8_t pp_od                    : 1;
+  uint8_t h_lactive                : 1;
+  uint8_t bdu                      : 1;
+  uint8_t boot                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t boot                     : 1;
+  uint8_t bdu                      : 1;
+  uint8_t h_lactive                : 1;
+  uint8_t pp_od                    : 1;
+  uint8_t sim                      : 1;
+  uint8_t if_inc                   : 1;
+  uint8_t ble                      : 1;
+  uint8_t sw_reset                 : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_ctrl3_c_t;
+
+#define LSM6DS3TR_C_CTRL4_C                      0x13U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t not_used_01              : 1;
+  uint8_t lpf1_sel_g               : 1;
+  uint8_t i2c_disable              : 1;
+  uint8_t drdy_mask                : 1;
+  uint8_t den_drdy_int1            : 1;
+  uint8_t int2_on_int1             : 1;
+  uint8_t sleep                    : 1;
+  uint8_t den_xl_en                : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t den_xl_en                : 1;
+  uint8_t sleep                    : 1;
+  uint8_t int2_on_int1             : 1;
+  uint8_t den_drdy_int1            : 1;
+  uint8_t drdy_mask                : 1;
+  uint8_t i2c_disable              : 1;
+  uint8_t lpf1_sel_g               : 1;
+  uint8_t not_used_01              : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_ctrl4_c_t;
+
+#define LSM6DS3TR_C_CTRL5_C                      0x14U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t st_xl                    : 2;
+  uint8_t st_g                     : 2;
+  uint8_t den_lh                   : 1;
+  uint8_t rounding                 : 3;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t rounding                 : 3;
+  uint8_t den_lh                   : 1;
+  uint8_t st_g                     : 2;
+  uint8_t st_xl                    : 2;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_ctrl5_c_t;
+
+#define LSM6DS3TR_C_CTRL6_C                      0x15U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t ftype                    : 2;
+  uint8_t not_used_01              : 1;
+  uint8_t usr_off_w                : 1;
+  uint8_t xl_hm_mode               : 1;
+uint8_t den_mode                 :
+  3;  /* trig_en + lvl_en + lvl2_en */
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+uint8_t den_mode                 :
+  3;  /* trig_en + lvl_en + lvl2_en */
+  uint8_t xl_hm_mode               : 1;
+  uint8_t usr_off_w                : 1;
+  uint8_t not_used_01              : 1;
+  uint8_t ftype                    : 2;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_ctrl6_c_t;
+
+#define LSM6DS3TR_C_CTRL7_G                      0x16U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t not_used_01              : 2;
+  uint8_t rounding_status          : 1;
+  uint8_t not_used_02              : 1;
+  uint8_t hpm_g                    : 2;
+  uint8_t hp_en_g                  : 1;
+  uint8_t g_hm_mode                : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t g_hm_mode                : 1;
+  uint8_t hp_en_g                  : 1;
+  uint8_t hpm_g                    : 2;
+  uint8_t not_used_02              : 1;
+  uint8_t rounding_status          : 1;
+  uint8_t not_used_01              : 2;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_ctrl7_g_t;
+
+#define LSM6DS3TR_C_CTRL8_XL                     0x17U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t low_pass_on_6d           : 1;
+  uint8_t not_used_01              : 1;
+  uint8_t hp_slope_xl_en           : 1;
+  uint8_t input_composite          : 1;
+  uint8_t hp_ref_mode              : 1;
+  uint8_t hpcf_xl                  : 2;
+  uint8_t lpf2_xl_en               : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t lpf2_xl_en               : 1;
+  uint8_t hpcf_xl                  : 2;
+  uint8_t hp_ref_mode              : 1;
+  uint8_t input_composite          : 1;
+  uint8_t hp_slope_xl_en           : 1;
+  uint8_t not_used_01              : 1;
+  uint8_t low_pass_on_6d           : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_ctrl8_xl_t;
+
+#define LSM6DS3TR_C_CTRL9_XL                     0x18U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t not_used_01              : 2;
+  uint8_t soft_en                  : 1;
+  uint8_t not_used_02              : 1;
+  uint8_t den_xl_g                 : 1;
+  uint8_t den_z                    : 1;
+  uint8_t den_y                    : 1;
+  uint8_t den_x                    : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t den_x                    : 1;
+  uint8_t den_y                    : 1;
+  uint8_t den_z                    : 1;
+  uint8_t den_xl_g                 : 1;
+  uint8_t not_used_02              : 1;
+  uint8_t soft_en                  : 1;
+  uint8_t not_used_01              : 2;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_ctrl9_xl_t;
+
+#define LSM6DS3TR_C_CTRL10_C                     0x19U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t sign_motion_en           : 1;
+  uint8_t pedo_rst_step            : 1;
+  uint8_t func_en                  : 1;
+  uint8_t tilt_en                  : 1;
+  uint8_t pedo_en                  : 1;
+  uint8_t timer_en                 : 1;
+  uint8_t not_used_01              : 1;
+  uint8_t wrist_tilt_en            : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t wrist_tilt_en            : 1;
+  uint8_t not_used_01              : 1;
+  uint8_t timer_en                 : 1;
+  uint8_t pedo_en                  : 1;
+  uint8_t tilt_en                  : 1;
+  uint8_t func_en                  : 1;
+  uint8_t pedo_rst_step            : 1;
+  uint8_t sign_motion_en           : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_ctrl10_c_t;
+
+#define LSM6DS3TR_C_MASTER_CONFIG                0x1AU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t master_on                : 1;
+  uint8_t iron_en                  : 1;
+  uint8_t pass_through_mode        : 1;
+  uint8_t pull_up_en               : 1;
+  uint8_t start_config             : 1;
+  uint8_t not_used_01              : 1;
+  uint8_t data_valid_sel_fifo      : 1;
+  uint8_t drdy_on_int1             : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t drdy_on_int1             : 1;
+  uint8_t data_valid_sel_fifo      : 1;
+  uint8_t not_used_01              : 1;
+  uint8_t start_config             : 1;
+  uint8_t pull_up_en               : 1;
+  uint8_t pass_through_mode        : 1;
+  uint8_t iron_en                  : 1;
+  uint8_t master_on                : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_master_config_t;
+
+#define LSM6DS3TR_C_WAKE_UP_SRC                  0x1BU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t z_wu                     : 1;
+  uint8_t y_wu                     : 1;
+  uint8_t x_wu                     : 1;
+  uint8_t wu_ia                    : 1;
+  uint8_t sleep_state_ia           : 1;
+  uint8_t ff_ia                    : 1;
+  uint8_t not_used_01              : 2;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t not_used_01              : 2;
+  uint8_t ff_ia                    : 1;
+  uint8_t sleep_state_ia           : 1;
+  uint8_t wu_ia                    : 1;
+  uint8_t x_wu                     : 1;
+  uint8_t y_wu                     : 1;
+  uint8_t z_wu                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_wake_up_src_t;
+
+#define LSM6DS3TR_C_TAP_SRC                      0x1CU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t z_tap                    : 1;
+  uint8_t y_tap                    : 1;
+  uint8_t x_tap                    : 1;
+  uint8_t tap_sign                 : 1;
+  uint8_t double_tap               : 1;
+  uint8_t single_tap               : 1;
+  uint8_t tap_ia                   : 1;
+  uint8_t not_used_01              : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t not_used_01              : 1;
+  uint8_t tap_ia                   : 1;
+  uint8_t single_tap               : 1;
+  uint8_t double_tap               : 1;
+  uint8_t tap_sign                 : 1;
+  uint8_t x_tap                    : 1;
+  uint8_t y_tap                    : 1;
+  uint8_t z_tap                    : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_tap_src_t;
+
+#define LSM6DS3TR_C_D6D_SRC                      0x1DU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t xl                       : 1;
+  uint8_t xh                       : 1;
+  uint8_t yl                       : 1;
+  uint8_t yh                       : 1;
+  uint8_t zl                       : 1;
+  uint8_t zh                       : 1;
+  uint8_t d6d_ia                   : 1;
+  uint8_t den_drdy                 : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t den_drdy                 : 1;
+  uint8_t d6d_ia                   : 1;
+  uint8_t zh                       : 1;
+  uint8_t zl                       : 1;
+  uint8_t yh                       : 1;
+  uint8_t yl                       : 1;
+  uint8_t xh                       : 1;
+  uint8_t xl                       : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_d6d_src_t;
+
+#define LSM6DS3TR_C_STATUS_REG                   0x1EU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t xlda                     : 1;
+  uint8_t gda                      : 1;
+  uint8_t tda                      : 1;
+  uint8_t not_used_01              : 5;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t not_used_01              : 5;
+  uint8_t tda                      : 1;
+  uint8_t gda                      : 1;
+  uint8_t xlda                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_status_reg_t;
+
+#define LSM6DS3TR_C_OUT_TEMP_L                   0x20U
+#define LSM6DS3TR_C_OUT_TEMP_H                   0x21U
+#define LSM6DS3TR_C_OUTX_L_G                     0x22U
+#define LSM6DS3TR_C_OUTX_H_G                     0x23U
+#define LSM6DS3TR_C_OUTY_L_G                     0x24U
+#define LSM6DS3TR_C_OUTY_H_G                     0x25U
+#define LSM6DS3TR_C_OUTZ_L_G                     0x26U
+#define LSM6DS3TR_C_OUTZ_H_G                     0x27U
+#define LSM6DS3TR_C_OUTX_L_XL                    0x28U
+#define LSM6DS3TR_C_OUTX_H_XL                    0x29U
+#define LSM6DS3TR_C_OUTY_L_XL                    0x2AU
+#define LSM6DS3TR_C_OUTY_H_XL                    0x2BU
+#define LSM6DS3TR_C_OUTZ_L_XL                    0x2CU
+#define LSM6DS3TR_C_OUTZ_H_XL                    0x2DU
+#define LSM6DS3TR_C_SENSORHUB1_REG               0x2EU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub1_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB2_REG               0x2FU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub2_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB3_REG               0x30U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub3_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB4_REG               0x31U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub4_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB5_REG               0x32U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub5_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB6_REG               0x33U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub6_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB7_REG               0x34U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub7_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB8_REG               0x35U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub8_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB9_REG               0x36U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub9_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB10_REG              0x37U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub10_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB11_REG              0x38U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub11_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB12_REG              0x39U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub12_reg_t;
+
+#define LSM6DS3TR_C_FIFO_STATUS1                 0x3AU
+typedef struct
+{
+  uint8_t diff_fifo                : 8;  /* + FIFO_STATUS2(diff_fifo) */
+} lsm6ds3tr_c_fifo_status1_t;
+
+#define LSM6DS3TR_C_FIFO_STATUS2                 0x3BU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t diff_fifo                : 3;  /* + FIFO_STATUS1(diff_fifo) */
+  uint8_t not_used_01              : 1;
+  uint8_t fifo_empty               : 1;
+  uint8_t fifo_full_smart          : 1;
+  uint8_t over_run                 : 1;
+  uint8_t waterm                   : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t waterm                   : 1;
+  uint8_t over_run                 : 1;
+  uint8_t fifo_full_smart          : 1;
+  uint8_t fifo_empty               : 1;
+  uint8_t not_used_01              : 1;
+  uint8_t diff_fifo                : 3;  /* + FIFO_STATUS1(diff_fifo) */
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_fifo_status2_t;
+
+#define LSM6DS3TR_C_FIFO_STATUS3                 0x3CU
+typedef struct
+{
+uint8_t fifo_pattern             :
+  8;  /* + FIFO_STATUS4(fifo_pattern) */
+} lsm6ds3tr_c_fifo_status3_t;
+
+#define LSM6DS3TR_C_FIFO_STATUS4                 0x3DU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+uint8_t fifo_pattern             :
+  2;  /* + FIFO_STATUS3(fifo_pattern) */
+  uint8_t not_used_01              : 6;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t not_used_01              : 6;
+uint8_t fifo_pattern             :
+  2;  /* + FIFO_STATUS3(fifo_pattern) */
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_fifo_status4_t;
+
+#define LSM6DS3TR_C_FIFO_DATA_OUT_L              0x3EU
+#define LSM6DS3TR_C_FIFO_DATA_OUT_H              0x3FU
+#define LSM6DS3TR_C_TIMESTAMP0_REG               0x40U
+#define LSM6DS3TR_C_TIMESTAMP1_REG               0x41U
+#define LSM6DS3TR_C_TIMESTAMP2_REG               0x42U
+#define LSM6DS3TR_C_STEP_TIMESTAMP_L             0x49U
+#define LSM6DS3TR_C_STEP_TIMESTAMP_H             0x4AU
+#define LSM6DS3TR_C_STEP_COUNTER_L               0x4BU
+#define LSM6DS3TR_C_STEP_COUNTER_H               0x4CU
+
+#define LSM6DS3TR_C_SENSORHUB13_REG              0x4DU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub13_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB14_REG              0x4EU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub14_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB15_REG              0x4FU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub15_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB16_REG              0x50U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub16_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB17_REG              0x51U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub17_reg_t;
+
+#define LSM6DS3TR_C_SENSORHUB18_REG              0x52U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t bit0                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit7                     : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t bit7                     : 1;
+  uint8_t bit6                     : 1;
+  uint8_t bit5                     : 1;
+  uint8_t bit4                     : 1;
+  uint8_t bit3                     : 1;
+  uint8_t bit2                     : 1;
+  uint8_t bit1                     : 1;
+  uint8_t bit0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_sensorhub18_reg_t;
+
+#define LSM6DS3TR_C_FUNC_SRC1                    0x53U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t sensorhub_end_op         : 1;
+  uint8_t si_end_op                : 1;
+  uint8_t hi_fail                  : 1;
+  uint8_t step_overflow            : 1;
+  uint8_t step_detected            : 1;
+  uint8_t tilt_ia                  : 1;
+  uint8_t sign_motion_ia           : 1;
+  uint8_t step_count_delta_ia      : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t step_count_delta_ia      : 1;
+  uint8_t sign_motion_ia           : 1;
+  uint8_t tilt_ia                  : 1;
+  uint8_t step_detected            : 1;
+  uint8_t step_overflow            : 1;
+  uint8_t hi_fail                  : 1;
+  uint8_t si_end_op                : 1;
+  uint8_t sensorhub_end_op         : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_func_src1_t;
+
+#define LSM6DS3TR_C_FUNC_SRC2                    0x54U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t wrist_tilt_ia            : 1;
+  uint8_t not_used_01              : 2;
+  uint8_t slave0_nack              : 1;
+  uint8_t slave1_nack              : 1;
+  uint8_t slave2_nack              : 1;
+  uint8_t slave3_nack              : 1;
+  uint8_t not_used_02              : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t not_used_02              : 1;
+  uint8_t slave3_nack              : 1;
+  uint8_t slave2_nack              : 1;
+  uint8_t slave1_nack              : 1;
+  uint8_t slave0_nack              : 1;
+  uint8_t not_used_01              : 2;
+  uint8_t wrist_tilt_ia            : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_func_src2_t;
+
+#define LSM6DS3TR_C_WRIST_TILT_IA                0x55U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t not_used_01              : 2;
+  uint8_t wrist_tilt_ia_zneg       : 1;
+  uint8_t wrist_tilt_ia_zpos       : 1;
+  uint8_t wrist_tilt_ia_yneg       : 1;
+  uint8_t wrist_tilt_ia_ypos       : 1;
+  uint8_t wrist_tilt_ia_xneg       : 1;
+  uint8_t wrist_tilt_ia_xpos       : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t wrist_tilt_ia_xpos       : 1;
+  uint8_t wrist_tilt_ia_xneg       : 1;
+  uint8_t wrist_tilt_ia_ypos       : 1;
+  uint8_t wrist_tilt_ia_yneg       : 1;
+  uint8_t wrist_tilt_ia_zpos       : 1;
+  uint8_t wrist_tilt_ia_zneg       : 1;
+  uint8_t not_used_01              : 2;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_wrist_tilt_ia_t;
+
+#define LSM6DS3TR_C_TAP_CFG                      0x58U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t lir                      : 1;
+  uint8_t tap_z_en                 : 1;
+  uint8_t tap_y_en                 : 1;
+  uint8_t tap_x_en                 : 1;
+  uint8_t slope_fds                : 1;
+  uint8_t inact_en                 : 2;
+  uint8_t interrupts_enable        : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t interrupts_enable        : 1;
+  uint8_t inact_en                 : 2;
+  uint8_t slope_fds                : 1;
+  uint8_t tap_x_en                 : 1;
+  uint8_t tap_y_en                 : 1;
+  uint8_t tap_z_en                 : 1;
+  uint8_t lir                      : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_tap_cfg_t;
+
+#define LSM6DS3TR_C_TAP_THS_6D                   0x59U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t tap_ths                  : 5;
+  uint8_t sixd_ths                 : 2;
+  uint8_t d4d_en                   : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t d4d_en                   : 1;
+  uint8_t sixd_ths                 : 2;
+  uint8_t tap_ths                  : 5;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_tap_ths_6d_t;
+
+#define LSM6DS3TR_C_INT_DUR2                     0x5AU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t shock                    : 2;
+  uint8_t quiet                    : 2;
+  uint8_t dur                      : 4;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t dur                      : 4;
+  uint8_t quiet                    : 2;
+  uint8_t shock                    : 2;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_int_dur2_t;
+
+#define LSM6DS3TR_C_WAKE_UP_THS                  0x5BU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t wk_ths                   : 6;
+  uint8_t not_used_01              : 1;
+  uint8_t single_double_tap        : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t single_double_tap        : 1;
+  uint8_t not_used_01              : 1;
+  uint8_t wk_ths                   : 6;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_wake_up_ths_t;
+
+#define LSM6DS3TR_C_WAKE_UP_DUR                  0x5CU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t sleep_dur                : 4;
+  uint8_t timer_hr                 : 1;
+  uint8_t wake_dur                 : 2;
+  uint8_t ff_dur                   : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t ff_dur                   : 1;
+  uint8_t wake_dur                 : 2;
+  uint8_t timer_hr                 : 1;
+  uint8_t sleep_dur                : 4;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_wake_up_dur_t;
+
+#define LSM6DS3TR_C_FREE_FALL                    0x5DU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t ff_ths                   : 3;
+  uint8_t ff_dur                   : 5;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t ff_dur                   : 5;
+  uint8_t ff_ths                   : 3;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_free_fall_t;
+
+#define LSM6DS3TR_C_MD1_CFG                      0x5EU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t int1_timer               : 1;
+  uint8_t int1_tilt                : 1;
+  uint8_t int1_6d                  : 1;
+  uint8_t int1_double_tap          : 1;
+  uint8_t int1_ff                  : 1;
+  uint8_t int1_wu                  : 1;
+  uint8_t int1_single_tap          : 1;
+  uint8_t int1_inact_state         : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t int1_inact_state         : 1;
+  uint8_t int1_single_tap          : 1;
+  uint8_t int1_wu                  : 1;
+  uint8_t int1_ff                  : 1;
+  uint8_t int1_double_tap          : 1;
+  uint8_t int1_6d                  : 1;
+  uint8_t int1_tilt                : 1;
+  uint8_t int1_timer               : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_md1_cfg_t;
+
+#define LSM6DS3TR_C_MD2_CFG                      0x5FU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t int2_iron                : 1;
+  uint8_t int2_tilt                : 1;
+  uint8_t int2_6d                  : 1;
+  uint8_t int2_double_tap          : 1;
+  uint8_t int2_ff                  : 1;
+  uint8_t int2_wu                  : 1;
+  uint8_t int2_single_tap          : 1;
+  uint8_t int2_inact_state         : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t int2_inact_state         : 1;
+  uint8_t int2_single_tap          : 1;
+  uint8_t int2_wu                  : 1;
+  uint8_t int2_ff                  : 1;
+  uint8_t int2_double_tap          : 1;
+  uint8_t int2_6d                  : 1;
+  uint8_t int2_tilt                : 1;
+  uint8_t int2_iron                : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_md2_cfg_t;
+
+#define LSM6DS3TR_C_MASTER_CMD_CODE              0x60U
+typedef struct
+{
+  uint8_t master_cmd_code          : 8;
+} lsm6ds3tr_c_master_cmd_code_t;
+
+#define LSM6DS3TR_C_SENS_SYNC_SPI_ERROR_CODE     0x61U
+typedef struct
+{
+  uint8_t error_code               : 8;
+} lsm6ds3tr_c_sens_sync_spi_error_code_t;
+
+#define LSM6DS3TR_C_OUT_MAG_RAW_X_L              0x66U
+#define LSM6DS3TR_C_OUT_MAG_RAW_X_H              0x67U
+#define LSM6DS3TR_C_OUT_MAG_RAW_Y_L              0x68U
+#define LSM6DS3TR_C_OUT_MAG_RAW_Y_H              0x69U
+#define LSM6DS3TR_C_OUT_MAG_RAW_Z_L              0x6AU
+#define LSM6DS3TR_C_OUT_MAG_RAW_Z_H              0x6BU
+#define LSM6DS3TR_C_X_OFS_USR                    0x73U
+#define LSM6DS3TR_C_Y_OFS_USR                    0x74U
+#define LSM6DS3TR_C_Z_OFS_USR                    0x75U
+#define LSM6DS3TR_C_SLV0_ADD                     0x02U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t rw_0                     : 1;
+  uint8_t slave0_add               : 7;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t slave0_add               : 7;
+  uint8_t rw_0                     : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_slv0_add_t;
+
+#define LSM6DS3TR_C_SLV0_SUBADD                  0x03U
+typedef struct
+{
+  uint8_t slave0_reg               : 8;
+} lsm6ds3tr_c_slv0_subadd_t;
+
+#define LSM6DS3TR_C_SLAVE0_CONFIG                0x04U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t slave0_numop             : 3;
+  uint8_t src_mode                 : 1;
+  uint8_t aux_sens_on              : 2;
+  uint8_t slave0_rate              : 2;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t slave0_rate              : 2;
+  uint8_t aux_sens_on              : 2;
+  uint8_t src_mode                 : 1;
+  uint8_t slave0_numop             : 3;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_slave0_config_t;
+
+#define LSM6DS3TR_C_SLV1_ADD                     0x05U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t r_1                      : 1;
+  uint8_t slave1_add               : 7;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t slave1_add               : 7;
+  uint8_t r_1                      : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_slv1_add_t;
+
+#define LSM6DS3TR_C_SLV1_SUBADD                  0x06U
+typedef struct
+{
+  uint8_t slave1_reg               : 8;
+} lsm6ds3tr_c_slv1_subadd_t;
+
+#define LSM6DS3TR_C_SLAVE1_CONFIG                0x07U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t slave1_numop             : 3;
+  uint8_t not_used_01              : 2;
+  uint8_t write_once               : 1;
+  uint8_t slave1_rate              : 2;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t slave1_rate              : 2;
+  uint8_t write_once               : 1;
+  uint8_t not_used_01              : 2;
+  uint8_t slave1_numop             : 3;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_slave1_config_t;
+
+#define LSM6DS3TR_C_SLV2_ADD                     0x08U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t r_2                      : 1;
+  uint8_t slave2_add               : 7;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t slave2_add               : 7;
+  uint8_t r_2                      : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_slv2_add_t;
+
+#define LSM6DS3TR_C_SLV2_SUBADD                  0x09U
+typedef struct
+{
+  uint8_t slave2_reg               : 8;
+} lsm6ds3tr_c_slv2_subadd_t;
+
+#define LSM6DS3TR_C_SLAVE2_CONFIG                0x0AU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t slave2_numop             : 3;
+  uint8_t not_used_01              : 3;
+  uint8_t slave2_rate              : 2;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t slave2_rate              : 2;
+  uint8_t not_used_01              : 3;
+  uint8_t slave2_numop             : 3;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_slave2_config_t;
+
+#define LSM6DS3TR_C_SLV3_ADD                     0x0BU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t r_3                      : 1;
+  uint8_t slave3_add               : 7;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t slave3_add               : 7;
+  uint8_t r_3                      : 1;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_slv3_add_t;
+
+#define LSM6DS3TR_C_SLV3_SUBADD                  0x0CU
+typedef struct
+{
+  uint8_t slave3_reg               : 8;
+} lsm6ds3tr_c_slv3_subadd_t;
+
+#define LSM6DS3TR_C_SLAVE3_CONFIG                0x0DU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t slave3_numop             : 3;
+  uint8_t not_used_01              : 3;
+  uint8_t slave3_rate              : 2;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t slave3_rate              : 2;
+  uint8_t not_used_01              : 3;
+  uint8_t slave3_numop             : 3;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_slave3_config_t;
+
+#define LSM6DS3TR_C_DATAWRITE_SRC_MODE_SUB_SLV0  0x0EU
+typedef struct
+{
+  uint8_t slave_dataw              : 8;
+} lsm6ds3tr_c_datawrite_src_mode_sub_slv0_t;
+
+#define LSM6DS3TR_C_CONFIG_PEDO_THS_MIN          0x0FU
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t ths_min                  : 5;
+  uint8_t not_used_01              : 2;
+  uint8_t pedo_fs                  : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t pedo_fs                  : 1;
+  uint8_t not_used_01              : 2;
+  uint8_t ths_min                  : 5;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_config_pedo_ths_min_t;
+
+#define LSM6DS3TR_C_SM_THS                       0x13U
+#define LSM6DS3TR_C_PEDO_DEB_REG                 0x14U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t deb_step      : 3;
+  uint8_t deb_time      : 5;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t deb_time      : 5;
+  uint8_t deb_step      : 3;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_pedo_deb_reg_t;
+
+#define LSM6DS3TR_C_STEP_COUNT_DELTA             0x15U
+#define LSM6DS3TR_C_MAG_SI_XX                    0x24U
+#define LSM6DS3TR_C_MAG_SI_XY                    0x25U
+#define LSM6DS3TR_C_MAG_SI_XZ                    0x26U
+#define LSM6DS3TR_C_MAG_SI_YX                    0x27U
+#define LSM6DS3TR_C_MAG_SI_YY                    0x28U
+#define LSM6DS3TR_C_MAG_SI_YZ                    0x29U
+#define LSM6DS3TR_C_MAG_SI_ZX                    0x2AU
+#define LSM6DS3TR_C_MAG_SI_ZY                    0x2BU
+#define LSM6DS3TR_C_MAG_SI_ZZ                    0x2CU
+#define LSM6DS3TR_C_MAG_OFFX_L                   0x2DU
+#define LSM6DS3TR_C_MAG_OFFX_H                   0x2EU
+#define LSM6DS3TR_C_MAG_OFFY_L                   0x2FU
+#define LSM6DS3TR_C_MAG_OFFY_H                   0x30U
+#define LSM6DS3TR_C_MAG_OFFZ_L                   0x31U
+#define LSM6DS3TR_C_MAG_OFFZ_H                   0x32U
+#define LSM6DS3TR_C_A_WRIST_TILT_LAT             0x50U
+#define LSM6DS3TR_C_A_WRIST_TILT_THS             0x54U
+#define LSM6DS3TR_C_A_WRIST_TILT_MASK            0x59U
+typedef struct
+{
+#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN
+  uint8_t not_used_01              : 2;
+  uint8_t  wrist_tilt_mask_zneg    : 1;
+  uint8_t  wrist_tilt_mask_zpos    : 1;
+  uint8_t  wrist_tilt_mask_yneg    : 1;
+  uint8_t  wrist_tilt_mask_ypos    : 1;
+  uint8_t  wrist_tilt_mask_xneg    : 1;
+  uint8_t  wrist_tilt_mask_xpos    : 1;
+#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN
+  uint8_t  wrist_tilt_mask_xpos    : 1;
+  uint8_t  wrist_tilt_mask_xneg    : 1;
+  uint8_t  wrist_tilt_mask_ypos    : 1;
+  uint8_t  wrist_tilt_mask_yneg    : 1;
+  uint8_t  wrist_tilt_mask_zpos    : 1;
+  uint8_t  wrist_tilt_mask_zneg    : 1;
+  uint8_t not_used_01              : 2;
+#endif /* DRV_BYTE_ORDER */
+} lsm6ds3tr_c_a_wrist_tilt_mask_t;
+
+/**
+  * @defgroup LSM6DS3TR_C_Register_Union
+  * @brief    This union group all the registers having a bit-field
+  *           description.
+  *           This union is useful but it's not needed by the driver.
+  *
+  *           REMOVING this union you are compliant with:
+  *           MISRA-C 2012 [Rule 19.2] -> " Union are not allowed "
+  *
+  * @{
+  *
+  */
+typedef union
+{
+  lsm6ds3tr_c_func_cfg_access_t                  func_cfg_access;
+  lsm6ds3tr_c_sensor_sync_time_frame_t           sensor_sync_time_frame;
+  lsm6ds3tr_c_sensor_sync_res_ratio_t            sensor_sync_res_ratio;
+  lsm6ds3tr_c_fifo_ctrl1_t                       fifo_ctrl1;
+  lsm6ds3tr_c_fifo_ctrl2_t                       fifo_ctrl2;
+  lsm6ds3tr_c_fifo_ctrl3_t                       fifo_ctrl3;
+  lsm6ds3tr_c_fifo_ctrl4_t                       fifo_ctrl4;
+  lsm6ds3tr_c_fifo_ctrl5_t                       fifo_ctrl5;
+  lsm6ds3tr_c_drdy_pulse_cfg_g_t                 drdy_pulse_cfg_g;
+  lsm6ds3tr_c_int1_ctrl_t                        int1_ctrl;
+  lsm6ds3tr_c_int2_ctrl_t                        int2_ctrl;
+  lsm6ds3tr_c_ctrl1_xl_t                         ctrl1_xl;
+  lsm6ds3tr_c_ctrl2_g_t                          ctrl2_g;
+  lsm6ds3tr_c_ctrl3_c_t                          ctrl3_c;
+  lsm6ds3tr_c_ctrl4_c_t                          ctrl4_c;
+  lsm6ds3tr_c_ctrl5_c_t                          ctrl5_c;
+  lsm6ds3tr_c_ctrl6_c_t                          ctrl6_c;
+  lsm6ds3tr_c_ctrl7_g_t                          ctrl7_g;
+  lsm6ds3tr_c_ctrl8_xl_t                         ctrl8_xl;
+  lsm6ds3tr_c_ctrl9_xl_t                         ctrl9_xl;
+  lsm6ds3tr_c_ctrl10_c_t                         ctrl10_c;
+  lsm6ds3tr_c_master_config_t                    master_config;
+  lsm6ds3tr_c_wake_up_src_t                      wake_up_src;
+  lsm6ds3tr_c_tap_src_t                          tap_src;
+  lsm6ds3tr_c_d6d_src_t                          d6d_src;
+  lsm6ds3tr_c_status_reg_t                       status_reg;
+  lsm6ds3tr_c_sensorhub1_reg_t                   sensorhub1_reg;
+  lsm6ds3tr_c_sensorhub2_reg_t                   sensorhub2_reg;
+  lsm6ds3tr_c_sensorhub3_reg_t                   sensorhub3_reg;
+  lsm6ds3tr_c_sensorhub4_reg_t                   sensorhub4_reg;
+  lsm6ds3tr_c_sensorhub5_reg_t                   sensorhub5_reg;
+  lsm6ds3tr_c_sensorhub6_reg_t                   sensorhub6_reg;
+  lsm6ds3tr_c_sensorhub7_reg_t                   sensorhub7_reg;
+  lsm6ds3tr_c_sensorhub8_reg_t                   sensorhub8_reg;
+  lsm6ds3tr_c_sensorhub9_reg_t                   sensorhub9_reg;
+  lsm6ds3tr_c_sensorhub10_reg_t                  sensorhub10_reg;
+  lsm6ds3tr_c_sensorhub11_reg_t                  sensorhub11_reg;
+  lsm6ds3tr_c_sensorhub12_reg_t                  sensorhub12_reg;
+  lsm6ds3tr_c_fifo_status1_t                     fifo_status1;
+  lsm6ds3tr_c_fifo_status2_t                     fifo_status2;
+  lsm6ds3tr_c_fifo_status3_t                     fifo_status3;
+  lsm6ds3tr_c_fifo_status4_t                     fifo_status4;
+  lsm6ds3tr_c_sensorhub13_reg_t                  sensorhub13_reg;
+  lsm6ds3tr_c_sensorhub14_reg_t                  sensorhub14_reg;
+  lsm6ds3tr_c_sensorhub15_reg_t                  sensorhub15_reg;
+  lsm6ds3tr_c_sensorhub16_reg_t                  sensorhub16_reg;
+  lsm6ds3tr_c_sensorhub17_reg_t                  sensorhub17_reg;
+  lsm6ds3tr_c_sensorhub18_reg_t                  sensorhub18_reg;
+  lsm6ds3tr_c_func_src1_t                        func_src1;
+  lsm6ds3tr_c_func_src2_t                        func_src2;
+  lsm6ds3tr_c_wrist_tilt_ia_t                    wrist_tilt_ia;
+  lsm6ds3tr_c_tap_cfg_t                          tap_cfg;
+  lsm6ds3tr_c_tap_ths_6d_t                       tap_ths_6d;
+  lsm6ds3tr_c_int_dur2_t                         int_dur2;
+  lsm6ds3tr_c_wake_up_ths_t                      wake_up_ths;
+  lsm6ds3tr_c_wake_up_dur_t                      wake_up_dur;
+  lsm6ds3tr_c_free_fall_t                        free_fall;
+  lsm6ds3tr_c_md1_cfg_t                          md1_cfg;
+  lsm6ds3tr_c_md2_cfg_t                          md2_cfg;
+  lsm6ds3tr_c_master_cmd_code_t                  master_cmd_code;
+  lsm6ds3tr_c_sens_sync_spi_error_code_t
+  sens_sync_spi_error_code;
+  lsm6ds3tr_c_slv0_add_t                         slv0_add;
+  lsm6ds3tr_c_slv0_subadd_t                      slv0_subadd;
+  lsm6ds3tr_c_slave0_config_t                    slave0_config;
+  lsm6ds3tr_c_slv1_add_t                         slv1_add;
+  lsm6ds3tr_c_slv1_subadd_t                      slv1_subadd;
+  lsm6ds3tr_c_slave1_config_t                    slave1_config;
+  lsm6ds3tr_c_slv2_add_t                         slv2_add;
+  lsm6ds3tr_c_slv2_subadd_t                      slv2_subadd;
+  lsm6ds3tr_c_slave2_config_t                    slave2_config;
+  lsm6ds3tr_c_slv3_add_t                         slv3_add;
+  lsm6ds3tr_c_slv3_subadd_t                      slv3_subadd;
+  lsm6ds3tr_c_slave3_config_t                    slave3_config;
+  lsm6ds3tr_c_datawrite_src_mode_sub_slv0_t
+  datawrite_src_mode_sub_slv0;
+  lsm6ds3tr_c_config_pedo_ths_min_t              config_pedo_ths_min;
+  lsm6ds3tr_c_pedo_deb_reg_t                     pedo_deb_reg;
+  lsm6ds3tr_c_a_wrist_tilt_mask_t                a_wrist_tilt_mask;
+  bitwise_t                                  bitwise;
+  uint8_t                                    byte;
+} lsm6ds3tr_c_reg_t;
+
+/**
+  * @}
+  *
+  */
+
+int32_t lsm6ds3tr_c_read_reg(stmdev_ctx_t *ctx, uint8_t reg,
+                             uint8_t *data,
+                             uint16_t len);
+int32_t lsm6ds3tr_c_write_reg(stmdev_ctx_t *ctx, uint8_t reg,
+                              uint8_t *data,
+                              uint16_t len);
+
+float_t lsm6ds3tr_c_from_fs2g_to_mg(int16_t lsb);
+float_t lsm6ds3tr_c_from_fs4g_to_mg(int16_t lsb);
+float_t lsm6ds3tr_c_from_fs8g_to_mg(int16_t lsb);
+float_t lsm6ds3tr_c_from_fs16g_to_mg(int16_t lsb);
+
+float_t lsm6ds3tr_c_from_fs125dps_to_mdps(int16_t lsb);
+float_t lsm6ds3tr_c_from_fs250dps_to_mdps(int16_t lsb);
+float_t lsm6ds3tr_c_from_fs500dps_to_mdps(int16_t lsb);
+float_t lsm6ds3tr_c_from_fs1000dps_to_mdps(int16_t lsb);
+float_t lsm6ds3tr_c_from_fs2000dps_to_mdps(int16_t lsb);
+
+float_t lsm6ds3tr_c_from_lsb_to_celsius(int16_t lsb);
+
+typedef enum
+{
+  LSM6DS3TR_C_2g       = 0,
+  LSM6DS3TR_C_16g      = 1,
+  LSM6DS3TR_C_4g       = 2,
+  LSM6DS3TR_C_8g       = 3,
+  LSM6DS3TR_C_XL_FS_ND = 4,  /* ERROR CODE */
+} lsm6ds3tr_c_fs_xl_t;
+int32_t lsm6ds3tr_c_xl_full_scale_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_fs_xl_t val);
+int32_t lsm6ds3tr_c_xl_full_scale_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_fs_xl_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_XL_ODR_OFF      =  0,
+  LSM6DS3TR_C_XL_ODR_12Hz5    =  1,
+  LSM6DS3TR_C_XL_ODR_26Hz     =  2,
+  LSM6DS3TR_C_XL_ODR_52Hz     =  3,
+  LSM6DS3TR_C_XL_ODR_104Hz    =  4,
+  LSM6DS3TR_C_XL_ODR_208Hz    =  5,
+  LSM6DS3TR_C_XL_ODR_416Hz    =  6,
+  LSM6DS3TR_C_XL_ODR_833Hz    =  7,
+  LSM6DS3TR_C_XL_ODR_1k66Hz   =  8,
+  LSM6DS3TR_C_XL_ODR_3k33Hz   =  9,
+  LSM6DS3TR_C_XL_ODR_6k66Hz   = 10,
+  LSM6DS3TR_C_XL_ODR_1Hz6     = 11,
+  LSM6DS3TR_C_XL_ODR_ND       = 12,  /* ERROR CODE */
+} lsm6ds3tr_c_odr_xl_t;
+int32_t lsm6ds3tr_c_xl_data_rate_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_odr_xl_t val);
+int32_t lsm6ds3tr_c_xl_data_rate_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_odr_xl_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_250dps     = 0,
+  LSM6DS3TR_C_125dps     = 1,
+  LSM6DS3TR_C_500dps     = 2,
+  LSM6DS3TR_C_1000dps    = 4,
+  LSM6DS3TR_C_2000dps    = 6,
+  LSM6DS3TR_C_GY_FS_ND   = 7,    /* ERROR CODE */
+} lsm6ds3tr_c_fs_g_t;
+int32_t lsm6ds3tr_c_gy_full_scale_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_fs_g_t val);
+int32_t lsm6ds3tr_c_gy_full_scale_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_fs_g_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_GY_ODR_OFF    =  0,
+  LSM6DS3TR_C_GY_ODR_12Hz5  =  1,
+  LSM6DS3TR_C_GY_ODR_26Hz   =  2,
+  LSM6DS3TR_C_GY_ODR_52Hz   =  3,
+  LSM6DS3TR_C_GY_ODR_104Hz  =  4,
+  LSM6DS3TR_C_GY_ODR_208Hz  =  5,
+  LSM6DS3TR_C_GY_ODR_416Hz  =  6,
+  LSM6DS3TR_C_GY_ODR_833Hz  =  7,
+  LSM6DS3TR_C_GY_ODR_1k66Hz =  8,
+  LSM6DS3TR_C_GY_ODR_3k33Hz =  9,
+  LSM6DS3TR_C_GY_ODR_6k66Hz = 10,
+  LSM6DS3TR_C_GY_ODR_ND     = 11,    /* ERROR CODE */
+} lsm6ds3tr_c_odr_g_t;
+int32_t lsm6ds3tr_c_gy_data_rate_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_odr_g_t val);
+int32_t lsm6ds3tr_c_gy_data_rate_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_odr_g_t *val);
+
+int32_t lsm6ds3tr_c_block_data_update_set(stmdev_ctx_t *ctx,
+                                          uint8_t val);
+int32_t lsm6ds3tr_c_block_data_update_get(stmdev_ctx_t *ctx,
+                                          uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_LSb_1mg   = 0,
+  LSM6DS3TR_C_LSb_16mg  = 1,
+  LSM6DS3TR_C_WEIGHT_ND = 2,
+} lsm6ds3tr_c_usr_off_w_t;
+int32_t lsm6ds3tr_c_xl_offset_weight_set(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_usr_off_w_t val);
+int32_t lsm6ds3tr_c_xl_offset_weight_get(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_usr_off_w_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_XL_HIGH_PERFORMANCE  = 0,
+  LSM6DS3TR_C_XL_NORMAL            = 1,
+  LSM6DS3TR_C_XL_PW_MODE_ND        = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_xl_hm_mode_t;
+int32_t lsm6ds3tr_c_xl_power_mode_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_xl_hm_mode_t val);
+int32_t lsm6ds3tr_c_xl_power_mode_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_xl_hm_mode_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_STAT_RND_DISABLE  = 0,
+  LSM6DS3TR_C_STAT_RND_ENABLE   = 1,
+  LSM6DS3TR_C_STAT_RND_ND       = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_rounding_status_t;
+int32_t lsm6ds3tr_c_rounding_on_status_set(stmdev_ctx_t *ctx,
+                                           lsm6ds3tr_c_rounding_status_t val);
+int32_t lsm6ds3tr_c_rounding_on_status_get(stmdev_ctx_t *ctx,
+                                           lsm6ds3tr_c_rounding_status_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_GY_HIGH_PERFORMANCE  = 0,
+  LSM6DS3TR_C_GY_NORMAL            = 1,
+  LSM6DS3TR_C_GY_PW_MODE_ND        = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_g_hm_mode_t;
+int32_t lsm6ds3tr_c_gy_power_mode_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_g_hm_mode_t val);
+int32_t lsm6ds3tr_c_gy_power_mode_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_g_hm_mode_t *val);
+
+typedef struct
+{
+  lsm6ds3tr_c_wake_up_src_t        wake_up_src;
+  lsm6ds3tr_c_tap_src_t            tap_src;
+  lsm6ds3tr_c_d6d_src_t            d6d_src;
+  lsm6ds3tr_c_status_reg_t         status_reg;
+  lsm6ds3tr_c_func_src1_t          func_src1;
+  lsm6ds3tr_c_func_src2_t          func_src2;
+  lsm6ds3tr_c_wrist_tilt_ia_t      wrist_tilt_ia;
+  lsm6ds3tr_c_a_wrist_tilt_mask_t  a_wrist_tilt_mask;
+} lsm6ds3tr_c_all_sources_t;
+int32_t lsm6ds3tr_c_all_sources_get(stmdev_ctx_t *ctx,
+                                    lsm6ds3tr_c_all_sources_t *val);
+
+int32_t lsm6ds3tr_c_status_reg_get(stmdev_ctx_t *ctx,
+                                   lsm6ds3tr_c_status_reg_t *val);
+
+int32_t lsm6ds3tr_c_xl_flag_data_ready_get(stmdev_ctx_t *ctx,
+                                           uint8_t *val);
+
+int32_t lsm6ds3tr_c_gy_flag_data_ready_get(stmdev_ctx_t *ctx,
+                                           uint8_t *val);
+
+int32_t lsm6ds3tr_c_temp_flag_data_ready_get(stmdev_ctx_t *ctx,
+                                             uint8_t *val);
+
+int32_t lsm6ds3tr_c_xl_usr_offset_set(stmdev_ctx_t *ctx,
+                                      uint8_t *buff);
+int32_t lsm6ds3tr_c_xl_usr_offset_get(stmdev_ctx_t *ctx,
+                                      uint8_t *buff);
+int32_t lsm6ds3tr_c_timestamp_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_timestamp_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_LSB_6ms4    = 0,
+  LSM6DS3TR_C_LSB_25us    = 1,
+  LSM6DS3TR_C_TS_RES_ND   = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_timer_hr_t;
+int32_t lsm6ds3tr_c_timestamp_res_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_timer_hr_t val);
+int32_t lsm6ds3tr_c_timestamp_res_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_timer_hr_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_ROUND_DISABLE            = 0,
+  LSM6DS3TR_C_ROUND_XL                 = 1,
+  LSM6DS3TR_C_ROUND_GY                 = 2,
+  LSM6DS3TR_C_ROUND_GY_XL              = 3,
+  LSM6DS3TR_C_ROUND_SH1_TO_SH6         = 4,
+  LSM6DS3TR_C_ROUND_XL_SH1_TO_SH6      = 5,
+  LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH12  = 6,
+  LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH6   = 7,
+  LSM6DS3TR_C_ROUND_OUT_ND             = 8,    /* ERROR CODE */
+} lsm6ds3tr_c_rounding_t;
+int32_t lsm6ds3tr_c_rounding_mode_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_rounding_t val);
+int32_t lsm6ds3tr_c_rounding_mode_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_rounding_t *val);
+
+int32_t lsm6ds3tr_c_temperature_raw_get(stmdev_ctx_t *ctx,
+                                        int16_t *val);
+int32_t lsm6ds3tr_c_angular_rate_raw_get(stmdev_ctx_t *ctx,
+                                         int16_t *val);
+int32_t lsm6ds3tr_c_acceleration_raw_get(stmdev_ctx_t *ctx,
+                                         int16_t *val);
+
+int32_t lsm6ds3tr_c_mag_calibrated_raw_get(stmdev_ctx_t *ctx,
+                                           int16_t *val);
+
+int32_t lsm6ds3tr_c_fifo_raw_data_get(stmdev_ctx_t *ctx,
+                                      uint8_t *buffer,
+                                      uint8_t len);
+
+typedef enum
+{
+  LSM6DS3TR_C_USER_BANK   = 0,
+  LSM6DS3TR_C_BANK_A      = 4,
+  LSM6DS3TR_C_BANK_B      = 5,
+  LSM6DS3TR_C_BANK_ND     = 6,    /* ERROR CODE */
+} lsm6ds3tr_c_func_cfg_en_t;
+int32_t lsm6ds3tr_c_mem_bank_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_func_cfg_en_t val);
+int32_t lsm6ds3tr_c_mem_bank_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_func_cfg_en_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_DRDY_LATCHED    = 0,
+  LSM6DS3TR_C_DRDY_PULSED     = 1,
+  LSM6DS3TR_C_DRDY_ND         = 2,  /* ERROR CODE */
+} lsm6ds3tr_c_drdy_pulsed_g_t;
+int32_t lsm6ds3tr_c_data_ready_mode_set(stmdev_ctx_t *ctx,
+                                        lsm6ds3tr_c_drdy_pulsed_g_t val);
+int32_t lsm6ds3tr_c_data_ready_mode_get(stmdev_ctx_t *ctx,
+                                        lsm6ds3tr_c_drdy_pulsed_g_t *val);
+
+int32_t lsm6ds3tr_c_device_id_get(stmdev_ctx_t *ctx, uint8_t *buff);
+int32_t lsm6ds3tr_c_reset_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_reset_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_LSB_AT_LOW_ADD  = 0,
+  LSM6DS3TR_C_MSB_AT_LOW_ADD  = 1,
+  LSM6DS3TR_C_DATA_FMT_ND     = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_ble_t;
+int32_t lsm6ds3tr_c_data_format_set(stmdev_ctx_t *ctx,
+                                    lsm6ds3tr_c_ble_t val);
+int32_t lsm6ds3tr_c_data_format_get(stmdev_ctx_t *ctx,
+                                    lsm6ds3tr_c_ble_t *val);
+
+int32_t lsm6ds3tr_c_auto_increment_set(stmdev_ctx_t *ctx,
+                                       uint8_t val);
+int32_t lsm6ds3tr_c_auto_increment_get(stmdev_ctx_t *ctx,
+                                       uint8_t *val);
+
+int32_t lsm6ds3tr_c_boot_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_boot_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_XL_ST_DISABLE    = 0,
+  LSM6DS3TR_C_XL_ST_POSITIVE   = 1,
+  LSM6DS3TR_C_XL_ST_NEGATIVE   = 2,
+  LSM6DS3TR_C_XL_ST_ND         = 3,    /* ERROR CODE */
+} lsm6ds3tr_c_st_xl_t;
+int32_t lsm6ds3tr_c_xl_self_test_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_st_xl_t val);
+int32_t lsm6ds3tr_c_xl_self_test_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_st_xl_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_GY_ST_DISABLE    = 0,
+  LSM6DS3TR_C_GY_ST_POSITIVE   = 1,
+  LSM6DS3TR_C_GY_ST_NEGATIVE   = 3,
+  LSM6DS3TR_C_GY_ST_ND         = 4,    /* ERROR CODE */
+} lsm6ds3tr_c_st_g_t;
+int32_t lsm6ds3tr_c_gy_self_test_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_st_g_t val);
+int32_t lsm6ds3tr_c_gy_self_test_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_st_g_t *val);
+
+int32_t lsm6ds3tr_c_filter_settling_mask_set(stmdev_ctx_t *ctx,
+                                             uint8_t val);
+int32_t lsm6ds3tr_c_filter_settling_mask_get(stmdev_ctx_t *ctx,
+                                             uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_USE_SLOPE    = 0,
+  LSM6DS3TR_C_USE_HPF      = 1,
+  LSM6DS3TR_C_HP_PATH_ND   = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_slope_fds_t;
+int32_t lsm6ds3tr_c_xl_hp_path_internal_set(stmdev_ctx_t *ctx,
+                                            lsm6ds3tr_c_slope_fds_t val);
+int32_t lsm6ds3tr_c_xl_hp_path_internal_get(stmdev_ctx_t *ctx,
+                                            lsm6ds3tr_c_slope_fds_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_XL_ANA_BW_1k5Hz = 0,
+  LSM6DS3TR_C_XL_ANA_BW_400Hz = 1,
+  LSM6DS3TR_C_XL_ANA_BW_ND    = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_bw0_xl_t;
+int32_t lsm6ds3tr_c_xl_filter_analog_set(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_bw0_xl_t val);
+int32_t lsm6ds3tr_c_xl_filter_analog_get(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_bw0_xl_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_XL_LP1_ODR_DIV_2 = 0,
+  LSM6DS3TR_C_XL_LP1_ODR_DIV_4 = 1,
+  LSM6DS3TR_C_XL_LP1_NA        = 2,  /* ERROR CODE */
+} lsm6ds3tr_c_lpf1_bw_sel_t;
+int32_t lsm6ds3tr_c_xl_lp1_bandwidth_set(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_lpf1_bw_sel_t val);
+int32_t lsm6ds3tr_c_xl_lp1_bandwidth_get(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_lpf1_bw_sel_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_50     = 0x00,
+  LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_100    = 0x01,
+  LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_9      = 0x02,
+  LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_400    = 0x03,
+  LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_50   = 0x10,
+  LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_100  = 0x11,
+  LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_9    = 0x12,
+  LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_400  = 0x13,
+  LSM6DS3TR_C_XL_LP_NA                     = 0x20, /* ERROR CODE */
+} lsm6ds3tr_c_input_composite_t;
+int32_t lsm6ds3tr_c_xl_lp2_bandwidth_set(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_input_composite_t val);
+int32_t lsm6ds3tr_c_xl_lp2_bandwidth_get(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_input_composite_t *val);
+
+int32_t lsm6ds3tr_c_xl_reference_mode_set(stmdev_ctx_t *ctx,
+                                          uint8_t val);
+int32_t lsm6ds3tr_c_xl_reference_mode_get(stmdev_ctx_t *ctx,
+                                          uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_XL_HP_ODR_DIV_4      = 0x00, /* Slope filter */
+  LSM6DS3TR_C_XL_HP_ODR_DIV_100    = 0x01,
+  LSM6DS3TR_C_XL_HP_ODR_DIV_9      = 0x02,
+  LSM6DS3TR_C_XL_HP_ODR_DIV_400    = 0x03,
+  LSM6DS3TR_C_XL_HP_NA             = 0x10, /* ERROR CODE */
+} lsm6ds3tr_c_hpcf_xl_t;
+int32_t lsm6ds3tr_c_xl_hp_bandwidth_set(stmdev_ctx_t *ctx,
+                                        lsm6ds3tr_c_hpcf_xl_t val);
+int32_t lsm6ds3tr_c_xl_hp_bandwidth_get(stmdev_ctx_t *ctx,
+                                        lsm6ds3tr_c_hpcf_xl_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_LP2_ONLY                    = 0x00,
+
+  LSM6DS3TR_C_HP_16mHz_LP2                = 0x80,
+  LSM6DS3TR_C_HP_65mHz_LP2                = 0x90,
+  LSM6DS3TR_C_HP_260mHz_LP2               = 0xA0,
+  LSM6DS3TR_C_HP_1Hz04_LP2                = 0xB0,
+
+  LSM6DS3TR_C_HP_DISABLE_LP1_LIGHT        = 0x0A,
+  LSM6DS3TR_C_HP_DISABLE_LP1_NORMAL       = 0x09,
+  LSM6DS3TR_C_HP_DISABLE_LP_STRONG        = 0x08,
+  LSM6DS3TR_C_HP_DISABLE_LP1_AGGRESSIVE   = 0x0B,
+
+  LSM6DS3TR_C_HP_16mHz_LP1_LIGHT          = 0x8A,
+  LSM6DS3TR_C_HP_65mHz_LP1_NORMAL         = 0x99,
+  LSM6DS3TR_C_HP_260mHz_LP1_STRONG        = 0xA8,
+  LSM6DS3TR_C_HP_1Hz04_LP1_AGGRESSIVE     = 0xBB,
+
+  LSM6DS3TR_C_HP_GY_BAND_NA               = 0xFF,    /* ERROR CODE */
+} lsm6ds3tr_c_lpf1_sel_g_t;
+int32_t lsm6ds3tr_c_gy_band_pass_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_lpf1_sel_g_t val);
+int32_t lsm6ds3tr_c_gy_band_pass_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_lpf1_sel_g_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_SPI_4_WIRE  = 0,
+  LSM6DS3TR_C_SPI_3_WIRE  = 1,
+  LSM6DS3TR_C_SPI_MODE_ND = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_sim_t;
+int32_t lsm6ds3tr_c_spi_mode_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_sim_t val);
+int32_t lsm6ds3tr_c_spi_mode_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_sim_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_I2C_ENABLE   = 0,
+  LSM6DS3TR_C_I2C_DISABLE  = 1,
+  LSM6DS3TR_C_I2C_MODE_ND  = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_i2c_disable_t;
+int32_t lsm6ds3tr_c_i2c_interface_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_i2c_disable_t val);
+int32_t lsm6ds3tr_c_i2c_interface_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_i2c_disable_t *val);
+
+typedef struct
+{
+  uint8_t int1_drdy_xl             : 1;
+  uint8_t int1_drdy_g              : 1;
+  uint8_t int1_boot                : 1;
+  uint8_t int1_fth                 : 1;
+  uint8_t int1_fifo_ovr            : 1;
+  uint8_t int1_full_flag           : 1;
+  uint8_t int1_sign_mot            : 1;
+  uint8_t int1_step_detector       : 1;
+  uint8_t int1_timer               : 1;
+  uint8_t int1_tilt                : 1;
+  uint8_t int1_6d                  : 1;
+  uint8_t int1_double_tap          : 1;
+  uint8_t int1_ff                  : 1;
+  uint8_t int1_wu                  : 1;
+  uint8_t int1_single_tap          : 1;
+  uint8_t int1_inact_state         : 1;
+  uint8_t den_drdy_int1            : 1;
+  uint8_t drdy_on_int1             : 1;
+} lsm6ds3tr_c_int1_route_t;
+int32_t lsm6ds3tr_c_pin_int1_route_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_int1_route_t val);
+int32_t lsm6ds3tr_c_pin_int1_route_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_int1_route_t *val);
+
+typedef struct
+{
+  uint8_t int2_drdy_xl             : 1;
+  uint8_t int2_drdy_g              : 1;
+  uint8_t int2_drdy_temp           : 1;
+  uint8_t int2_fth                 : 1;
+  uint8_t int2_fifo_ovr            : 1;
+  uint8_t int2_full_flag           : 1;
+  uint8_t int2_step_count_ov       : 1;
+  uint8_t int2_step_delta          : 1;
+  uint8_t int2_iron                : 1;
+  uint8_t int2_tilt                : 1;
+  uint8_t int2_6d                  : 1;
+  uint8_t int2_double_tap          : 1;
+  uint8_t int2_ff                  : 1;
+  uint8_t int2_wu                  : 1;
+  uint8_t int2_single_tap          : 1;
+  uint8_t int2_inact_state         : 1;
+  uint8_t int2_wrist_tilt          : 1;
+} lsm6ds3tr_c_int2_route_t;
+int32_t lsm6ds3tr_c_pin_int2_route_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_int2_route_t val);
+int32_t lsm6ds3tr_c_pin_int2_route_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_int2_route_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_PUSH_PULL   = 0,
+  LSM6DS3TR_C_OPEN_DRAIN  = 1,
+  LSM6DS3TR_C_PIN_MODE_ND = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_pp_od_t;
+int32_t lsm6ds3tr_c_pin_mode_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_pp_od_t val);
+int32_t lsm6ds3tr_c_pin_mode_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_pp_od_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_ACTIVE_HIGH   = 0,
+  LSM6DS3TR_C_ACTIVE_LOW    = 1,
+  LSM6DS3TR_C_POLARITY_ND   = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_h_lactive_t;
+int32_t lsm6ds3tr_c_pin_polarity_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_h_lactive_t val);
+int32_t lsm6ds3tr_c_pin_polarity_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_h_lactive_t *val);
+
+int32_t lsm6ds3tr_c_all_on_int1_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_all_on_int1_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_INT_PULSED   = 0,
+  LSM6DS3TR_C_INT_LATCHED  = 1,
+  LSM6DS3TR_C_INT_MODE     = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_lir_t;
+int32_t lsm6ds3tr_c_int_notification_set(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_lir_t val);
+int32_t lsm6ds3tr_c_int_notification_get(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_lir_t *val);
+
+int32_t lsm6ds3tr_c_wkup_threshold_set(stmdev_ctx_t *ctx,
+                                       uint8_t val);
+int32_t lsm6ds3tr_c_wkup_threshold_get(stmdev_ctx_t *ctx,
+                                       uint8_t *val);
+
+int32_t lsm6ds3tr_c_wkup_dur_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_wkup_dur_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+int32_t lsm6ds3tr_c_gy_sleep_mode_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_gy_sleep_mode_get(stmdev_ctx_t *ctx,
+                                      uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_PROPERTY_DISABLE          = 0,
+  LSM6DS3TR_C_XL_12Hz5_GY_NOT_AFFECTED  = 1,
+  LSM6DS3TR_C_XL_12Hz5_GY_SLEEP         = 2,
+  LSM6DS3TR_C_XL_12Hz5_GY_PD            = 3,
+  LSM6DS3TR_C_ACT_MODE_ND               = 4,    /* ERROR CODE */
+} lsm6ds3tr_c_inact_en_t;
+int32_t lsm6ds3tr_c_act_mode_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_inact_en_t val);
+int32_t lsm6ds3tr_c_act_mode_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_inact_en_t *val);
+
+int32_t lsm6ds3tr_c_act_sleep_dur_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_act_sleep_dur_get(stmdev_ctx_t *ctx,
+                                      uint8_t *val);
+
+int32_t lsm6ds3tr_c_tap_src_get(stmdev_ctx_t *ctx,
+                                lsm6ds3tr_c_tap_src_t *val);
+
+int32_t lsm6ds3tr_c_tap_detection_on_z_set(stmdev_ctx_t *ctx,
+                                           uint8_t val);
+int32_t lsm6ds3tr_c_tap_detection_on_z_get(stmdev_ctx_t *ctx,
+                                           uint8_t *val);
+
+int32_t lsm6ds3tr_c_tap_detection_on_y_set(stmdev_ctx_t *ctx,
+                                           uint8_t val);
+int32_t lsm6ds3tr_c_tap_detection_on_y_get(stmdev_ctx_t *ctx,
+                                           uint8_t *val);
+
+int32_t lsm6ds3tr_c_tap_detection_on_x_set(stmdev_ctx_t *ctx,
+                                           uint8_t val);
+int32_t lsm6ds3tr_c_tap_detection_on_x_get(stmdev_ctx_t *ctx,
+                                           uint8_t *val);
+
+int32_t lsm6ds3tr_c_tap_threshold_x_set(stmdev_ctx_t *ctx,
+                                        uint8_t val);
+int32_t lsm6ds3tr_c_tap_threshold_x_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val);
+
+int32_t lsm6ds3tr_c_tap_shock_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_tap_shock_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+int32_t lsm6ds3tr_c_tap_quiet_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_tap_quiet_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+int32_t lsm6ds3tr_c_tap_dur_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_tap_dur_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_ONLY_SINGLE          = 0,
+  LSM6DS3TR_C_BOTH_SINGLE_DOUBLE   = 1,
+  LSM6DS3TR_C_TAP_MODE_ND          = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_single_double_tap_t;
+int32_t lsm6ds3tr_c_tap_mode_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_single_double_tap_t val);
+int32_t lsm6ds3tr_c_tap_mode_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_single_double_tap_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_ODR_DIV_2_FEED      = 0,
+  LSM6DS3TR_C_LPF2_FEED           = 1,
+  LSM6DS3TR_C_6D_FEED_ND          = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_low_pass_on_6d_t;
+int32_t lsm6ds3tr_c_6d_feed_data_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_low_pass_on_6d_t val);
+int32_t lsm6ds3tr_c_6d_feed_data_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_low_pass_on_6d_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_DEG_80      = 0,
+  LSM6DS3TR_C_DEG_70      = 1,
+  LSM6DS3TR_C_DEG_60      = 2,
+  LSM6DS3TR_C_DEG_50      = 3,
+  LSM6DS3TR_C_6D_TH_ND    = 4,    /* ERROR CODE */
+} lsm6ds3tr_c_sixd_ths_t;
+int32_t lsm6ds3tr_c_6d_threshold_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_sixd_ths_t val);
+int32_t lsm6ds3tr_c_6d_threshold_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_sixd_ths_t *val);
+
+int32_t lsm6ds3tr_c_4d_mode_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_4d_mode_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+int32_t lsm6ds3tr_c_ff_dur_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_ff_dur_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_FF_TSH_156mg = 0,
+  LSM6DS3TR_C_FF_TSH_219mg = 1,
+  LSM6DS3TR_C_FF_TSH_250mg = 2,
+  LSM6DS3TR_C_FF_TSH_312mg = 3,
+  LSM6DS3TR_C_FF_TSH_344mg = 4,
+  LSM6DS3TR_C_FF_TSH_406mg = 5,
+  LSM6DS3TR_C_FF_TSH_469mg = 6,
+  LSM6DS3TR_C_FF_TSH_500mg = 7,
+  LSM6DS3TR_C_FF_TSH_ND    = 8,    /* ERROR CODE */
+} lsm6ds3tr_c_ff_ths_t;
+int32_t lsm6ds3tr_c_ff_threshold_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_ff_ths_t val);
+int32_t lsm6ds3tr_c_ff_threshold_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_ff_ths_t *val);
+
+int32_t lsm6ds3tr_c_fifo_watermark_set(stmdev_ctx_t *ctx,
+                                       uint16_t val);
+int32_t lsm6ds3tr_c_fifo_watermark_get(stmdev_ctx_t *ctx,
+                                       uint16_t *val);
+
+int32_t lsm6ds3tr_c_fifo_data_level_get(stmdev_ctx_t *ctx,
+                                        uint16_t *val);
+
+int32_t lsm6ds3tr_c_fifo_wtm_flag_get(stmdev_ctx_t *ctx,
+                                      uint8_t *val);
+
+int32_t lsm6ds3tr_c_fifo_pattern_get(stmdev_ctx_t *ctx,
+                                     uint16_t *val);
+
+int32_t lsm6ds3tr_c_fifo_temp_batch_set(stmdev_ctx_t *ctx,
+                                        uint8_t val);
+int32_t lsm6ds3tr_c_fifo_temp_batch_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_TRG_XL_GY_DRDY     = 0,
+  LSM6DS3TR_C_TRG_STEP_DETECT    = 1,
+  LSM6DS3TR_C_TRG_SH_DRDY        = 2,
+  LSM6DS3TR_C_TRG_SH_ND          = 3,    /* ERROR CODE */
+} lsm6ds3tr_c_trigger_fifo_t;
+int32_t lsm6ds3tr_c_fifo_write_trigger_set(stmdev_ctx_t *ctx,
+                                           lsm6ds3tr_c_trigger_fifo_t val);
+int32_t lsm6ds3tr_c_fifo_write_trigger_get(stmdev_ctx_t *ctx,
+                                           lsm6ds3tr_c_trigger_fifo_t *val);
+
+int32_t lsm6ds3tr_c_fifo_pedo_and_timestamp_batch_set(
+  stmdev_ctx_t *ctx,
+  uint8_t val);
+int32_t lsm6ds3tr_c_fifo_pedo_and_timestamp_batch_get(
+  stmdev_ctx_t *ctx,
+  uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_FIFO_XL_DISABLE  = 0,
+  LSM6DS3TR_C_FIFO_XL_NO_DEC   = 1,
+  LSM6DS3TR_C_FIFO_XL_DEC_2    = 2,
+  LSM6DS3TR_C_FIFO_XL_DEC_3    = 3,
+  LSM6DS3TR_C_FIFO_XL_DEC_4    = 4,
+  LSM6DS3TR_C_FIFO_XL_DEC_8    = 5,
+  LSM6DS3TR_C_FIFO_XL_DEC_16   = 6,
+  LSM6DS3TR_C_FIFO_XL_DEC_32   = 7,
+  LSM6DS3TR_C_FIFO_XL_DEC_ND   = 8,    /* ERROR CODE */
+} lsm6ds3tr_c_dec_fifo_xl_t;
+int32_t lsm6ds3tr_c_fifo_xl_batch_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_dec_fifo_xl_t val);
+int32_t lsm6ds3tr_c_fifo_xl_batch_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_dec_fifo_xl_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_FIFO_GY_DISABLE = 0,
+  LSM6DS3TR_C_FIFO_GY_NO_DEC  = 1,
+  LSM6DS3TR_C_FIFO_GY_DEC_2   = 2,
+  LSM6DS3TR_C_FIFO_GY_DEC_3   = 3,
+  LSM6DS3TR_C_FIFO_GY_DEC_4   = 4,
+  LSM6DS3TR_C_FIFO_GY_DEC_8   = 5,
+  LSM6DS3TR_C_FIFO_GY_DEC_16  = 6,
+  LSM6DS3TR_C_FIFO_GY_DEC_32  = 7,
+  LSM6DS3TR_C_FIFO_GY_DEC_ND  = 8,    /* ERROR CODE */
+} lsm6ds3tr_c_dec_fifo_gyro_t;
+int32_t lsm6ds3tr_c_fifo_gy_batch_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_dec_fifo_gyro_t val);
+int32_t lsm6ds3tr_c_fifo_gy_batch_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_dec_fifo_gyro_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_FIFO_DS3_DISABLE   = 0,
+  LSM6DS3TR_C_FIFO_DS3_NO_DEC    = 1,
+  LSM6DS3TR_C_FIFO_DS3_DEC_2     = 2,
+  LSM6DS3TR_C_FIFO_DS3_DEC_3     = 3,
+  LSM6DS3TR_C_FIFO_DS3_DEC_4     = 4,
+  LSM6DS3TR_C_FIFO_DS3_DEC_8     = 5,
+  LSM6DS3TR_C_FIFO_DS3_DEC_16    = 6,
+  LSM6DS3TR_C_FIFO_DS3_DEC_32    = 7,
+  LSM6DS3TR_C_FIFO_DS3_DEC_ND    = 8,    /* ERROR CODE */
+} lsm6ds3tr_c_dec_ds3_fifo_t;
+int32_t lsm6ds3tr_c_fifo_dataset_3_batch_set(stmdev_ctx_t *ctx,
+                                             lsm6ds3tr_c_dec_ds3_fifo_t val);
+int32_t lsm6ds3tr_c_fifo_dataset_3_batch_get(stmdev_ctx_t *ctx,
+                                             lsm6ds3tr_c_dec_ds3_fifo_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_FIFO_DS4_DISABLE  = 0,
+  LSM6DS3TR_C_FIFO_DS4_NO_DEC   = 1,
+  LSM6DS3TR_C_FIFO_DS4_DEC_2    = 2,
+  LSM6DS3TR_C_FIFO_DS4_DEC_3    = 3,
+  LSM6DS3TR_C_FIFO_DS4_DEC_4    = 4,
+  LSM6DS3TR_C_FIFO_DS4_DEC_8    = 5,
+  LSM6DS3TR_C_FIFO_DS4_DEC_16   = 6,
+  LSM6DS3TR_C_FIFO_DS4_DEC_32   = 7,
+  LSM6DS3TR_C_FIFO_DS4_DEC_ND   = 8,    /* ERROR CODE */
+} lsm6ds3tr_c_dec_ds4_fifo_t;
+int32_t lsm6ds3tr_c_fifo_dataset_4_batch_set(stmdev_ctx_t *ctx,
+                                             lsm6ds3tr_c_dec_ds4_fifo_t val);
+int32_t lsm6ds3tr_c_fifo_dataset_4_batch_get(stmdev_ctx_t *ctx,
+                                             lsm6ds3tr_c_dec_ds4_fifo_t *val);
+
+int32_t lsm6ds3tr_c_fifo_xl_gy_8bit_format_set(stmdev_ctx_t *ctx,
+                                               uint8_t val);
+int32_t lsm6ds3tr_c_fifo_xl_gy_8bit_format_get(stmdev_ctx_t *ctx,
+                                               uint8_t *val);
+
+int32_t lsm6ds3tr_c_fifo_stop_on_wtm_set(stmdev_ctx_t *ctx,
+                                         uint8_t val);
+int32_t lsm6ds3tr_c_fifo_stop_on_wtm_get(stmdev_ctx_t *ctx,
+                                         uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_BYPASS_MODE           = 0,
+  LSM6DS3TR_C_FIFO_MODE             = 1,
+  LSM6DS3TR_C_STREAM_TO_FIFO_MODE   = 3,
+  LSM6DS3TR_C_BYPASS_TO_STREAM_MODE = 4,
+  LSM6DS3TR_C_STREAM_MODE           = 6,
+  LSM6DS3TR_C_FIFO_MODE_ND          = 8,    /* ERROR CODE */
+} lsm6ds3tr_c_fifo_mode_t;
+int32_t lsm6ds3tr_c_fifo_mode_set(stmdev_ctx_t *ctx,
+                                  lsm6ds3tr_c_fifo_mode_t val);
+int32_t lsm6ds3tr_c_fifo_mode_get(stmdev_ctx_t *ctx,
+                                  lsm6ds3tr_c_fifo_mode_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_FIFO_DISABLE   =  0,
+  LSM6DS3TR_C_FIFO_12Hz5     =  1,
+  LSM6DS3TR_C_FIFO_26Hz      =  2,
+  LSM6DS3TR_C_FIFO_52Hz      =  3,
+  LSM6DS3TR_C_FIFO_104Hz     =  4,
+  LSM6DS3TR_C_FIFO_208Hz     =  5,
+  LSM6DS3TR_C_FIFO_416Hz     =  6,
+  LSM6DS3TR_C_FIFO_833Hz     =  7,
+  LSM6DS3TR_C_FIFO_1k66Hz    =  8,
+  LSM6DS3TR_C_FIFO_3k33Hz    =  9,
+  LSM6DS3TR_C_FIFO_6k66Hz    = 10,
+  LSM6DS3TR_C_FIFO_RATE_ND   = 11,    /* ERROR CODE */
+} lsm6ds3tr_c_odr_fifo_t;
+int32_t lsm6ds3tr_c_fifo_data_rate_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_odr_fifo_t val);
+int32_t lsm6ds3tr_c_fifo_data_rate_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_odr_fifo_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_DEN_ACT_LOW    = 0,
+  LSM6DS3TR_C_DEN_ACT_HIGH   = 1,
+  LSM6DS3TR_C_DEN_POL_ND     = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_den_lh_t;
+int32_t lsm6ds3tr_c_den_polarity_set(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_den_lh_t val);
+int32_t lsm6ds3tr_c_den_polarity_get(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_den_lh_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_DEN_DISABLE    = 0,
+  LSM6DS3TR_C_LEVEL_FIFO     = 6,
+  LSM6DS3TR_C_LEVEL_LETCHED  = 3,
+  LSM6DS3TR_C_LEVEL_TRIGGER  = 2,
+  LSM6DS3TR_C_EDGE_TRIGGER   = 4,
+  LSM6DS3TR_C_DEN_MODE_ND    = 5,    /* ERROR CODE */
+} lsm6ds3tr_c_den_mode_t;
+int32_t lsm6ds3tr_c_den_mode_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_den_mode_t val);
+int32_t lsm6ds3tr_c_den_mode_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_den_mode_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_STAMP_IN_GY_DATA     = 0,
+  LSM6DS3TR_C_STAMP_IN_XL_DATA     = 1,
+  LSM6DS3TR_C_STAMP_IN_GY_XL_DATA  = 2,
+  LSM6DS3TR_C_DEN_STAMP_ND         = 3,    /* ERROR CODE */
+} lsm6ds3tr_c_den_xl_en_t;
+int32_t lsm6ds3tr_c_den_enable_set(stmdev_ctx_t *ctx,
+                                   lsm6ds3tr_c_den_xl_en_t val);
+int32_t lsm6ds3tr_c_den_enable_get(stmdev_ctx_t *ctx,
+                                   lsm6ds3tr_c_den_xl_en_t *val);
+
+int32_t lsm6ds3tr_c_den_mark_axis_z_set(stmdev_ctx_t *ctx,
+                                        uint8_t val);
+int32_t lsm6ds3tr_c_den_mark_axis_z_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val);
+
+int32_t lsm6ds3tr_c_den_mark_axis_y_set(stmdev_ctx_t *ctx,
+                                        uint8_t val);
+int32_t lsm6ds3tr_c_den_mark_axis_y_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val);
+
+int32_t lsm6ds3tr_c_den_mark_axis_x_set(stmdev_ctx_t *ctx,
+                                        uint8_t val);
+int32_t lsm6ds3tr_c_den_mark_axis_x_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val);
+
+int32_t lsm6ds3tr_c_pedo_step_reset_set(stmdev_ctx_t *ctx,
+                                        uint8_t val);
+int32_t lsm6ds3tr_c_pedo_step_reset_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val);
+
+int32_t lsm6ds3tr_c_pedo_sens_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_pedo_sens_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+int32_t lsm6ds3tr_c_pedo_threshold_set(stmdev_ctx_t *ctx,
+                                       uint8_t val);
+int32_t lsm6ds3tr_c_pedo_threshold_get(stmdev_ctx_t *ctx,
+                                       uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_PEDO_AT_2g = 0,
+  LSM6DS3TR_C_PEDO_AT_4g = 1,
+  LSM6DS3TR_C_PEDO_FS_ND = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_pedo_fs_t;
+int32_t lsm6ds3tr_c_pedo_full_scale_set(stmdev_ctx_t *ctx,
+                                        lsm6ds3tr_c_pedo_fs_t val);
+int32_t lsm6ds3tr_c_pedo_full_scale_get(stmdev_ctx_t *ctx,
+                                        lsm6ds3tr_c_pedo_fs_t *val);
+
+int32_t lsm6ds3tr_c_pedo_debounce_steps_set(stmdev_ctx_t *ctx,
+                                            uint8_t val);
+int32_t lsm6ds3tr_c_pedo_debounce_steps_get(stmdev_ctx_t *ctx,
+                                            uint8_t *val);
+
+int32_t lsm6ds3tr_c_pedo_timeout_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_pedo_timeout_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+int32_t lsm6ds3tr_c_pedo_steps_period_set(stmdev_ctx_t *ctx,
+                                          uint8_t *buff);
+int32_t lsm6ds3tr_c_pedo_steps_period_get(stmdev_ctx_t *ctx,
+                                          uint8_t *buff);
+
+int32_t lsm6ds3tr_c_motion_sens_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_motion_sens_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+int32_t lsm6ds3tr_c_motion_threshold_set(stmdev_ctx_t *ctx,
+                                         uint8_t *buff);
+int32_t lsm6ds3tr_c_motion_threshold_get(stmdev_ctx_t *ctx,
+                                         uint8_t *buff);
+
+int32_t lsm6ds3tr_c_tilt_sens_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_tilt_sens_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+int32_t lsm6ds3tr_c_wrist_tilt_sens_set(stmdev_ctx_t *ctx,
+                                        uint8_t val);
+int32_t lsm6ds3tr_c_wrist_tilt_sens_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val);
+
+int32_t lsm6ds3tr_c_tilt_latency_set(stmdev_ctx_t *ctx,
+                                     uint8_t *buff);
+int32_t lsm6ds3tr_c_tilt_latency_get(stmdev_ctx_t *ctx,
+                                     uint8_t *buff);
+
+int32_t lsm6ds3tr_c_tilt_threshold_set(stmdev_ctx_t *ctx,
+                                       uint8_t *buff);
+int32_t lsm6ds3tr_c_tilt_threshold_get(stmdev_ctx_t *ctx,
+                                       uint8_t *buff);
+
+int32_t lsm6ds3tr_c_tilt_src_set(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_a_wrist_tilt_mask_t *val);
+int32_t lsm6ds3tr_c_tilt_src_get(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_a_wrist_tilt_mask_t *val);
+
+int32_t lsm6ds3tr_c_mag_soft_iron_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_mag_soft_iron_get(stmdev_ctx_t *ctx,
+                                      uint8_t *val);
+
+int32_t lsm6ds3tr_c_mag_hard_iron_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_mag_hard_iron_get(stmdev_ctx_t *ctx,
+                                      uint8_t *val);
+
+int32_t lsm6ds3tr_c_mag_soft_iron_mat_set(stmdev_ctx_t *ctx,
+                                          uint8_t *buff);
+int32_t lsm6ds3tr_c_mag_soft_iron_mat_get(stmdev_ctx_t *ctx,
+                                          uint8_t *buff);
+
+int32_t lsm6ds3tr_c_mag_offset_set(stmdev_ctx_t *ctx, int16_t *val);
+int32_t lsm6ds3tr_c_mag_offset_get(stmdev_ctx_t *ctx, int16_t *val);
+
+int32_t lsm6ds3tr_c_func_en_set(stmdev_ctx_t *ctx, uint8_t val);
+
+int32_t lsm6ds3tr_c_sh_sync_sens_frame_set(stmdev_ctx_t *ctx,
+                                           uint8_t val);
+int32_t lsm6ds3tr_c_sh_sync_sens_frame_get(stmdev_ctx_t *ctx,
+                                           uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_RES_RATIO_2_11  = 0,
+  LSM6DS3TR_C_RES_RATIO_2_12  = 1,
+  LSM6DS3TR_C_RES_RATIO_2_13  = 2,
+  LSM6DS3TR_C_RES_RATIO_2_14  = 3,
+  LSM6DS3TR_C_RES_RATIO_ND    = 4,    /* ERROR CODE */
+} lsm6ds3tr_c_rr_t;
+int32_t lsm6ds3tr_c_sh_sync_sens_ratio_set(stmdev_ctx_t *ctx,
+                                           lsm6ds3tr_c_rr_t val);
+int32_t lsm6ds3tr_c_sh_sync_sens_ratio_get(stmdev_ctx_t *ctx,
+                                           lsm6ds3tr_c_rr_t *val);
+
+int32_t lsm6ds3tr_c_sh_master_set(stmdev_ctx_t *ctx, uint8_t val);
+int32_t lsm6ds3tr_c_sh_master_get(stmdev_ctx_t *ctx, uint8_t *val);
+
+int32_t lsm6ds3tr_c_sh_pass_through_set(stmdev_ctx_t *ctx,
+                                        uint8_t val);
+int32_t lsm6ds3tr_c_sh_pass_through_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_EXT_PULL_UP       = 0,
+  LSM6DS3TR_C_INTERNAL_PULL_UP  = 1,
+  LSM6DS3TR_C_SH_PIN_MODE       = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_pull_up_en_t;
+int32_t lsm6ds3tr_c_sh_pin_mode_set(stmdev_ctx_t *ctx,
+                                    lsm6ds3tr_c_pull_up_en_t val);
+int32_t lsm6ds3tr_c_sh_pin_mode_get(stmdev_ctx_t *ctx,
+                                    lsm6ds3tr_c_pull_up_en_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_XL_GY_DRDY        = 0,
+  LSM6DS3TR_C_EXT_ON_INT2_PIN   = 1,
+  LSM6DS3TR_C_SH_SYNCRO_ND      = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_start_config_t;
+int32_t lsm6ds3tr_c_sh_syncro_mode_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_start_config_t val);
+int32_t lsm6ds3tr_c_sh_syncro_mode_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_start_config_t *val);
+
+int32_t lsm6ds3tr_c_sh_drdy_on_int1_set(stmdev_ctx_t *ctx,
+                                        uint8_t val);
+int32_t lsm6ds3tr_c_sh_drdy_on_int1_get(stmdev_ctx_t *ctx,
+                                        uint8_t *val);
+
+typedef struct
+{
+  lsm6ds3tr_c_sensorhub1_reg_t   sh_byte_1;
+  lsm6ds3tr_c_sensorhub2_reg_t   sh_byte_2;
+  lsm6ds3tr_c_sensorhub3_reg_t   sh_byte_3;
+  lsm6ds3tr_c_sensorhub4_reg_t   sh_byte_4;
+  lsm6ds3tr_c_sensorhub5_reg_t   sh_byte_5;
+  lsm6ds3tr_c_sensorhub6_reg_t   sh_byte_6;
+  lsm6ds3tr_c_sensorhub7_reg_t   sh_byte_7;
+  lsm6ds3tr_c_sensorhub8_reg_t   sh_byte_8;
+  lsm6ds3tr_c_sensorhub9_reg_t   sh_byte_9;
+  lsm6ds3tr_c_sensorhub10_reg_t  sh_byte_10;
+  lsm6ds3tr_c_sensorhub11_reg_t  sh_byte_11;
+  lsm6ds3tr_c_sensorhub12_reg_t  sh_byte_12;
+  lsm6ds3tr_c_sensorhub13_reg_t  sh_byte_13;
+  lsm6ds3tr_c_sensorhub14_reg_t  sh_byte_14;
+  lsm6ds3tr_c_sensorhub15_reg_t  sh_byte_15;
+  lsm6ds3tr_c_sensorhub16_reg_t  sh_byte_16;
+  lsm6ds3tr_c_sensorhub17_reg_t  sh_byte_17;
+  lsm6ds3tr_c_sensorhub18_reg_t  sh_byte_18;
+} lsm6ds3tr_c_emb_sh_read_t;
+int32_t lsm6ds3tr_c_sh_read_data_raw_get(stmdev_ctx_t *ctx,
+                                         lsm6ds3tr_c_emb_sh_read_t *val);
+
+int32_t lsm6ds3tr_c_sh_cmd_sens_sync_set(stmdev_ctx_t *ctx,
+                                         uint8_t val);
+int32_t lsm6ds3tr_c_sh_cmd_sens_sync_get(stmdev_ctx_t *ctx,
+                                         uint8_t *val);
+
+int32_t lsm6ds3tr_c_sh_spi_sync_error_set(stmdev_ctx_t *ctx,
+                                          uint8_t val);
+int32_t lsm6ds3tr_c_sh_spi_sync_error_get(stmdev_ctx_t *ctx,
+                                          uint8_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_SLV_0        = 0,
+  LSM6DS3TR_C_SLV_0_1      = 1,
+  LSM6DS3TR_C_SLV_0_1_2    = 2,
+  LSM6DS3TR_C_SLV_0_1_2_3  = 3,
+  LSM6DS3TR_C_SLV_EN_ND    = 4,    /* ERROR CODE */
+} lsm6ds3tr_c_aux_sens_on_t;
+int32_t lsm6ds3tr_c_sh_num_of_dev_connected_set(stmdev_ctx_t *ctx,
+                                                lsm6ds3tr_c_aux_sens_on_t val);
+int32_t lsm6ds3tr_c_sh_num_of_dev_connected_get(stmdev_ctx_t *ctx,
+                                                lsm6ds3tr_c_aux_sens_on_t *val);
+
+typedef struct
+{
+  uint8_t   slv0_add;
+  uint8_t   slv0_subadd;
+  uint8_t   slv0_data;
+} lsm6ds3tr_c_sh_cfg_write_t;
+int32_t lsm6ds3tr_c_sh_cfg_write(stmdev_ctx_t *ctx,
+                                 lsm6ds3tr_c_sh_cfg_write_t *val);
+
+typedef struct
+{
+  uint8_t   slv_add;
+  uint8_t   slv_subadd;
+  uint8_t   slv_len;
+} lsm6ds3tr_c_sh_cfg_read_t;
+int32_t lsm6ds3tr_c_sh_slv0_cfg_read(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_sh_cfg_read_t *val);
+int32_t lsm6ds3tr_c_sh_slv1_cfg_read(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_sh_cfg_read_t *val);
+int32_t lsm6ds3tr_c_sh_slv2_cfg_read(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_sh_cfg_read_t *val);
+int32_t lsm6ds3tr_c_sh_slv3_cfg_read(stmdev_ctx_t *ctx,
+                                     lsm6ds3tr_c_sh_cfg_read_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_SL0_NO_DEC   = 0,
+  LSM6DS3TR_C_SL0_DEC_2    = 1,
+  LSM6DS3TR_C_SL0_DEC_4    = 2,
+  LSM6DS3TR_C_SL0_DEC_8    = 3,
+  LSM6DS3TR_C_SL0_DEC_ND   = 4,    /* ERROR CODE */
+} lsm6ds3tr_c_slave0_rate_t;
+int32_t lsm6ds3tr_c_sh_slave_0_dec_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave0_rate_t val);
+int32_t lsm6ds3tr_c_sh_slave_0_dec_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave0_rate_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_EACH_SH_CYCLE     = 0,
+  LSM6DS3TR_C_ONLY_FIRST_CYCLE  = 1,
+  LSM6DS3TR_C_SH_WR_MODE_ND     = 2,    /* ERROR CODE */
+} lsm6ds3tr_c_write_once_t;
+int32_t lsm6ds3tr_c_sh_write_mode_set(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_write_once_t val);
+int32_t lsm6ds3tr_c_sh_write_mode_get(stmdev_ctx_t *ctx,
+                                      lsm6ds3tr_c_write_once_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_SL1_NO_DEC   = 0,
+  LSM6DS3TR_C_SL1_DEC_2    = 1,
+  LSM6DS3TR_C_SL1_DEC_4    = 2,
+  LSM6DS3TR_C_SL1_DEC_8    = 3,
+  LSM6DS3TR_C_SL1_DEC_ND   = 4,    /* ERROR CODE */
+} lsm6ds3tr_c_slave1_rate_t;
+int32_t lsm6ds3tr_c_sh_slave_1_dec_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave1_rate_t val);
+int32_t lsm6ds3tr_c_sh_slave_1_dec_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave1_rate_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_SL2_NO_DEC  = 0,
+  LSM6DS3TR_C_SL2_DEC_2   = 1,
+  LSM6DS3TR_C_SL2_DEC_4   = 2,
+  LSM6DS3TR_C_SL2_DEC_8   = 3,
+  LSM6DS3TR_C_SL2_DEC_ND  = 4,    /* ERROR CODE */
+} lsm6ds3tr_c_slave2_rate_t;
+int32_t lsm6ds3tr_c_sh_slave_2_dec_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave2_rate_t val);
+int32_t lsm6ds3tr_c_sh_slave_2_dec_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave2_rate_t *val);
+
+typedef enum
+{
+  LSM6DS3TR_C_SL3_NO_DEC  = 0,
+  LSM6DS3TR_C_SL3_DEC_2   = 1,
+  LSM6DS3TR_C_SL3_DEC_4   = 2,
+  LSM6DS3TR_C_SL3_DEC_8   = 3,
+  LSM6DS3TR_C_SL3_DEC_ND  = 4,    /* ERROR CODE */
+} lsm6ds3tr_c_slave3_rate_t;
+int32_t lsm6ds3tr_c_sh_slave_3_dec_set(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave3_rate_t val);
+int32_t lsm6ds3tr_c_sh_slave_3_dec_get(stmdev_ctx_t *ctx,
+                                       lsm6ds3tr_c_slave3_rate_t *val);
+
+/**
+  * @}
+  *
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LSM6DS3TR_C_DRIVER_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 188 - 0
tracking/main_loop.cc

@@ -0,0 +1,188 @@
+#include "main_loop.h"
+
+#include <furi.h>
+#include <furi_hal.h>
+
+#include "imu/imu.h"
+#include "orientation_tracker.h"
+#include "calibration_data.h"
+
+#define TAG "tracker"
+
+static const float CURSOR_SPEED = 1024.0 / (M_PI / 4);
+static const float STABILIZE_BIAS = 16.0;
+
+float g_yaw = 0;
+float g_pitch = 0;
+float g_dYaw = 0;
+float g_dPitch = 0;
+bool firstRead = true;
+bool stabilize = true;
+CalibrationData calibration;
+cardboard::OrientationTracker tracker(10000000l); // 10 ms / 100 Hz
+uint64_t ippms, ippms2;
+
+static inline float clamp(float val)
+{
+    while (val <= -M_PI) {
+        val += 2 * M_PI;
+    }
+    while (val >= M_PI) {
+        val -= 2 * M_PI;
+    }
+    return val;
+}
+
+static inline float highpass(float oldVal, float newVal)
+{
+    if (!stabilize) {
+        return newVal;
+    }
+    float delta = clamp(oldVal - newVal);
+    float alpha = (float) std::max(0.0, 1 - std::pow(std::fabs(delta) * CURSOR_SPEED / STABILIZE_BIAS, 3.0));
+    return newVal + alpha * delta;
+}
+
+void sendCurrentState(MouseMoveCallback mouse_move)
+{
+    float dX = g_dYaw * CURSOR_SPEED;
+    float dY = g_dPitch * CURSOR_SPEED;
+
+    // Scale the shift down to fit the protocol.
+    if (dX > 127) {
+        dY *= 127.0 / dX;
+        dX = 127;
+    }
+    if (dX < -127) {
+        dY *= -127.0 / dX;
+        dX = -127;
+    }
+    if (dY > 127) {
+        dX *= 127.0 / dY;
+        dY = 127;
+    }
+    if (dY < -127) {
+        dX *= -127.0 / dY;
+        dY = -127;
+    }
+
+    const int8_t x = (int8_t)std::floor(dX + 0.5);
+    const int8_t y = (int8_t)std::floor(dY + 0.5);
+
+    mouse_move(x, y);
+
+    // Only subtract the part of the error that was already sent.
+    if (x != 0) {
+        g_dYaw -= x / CURSOR_SPEED;
+    }
+    if (y != 0) {
+        g_dPitch -= y / CURSOR_SPEED;
+    }
+}
+
+void onOrientation(cardboard::Vector4& quaternion)
+{
+    float q1 = quaternion[0]; // X * sin(T/2)
+    float q2 = quaternion[1]; // Y * sin(T/2)
+    float q3 = quaternion[2]; // Z * sin(T/2)
+    float q0 = quaternion[3]; // cos(T/2)
+
+    float yaw = std::atan2(2 * (q0 * q3 - q1 * q2), (1 - 2 * (q1 * q1 + q3 * q3)));
+    float pitch = std::asin(2 * (q0 * q1 + q2 * q3));
+    // float roll = std::atan2(2 * (q0 * q2 - q1 * q3), (1 - 2 * (q1 * q1 + q2 * q2)));
+
+    if (yaw == NAN || pitch == NAN) {
+        // NaN case, skip it
+        return;
+    }
+
+    if (firstRead) {
+        g_yaw = yaw;
+        g_pitch = pitch;
+        firstRead = false;
+    } else {
+        const float newYaw = highpass(g_yaw, yaw);
+        const float newPitch = highpass(g_pitch, pitch);
+
+        float dYaw = clamp(g_yaw - newYaw);
+        float dPitch = g_pitch - newPitch;
+        g_yaw = newYaw;
+        g_pitch = newPitch;
+
+        // Accumulate the error locally.
+        g_dYaw += dYaw;
+        g_dPitch += dPitch;
+    }
+}
+
+extern "C" {
+
+void calibration_begin() {
+    calibration.reset();
+    FURI_LOG_I(TAG, "Calibrating");
+}
+
+bool calibration_step() {
+    if (calibration.isComplete())
+        return true;
+
+    double vec[6] = { 0, 0, 0, 0, 0, 0 };
+    if (imu_read(vec) & GYR_DATA_READY) {
+        cardboard::Vector3 data(vec[5], vec[3], vec[4]);
+        return calibration.add(data);
+    }
+
+    return false;
+}
+
+void calibration_end() {
+    CalibrationMedian store;
+    cardboard::Vector3 median = calibration.getMedian();
+    store.x = median[0];
+    store.y = median[1];
+    store.z = median[2];
+    CALIBRATION_DATA_SAVE(&store);
+}
+
+void tracking_begin() {
+    CalibrationMedian store;
+    cardboard::Vector3 median = calibration.getMedian();
+    if (CALIBRATION_DATA_LOAD(&store)) {
+        median[0] = store.x;
+        median[1] = store.y;
+        median[2] = store.z;
+    }
+
+    ippms = furi_hal_cortex_instructions_per_microsecond();
+    ippms2 = ippms / 2;
+    tracker.SetCalibration(median);
+    tracker.Resume();
+}
+
+void tracking_step(MouseMoveCallback mouse_move) {
+    double vec[6] = { 0, 0, 0, 0, 0, 0 };
+    int ret = imu_read(vec);
+    if (ret != 0) {
+        uint64_t t = (DWT->CYCCNT * 1000llu + ippms2) / ippms;
+        if (ret & ACC_DATA_READY) {
+            cardboard::AccelerometerData adata
+                = { .system_timestamp = t, .sensor_timestamp_ns = t,
+                    .data = cardboard::Vector3(vec[2], vec[0], vec[1]) };
+            tracker.OnAccelerometerData(adata);
+        }
+        if (ret & GYR_DATA_READY) {
+            cardboard::GyroscopeData gdata
+                = { .system_timestamp = t, .sensor_timestamp_ns = t,
+                    .data = cardboard::Vector3(vec[5], vec[3], vec[4]) };
+            cardboard::Vector4 pose = tracker.OnGyroscopeData(gdata);
+            onOrientation(pose);
+            sendCurrentState(mouse_move);
+        }
+    }
+}
+
+void tracking_end() {
+    tracker.Pause();
+}
+
+}

+ 21 - 0
tracking/main_loop.h

@@ -0,0 +1,21 @@
+#pragma once
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef bool (*MouseMoveCallback)(int8_t x, int8_t y);
+
+void calibration_begin();
+bool calibration_step();
+void calibration_end();
+
+void tracking_begin();
+void tracking_step(MouseMoveCallback mouse_move);
+void tracking_end();
+
+#ifdef __cplusplus
+}
+#endif

+ 95 - 0
tracking/orientation_tracker.cc

@@ -0,0 +1,95 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 "orientation_tracker.h"
+
+#include "sensors/pose_prediction.h"
+#include "util/logging.h"
+#include "util/vector.h"
+#include "util/vectorutils.h"
+
+namespace cardboard {
+
+OrientationTracker::OrientationTracker(const long sampling_period_ns)
+    : sampling_period_ns_(sampling_period_ns)
+    , calibration_(Vector3::Zero())
+    , is_tracking_(false)
+    , sensor_fusion_(new SensorFusionEkf())
+    , latest_gyroscope_data_({ 0, 0, Vector3::Zero() })
+{
+    sensor_fusion_->SetBiasEstimationEnabled(/*kGyroBiasEstimationEnabled*/ true);
+}
+
+void OrientationTracker::SetCalibration(const Vector3& calibration) {
+    calibration_ = calibration;
+}
+
+void OrientationTracker::Pause()
+{
+    if (!is_tracking_) {
+        return;
+    }
+
+    // Create a gyro event with zero velocity. This effectively stops the prediction.
+    GyroscopeData event = latest_gyroscope_data_;
+    event.data = Vector3::Zero();
+
+    OnGyroscopeData(event);
+
+    is_tracking_ = false;
+}
+
+void OrientationTracker::Resume() { is_tracking_ = true; }
+
+Vector4 OrientationTracker::GetPose(int64_t timestamp_ns) const
+{
+    Rotation predicted_rotation;
+    const PoseState pose_state = sensor_fusion_->GetLatestPoseState();
+    if (sensor_fusion_->IsFullyInitialized()) {
+        predicted_rotation = pose_state.sensor_from_start_rotation;
+    } else {
+        CARDBOARD_LOGI("Tracker not fully initialized yet. Using pose prediction only.");
+        predicted_rotation = pose_prediction::PredictPose(timestamp_ns, pose_state);
+    }
+
+    return (-predicted_rotation).GetQuaternion();
+}
+
+void OrientationTracker::OnAccelerometerData(const AccelerometerData& event)
+{
+    if (!is_tracking_) {
+        return;
+    }
+    sensor_fusion_->ProcessAccelerometerSample(event);
+}
+
+Vector4 OrientationTracker::OnGyroscopeData(const GyroscopeData& event)
+{
+    if (!is_tracking_) {
+        return Vector4();
+    }
+
+    const GyroscopeData data = { .system_timestamp = event.system_timestamp,
+        .sensor_timestamp_ns = event.sensor_timestamp_ns,
+        .data = event.data - calibration_ };
+
+    latest_gyroscope_data_ = data;
+
+    sensor_fusion_->ProcessGyroscopeSample(data);
+
+    return OrientationTracker::GetPose(data.sensor_timestamp_ns + sampling_period_ns_);
+}
+
+} // namespace cardboard

+ 68 - 0
tracking/orientation_tracker.h

@@ -0,0 +1,68 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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.
+ */
+#pragma once
+
+#include <array>
+#include <memory>
+#include <mutex> // NOLINT
+
+#include "sensors/accelerometer_data.h"
+#include "sensors/gyroscope_data.h"
+#include "sensors/sensor_fusion_ekf.h"
+#include "util/rotation.h"
+
+namespace cardboard {
+
+// OrientationTracker encapsulates pose tracking by connecting sensors
+// to SensorFusion.
+// This pose tracker reports poses in display space.
+class OrientationTracker {
+public:
+    OrientationTracker(const long sampling_period_ns);
+
+    void SetCalibration(const Vector3& calibration);
+
+    // Pauses tracking and sensors.
+    void Pause();
+
+    // Resumes tracking ans sensors.
+    void Resume();
+
+    // Gets the predicted pose for a given timestamp.
+    Vector4 GetPose(int64_t timestamp_ns) const;
+
+    // Function called when receiving AccelerometerData.
+    //
+    // @param event sensor event.
+    void OnAccelerometerData(const AccelerometerData& event);
+
+    // Function called when receiving GyroscopeData.
+    //
+    // @param event sensor event.
+    Vector4 OnGyroscopeData(const GyroscopeData& event);
+
+private:
+    long sampling_period_ns_;
+    Vector3 calibration_;
+
+    std::atomic<bool> is_tracking_;
+    // Sensor Fusion object that stores the internal state of the filter.
+    std::unique_ptr<SensorFusionEkf> sensor_fusion_;
+    // Latest gyroscope data.
+    GyroscopeData latest_gyroscope_data_;
+};
+
+} // namespace cardboard

+ 38 - 0
tracking/sensors/accelerometer_data.h

@@ -0,0 +1,38 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_SENSORS_ACCELEROMETER_DATA_H_
+#define CARDBOARD_SDK_SENSORS_ACCELEROMETER_DATA_H_
+
+#include "../util/vector.h"
+
+namespace cardboard {
+
+struct AccelerometerData {
+    // System wall time.
+    uint64_t system_timestamp;
+
+    // Sensor clock time in nanoseconds.
+    uint64_t sensor_timestamp_ns;
+
+    // Acceleration force along the x,y,z axes in m/s^2. This follows android
+    // specification
+    // (https://developer.android.com/guide/topics/sensors/sensors_overview.html#sensors-coords).
+    Vector3 data;
+};
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_SENSORS_ACCELEROMETER_DATA_H_

+ 313 - 0
tracking/sensors/gyroscope_bias_estimator.cc

@@ -0,0 +1,313 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 "gyroscope_bias_estimator.h"
+
+#include <algorithm>
+#include <chrono> // NOLINT
+
+#include "../util/rotation.h"
+#include "../util/vector.h"
+
+namespace {
+
+// Cutoff frequencies in Hertz applied to our various signals, and their
+// corresponding filters.
+const float kAccelerometerLowPassCutOffFrequencyHz = 1.0f;
+const float kRotationVelocityBasedAccelerometerLowPassCutOffFrequencyHz = 0.15f;
+const float kGyroscopeLowPassCutOffFrequencyHz = 1.0f;
+const float kGyroscopeBiasLowPassCutOffFrequencyHz = 0.15f;
+
+// Note that MEMS IMU are not that precise.
+const double kEpsilon = 1.0e-8;
+
+// Size of the filtering window for the mean and median filter. The larger the
+// windows the larger the filter delay.
+const int kFilterWindowSize = 5;
+
+// Threshold used to compare rotation computed from the accelerometer and the
+// gyroscope bias.
+const double kRatioBetweenGyroBiasAndAccel = 1.5;
+
+// The minimum sum of weights we need to acquire before returning a bias
+// estimation.
+const float kMinSumOfWeightsGyroBiasThreshold = 25.0f;
+
+// Amount of change in m/s^3 we allow on the smoothed accelerometer values to
+// consider the phone static.
+const double kAccelerometerDeltaStaticThreshold = 0.5;
+
+// Amount of change in radians/s^2 we allow on the smoothed gyroscope values to
+// consider the phone static.
+const double kGyroscopeDeltaStaticThreshold = 0.03;
+
+// If the gyroscope value is above this threshold, don't update the gyroscope
+// bias estimation. This threshold is applied to the magnitude of gyroscope
+// vectors in radians/s.
+const float kGyroscopeForBiasThreshold = 0.30f;
+
+// Used to monitor if accelerometer and gyroscope have been static for a few
+// frames.
+const int kStaticFrameDetectionThreshold = 50;
+
+// Minimum time step between sensor updates.
+const double kMinTimestep = 1; // std::chrono::nanoseconds(1);
+} // namespace
+
+namespace cardboard {
+
+// A helper class to keep track of whether some signal can be considered static
+// over specified number of frames.
+class GyroscopeBiasEstimator::IsStaticCounter {
+public:
+    // Initializes a counter with the number of consecutive frames we require
+    // the signal to be static before IsRecentlyStatic returns true.
+    //
+    // @param min_static_frames_threshold number of consecutive frames we
+    //     require the signal to be static before IsRecentlyStatic returns true.
+    explicit IsStaticCounter(int min_static_frames_threshold)
+        : min_static_frames_threshold_(min_static_frames_threshold)
+        , consecutive_static_frames_(0)
+    {
+    }
+
+    // Specifies whether the current frame is considered static.
+    //
+    // @param is_static static flag for current frame.
+    void AppendFrame(bool is_static)
+    {
+        if (is_static) {
+            ++consecutive_static_frames_;
+        } else {
+            consecutive_static_frames_ = 0;
+        }
+    }
+
+    // Returns if static movement is assumed.
+    bool IsRecentlyStatic() const
+    {
+        return consecutive_static_frames_ >= min_static_frames_threshold_;
+    }
+    // Resets counter.
+    void Reset() { consecutive_static_frames_ = 0; }
+
+private:
+    const int min_static_frames_threshold_;
+    int consecutive_static_frames_;
+};
+
+GyroscopeBiasEstimator::GyroscopeBiasEstimator()
+    : accelerometer_lowpass_filter_(kAccelerometerLowPassCutOffFrequencyHz)
+    , simulated_gyroscope_from_accelerometer_lowpass_filter_(
+          kRotationVelocityBasedAccelerometerLowPassCutOffFrequencyHz)
+    , gyroscope_lowpass_filter_(kGyroscopeLowPassCutOffFrequencyHz)
+    , gyroscope_bias_lowpass_filter_(kGyroscopeBiasLowPassCutOffFrequencyHz)
+    , accelerometer_static_counter_(new IsStaticCounter(kStaticFrameDetectionThreshold))
+    , gyroscope_static_counter_(new IsStaticCounter(kStaticFrameDetectionThreshold))
+    , current_accumulated_weights_gyroscope_bias_(0.f)
+    , mean_filter_(kFilterWindowSize)
+    , median_filter_(kFilterWindowSize)
+    , last_mean_filtered_accelerometer_value_({ 0, 0, 0 })
+{
+    Reset();
+}
+
+GyroscopeBiasEstimator::~GyroscopeBiasEstimator() { }
+
+void GyroscopeBiasEstimator::Reset()
+{
+    accelerometer_lowpass_filter_.Reset();
+    gyroscope_lowpass_filter_.Reset();
+    gyroscope_bias_lowpass_filter_.Reset();
+    accelerometer_static_counter_->Reset();
+    gyroscope_static_counter_->Reset();
+}
+
+void GyroscopeBiasEstimator::ProcessGyroscope(
+    const Vector3& gyroscope_sample, uint64_t timestamp_ns)
+{
+    // Update gyroscope and gyroscope delta low-pass filters.
+    gyroscope_lowpass_filter_.AddSample(gyroscope_sample, timestamp_ns);
+
+    const auto smoothed_gyroscope_delta
+        = gyroscope_sample - gyroscope_lowpass_filter_.GetFilteredData();
+
+    gyroscope_static_counter_->AppendFrame(
+        Length(smoothed_gyroscope_delta) < kGyroscopeDeltaStaticThreshold);
+
+    // Only update the bias if the gyroscope and accelerometer signals have been
+    // relatively static recently.
+    if (gyroscope_static_counter_->IsRecentlyStatic()
+        && accelerometer_static_counter_->IsRecentlyStatic()) {
+        // Reset static counter when updating the bias fails.
+        if (!UpdateGyroscopeBias(gyroscope_sample, timestamp_ns)) {
+            // Bias update fails because of large motion, thus reset the static
+            // counter.
+            gyroscope_static_counter_->AppendFrame(false);
+        }
+    } else {
+        // Reset weights, if not static.
+        current_accumulated_weights_gyroscope_bias_ = 0;
+    }
+}
+
+void GyroscopeBiasEstimator::ProcessAccelerometer(
+    const Vector3& accelerometer_sample, uint64_t timestamp_ns)
+{
+    // Get current state of the filter.
+    const uint64_t previous_accel_timestamp_ns
+        = accelerometer_lowpass_filter_.GetMostRecentTimestampNs();
+    const bool is_low_pass_filter_init = accelerometer_lowpass_filter_.IsInitialized();
+
+    // Update accel and accel delta low-pass filters.
+    accelerometer_lowpass_filter_.AddSample(accelerometer_sample, timestamp_ns);
+
+    const auto smoothed_accelerometer_delta
+        = accelerometer_sample - accelerometer_lowpass_filter_.GetFilteredData();
+
+    accelerometer_static_counter_->AppendFrame(
+        Length(smoothed_accelerometer_delta) < kAccelerometerDeltaStaticThreshold);
+
+    // Rotation from accel cannot be differentiated with only one sample.
+    if (!is_low_pass_filter_init) {
+        simulated_gyroscope_from_accelerometer_lowpass_filter_.AddSample({ 0, 0, 0 }, timestamp_ns);
+        return;
+    }
+
+    // No need to update the simulated gyroscope at this point because the motion
+    // is too large.
+    if (!accelerometer_static_counter_->IsRecentlyStatic()) {
+        return;
+    }
+
+    median_filter_.AddSample(accelerometer_lowpass_filter_.GetFilteredData());
+
+    // This processing can only be started if the buffer is fully initialized.
+    if (!median_filter_.IsValid()) {
+        mean_filter_.AddSample(accelerometer_lowpass_filter_.GetFilteredData());
+
+        // Update the last filtered accelerometer value.
+        last_mean_filtered_accelerometer_value_ = accelerometer_lowpass_filter_.GetFilteredData();
+        return;
+    }
+
+    mean_filter_.AddSample(median_filter_.GetFilteredData());
+
+    // Compute a mock gyroscope value from accelerometer.
+    const int64_t diff = timestamp_ns - previous_accel_timestamp_ns;
+    const double timestep = static_cast<double>(diff);
+
+    simulated_gyroscope_from_accelerometer_lowpass_filter_.AddSample(
+        ComputeAngularVelocityFromLatestAccelerometer(timestep), timestamp_ns);
+    last_mean_filtered_accelerometer_value_ = mean_filter_.GetFilteredData();
+}
+
+Vector3 GyroscopeBiasEstimator::ComputeAngularVelocityFromLatestAccelerometer(double timestep) const
+{
+    if (timestep < kMinTimestep) {
+        return { 0, 0, 0 };
+    }
+
+    const auto mean_of_median = mean_filter_.GetFilteredData();
+
+    // Compute an incremental rotation between the last state and the current
+    // state.
+    //
+    // Note that we switch to double precision here because of precision problem
+    // with small rotation.
+    const auto incremental_rotation = Rotation::RotateInto(
+        Vector3(last_mean_filtered_accelerometer_value_[0],
+            last_mean_filtered_accelerometer_value_[1], last_mean_filtered_accelerometer_value_[2]),
+        Vector3(mean_of_median[0], mean_of_median[1], mean_of_median[2]));
+
+    // We use axis angle here because this is how gyroscope values are stored.
+    Vector3 incremental_rotation_axis;
+    double incremental_rotation_angle;
+    incremental_rotation.GetAxisAndAngle(&incremental_rotation_axis, &incremental_rotation_angle);
+
+    incremental_rotation_axis *= incremental_rotation_angle / timestep;
+
+    return { static_cast<float>(incremental_rotation_axis[0]),
+        static_cast<float>(incremental_rotation_axis[1]),
+        static_cast<float>(incremental_rotation_axis[2]) };
+}
+
+bool GyroscopeBiasEstimator::UpdateGyroscopeBias(
+    const Vector3& gyroscope_sample, uint64_t timestamp_ns)
+{
+    // Gyroscope values that are too big are potentially dangerous as they could
+    // originate from slow and steady head rotations.
+    //
+    // Therefore we compute an update weight which:
+    // * favors gyroscope values that are closer to 0
+    // * is set to zero if gyroscope values are greater than a threshold.
+    //
+    // This way, the gyroscope bias estimation converges faster if the phone is
+    // flat on a table, as opposed to held up somewhat stationary in the user's
+    // hands.
+
+    // If magnitude is too big, don't update the filter at all so that we don't
+    // artificially increase the number of samples accumulated by the filter.
+    const float gyroscope_sample_norm2 = Length(gyroscope_sample);
+    if (gyroscope_sample_norm2 >= kGyroscopeForBiasThreshold) {
+        return false;
+    }
+
+    float update_weight
+        = std::max(0.0f, 1 - gyroscope_sample_norm2 / kGyroscopeForBiasThreshold);
+    update_weight *= update_weight;
+    gyroscope_bias_lowpass_filter_.AddWeightedSample(
+        gyroscope_lowpass_filter_.GetFilteredData(), timestamp_ns, update_weight);
+
+    // This counter is only partially valid as the low pass filter drops large
+    // samples.
+    current_accumulated_weights_gyroscope_bias_ += update_weight;
+
+    return true;
+}
+
+Vector3 GyroscopeBiasEstimator::GetGyroscopeBias() const
+{
+    return gyroscope_bias_lowpass_filter_.GetFilteredData();
+}
+
+bool GyroscopeBiasEstimator::IsCurrentEstimateValid() const
+{
+    // Remove any bias component along the gravity because they cannot be
+    // evaluated from accelerometer.
+    const auto current_gravity_dir = Normalized(last_mean_filtered_accelerometer_value_);
+    const auto gyro_bias_lowpass = gyroscope_bias_lowpass_filter_.GetFilteredData();
+
+    const auto off_gravity_gyro_bias
+        = gyro_bias_lowpass - current_gravity_dir * Dot(gyro_bias_lowpass, current_gravity_dir);
+
+    // Checks that the current bias estimate is not correlated with the
+    // rotation computed from accelerometer.
+    const auto gyro_from_accel
+        = simulated_gyroscope_from_accelerometer_lowpass_filter_.GetFilteredData();
+    const bool isGyroscopeBiasCorrelatedWithSimulatedGyro
+        = (Length(gyro_from_accel) * kRatioBetweenGyroBiasAndAccel
+            > (Length(off_gravity_gyro_bias) + kEpsilon));
+    const bool hasEnoughSamples
+        = current_accumulated_weights_gyroscope_bias_ > kMinSumOfWeightsGyroBiasThreshold;
+    const bool areCountersStatic = gyroscope_static_counter_->IsRecentlyStatic()
+        && accelerometer_static_counter_->IsRecentlyStatic();
+
+    const bool isStatic
+        = hasEnoughSamples && areCountersStatic && !isGyroscopeBiasCorrelatedWithSimulatedGyro;
+    return isStatic;
+}
+
+} // namespace cardboard

+ 134 - 0
tracking/sensors/gyroscope_bias_estimator.h

@@ -0,0 +1,134 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_SENSORS_GYROSCOPE_BIAS_ESTIMATOR_H_
+#define CARDBOARD_SDK_SENSORS_GYROSCOPE_BIAS_ESTIMATOR_H_
+
+#include <chrono> // NOLINT
+#include <cstdint>
+#include <list>
+#include <memory>
+#include <vector>
+
+#include "lowpass_filter.h"
+#include "mean_filter.h"
+#include "median_filter.h"
+#include "../util/vector.h"
+
+namespace cardboard {
+
+// Class that attempts to estimate the gyroscope's bias.
+// Its main idea is that it averages the gyroscope values when the phone is
+// considered stationary.
+// Usage: A client should call the ProcessGyroscope and ProcessAccelerometer
+// methods for every accelerometer and gyroscope sensor sample. This class
+// expects these calls to be frequent, i.e., at least at 10 Hz. The client can
+// then call GetGyroBias to retrieve the current estimate of the gyroscope bias.
+// For best results, the fastest available delay option should be used when
+// registering to sensors. Note that this class is not thread-safe.
+//
+// The filtering applied to the accelerometer to estimate a rotation
+// from it follows :
+// Baptiste Delporte, Laurent Perroton, Thierry Grandpierre, Jacques Trichet.
+// Accelerometer and Magnetometer Based Gyroscope Emulation on Smart Sensor
+// for a Virtual Reality Application. Sensor and Transducers Journal, 2012.
+//
+// which is a combination of a IIR filter, a median and a mean filter.
+class GyroscopeBiasEstimator {
+public:
+    GyroscopeBiasEstimator();
+    virtual ~GyroscopeBiasEstimator();
+
+    // Updates the estimator with a gyroscope event.
+    //
+    // @param gyroscope_sample the angular speed around the x, y, z axis in
+    //     radians/sec.
+    // @param timestamp_ns the nanosecond at which the event occurred. Only
+    //     guaranteed to be comparable with timestamps from other PocessGyroscope
+    //     invocations.
+    virtual void ProcessGyroscope(const Vector3& gyroscope_sample, uint64_t timestamp_ns);
+
+    // Processes accelerometer samples to estimate if device is
+    // stable or not.
+    //
+    // First we filter the accelerometer. This is done with 3 filters.
+    //  - A IIR low-pass filter
+    //  - A median filter
+    //  - A mean filter.
+    // Then a rotation is computed between consecutive filtered accelerometer
+    // samples.
+    // Finally this is converted to a velocity to emulate a gyroscope.
+    //
+    // @param accelerometer_sample the acceleration (including gravity) on the x,
+    //     y, z axis in meters/s^2.
+    // @param timestamp_ns the nanosecond at which the event occurred. Only
+    //     guaranteed to be comparable with timestamps from other
+    //     ProcessAccelerometer invocations.
+    virtual void ProcessAccelerometer(const Vector3& accelerometer_sample, uint64_t timestamp_ns);
+
+    // Returns the estimated gyroscope bias.
+    //
+    // @return Estimated gyroscope bias. A vector with zeros is returned if no
+    //     estimate has been computed.
+    virtual Vector3 GetGyroscopeBias() const;
+
+    // Resets the estimator state.
+    void Reset();
+
+    // Returns true if the current estimate returned by GetGyroscopeBias is
+    // correct. The device (measured using the sensors) has to be static for this
+    // function to return true.
+    virtual bool IsCurrentEstimateValid() const;
+
+private:
+    // A helper class to keep track of whether some signal can be considered
+    // static over specified number of frames.
+    class IsStaticCounter;
+
+    // Updates gyroscope bias estimation.
+    //
+    // @return false if the current sample is too large.
+    bool UpdateGyroscopeBias(const Vector3& gyroscope_sample, uint64_t timestamp_ns);
+
+    // Returns device angular velocity (rad/s) from the latest accelerometer data.
+    //
+    // @param timestep in seconds between the last two samples.
+    // @return rotation velocity from latest accelerometer. This can be
+    // interpreted as an gyroscope.
+    Vector3 ComputeAngularVelocityFromLatestAccelerometer(double timestep) const;
+
+    LowpassFilter accelerometer_lowpass_filter_;
+    LowpassFilter simulated_gyroscope_from_accelerometer_lowpass_filter_;
+    LowpassFilter gyroscope_lowpass_filter_;
+    LowpassFilter gyroscope_bias_lowpass_filter_;
+
+    std::unique_ptr<IsStaticCounter> accelerometer_static_counter_;
+    std::unique_ptr<IsStaticCounter> gyroscope_static_counter_;
+
+    // Sum of the weight of sample used for gyroscope filtering.
+    float current_accumulated_weights_gyroscope_bias_;
+
+    // Set of filters for accelerometer data to estimate a rotation
+    // based only on accelerometer.
+    MeanFilter mean_filter_;
+    MedianFilter median_filter_;
+
+    // Last computed filter accelerometer value used for finite differences.
+    Vector3 last_mean_filtered_accelerometer_value_;
+};
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_SENSORS_GYROSCOPE_BIAS_ESTIMATOR_H_

+ 38 - 0
tracking/sensors/gyroscope_data.h

@@ -0,0 +1,38 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_SENSORS_GYROSCOPE_DATA_H_
+#define CARDBOARD_SDK_SENSORS_GYROSCOPE_DATA_H_
+
+#include "../util/vector.h"
+
+namespace cardboard {
+
+struct GyroscopeData {
+    // System wall time.
+    uint64_t system_timestamp;
+
+    // Sensor clock time in nanoseconds.
+    uint64_t sensor_timestamp_ns;
+
+    // Rate of rotation around the x,y,z axes in rad/s. This follows android
+    // specification
+    // (https://developer.android.com/guide/topics/sensors/sensors_overview.html#sensors-coords).
+    Vector3 data;
+};
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_SENSORS_GYROSCOPE_DATA_H_

+ 84 - 0
tracking/sensors/lowpass_filter.cc

@@ -0,0 +1,84 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 "lowpass_filter.h"
+
+#include <cmath>
+
+namespace {
+
+const double kSecondsFromNanoseconds = 1.0e-9;
+
+// Minimum time step between sensor updates. This corresponds to 1000 Hz.
+const double kMinTimestepS = 0.001f;
+
+// Maximum time step between sensor updates. This corresponds to 1 Hz.
+const double kMaxTimestepS = 1.00f;
+
+} // namespace
+
+namespace cardboard {
+
+LowpassFilter::LowpassFilter(double cutoff_freq_hz)
+    : cutoff_time_constant_(1 / (2 * (double)M_PI * cutoff_freq_hz))
+    , initialized_(false)
+{
+    Reset();
+}
+
+void LowpassFilter::AddSample(const Vector3& sample, uint64_t timestamp_ns)
+{
+    AddWeightedSample(sample, timestamp_ns, 1.0);
+}
+
+void LowpassFilter::AddWeightedSample(const Vector3& sample, uint64_t timestamp_ns, double weight)
+{
+    if (!initialized_) {
+        // Initialize filter state
+        filtered_data_ = { sample[0], sample[1], sample[2] };
+        timestamp_most_recent_update_ns_ = timestamp_ns;
+        initialized_ = true;
+        return;
+    }
+
+    if (timestamp_ns < timestamp_most_recent_update_ns_) {
+        timestamp_most_recent_update_ns_ = timestamp_ns;
+        return;
+    }
+
+    const double delta_s = static_cast<double>(timestamp_ns - timestamp_most_recent_update_ns_)
+        * kSecondsFromNanoseconds;
+    if (delta_s <= kMinTimestepS || delta_s > kMaxTimestepS) {
+        timestamp_most_recent_update_ns_ = timestamp_ns;
+        return;
+    }
+
+    const double weighted_delta_secs = weight * delta_s;
+
+    const double alpha = weighted_delta_secs / (cutoff_time_constant_ + weighted_delta_secs);
+
+    for (int i = 0; i < 3; ++i) {
+        filtered_data_[i] = (1 - alpha) * filtered_data_[i] + alpha * sample[i];
+    }
+    timestamp_most_recent_update_ns_ = timestamp_ns;
+}
+
+void LowpassFilter::Reset()
+{
+    initialized_ = false;
+    filtered_data_ = { 0, 0, 0 };
+}
+
+} // namespace cardboard

+ 75 - 0
tracking/sensors/lowpass_filter.h

@@ -0,0 +1,75 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_SENSORS_LOWPASS_FILTER_H_
+#define CARDBOARD_SDK_SENSORS_LOWPASS_FILTER_H_
+
+#include <array>
+#include <memory>
+
+#include "../util/vector.h"
+
+namespace cardboard {
+
+// Implements an IIR, first order, low pass filter over vectors of the given
+// dimension = 3.
+// See http://en.wikipedia.org/wiki/Low-pass_filter
+class LowpassFilter {
+public:
+    // Initializes a filter with the given cutoff frequency in Hz.
+    explicit LowpassFilter(double cutoff_freq_hz);
+
+    // Updates the filter with the given sample. Note that samples with
+    // non-monotonic timestamps and successive samples with a time steps below 1
+    // ms or above 1 s are ignored.
+    //
+    // @param sample current sample data.
+    // @param timestamp_ns timestamp associated to this sample in nanoseconds.
+    void AddSample(const Vector3& sample, uint64_t timestamp_ns);
+
+    // Updates the filter with the given weighted sample.
+    //
+    // @param sample current sample data.
+    // @param timestamp_ns timestamp associated to this sample in nanoseconds.
+    // @param weight typically a [0, 1] weight factor used when applying a new
+    //     sample. A weight of 1 corresponds to calling AddSample. A weight of 0
+    //     makes the update no-op. The first initial sample is not affected by
+    //     this.
+    void AddWeightedSample(const Vector3& sample, uint64_t timestamp_ns, double weight);
+
+    // Returns the filtered value. A vector with zeros is returned if no samples
+    // have been added.
+    Vector3 GetFilteredData() const { return filtered_data_; }
+
+    // Returns the most recent update timestamp in ns.
+    uint64_t GetMostRecentTimestampNs() const { return timestamp_most_recent_update_ns_; }
+
+    // Returns true when the filter is initialized.
+    bool IsInitialized() const { return initialized_; }
+
+    // Resets filter state.
+    void Reset();
+
+private:
+    const double cutoff_time_constant_;
+    uint64_t timestamp_most_recent_update_ns_;
+    bool initialized_;
+
+    Vector3 filtered_data_;
+};
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_SENSORS_LOWPASS_FILTER_H_

+ 46 - 0
tracking/sensors/mean_filter.cc

@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 "mean_filter.h"
+
+namespace cardboard {
+
+MeanFilter::MeanFilter(size_t filter_size)
+    : filter_size_(filter_size)
+{
+}
+
+void MeanFilter::AddSample(const Vector3& sample)
+{
+    buffer_.push_back(sample);
+    if (buffer_.size() > filter_size_) {
+        buffer_.pop_front();
+    }
+}
+
+bool MeanFilter::IsValid() const { return buffer_.size() == filter_size_; }
+
+Vector3 MeanFilter::GetFilteredData() const
+{
+    // Compute mean of the samples stored in buffer_.
+    Vector3 mean = Vector3::Zero();
+    for (auto sample : buffer_) {
+        mean += sample;
+    }
+
+    return mean / static_cast<double>(filter_size_);
+}
+
+} // namespace cardboard

+ 48 - 0
tracking/sensors/mean_filter.h

@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_SENSORS_MEAN_FILTER_H_
+#define CARDBOARD_SDK_SENSORS_MEAN_FILTER_H_
+
+#include <deque>
+
+#include "../util/vector.h"
+
+namespace cardboard {
+
+// Fixed window FIFO mean filter for vectors of the given dimension.
+class MeanFilter {
+public:
+    // Create a mean filter of size filter_size.
+    // @param filter_size size of the internal filter.
+    explicit MeanFilter(size_t filter_size);
+
+    // Add sample to buffer_ if buffer_ is full it drop the oldest sample.
+    void AddSample(const Vector3& sample);
+
+    // Returns true if buffer has filter_size_ sample, false otherwise.
+    bool IsValid() const;
+
+    // Returns the mean of values stored in the internal buffer.
+    Vector3 GetFilteredData() const;
+
+private:
+    const size_t filter_size_;
+    std::deque<Vector3> buffer_;
+};
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_SENSORS_MEAN_FILTER_H_

+ 69 - 0
tracking/sensors/median_filter.cc

@@ -0,0 +1,69 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 "median_filter.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "../util/vector.h"
+#include "../util/vectorutils.h"
+
+namespace cardboard {
+
+MedianFilter::MedianFilter(size_t filter_size)
+    : filter_size_(filter_size)
+{
+}
+
+void MedianFilter::AddSample(const Vector3& sample)
+{
+    buffer_.push_back(sample);
+    norms_.push_back(Length(sample));
+    if (buffer_.size() > filter_size_) {
+        buffer_.pop_front();
+        norms_.pop_front();
+    }
+}
+
+bool MedianFilter::IsValid() const { return buffer_.size() == filter_size_; }
+
+Vector3 MedianFilter::GetFilteredData() const
+{
+    std::vector<float> norms(norms_.begin(), norms_.end());
+
+    // Get median of value of the norms.
+    std::nth_element(norms.begin(), norms.begin() + filter_size_ / 2, norms.end());
+    const float median_norm = norms[filter_size_ / 2];
+
+    // Get median value based on their norm.
+    auto median_it = buffer_.begin();
+    for (const auto norm : norms_) {
+        if (norm == median_norm) {
+            break;
+        }
+        ++median_it;
+    }
+
+    return *median_it;
+}
+
+void MedianFilter::Reset()
+{
+    buffer_.clear();
+    norms_.clear();
+}
+
+} // namespace cardboard

+ 53 - 0
tracking/sensors/median_filter.h

@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_SENSORS_MEDIAN_FILTER_H_
+#define CARDBOARD_SDK_SENSORS_MEDIAN_FILTER_H_
+
+#include <deque>
+
+#include "../util/vector.h"
+
+namespace cardboard {
+
+// Fixed window FIFO median filter for vectors of the given dimension = 3.
+class MedianFilter {
+public:
+    // Creates a median filter of size filter_size.
+    // @param filter_size size of the internal filter.
+    explicit MedianFilter(size_t filter_size);
+
+    // Adds sample to buffer_ if buffer_ is full it drops the oldest sample.
+    void AddSample(const Vector3& sample);
+
+    // Returns true if buffer has filter_size_ sample, false otherwise.
+    bool IsValid() const;
+
+    // Returns the median of values store in the internal buffer.
+    Vector3 GetFilteredData() const;
+
+    // Resets the filter, removing all samples that have been added.
+    void Reset();
+
+private:
+    const size_t filter_size_;
+    std::deque<Vector3> buffer_;
+    // Contains norms of the elements stored in buffer_.
+    std::deque<float> norms_;
+};
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_SENSORS_MEDIAN_FILTER_H_

+ 71 - 0
tracking/sensors/pose_prediction.cc

@@ -0,0 +1,71 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 "pose_prediction.h"
+
+#include <chrono> // NOLINT
+
+#include "../util/logging.h"
+#include "../util/vectorutils.h"
+
+namespace cardboard {
+
+namespace {
+    const double kEpsilon = 1.0e-15;
+} // namespace
+
+namespace pose_prediction {
+
+    Rotation GetRotationFromGyroscope(const Vector3& gyroscope_value, double timestep_s)
+    {
+        const double velocity = Length(gyroscope_value);
+
+        // When there is no rotation data return an identity rotation.
+        if (velocity < kEpsilon) {
+            CARDBOARD_LOGI("PosePrediction::GetRotationFromGyroscope: Velocity really small, "
+                           "returning identity rotation.");
+            return Rotation::Identity();
+        }
+        // Since the gyroscope_value is a start from sensor transformation we need to
+        // invert it to have a sensor from start transformation, hence the minus sign.
+        // For more info:
+        // http://developer.android.com/guide/topics/sensors/sensors_motion.html#sensors-motion-gyro
+        return Rotation::FromAxisAndAngle(gyroscope_value / velocity, -timestep_s * velocity);
+    }
+
+    Rotation PredictPose(int64_t requested_pose_timestamp, const PoseState& current_state)
+    {
+        // Subtracting unsigned numbers is bad when the result is negative.
+        const int64_t diff = requested_pose_timestamp - current_state.timestamp;
+        const double timestep_s = diff * 1.0e-9;
+
+        const Rotation update = GetRotationFromGyroscope(
+            current_state.sensor_from_start_rotation_velocity, timestep_s);
+        return update * current_state.sensor_from_start_rotation;
+    }
+
+    Rotation PredictPoseInv(int64_t requested_pose_timestamp, const PoseState& current_state)
+    {
+        // Subtracting unsigned numbers is bad when the result is negative.
+        const int64_t diff = requested_pose_timestamp - current_state.timestamp;
+        const double timestep_s = diff * 1.0e-9;
+
+        const Rotation update = GetRotationFromGyroscope(
+            current_state.sensor_from_start_rotation_velocity, timestep_s);
+        return current_state.sensor_from_start_rotation * (-update);
+    }
+
+} // namespace pose_prediction
+} // namespace cardboard

+ 55 - 0
tracking/sensors/pose_prediction.h

@@ -0,0 +1,55 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_SENSORS_POSE_PREDICTION_H_
+#define CARDBOARD_SDK_SENSORS_POSE_PREDICTION_H_
+
+#include <cstdint>
+
+#include "pose_state.h"
+#include "../util/rotation.h"
+
+namespace cardboard {
+namespace pose_prediction {
+
+    // Returns a rotation matrix based on the integration of the gyroscope_value
+    // over the timestep_s in seconds.
+    // TODO(pfg): Document the space better here.
+    //
+    // @param gyroscope_value gyroscope sensor values.
+    // @param timestep_s integration period in seconds.
+    // @return Integration of the gyroscope value the rotation is from Start to
+    //         Sensor Space.
+    Rotation GetRotationFromGyroscope(const Vector3& gyroscope_value, double timestep_s);
+
+    // Gets a predicted pose for a given time in the future (e.g. rendering time)
+    // based on a linear prediction model. This uses the system current state
+    // (position, velocity, etc) from the past to extrapolate a position in the
+    // future.
+    //
+    // @param requested_pose_timestamp time at which you want the pose.
+    // @param current_state current state that stores the pose and linear model at a
+    //        given time prior to requested_pose_timestamp_ns.
+    // @return pose from Start to Sensor Space.
+    Rotation PredictPose(int64_t requested_pose_timestamp, const PoseState& current_state);
+
+    // Equivalent to PredictPose, but for use with poses relative to Start Space
+    // rather than sensor space.
+    Rotation PredictPoseInv(int64_t requested_pose_timestamp, const PoseState& current_state);
+
+} // namespace pose_prediction
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_SENSORS_POSE_PREDICTION_H_

+ 56 - 0
tracking/sensors/pose_state.h

@@ -0,0 +1,56 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_SENSORS_POSE_STATE_H_
+#define CARDBOARD_SDK_SENSORS_POSE_STATE_H_
+
+#include "../util/rotation.h"
+#include "../util/vector.h"
+
+namespace cardboard {
+
+enum {
+    kPoseStateFlagInvalid = 1U << 0,
+    kPoseStateFlagInitializing = 1U << 1,
+    kPoseStateFlagHas6DoF = 1U << 2,
+};
+
+// Stores a head pose pose plus derivatives. This can be used for prediction.
+struct PoseState {
+    // System wall time.
+    int64_t timestamp;
+
+    // Rotation from Sensor Space to Start Space.
+    Rotation sensor_from_start_rotation;
+
+    // First derivative of the rotation.
+    Vector3 sensor_from_start_rotation_velocity;
+
+    // Current gyroscope bias in rad/s.
+    Vector3 bias;
+
+    // The position of the headset.
+    Vector3 position = Vector3(0, 0, 0);
+
+    // In the same coordinate frame as the position.
+    Vector3 velocity = Vector3(0, 0, 0);
+
+    // Flags indicating the status of the pose.
+    uint64_t flags = 0U;
+};
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_SENSORS_POSE_STATE_H_

+ 333 - 0
tracking/sensors/sensor_fusion_ekf.cc

@@ -0,0 +1,333 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 "sensor_fusion_ekf.h"
+
+#include <algorithm>
+#include <cmath>
+
+#include "accelerometer_data.h"
+#include "gyroscope_data.h"
+#include "pose_prediction.h"
+#include "../util/matrixutils.h"
+
+namespace cardboard {
+
+namespace {
+
+    const double kFiniteDifferencingEpsilon = 1.0e-7;
+    const double kEpsilon = 1.0e-15;
+    // Default gyroscope frequency. This corresponds to 100 Hz.
+    const double kDefaultGyroscopeTimestep_s = 0.01f;
+    // Maximum time between gyroscope before we start limiting the integration.
+    const double kMaximumGyroscopeSampleDelay_s = 0.04f;
+    // Compute a first-order exponential moving average of changes in accel norm per
+    // frame.
+    const double kSmoothingFactor = 0.5;
+    // Minimum and maximum values used for accelerometer noise covariance matrix.
+    // The smaller the sigma value, the more weight is given to the accelerometer
+    // signal.
+    const double kMinAccelNoiseSigma = 0.75;
+    const double kMaxAccelNoiseSigma = 7.0;
+    // Initial value for the diagonal elements of the different covariance matrices.
+    const double kInitialStateCovarianceValue = 25.0;
+    const double kInitialProcessCovarianceValue = 1.0;
+    // Maximum accelerometer norm change allowed before capping it covariance to a
+    // large value.
+    const double kMaxAccelNormChange = 0.15;
+    // Timestep IIR filtering coefficient.
+    const double kTimestepFilterCoeff = 0.95;
+    // Minimum number of sample for timestep filtering.
+    const int kTimestepFilterMinSamples = 10;
+
+    // Z direction in start space.
+    const Vector3 kCanonicalZDirection(0.0, 0.0, 1.0);
+
+    // Computes an axis-angle rotation from the input vector.
+    // angle = norm(a)
+    // axis = a.normalized()
+    // If norm(a) == 0, it returns an identity rotation.
+    static inline Rotation RotationFromVector(const Vector3& a)
+    {
+        const double norm_a = Length(a);
+        if (norm_a < kEpsilon) {
+            return Rotation::Identity();
+        }
+        return Rotation::FromAxisAndAngle(a / norm_a, norm_a);
+    }
+
+} // namespace
+
+SensorFusionEkf::SensorFusionEkf()
+    : execute_reset_with_next_accelerometer_sample_(false)
+    , bias_estimation_enabled_(true)
+    , gyroscope_bias_estimate_({ 0, 0, 0 })
+{
+    ResetState();
+}
+
+void SensorFusionEkf::Reset() { execute_reset_with_next_accelerometer_sample_ = true; }
+
+void SensorFusionEkf::ResetState()
+{
+    current_state_.sensor_from_start_rotation = Rotation::Identity();
+    current_state_.sensor_from_start_rotation_velocity = Vector3::Zero();
+
+    current_gyroscope_sensor_timestamp_ns_ = 0;
+    current_accelerometer_sensor_timestamp_ns_ = 0;
+
+    state_covariance_ = Matrix3x3::Identity() * kInitialStateCovarianceValue;
+    process_covariance_ = Matrix3x3::Identity() * kInitialProcessCovarianceValue;
+    accelerometer_measurement_covariance_
+        = Matrix3x3::Identity() * kMinAccelNoiseSigma * kMinAccelNoiseSigma;
+    innovation_covariance_ = Matrix3x3::Identity();
+
+    accelerometer_measurement_jacobian_ = Matrix3x3::Zero();
+    kalman_gain_ = Matrix3x3::Zero();
+    innovation_ = Vector3::Zero();
+    accelerometer_measurement_ = Vector3::Zero();
+    prediction_ = Vector3::Zero();
+    control_input_ = Vector3::Zero();
+    state_update_ = Vector3::Zero();
+
+    moving_average_accelerometer_norm_change_ = 0.0;
+
+    is_timestep_filter_initialized_ = false;
+    is_gyroscope_filter_valid_ = false;
+    is_aligned_with_gravity_ = false;
+
+    // Reset biases.
+    gyroscope_bias_estimator_.Reset();
+    gyroscope_bias_estimate_ = { 0, 0, 0 };
+}
+
+// Here I am doing something wrong relative to time stamps. The state timestamps
+// always correspond to the gyrostamps because it would require additional
+// extrapolation if I wanted to do otherwise.
+PoseState SensorFusionEkf::GetLatestPoseState() const { return current_state_; }
+
+void SensorFusionEkf::ProcessGyroscopeSample(const GyroscopeData& sample)
+{
+    // Don't accept gyroscope sample when waiting for a reset.
+    if (execute_reset_with_next_accelerometer_sample_) {
+        return;
+    }
+
+    // Discard outdated samples.
+    if (current_gyroscope_sensor_timestamp_ns_ >= sample.sensor_timestamp_ns) {
+        current_gyroscope_sensor_timestamp_ns_ = sample.sensor_timestamp_ns;
+        return;
+    }
+
+    // Checks that we received at least one gyroscope sample in the past.
+    if (current_gyroscope_sensor_timestamp_ns_ != 0) {
+        double current_timestep_s = std::chrono::duration_cast<std::chrono::duration<double>>(
+            std::chrono::nanoseconds(
+                sample.sensor_timestamp_ns - current_gyroscope_sensor_timestamp_ns_))
+                                        .count();
+        if (current_timestep_s > kMaximumGyroscopeSampleDelay_s) {
+            if (is_gyroscope_filter_valid_) {
+                // Replaces the delta timestamp by the filtered estimates of the delta time.
+                current_timestep_s = filtered_gyroscope_timestep_s_;
+            } else {
+                current_timestep_s = kDefaultGyroscopeTimestep_s;
+            }
+        } else {
+            FilterGyroscopeTimestep(current_timestep_s);
+        }
+
+        if (bias_estimation_enabled_) {
+            gyroscope_bias_estimator_.ProcessGyroscope(sample.data, sample.sensor_timestamp_ns);
+
+            if (gyroscope_bias_estimator_.IsCurrentEstimateValid()) {
+                // As soon as the device is considered to be static, the bias estimator
+                // should have a precise estimate of the gyroscope bias.
+                gyroscope_bias_estimate_ = gyroscope_bias_estimator_.GetGyroscopeBias();
+            }
+        }
+
+        // Only integrate after receiving an accelerometer sample.
+        if (is_aligned_with_gravity_) {
+            const Rotation rotation_from_gyroscope = pose_prediction::GetRotationFromGyroscope(
+                { sample.data[0] - gyroscope_bias_estimate_[0],
+                    sample.data[1] - gyroscope_bias_estimate_[1],
+                    sample.data[2] - gyroscope_bias_estimate_[2] },
+                current_timestep_s);
+            current_state_.sensor_from_start_rotation
+                = rotation_from_gyroscope * current_state_.sensor_from_start_rotation;
+            UpdateStateCovariance(RotationMatrixNH(rotation_from_gyroscope));
+            state_covariance_ = state_covariance_
+                + ((current_timestep_s * current_timestep_s) * process_covariance_);
+        }
+    }
+
+    // Saves gyroscope event for future prediction.
+    current_state_.timestamp = sample.system_timestamp;
+    current_gyroscope_sensor_timestamp_ns_ = sample.sensor_timestamp_ns;
+    current_state_.sensor_from_start_rotation_velocity.Set(
+        sample.data[0] - gyroscope_bias_estimate_[0], sample.data[1] - gyroscope_bias_estimate_[1],
+        sample.data[2] - gyroscope_bias_estimate_[2]);
+}
+
+Vector3 SensorFusionEkf::ComputeInnovation(const Rotation& pose)
+{
+    const Vector3 predicted_down_direction = pose * kCanonicalZDirection;
+
+    const Rotation rotation
+        = Rotation::RotateInto(predicted_down_direction, accelerometer_measurement_);
+    Vector3 axis;
+    double angle;
+    rotation.GetAxisAndAngle(&axis, &angle);
+    return axis * angle;
+}
+
+void SensorFusionEkf::ComputeMeasurementJacobian()
+{
+    for (int dof = 0; dof < 3; dof++) {
+        Vector3 delta = Vector3::Zero();
+        delta[dof] = kFiniteDifferencingEpsilon;
+
+        const Rotation epsilon_rotation = RotationFromVector(delta);
+        const Vector3 delta_rotation
+            = ComputeInnovation(epsilon_rotation * current_state_.sensor_from_start_rotation);
+
+        const Vector3 col = (innovation_ - delta_rotation) / kFiniteDifferencingEpsilon;
+        accelerometer_measurement_jacobian_(0, dof) = col[0];
+        accelerometer_measurement_jacobian_(1, dof) = col[1];
+        accelerometer_measurement_jacobian_(2, dof) = col[2];
+    }
+}
+
+void SensorFusionEkf::ProcessAccelerometerSample(const AccelerometerData& sample)
+{
+    // Discard outdated samples.
+    if (current_accelerometer_sensor_timestamp_ns_ >= sample.sensor_timestamp_ns) {
+        current_accelerometer_sensor_timestamp_ns_ = sample.sensor_timestamp_ns;
+        return;
+    }
+
+    // Call reset state if required.
+    if (execute_reset_with_next_accelerometer_sample_.exchange(false)) {
+        ResetState();
+    }
+
+    accelerometer_measurement_.Set(sample.data[0], sample.data[1], sample.data[2]);
+    current_accelerometer_sensor_timestamp_ns_ = sample.sensor_timestamp_ns;
+
+    if (bias_estimation_enabled_) {
+        gyroscope_bias_estimator_.ProcessAccelerometer(sample.data, sample.sensor_timestamp_ns);
+    }
+
+    if (!is_aligned_with_gravity_) {
+        // This is the first accelerometer measurement so it initializes the
+        // orientation estimate.
+        current_state_.sensor_from_start_rotation
+            = Rotation::RotateInto(kCanonicalZDirection, accelerometer_measurement_);
+        is_aligned_with_gravity_ = true;
+
+        previous_accelerometer_norm_ = Length(accelerometer_measurement_);
+        return;
+    }
+
+    UpdateMeasurementCovariance();
+
+    innovation_ = ComputeInnovation(current_state_.sensor_from_start_rotation);
+    ComputeMeasurementJacobian();
+
+    // S = H * P * H' + R
+    innovation_covariance_ = accelerometer_measurement_jacobian_ * state_covariance_
+            * Transpose(accelerometer_measurement_jacobian_)
+        + accelerometer_measurement_covariance_;
+
+    // K = P * H' * S^-1
+    kalman_gain_ = state_covariance_ * Transpose(accelerometer_measurement_jacobian_)
+        * Inverse(innovation_covariance_);
+
+    // x_update = K*nu
+    state_update_ = kalman_gain_ * innovation_;
+
+    // P = (I - K * H) * P;
+    state_covariance_ = (Matrix3x3::Identity() - kalman_gain_ * accelerometer_measurement_jacobian_)
+        * state_covariance_;
+
+    // Updates pose and associate covariance matrix.
+    const Rotation rotation_from_state_update = RotationFromVector(state_update_);
+
+    current_state_.sensor_from_start_rotation
+        = rotation_from_state_update * current_state_.sensor_from_start_rotation;
+    UpdateStateCovariance(RotationMatrixNH(rotation_from_state_update));
+}
+
+void SensorFusionEkf::UpdateStateCovariance(const Matrix3x3& motion_update)
+{
+    state_covariance_ = motion_update * state_covariance_ * Transpose(motion_update);
+}
+
+void SensorFusionEkf::FilterGyroscopeTimestep(double gyroscope_timestep_s)
+{
+    if (!is_timestep_filter_initialized_) {
+        // Initializes the filter.
+        filtered_gyroscope_timestep_s_ = gyroscope_timestep_s;
+        num_gyroscope_timestep_samples_ = 1;
+        is_timestep_filter_initialized_ = true;
+        return;
+    }
+
+    // Computes the IIR filter response.
+    filtered_gyroscope_timestep_s_ = kTimestepFilterCoeff * filtered_gyroscope_timestep_s_
+        + (1 - kTimestepFilterCoeff) * gyroscope_timestep_s;
+    ++num_gyroscope_timestep_samples_;
+
+    if (num_gyroscope_timestep_samples_ > kTimestepFilterMinSamples) {
+        is_gyroscope_filter_valid_ = true;
+    }
+}
+
+void SensorFusionEkf::UpdateMeasurementCovariance()
+{
+    const double current_accelerometer_norm = Length(accelerometer_measurement_);
+    // Norm change between current and previous accel readings.
+    const double current_accelerometer_norm_change
+        = std::abs(current_accelerometer_norm - previous_accelerometer_norm_);
+    previous_accelerometer_norm_ = current_accelerometer_norm;
+
+    moving_average_accelerometer_norm_change_ = kSmoothingFactor * current_accelerometer_norm_change
+        + (1 - kSmoothingFactor) * moving_average_accelerometer_norm_change_;
+
+    // If we hit the accel norm change threshold, we use the maximum noise sigma
+    // for the accel covariance. For anything below that, we use a linear
+    // combination between min and max sigma values.
+    const double norm_change_ratio
+        = moving_average_accelerometer_norm_change_ / kMaxAccelNormChange;
+    const double accelerometer_noise_sigma = std::min(kMaxAccelNoiseSigma,
+        kMinAccelNoiseSigma + norm_change_ratio * (kMaxAccelNoiseSigma - kMinAccelNoiseSigma));
+
+    // Updates the accel covariance matrix with the new sigma value.
+    accelerometer_measurement_covariance_
+        = Matrix3x3::Identity() * accelerometer_noise_sigma * accelerometer_noise_sigma;
+}
+
+bool SensorFusionEkf::IsBiasEstimationEnabled() const { return bias_estimation_enabled_; }
+
+void SensorFusionEkf::SetBiasEstimationEnabled(bool enable)
+{
+    if (bias_estimation_enabled_ != enable) {
+        bias_estimation_enabled_ = enable;
+        gyroscope_bias_estimate_ = { 0, 0, 0 };
+        gyroscope_bias_estimator_.Reset();
+    }
+}
+
+} // namespace cardboard

+ 187 - 0
tracking/sensors/sensor_fusion_ekf.h

@@ -0,0 +1,187 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_SENSORS_SENSOR_FUSION_EKF_H_
+#define CARDBOARD_SDK_SENSORS_SENSOR_FUSION_EKF_H_
+
+#include <array>
+#include <atomic>
+#include <cstdint>
+
+#include "accelerometer_data.h"
+#include "gyroscope_bias_estimator.h"
+#include "gyroscope_data.h"
+#include "pose_state.h"
+#include "../util/matrix_3x3.h"
+#include "../util/rotation.h"
+#include "../util/vector.h"
+
+namespace cardboard {
+
+// Sensor fusion class that implements an Extended Kalman Filter (EKF) to
+// estimate a 3D rotation from a gyroscope and an accelerometer.
+// This system only has one state, the pose. It does not estimate any velocity
+// or acceleration.
+//
+// To learn more about Kalman filtering one can read this article which is a
+// good introduction: https://en.wikipedia.org/wiki/Kalman_filter
+class SensorFusionEkf {
+public:
+    SensorFusionEkf();
+
+    // Resets the state of the sensor fusion. It sets the velocity for
+    // prediction to zero. The reset will happen with the next
+    // accelerometer sample. Gyroscope sample will be discarded until a new
+    // accelerometer sample arrives.
+    void Reset();
+
+    // Gets the PoseState representing the latest pose and  derivatives at a
+    // particular timestamp as estimated by SensorFusion.
+    PoseState GetLatestPoseState() const;
+
+    // Processes one gyroscope sample event. This updates the pose of the system
+    // and the prediction model. The gyroscope data is assumed to be in axis angle
+    // form. Angle = ||v|| and Axis = v / ||v||, with v = [v_x, v_y, v_z]^T.
+    //
+    // @param sample gyroscope sample data.
+    void ProcessGyroscopeSample(const GyroscopeData& sample);
+
+    // Processes one accelerometer sample event. This updates the pose of the
+    // system. If the Accelerometer norm changes too much between sample it is not
+    // trusted as much.
+    //
+    // @param sample accelerometer sample data.
+    void ProcessAccelerometerSample(const AccelerometerData& sample);
+
+    // Enables or disables the drift correction by estimating the gyroscope bias.
+    //
+    // @param enable Enable drift correction.
+    void SetBiasEstimationEnabled(bool enable);
+
+    // Returns a boolean that indicates if bias estimation is enabled or disabled.
+    //
+    // @return true if bias estimation is enabled, false otherwise.
+    bool IsBiasEstimationEnabled() const;
+
+    // Returns the current gyroscope bias estimate from GyroscopeBiasEstimator.
+    Vector3 GetGyroscopeBias() const
+    {
+        return { gyroscope_bias_estimate_[0], gyroscope_bias_estimate_[1],
+            gyroscope_bias_estimate_[2] };
+    }
+
+    // Returns true after receiving the first accelerometer measurement.
+    bool IsFullyInitialized() const { return is_aligned_with_gravity_; }
+
+private:
+    // Estimates the average timestep between gyroscope event.
+    void FilterGyroscopeTimestep(double gyroscope_timestep);
+
+    // Updates the state covariance with an incremental motion. It changes the
+    // space of the quadric.
+    void UpdateStateCovariance(const Matrix3x3& motion_update);
+
+    // Computes the innovation vector of the Kalman based on the input pose.
+    // It uses the latest measurement vector (i.e. accelerometer data), which must
+    // be set prior to calling this function.
+    Vector3 ComputeInnovation(const Rotation& pose);
+
+    // This computes the measurement_jacobian_ via numerical differentiation based
+    // on the current value of sensor_from_start_rotation_.
+    void ComputeMeasurementJacobian();
+
+    // Updates the accelerometer covariance matrix.
+    //
+    // This looks at the norm of recent accelerometer readings. If it has changed
+    // significantly, it means the phone receives additional acceleration than
+    // just gravity, and so the down vector information gravity signal is noisier.
+    void UpdateMeasurementCovariance();
+
+    // Reset all internal states. This is not thread safe. Lock should be acquired
+    // outside of it. This function is called in ProcessAccelerometerSample.
+    void ResetState();
+
+    // Current transformation from Sensor Space to Start Space.
+    // x_sensor = sensor_from_start_rotation_ * x_start;
+    PoseState current_state_;
+
+    // Filtering of the gyroscope timestep started?
+    bool is_timestep_filter_initialized_;
+    // Filtered gyroscope timestep valid?
+    bool is_gyroscope_filter_valid_;
+    // Sensor fusion currently aligned with gravity? After initialization
+    // it will requires a couple of accelerometer data for the system to get
+    // aligned.
+    std::atomic<bool> is_aligned_with_gravity_;
+
+    // Covariance of Kalman filter state (P in common formulation).
+    Matrix3x3 state_covariance_;
+    // Covariance of the process noise (Q in common formulation).
+    Matrix3x3 process_covariance_;
+    // Covariance of the accelerometer measurement (R in common formulation).
+    Matrix3x3 accelerometer_measurement_covariance_;
+    // Covariance of innovation (S in common formulation).
+    Matrix3x3 innovation_covariance_;
+    // Jacobian of the measurements (H in common formulation).
+    Matrix3x3 accelerometer_measurement_jacobian_;
+    // Gain of the Kalman filter (K in common formulation).
+    Matrix3x3 kalman_gain_;
+    // Parameter update a.k.a. innovation vector. (\nu in common formulation).
+    Vector3 innovation_;
+    // Measurement vector (z in common formulation).
+    Vector3 accelerometer_measurement_;
+    // Current prediction vector (g in common formulation).
+    Vector3 prediction_;
+    // Control input, currently this is only the gyroscope data (\mu in common
+    // formulation).
+    Vector3 control_input_;
+    // Update of the state vector. (x in common formulation).
+    Vector3 state_update_;
+
+    // Sensor time of the last gyroscope processed event.
+    uint64_t current_gyroscope_sensor_timestamp_ns_;
+    // Sensor time of the last accelerometer processed event.
+    uint64_t current_accelerometer_sensor_timestamp_ns_;
+
+    // Estimates of the timestep between gyroscope event in seconds.
+    double filtered_gyroscope_timestep_s_;
+    // Number of timestep samples processed so far by the filter.
+    uint32_t num_gyroscope_timestep_samples_;
+    // Norm of the accelerometer for the previous measurement.
+    double previous_accelerometer_norm_;
+    // Moving average of the accelerometer norm changes. It is computed for every
+    // sensor datum.
+    double moving_average_accelerometer_norm_change_;
+
+    // Flag indicating if a state reset should be executed with the next
+    // accelerometer sample.
+    std::atomic<bool> execute_reset_with_next_accelerometer_sample_;
+
+    // Flag indicating if bias estimation is enabled (enabled by default).
+    std::atomic<bool> bias_estimation_enabled_;
+
+    // Bias estimator and static device detector.
+    GyroscopeBiasEstimator gyroscope_bias_estimator_;
+
+    // Current bias estimate_;
+    Vector3 gyroscope_bias_estimate_;
+
+    SensorFusionEkf(const SensorFusionEkf&) = delete;
+    SensorFusionEkf& operator=(const SensorFusionEkf&) = delete;
+};
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_SENSORS_SENSOR_FUSION_EKF_H_

+ 38 - 0
tracking/util/logging.h

@@ -0,0 +1,38 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_UTIL_LOGGING_H_
+#define CARDBOARD_SDK_UTIL_LOGGING_H_
+
+#include <furi.h>
+#include <furi_hal.h>
+
+#if defined(__ANDROID__)
+
+#include <android/log.h>
+
+// Uncomment these to enable debug logging from native code
+
+#define CARDBOARD_LOGI(...) // __android_log_print(ANDROID_LOG_INFO, "CardboardSDK", __VA_ARGS__)
+#define CARDBOARD_LOGE(...) // __android_log_print(ANDROID_LOG_ERROR, "CardboardSDK", __VA_ARGS__)
+
+#else
+
+#define CARDBOARD_LOGI(...) // FURI_LOG_I("CardboardSDK", __VA_ARGS__)
+#define CARDBOARD_LOGE(...) // FURI_LOG_E("CardboardSDK", __VA_ARGS__)
+
+#endif
+
+#endif // CARDBOARD_SDK_UTIL_LOGGING_H_

+ 121 - 0
tracking/util/matrix_3x3.cc

@@ -0,0 +1,121 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 "matrix_3x3.h"
+
+namespace cardboard {
+
+Matrix3x3::Matrix3x3(double m00, double m01, double m02, double m10, double m11, double m12,
+    double m20, double m21, double m22)
+    : elem_ { { { m00, m01, m02 }, { m10, m11, m12 }, { m20, m21, m22 } } }
+{
+}
+
+Matrix3x3::Matrix3x3()
+{
+    for (int row = 0; row < 3; ++row) {
+        for (int col = 0; col < 3; ++col)
+            elem_[row][col] = 0;
+    }
+}
+
+Matrix3x3 Matrix3x3::Zero()
+{
+    Matrix3x3 result;
+    return result;
+}
+
+Matrix3x3 Matrix3x3::Identity()
+{
+    Matrix3x3 result;
+    for (int row = 0; row < 3; ++row) {
+        result.elem_[row][row] = 1;
+    }
+    return result;
+}
+
+void Matrix3x3::MultiplyScalar(double s)
+{
+    for (int row = 0; row < 3; ++row) {
+        for (int col = 0; col < 3; ++col)
+            elem_[row][col] *= s;
+    }
+}
+
+Matrix3x3 Matrix3x3::Negation() const
+{
+    Matrix3x3 result;
+    for (int row = 0; row < 3; ++row) {
+        for (int col = 0; col < 3; ++col)
+            result.elem_[row][col] = -elem_[row][col];
+    }
+    return result;
+}
+
+Matrix3x3 Matrix3x3::Scale(const Matrix3x3& m, double s)
+{
+    Matrix3x3 result;
+    for (int row = 0; row < 3; ++row) {
+        for (int col = 0; col < 3; ++col)
+            result.elem_[row][col] = m.elem_[row][col] * s;
+    }
+    return result;
+}
+
+Matrix3x3 Matrix3x3::Addition(const Matrix3x3& lhs, const Matrix3x3& rhs)
+{
+    Matrix3x3 result;
+    for (int row = 0; row < 3; ++row) {
+        for (int col = 0; col < 3; ++col)
+            result.elem_[row][col] = lhs.elem_[row][col] + rhs.elem_[row][col];
+    }
+    return result;
+}
+
+Matrix3x3 Matrix3x3::Subtraction(const Matrix3x3& lhs, const Matrix3x3& rhs)
+{
+    Matrix3x3 result;
+    for (int row = 0; row < 3; ++row) {
+        for (int col = 0; col < 3; ++col)
+            result.elem_[row][col] = lhs.elem_[row][col] - rhs.elem_[row][col];
+    }
+    return result;
+}
+
+Matrix3x3 Matrix3x3::Product(const Matrix3x3& m0, const Matrix3x3& m1)
+{
+    Matrix3x3 result;
+    for (int row = 0; row < 3; ++row) {
+        for (int col = 0; col < 3; ++col) {
+            result.elem_[row][col] = 0;
+            for (int i = 0; i < 3; ++i)
+                result.elem_[row][col] += m0.elem_[row][i] * m1.elem_[i][col];
+        }
+    }
+    return result;
+}
+
+bool Matrix3x3::AreEqual(const Matrix3x3& m0, const Matrix3x3& m1)
+{
+    for (int row = 0; row < 3; ++row) {
+        for (int col = 0; col < 3; ++col) {
+            if (m0.elem_[row][col] != m1.elem_[row][col])
+                return false;
+        }
+    }
+    return true;
+}
+
+} // namespace cardboard

+ 104 - 0
tracking/util/matrix_3x3.h

@@ -0,0 +1,104 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_UTIL_MATRIX_3X3_H_
+#define CARDBOARD_SDK_UTIL_MATRIX_3X3_H_
+
+#include <array>
+#include <cstring> // For memcpy().
+#include <istream> // NOLINT
+#include <ostream> // NOLINT
+
+namespace cardboard {
+
+// The Matrix3x3 class defines a square 3-dimensional matrix. Elements are
+// stored in row-major order.
+// TODO(b/135461889): Make this class consistent with Matrix4x4.
+class Matrix3x3 {
+public:
+    // The default constructor zero-initializes all elements.
+    Matrix3x3();
+
+    // Dimension-specific constructors that are passed individual element values.
+    Matrix3x3(double m00, double m01, double m02, double m10, double m11, double m12, double m20,
+        double m21, double m22);
+
+    // Constructor that reads elements from a linear array of the correct size.
+    explicit Matrix3x3(const double array[3 * 3]);
+
+    // Returns a Matrix3x3 containing all zeroes.
+    static Matrix3x3 Zero();
+
+    // Returns an identity Matrix3x3.
+    static Matrix3x3 Identity();
+
+    // Mutable element accessors.
+    double& operator()(int row, int col) { return elem_[row][col]; }
+    std::array<double, 3>& operator[](int row) { return elem_[row]; }
+
+    // Read-only element accessors.
+    const double& operator()(int row, int col) const { return elem_[row][col]; }
+    const std::array<double, 3>& operator[](int row) const { return elem_[row]; }
+
+    // Return a pointer to the data for interfacing with libraries.
+    double* Data() { return &elem_[0][0]; }
+    const double* Data() const { return &elem_[0][0]; }
+
+    // Self-modifying multiplication operators.
+    void operator*=(double s) { MultiplyScalar(s); }
+    void operator*=(const Matrix3x3& m) { *this = Product(*this, m); }
+
+    // Unary operators.
+    Matrix3x3 operator-() const { return Negation(); }
+
+    // Binary scale operators.
+    friend Matrix3x3 operator*(const Matrix3x3& m, double s) { return Scale(m, s); }
+    friend Matrix3x3 operator*(double s, const Matrix3x3& m) { return Scale(m, s); }
+
+    // Binary matrix addition.
+    friend Matrix3x3 operator+(const Matrix3x3& lhs, const Matrix3x3& rhs)
+    {
+        return Addition(lhs, rhs);
+    }
+
+    // Binary matrix subtraction.
+    friend Matrix3x3 operator-(const Matrix3x3& lhs, const Matrix3x3& rhs)
+    {
+        return Subtraction(lhs, rhs);
+    }
+
+    // Binary multiplication operator.
+    friend Matrix3x3 operator*(const Matrix3x3& m0, const Matrix3x3& m1) { return Product(m0, m1); }
+
+    // Exact equality and inequality comparisons.
+    friend bool operator==(const Matrix3x3& m0, const Matrix3x3& m1) { return AreEqual(m0, m1); }
+    friend bool operator!=(const Matrix3x3& m0, const Matrix3x3& m1) { return !AreEqual(m0, m1); }
+
+private:
+    // These private functions implement most of the operators.
+    void MultiplyScalar(double s);
+    Matrix3x3 Negation() const;
+    static Matrix3x3 Addition(const Matrix3x3& lhs, const Matrix3x3& rhs);
+    static Matrix3x3 Subtraction(const Matrix3x3& lhs, const Matrix3x3& rhs);
+    static Matrix3x3 Scale(const Matrix3x3& m, double s);
+    static Matrix3x3 Product(const Matrix3x3& m0, const Matrix3x3& m1);
+    static bool AreEqual(const Matrix3x3& m0, const Matrix3x3& m1);
+
+    std::array<std::array<double, 3>, 3> elem_;
+};
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_UTIL_MATRIX_3X3_H_

+ 87 - 0
tracking/util/matrix_4x4.cc

@@ -0,0 +1,87 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 "matrix_4x4.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstring>
+
+namespace cardboard {
+
+Matrix4x4 Matrix4x4::Identity()
+{
+    Matrix4x4 ret;
+    for (int j = 0; j < 4; ++j) {
+        for (int i = 0; i < 4; ++i) {
+            ret.m[j][i] = (i == j) ? 1 : 0;
+        }
+    }
+
+    return ret;
+}
+
+Matrix4x4 Matrix4x4::Zeros()
+{
+    Matrix4x4 ret;
+    for (int j = 0; j < 4; ++j) {
+        for (int i = 0; i < 4; ++i) {
+            ret.m[j][i] = 0;
+        }
+    }
+
+    return ret;
+}
+
+Matrix4x4 Matrix4x4::Translation(float x, float y, float z)
+{
+    Matrix4x4 ret = Matrix4x4::Identity();
+    ret.m[3][0] = x;
+    ret.m[3][1] = y;
+    ret.m[3][2] = z;
+
+    return ret;
+}
+
+Matrix4x4 Matrix4x4::Perspective(const std::array<float, 4>& fov, float zNear, float zFar)
+{
+    Matrix4x4 ret = Matrix4x4::Zeros();
+
+    const float xLeft = -std::tan(fov[0] * M_PI / 180.0f) * zNear;
+    const float xRight = std::tan(fov[1] * M_PI / 180.0f) * zNear;
+    const float yBottom = -std::tan(fov[2] * M_PI / 180.0f) * zNear;
+    const float yTop = std::tan(fov[3] * M_PI / 180.0f) * zNear;
+
+    const float X = (2 * zNear) / (xRight - xLeft);
+    const float Y = (2 * zNear) / (yTop - yBottom);
+    const float A = (xRight + xLeft) / (xRight - xLeft);
+    const float B = (yTop + yBottom) / (yTop - yBottom);
+    const float C = (zNear + zFar) / (zNear - zFar);
+    const float D = (2 * zNear * zFar) / (zNear - zFar);
+
+    ret.m[0][0] = X;
+    ret.m[2][0] = A;
+    ret.m[1][1] = Y;
+    ret.m[2][1] = B;
+    ret.m[2][2] = C;
+    ret.m[3][2] = D;
+    ret.m[2][3] = -1;
+
+    return ret;
+}
+
+void Matrix4x4::ToArray(float* array) const { std::memcpy(array, &m[0][0], 16 * sizeof(float)); }
+
+} // namespace cardboard

+ 37 - 0
tracking/util/matrix_4x4.h

@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_UTIL_MATRIX_4X4_H_
+#define CARDBOARD_SDK_UTIL_MATRIX_4X4_H_
+
+#include <array>
+
+namespace cardboard {
+
+class Matrix4x4 {
+public:
+    static Matrix4x4 Identity();
+    static Matrix4x4 Zeros();
+    static Matrix4x4 Translation(float x, float y, float z);
+    static Matrix4x4 Perspective(const std::array<float, 4>& fov, float zNear, float zFar);
+    void ToArray(float* array) const;
+
+private:
+    std::array<std::array<float, 4>, 4> m;
+};
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_UTIL_MATRIX4X4_H_

+ 148 - 0
tracking/util/matrixutils.cc

@@ -0,0 +1,148 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 "matrixutils.h"
+
+#include "vectorutils.h"
+
+namespace cardboard {
+
+namespace {
+
+    // Returns true if the cofactor for a given row and column should be negated.
+    static bool IsCofactorNegated(int row, int col)
+    {
+        // Negated iff (row + col) is odd.
+        return ((row + col) & 1) != 0;
+    }
+
+    static double CofactorElement3(const Matrix3x3& m, int row, int col)
+    {
+        static const int index[3][2] = { { 1, 2 }, { 0, 2 }, { 0, 1 } };
+        const int i0 = index[row][0];
+        const int i1 = index[row][1];
+        const int j0 = index[col][0];
+        const int j1 = index[col][1];
+        const double cofactor = m(i0, j0) * m(i1, j1) - m(i0, j1) * m(i1, j0);
+        return IsCofactorNegated(row, col) ? -cofactor : cofactor;
+    }
+
+    // Multiplies a matrix and some type of column vector to
+    // produce another column vector of the same type.
+    Vector3 MultiplyMatrixAndVector(const Matrix3x3& m, const Vector3& v)
+    {
+        Vector3 result = Vector3::Zero();
+        for (int row = 0; row < 3; ++row) {
+            for (int col = 0; col < 3; ++col)
+                result[row] += m(row, col) * v[col];
+        }
+        return result;
+    }
+
+    // Sets the upper 3x3 of a Matrix to represent a 3D rotation.
+    void RotationMatrix3x3(const Rotation& r, Matrix3x3* matrix)
+    {
+        //
+        // Given a quaternion (a,b,c,d) where d is the scalar part, the 3x3 rotation
+        // matrix is:
+        //
+        //   a^2 - b^2 - c^2 + d^2         2ab - 2cd               2ac + 2bd
+        //         2ab + 2cd        -a^2 + b^2 - c^2 + d^2         2bc - 2ad
+        //         2ac - 2bd               2bc + 2ad        -a^2 - b^2 + c^2 + d^2
+        //
+        const Vector<4>& quat = r.GetQuaternion();
+        const double aa = quat[0] * quat[0];
+        const double bb = quat[1] * quat[1];
+        const double cc = quat[2] * quat[2];
+        const double dd = quat[3] * quat[3];
+
+        const double ab = quat[0] * quat[1];
+        const double ac = quat[0] * quat[2];
+        const double bc = quat[1] * quat[2];
+
+        const double ad = quat[0] * quat[3];
+        const double bd = quat[1] * quat[3];
+        const double cd = quat[2] * quat[3];
+
+        Matrix3x3& m = *matrix;
+        m[0][0] = aa - bb - cc + dd;
+        m[0][1] = 2 * ab - 2 * cd;
+        m[0][2] = 2 * ac + 2 * bd;
+        m[1][0] = 2 * ab + 2 * cd;
+        m[1][1] = -aa + bb - cc + dd;
+        m[1][2] = 2 * bc - 2 * ad;
+        m[2][0] = 2 * ac - 2 * bd;
+        m[2][1] = 2 * bc + 2 * ad;
+        m[2][2] = -aa - bb + cc + dd;
+    }
+
+} // anonymous namespace
+
+Vector3 operator*(const Matrix3x3& m, const Vector3& v) { return MultiplyMatrixAndVector(m, v); }
+
+Matrix3x3 CofactorMatrix(const Matrix3x3& m)
+{
+    Matrix3x3 result;
+    for (int row = 0; row < 3; ++row) {
+        for (int col = 0; col < 3; ++col)
+            result(row, col) = CofactorElement3(m, row, col);
+    }
+    return result;
+}
+
+Matrix3x3 AdjugateWithDeterminant(const Matrix3x3& m, double* determinant)
+{
+    const Matrix3x3 cofactor_matrix = CofactorMatrix(m);
+    if (determinant) {
+        *determinant = m(0, 0) * cofactor_matrix(0, 0) + m(0, 1) * cofactor_matrix(0, 1)
+            + m(0, 2) * cofactor_matrix(0, 2);
+    }
+    return Transpose(cofactor_matrix);
+}
+
+// Returns the transpose of a matrix.
+Matrix3x3 Transpose(const Matrix3x3& m)
+{
+    Matrix3x3 result;
+    for (int row = 0; row < 3; ++row) {
+        for (int col = 0; col < 3; ++col)
+            result(row, col) = m(col, row);
+    }
+    return result;
+}
+
+Matrix3x3 InverseWithDeterminant(const Matrix3x3& m, double* determinant)
+{
+    // The inverse is the adjugate divided by the determinant.
+    double det;
+    Matrix3x3 adjugate = AdjugateWithDeterminant(m, &det);
+    if (determinant)
+        *determinant = det;
+    if (det == 0)
+        return Matrix3x3::Zero();
+    else
+        return adjugate * (1 / det);
+}
+
+Matrix3x3 Inverse(const Matrix3x3& m) { return InverseWithDeterminant(m, nullptr); }
+
+Matrix3x3 RotationMatrixNH(const Rotation& r)
+{
+    Matrix3x3 m;
+    RotationMatrix3x3(r, &m);
+    return m;
+}
+
+} // namespace cardboard

+ 65 - 0
tracking/util/matrixutils.h

@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_UTIL_MATRIXUTILS_H_
+#define CARDBOARD_SDK_UTIL_MATRIXUTILS_H_
+
+//
+// This file contains operators and free functions that define generic Matrix
+// operations.
+//
+
+#include "matrix_3x3.h"
+#include "rotation.h"
+#include "vector.h"
+
+namespace cardboard {
+
+// Returns the transpose of a matrix.
+Matrix3x3 Transpose(const Matrix3x3& m);
+
+// Multiplies a Matrix and a column Vector of the same Dimension to produce
+// another column Vector.
+Vector3 operator*(const Matrix3x3& m, const Vector3& v);
+
+// Returns the determinant of the matrix. This function is defined for all the
+// typedef'ed Matrix types.
+double Determinant(const Matrix3x3& m);
+
+// Returns the adjugate of the matrix, which is defined as the transpose of the
+// cofactor matrix. This function is defined for all the typedef'ed Matrix
+// types.  The determinant of the matrix is computed as a side effect, so it is
+// returned in the determinant parameter if it is not null.
+Matrix3x3 AdjugateWithDeterminant(const Matrix3x3& m, double* determinant);
+
+// Returns the inverse of the matrix. This function is defined for all the
+// typedef'ed Matrix types.  The determinant of the matrix is computed as a
+// side effect, so it is returned in the determinant parameter if it is not
+// null. If the determinant is 0, the returned matrix has all zeroes.
+Matrix3x3 InverseWithDeterminant(const Matrix3x3& m, double* determinant);
+
+// Returns the inverse of the matrix. This function is defined for all the
+// typedef'ed Matrix types. If the determinant of the matrix is 0, the returned
+// matrix has all zeroes.
+Matrix3x3 Inverse(const Matrix3x3& m);
+
+// Returns a 3x3 Matrix representing a 3D rotation. This creates a Matrix that
+// does not work with homogeneous coordinates, so the function name ends in
+// "NH".
+Matrix3x3 RotationMatrixNH(const Rotation& r);
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_UTIL_MATRIXUTILS_H_

+ 117 - 0
tracking/util/rotation.cc

@@ -0,0 +1,117 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 "rotation.h"
+
+#include <cmath>
+#include <limits>
+
+#include "vectorutils.h"
+
+namespace cardboard {
+
+void Rotation::SetAxisAndAngle(const VectorType& axis, double angle)
+{
+    VectorType unit_axis = axis;
+    if (!Normalize(&unit_axis)) {
+        *this = Identity();
+    } else {
+        double a = angle / 2;
+        const double s = sin(a);
+        const VectorType v(unit_axis * s);
+        SetQuaternion(QuaternionType(v[0], v[1], v[2], cos(a)));
+    }
+}
+
+Rotation Rotation::FromRotationMatrix(const Matrix3x3& mat)
+{
+    static const double kOne = 1.0;
+    static const double kFour = 4.0;
+
+    const double d0 = mat(0, 0), d1 = mat(1, 1), d2 = mat(2, 2);
+    const double ww = kOne + d0 + d1 + d2;
+    const double xx = kOne + d0 - d1 - d2;
+    const double yy = kOne - d0 + d1 - d2;
+    const double zz = kOne - d0 - d1 + d2;
+
+    const double max = std::max(ww, std::max(xx, std::max(yy, zz)));
+    if (ww == max) {
+        const double w4 = sqrt(ww * kFour);
+        return Rotation::FromQuaternion(QuaternionType((mat(2, 1) - mat(1, 2)) / w4,
+            (mat(0, 2) - mat(2, 0)) / w4, (mat(1, 0) - mat(0, 1)) / w4, w4 / kFour));
+    }
+
+    if (xx == max) {
+        const double x4 = sqrt(xx * kFour);
+        return Rotation::FromQuaternion(QuaternionType(x4 / kFour, (mat(0, 1) + mat(1, 0)) / x4,
+            (mat(0, 2) + mat(2, 0)) / x4, (mat(2, 1) - mat(1, 2)) / x4));
+    }
+
+    if (yy == max) {
+        const double y4 = sqrt(yy * kFour);
+        return Rotation::FromQuaternion(QuaternionType((mat(0, 1) + mat(1, 0)) / y4, y4 / kFour,
+            (mat(1, 2) + mat(2, 1)) / y4, (mat(0, 2) - mat(2, 0)) / y4));
+    }
+
+    // zz is the largest component.
+    const double z4 = sqrt(zz * kFour);
+    return Rotation::FromQuaternion(QuaternionType((mat(0, 2) + mat(2, 0)) / z4,
+        (mat(1, 2) + mat(2, 1)) / z4, z4 / kFour, (mat(1, 0) - mat(0, 1)) / z4));
+}
+
+void Rotation::GetAxisAndAngle(VectorType* axis, double* angle) const
+{
+    VectorType vec(quat_[0], quat_[1], quat_[2]);
+    if (Normalize(&vec)) {
+        *angle = 2 * acos(quat_[3]);
+        *axis = vec;
+    } else {
+        *axis = VectorType(1, 0, 0);
+        *angle = 0.0;
+    }
+}
+
+Rotation Rotation::RotateInto(const VectorType& from, const VectorType& to)
+{
+    static const double kTolerance = std::numeric_limits<double>::epsilon() * 100;
+
+    // Directly build the quaternion using the following technique:
+    // http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
+    const double norm_u_norm_v = sqrt(LengthSquared(from) * LengthSquared(to));
+    double real_part = norm_u_norm_v + Dot(from, to);
+    VectorType w;
+    if (real_part < kTolerance * norm_u_norm_v) {
+        // If |from| and |to| are exactly opposite, rotate 180 degrees around an
+        // arbitrary orthogonal axis. Axis normalization can happen later, when we
+        // normalize the quaternion.
+        real_part = 0.0;
+        w = (abs(from[0]) > abs(from[2])) ? VectorType(-from[1], from[0], 0)
+                                          : VectorType(0, -from[2], from[1]);
+    } else {
+        // Otherwise, build the quaternion the standard way.
+        w = Cross(from, to);
+    }
+
+    // Build and return a normalized quaternion.
+    // Note that Rotation::FromQuaternion automatically performs normalization.
+    return Rotation::FromQuaternion(QuaternionType(w[0], w[1], w[2], real_part));
+}
+
+Rotation::VectorType Rotation::operator*(const Rotation::VectorType& v) const
+{
+    return ApplyToVector(v);
+}
+
+} // namespace cardboard

+ 156 - 0
tracking/util/rotation.h

@@ -0,0 +1,156 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_UTIL_ROTATION_H_
+#define CARDBOARD_SDK_UTIL_ROTATION_H_
+
+#include "matrix_3x3.h"
+#include "vector.h"
+#include "vectorutils.h"
+
+namespace cardboard {
+
+// The Rotation class represents a rotation around a 3-dimensional axis. It
+// uses normalized quaternions internally to make the math robust.
+class Rotation {
+public:
+    // Convenience typedefs for vector of the correct type.
+    typedef Vector<3> VectorType;
+    typedef Vector<4> QuaternionType;
+
+    // The default constructor creates an identity Rotation, which has no effect.
+    Rotation() { quat_.Set(0, 0, 0, 1); }
+
+    // Returns an identity Rotation, which has no effect.
+    static Rotation Identity() { return Rotation(); }
+
+    // Sets the Rotation from a quaternion (4D vector), which is first normalized.
+    void SetQuaternion(const QuaternionType& quaternion) { quat_ = Normalized(quaternion); }
+
+    // Returns the Rotation as a normalized quaternion (4D vector).
+    const QuaternionType& GetQuaternion() const { return quat_; }
+
+    // Sets the Rotation to rotate by the given angle around the given axis,
+    // following the right-hand rule. The axis does not need to be unit
+    // length. If it is zero length, this results in an identity Rotation.
+    void SetAxisAndAngle(const VectorType& axis, double angle);
+
+    // Returns the right-hand rule axis and angle corresponding to the
+    // Rotation. If the Rotation is the identity rotation, this returns the +X
+    // axis and an angle of 0.
+    void GetAxisAndAngle(VectorType* axis, double* angle) const;
+
+    // Convenience function that constructs and returns a Rotation given an axis
+    // and angle.
+    static Rotation FromAxisAndAngle(const VectorType& axis, double angle)
+    {
+        Rotation r;
+        r.SetAxisAndAngle(axis, angle);
+        return r;
+    }
+
+    // Convenience function that constructs and returns a Rotation given a
+    // quaternion.
+    static Rotation FromQuaternion(const QuaternionType& quat)
+    {
+        Rotation r;
+        r.SetQuaternion(quat);
+        return r;
+    }
+
+    // Convenience function that constructs and returns a Rotation given a
+    // rotation matrix R with $R^\top R = I && det(R) = 1$.
+    static Rotation FromRotationMatrix(const Matrix3x3& mat);
+
+    // Convenience function that constructs and returns a Rotation given Euler
+    // angles that are applied in the order of rotate-Z by roll, rotate-X by
+    // pitch, rotate-Y by yaw (same as GetRollPitchYaw).
+    static Rotation FromRollPitchYaw(double roll, double pitch, double yaw)
+    {
+        VectorType x(1, 0, 0), y(0, 1, 0), z(0, 0, 1);
+        return FromAxisAndAngle(z, roll) * (FromAxisAndAngle(x, pitch) * FromAxisAndAngle(y, yaw));
+    }
+
+    // Convenience function that constructs and returns a Rotation given Euler
+    // angles that are applied in the order of rotate-Y by yaw, rotate-X by
+    // pitch, rotate-Z by roll (same as GetYawPitchRoll).
+    static Rotation FromYawPitchRoll(double yaw, double pitch, double roll)
+    {
+        VectorType x(1, 0, 0), y(0, 1, 0), z(0, 0, 1);
+        return FromAxisAndAngle(y, yaw) * (FromAxisAndAngle(x, pitch) * FromAxisAndAngle(z, roll));
+    }
+
+    // Constructs and returns a Rotation that rotates one vector to another along
+    // the shortest arc. This returns an identity rotation if either vector has
+    // zero length.
+    static Rotation RotateInto(const VectorType& from, const VectorType& to);
+
+    // The negation operator returns the inverse rotation.
+    friend Rotation operator-(const Rotation& r)
+    {
+        // Because we store normalized quaternions, the inverse is found by
+        // negating the vector part.
+        return Rotation(-r.quat_[0], -r.quat_[1], -r.quat_[2], r.quat_[3]);
+    }
+
+    // Appends a rotation to this one.
+    Rotation& operator*=(const Rotation& r)
+    {
+        const QuaternionType& qr = r.quat_;
+        QuaternionType& qt = quat_;
+        SetQuaternion(QuaternionType(qr[3] * qt[0] + qr[0] * qt[3] + qr[2] * qt[1] - qr[1] * qt[2],
+            qr[3] * qt[1] + qr[1] * qt[3] + qr[0] * qt[2] - qr[2] * qt[0],
+            qr[3] * qt[2] + qr[2] * qt[3] + qr[1] * qt[0] - qr[0] * qt[1],
+            qr[3] * qt[3] - qr[0] * qt[0] - qr[1] * qt[1] - qr[2] * qt[2]));
+        return *this;
+    }
+
+    // Binary multiplication operator - returns a composite Rotation.
+    friend const Rotation operator*(const Rotation& r0, const Rotation& r1)
+    {
+        Rotation r = r0;
+        r *= r1;
+        return r;
+    }
+
+    // Multiply a Rotation and a Vector to get a Vector.
+    VectorType operator*(const VectorType& v) const;
+
+private:
+    // Private constructor that builds a Rotation from quaternion components.
+    Rotation(double q0, double q1, double q2, double q3)
+        : quat_(q0, q1, q2, q3)
+    {
+    }
+
+    // Applies a Rotation to a Vector to rotate the Vector. Method borrowed from:
+    // http://blog.molecular-matters.com/2013/05/24/a-faster-quaternion-vector-multiplication/
+    VectorType ApplyToVector(const VectorType& v) const
+    {
+        VectorType im(quat_[0], quat_[1], quat_[2]);
+        VectorType temp = 2.0 * Cross(im, v);
+        return v + quat_[3] * temp + Cross(im, temp);
+    }
+
+    // The rotation represented as a normalized quaternion. (Unit quaternions are
+    // required for constructing rotation matrices, so it makes sense to always
+    // store them that way.) The vector part is in the first 3 elements, and the
+    // scalar part is in the last element.
+    QuaternionType quat_;
+};
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_UTIL_ROTATION_H_

+ 229 - 0
tracking/util/vector.h

@@ -0,0 +1,229 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_UTIL_VECTOR_H_
+#define CARDBOARD_SDK_UTIL_VECTOR_H_
+
+#include <array>
+
+namespace cardboard {
+
+// Geometric N-dimensional Vector class.
+template <int Dimension> class Vector {
+public:
+    // The default constructor zero-initializes all elements.
+    Vector();
+
+    // Dimension-specific constructors that are passed individual element values.
+    constexpr Vector(double e0, double e1, double e2);
+    constexpr Vector(double e0, double e1, double e2, double e3);
+
+    // Constructor for a Vector of dimension N from a Vector of dimension N-1 and
+    // a scalar of the correct type, assuming N is at least 2.
+    // constexpr Vector(const Vector<Dimension - 1>& v, double s);
+
+    void Set(double e0, double e1, double e2); // Only when Dimension == 3.
+    void Set(double e0, double e1, double e2,
+        double e3); // Only when Dimension == 4.
+
+    // Mutable element accessor.
+    double& operator[](int index) { return elem_[index]; }
+
+    // Element accessor.
+    double operator[](int index) const { return elem_[index]; }
+
+    // Returns a Vector containing all zeroes.
+    static Vector Zero();
+
+    // Self-modifying operators.
+    void operator+=(const Vector& v) { Add(v); }
+    void operator-=(const Vector& v) { Subtract(v); }
+    void operator*=(double s) { Multiply(s); }
+    void operator/=(double s) { Divide(s); }
+
+    // Unary negation operator.
+    Vector operator-() const { return Negation(); }
+
+    // Binary operators.
+    friend Vector operator+(const Vector& v0, const Vector& v1) { return Sum(v0, v1); }
+    friend Vector operator-(const Vector& v0, const Vector& v1) { return Difference(v0, v1); }
+    friend Vector operator*(const Vector& v, double s) { return Scale(v, s); }
+    friend Vector operator*(double s, const Vector& v) { return Scale(v, s); }
+    friend Vector operator*(const Vector& v, const Vector& s) { return Product(v, s); }
+    friend Vector operator/(const Vector& v, double s) { return Divide(v, s); }
+
+    // Self-modifying addition.
+    void Add(const Vector& v);
+    // Self-modifying subtraction.
+    void Subtract(const Vector& v);
+    // Self-modifying multiplication by a scalar.
+    void Multiply(double s);
+    // Self-modifying division by a scalar.
+    void Divide(double s);
+
+    // Unary negation.
+    Vector Negation() const;
+
+    // Binary component-wise multiplication.
+    static Vector Product(const Vector& v0, const Vector& v1);
+    // Binary component-wise addition.
+    static Vector Sum(const Vector& v0, const Vector& v1);
+    // Binary component-wise subtraction.
+    static Vector Difference(const Vector& v0, const Vector& v1);
+    // Binary multiplication by a scalar.
+    static Vector Scale(const Vector& v, double s);
+    // Binary division by a scalar.
+    static Vector Divide(const Vector& v, double s);
+
+private:
+    std::array<double, Dimension> elem_;
+};
+//------------------------------------------------------------------------------
+
+template <int Dimension> Vector<Dimension>::Vector()
+{
+    for (int i = 0; i < Dimension; i++) {
+        elem_[i] = 0;
+    }
+}
+
+template <int Dimension>
+constexpr Vector<Dimension>::Vector(double e0, double e1, double e2)
+    : elem_ { e0, e1, e2 }
+{
+}
+
+template <int Dimension>
+constexpr Vector<Dimension>::Vector(double e0, double e1, double e2, double e3)
+    : elem_ { e0, e1, e2, e3 }
+{
+}
+/*
+template <>
+constexpr Vector<4>::Vector(const Vector<3>& v, double s)
+    : elem_{v[0], v[1], v[2], s} {}
+*/
+template <int Dimension> void Vector<Dimension>::Set(double e0, double e1, double e2)
+{
+    elem_[0] = e0;
+    elem_[1] = e1;
+    elem_[2] = e2;
+}
+
+template <int Dimension> void Vector<Dimension>::Set(double e0, double e1, double e2, double e3)
+{
+    elem_[0] = e0;
+    elem_[1] = e1;
+    elem_[2] = e2;
+    elem_[3] = e3;
+}
+
+template <int Dimension> Vector<Dimension> Vector<Dimension>::Zero()
+{
+    Vector<Dimension> v;
+    return v;
+}
+
+template <int Dimension> void Vector<Dimension>::Add(const Vector& v)
+{
+    for (int i = 0; i < Dimension; i++) {
+        elem_[i] += v[i];
+    }
+}
+
+template <int Dimension> void Vector<Dimension>::Subtract(const Vector& v)
+{
+    for (int i = 0; i < Dimension; i++) {
+        elem_[i] -= v[i];
+    }
+}
+
+template <int Dimension> void Vector<Dimension>::Multiply(double s)
+{
+    for (int i = 0; i < Dimension; i++) {
+        elem_[i] *= s;
+    }
+}
+
+template <int Dimension> void Vector<Dimension>::Divide(double s)
+{
+    for (int i = 0; i < Dimension; i++) {
+        elem_[i] /= s;
+    }
+}
+
+template <int Dimension> Vector<Dimension> Vector<Dimension>::Negation() const
+{
+    Vector<Dimension> ret;
+    for (int i = 0; i < Dimension; i++) {
+        ret.elem_[i] = -elem_[i];
+    }
+    return ret;
+}
+
+template <int Dimension>
+Vector<Dimension> Vector<Dimension>::Product(const Vector& v0, const Vector& v1)
+{
+    Vector<Dimension> ret;
+    for (int i = 0; i < Dimension; i++) {
+        ret.elem_[i] = v0[i] * v1[i];
+    }
+    return ret;
+}
+
+template <int Dimension>
+Vector<Dimension> Vector<Dimension>::Sum(const Vector& v0, const Vector& v1)
+{
+    Vector<Dimension> ret;
+    for (int i = 0; i < Dimension; i++) {
+        ret.elem_[i] = v0[i] + v1[i];
+    }
+    return ret;
+}
+
+template <int Dimension>
+Vector<Dimension> Vector<Dimension>::Difference(const Vector& v0, const Vector& v1)
+{
+    Vector<Dimension> ret;
+    for (int i = 0; i < Dimension; i++) {
+        ret.elem_[i] = v0[i] - v1[i];
+    }
+    return ret;
+}
+
+template <int Dimension> Vector<Dimension> Vector<Dimension>::Scale(const Vector& v, double s)
+{
+    Vector<Dimension> ret;
+    for (int i = 0; i < Dimension; i++) {
+        ret.elem_[i] = v[i] * s;
+    }
+    return ret;
+}
+
+template <int Dimension> Vector<Dimension> Vector<Dimension>::Divide(const Vector& v, double s)
+{
+    Vector<Dimension> ret;
+    for (int i = 0; i < Dimension; i++) {
+        ret.elem_[i] = v[i] / s;
+    }
+    return ret;
+}
+
+typedef Vector<3> Vector3;
+typedef Vector<4> Vector4;
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_UTIL_VECTOR_H_

+ 40 - 0
tracking/util/vectorutils.cc

@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 "vectorutils.h"
+
+namespace cardboard {
+
+// Returns the dot (inner) product of two Vectors.
+double Dot(const Vector<3>& v0, const Vector<3>& v1)
+{
+    return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2];
+}
+
+// Returns the dot (inner) product of two Vectors.
+double Dot(const Vector<4>& v0, const Vector<4>& v1)
+{
+    return v0[0] * v1[0] + v0[1] * v1[1] + v0[2] * v1[2] + v0[3] * v1[3];
+}
+
+// Returns the 3-dimensional cross product of 2 Vectors. Note that this is
+// defined only for 3-dimensional Vectors.
+Vector<3> Cross(const Vector<3>& v0, const Vector<3>& v1)
+{
+    return Vector<3>(v0[1] * v1[2] - v0[2] * v1[1], v0[2] * v1[0] - v0[0] * v1[2],
+        v0[0] * v1[1] - v0[1] * v1[0]);
+}
+
+} // namespace cardboard

+ 73 - 0
tracking/util/vectorutils.h

@@ -0,0 +1,73 @@
+/*
+ * Copyright 2019 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 CARDBOARD_SDK_UTIL_VECTORUTILS_H_
+#define CARDBOARD_SDK_UTIL_VECTORUTILS_H_
+
+//
+// This file contains free functions that operate on Vector instances.
+//
+
+#include <cmath>
+
+#include "vector.h"
+
+namespace cardboard {
+
+// Returns the dot (inner) product of two Vectors.
+double Dot(const Vector<3>& v0, const Vector<3>& v1);
+
+// Returns the dot (inner) product of two Vectors.
+double Dot(const Vector<4>& v0, const Vector<4>& v1);
+
+// Returns the 3-dimensional cross product of 2 Vectors. Note that this is
+// defined only for 3-dimensional Vectors.
+Vector<3> Cross(const Vector<3>& v0, const Vector<3>& v1);
+
+// Returns the square of the length of a Vector.
+template <int Dimension> double LengthSquared(const Vector<Dimension>& v) { return Dot(v, v); }
+
+// Returns the geometric length of a Vector.
+template <int Dimension> double Length(const Vector<Dimension>& v)
+{
+    return sqrt(LengthSquared(v));
+}
+
+// the Vector untouched and returns false.
+template <int Dimension> bool Normalize(Vector<Dimension>* v)
+{
+    const double len = Length(*v);
+    if (len == 0) {
+        return false;
+    } else {
+        (*v) /= len;
+        return true;
+    }
+}
+
+// Returns a unit-length version of a Vector. If the given Vector has no
+// length, this returns a Zero() Vector.
+template <int Dimension> Vector<Dimension> Normalized(const Vector<Dimension>& v)
+{
+    Vector<Dimension> result = v;
+    if (Normalize(&result))
+        return result;
+    else
+        return Vector<Dimension>::Zero();
+}
+
+} // namespace cardboard
+
+#endif // CARDBOARD_SDK_UTIL_VECTORUTILS_H_

+ 156 - 0
views/bt_mouse.c

@@ -0,0 +1,156 @@
+#include "bt_mouse.h"
+#include "../tracking/main_loop.h"
+
+#include <furi.h>
+#include <furi_hal_bt.h>
+#include <furi_hal_bt_hid.h>
+#include <furi_hal_usb_hid.h>
+#include <bt/bt_service/bt.h>
+#include <gui/elements.h>
+#include <notification/notification.h>
+#include <notification/notification_messages.h>
+
+struct BtMouse {
+    View* view;
+    ViewDispatcher* view_dispatcher;
+    Bt* bt;
+    NotificationApp* notifications;
+};
+
+#define MOUSE_MOVE_SHORT 5
+#define MOUSE_MOVE_LONG 20
+
+static void bt_mouse_draw_callback(Canvas* canvas, void* context) {
+    UNUSED(context);
+    canvas_clear(canvas);
+    canvas_set_font(canvas, FontPrimary);
+    canvas_draw_str(canvas, 0, 10, "Bluetooth Mouse mode");
+    canvas_set_font(canvas, FontSecondary);
+    canvas_draw_str(canvas, 0, 63, "Hold [back] to exit");
+}
+
+static void bt_mouse_process(BtMouse* bt_mouse, InputEvent* event) {
+    with_view_model(
+        bt_mouse->view,
+        void * model,
+        {
+            UNUSED(model);
+            if (event->key == InputKeyUp) {
+                if (event->type == InputTypePress) {
+                    furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_LEFT);
+                } else if (event->type == InputTypeRelease) {
+                    furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_LEFT);
+                }
+            } else if (event->key == InputKeyDown) {
+                if (event->type == InputTypePress) {
+                    furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_RIGHT);
+                } else if (event->type == InputTypeRelease) {
+                    furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_RIGHT);
+                }
+            } else if (event->key == InputKeyOk) {
+                if (event->type == InputTypePress) {
+                    furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_WHEEL);
+                } else if (event->type == InputTypeRelease) {
+                    furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_WHEEL);
+                }
+            }
+        },
+        true);
+}
+
+static bool bt_mouse_input_callback(InputEvent* event, void* context) {
+    furi_assert(context);
+    BtMouse* bt_mouse = context;
+    bool consumed = false;
+
+    if (event->type == InputTypeLong && event->key == InputKeyBack) {
+        furi_hal_bt_hid_mouse_release_all();
+    } else {
+        bt_mouse_process(bt_mouse, event);
+        consumed = true;
+    }
+
+    return consumed;
+}
+
+void bt_mouse_connection_status_changed_callback(BtStatus status, void* context) {
+    furi_assert(context);
+    BtMouse* bt_mouse = context;
+
+    bool connected = (status == BtStatusConnected);
+    if (connected) {
+        notification_internal_message(bt_mouse->notifications, &sequence_set_blue_255);
+    } else {
+        notification_internal_message(bt_mouse->notifications, &sequence_reset_blue);
+    }
+
+    //with_view_model(
+    //    bt_mouse->view, void * model, { model->connected = connected; }, true);
+}
+
+void bt_mouse_enter_callback(void *context) {
+    furi_assert(context);
+    BtMouse* bt_mouse = context;
+
+    bt_mouse->bt = furi_record_open(RECORD_BT);
+    bt_mouse->notifications = furi_record_open(RECORD_NOTIFICATION);
+    bt_set_status_changed_callback(bt_mouse->bt, bt_mouse_connection_status_changed_callback, bt_mouse);
+    furi_assert(bt_set_profile(bt_mouse->bt, BtProfileHidKeyboard));
+    furi_hal_bt_start_advertising();
+
+    tracking_begin();
+
+    view_dispatcher_send_custom_event(bt_mouse->view_dispatcher, 0);
+}
+
+bool bt_mouse_custom_callback(uint32_t event, void* context) {
+    UNUSED(event);
+    furi_assert(context);
+    BtMouse* bt_mouse = context;
+
+    tracking_step(furi_hal_bt_hid_mouse_move);
+
+    view_dispatcher_send_custom_event(bt_mouse->view_dispatcher, 0);
+    return true;
+}
+
+void bt_mouse_exit_callback(void *context) {
+    furi_assert(context);
+    BtMouse* bt_mouse = context;
+
+    tracking_end();
+
+    notification_internal_message(bt_mouse->notifications, &sequence_reset_blue);
+
+    furi_hal_bt_stop_advertising();
+    bt_set_profile(bt_mouse->bt, BtProfileSerial);
+
+    furi_record_close(RECORD_NOTIFICATION);
+    bt_mouse->notifications = NULL;
+    furi_record_close(RECORD_BT);
+    bt_mouse->bt = NULL;
+}
+
+BtMouse* bt_mouse_alloc(ViewDispatcher* view_dispatcher) {
+    BtMouse* bt_mouse = malloc(sizeof(BtMouse));
+    bt_mouse->view = view_alloc();
+    bt_mouse->view_dispatcher = view_dispatcher;
+    view_set_context(bt_mouse->view, bt_mouse);
+    view_set_draw_callback(bt_mouse->view, bt_mouse_draw_callback);
+    view_set_input_callback(bt_mouse->view, bt_mouse_input_callback);
+    view_set_enter_callback(bt_mouse->view, bt_mouse_enter_callback);
+    view_set_custom_callback(bt_mouse->view, bt_mouse_custom_callback);
+    view_set_exit_callback(bt_mouse->view, bt_mouse_exit_callback);
+    return bt_mouse;
+}
+
+void bt_mouse_free(BtMouse* bt_mouse) {
+    furi_assert(bt_mouse);
+    view_free(bt_mouse->view);
+    free(bt_mouse);
+}
+
+View* bt_mouse_get_view(BtMouse* bt_mouse) {
+    furi_assert(bt_mouse);
+    return bt_mouse->view;
+}

+ 14 - 0
views/bt_mouse.h

@@ -0,0 +1,14 @@
+#pragma once
+
+#include <gui/view.h>
+#include <gui/view_dispatcher.h>
+
+typedef struct BtMouse BtMouse;
+
+BtMouse* bt_mouse_alloc(ViewDispatcher* view_dispatcher);
+
+void bt_mouse_free(BtMouse* bt_mouse);
+
+View* bt_mouse_get_view(BtMouse* bt_mouse);
+
+void bt_mouse_set_connected_status(BtMouse* bt_mouse, bool connected);

+ 69 - 0
views/calibration.c

@@ -0,0 +1,69 @@
+#include "calibration.h"
+#include "../tracking/main_loop.h"
+#include "../air_mouse.h"
+
+#include <furi.h>
+#include <gui/elements.h>
+
+struct Calibration {
+    View* view;
+    ViewDispatcher* view_dispatcher;
+};
+
+static void calibration_draw_callback(Canvas* canvas, void* context) {
+    UNUSED(context);
+    canvas_clear(canvas);
+    canvas_set_font(canvas, FontPrimary);
+    canvas_draw_str(canvas, 0, 10, "Calibrating...");
+    canvas_set_font(canvas, FontSecondary);
+    canvas_draw_str(canvas, 0, 63, "Please wait");
+}
+
+void calibration_enter_callback(void* context) {
+    furi_assert(context);
+    Calibration* calibration = context;
+    calibration_begin();
+    view_dispatcher_send_custom_event(calibration->view_dispatcher, 0);
+}
+
+bool calibration_custom_callback(uint32_t event, void* context) {
+    UNUSED(event);
+    furi_assert(context);
+    Calibration* calibration = context;
+
+    if (calibration_step()) {
+        view_dispatcher_switch_to_view(calibration->view_dispatcher, AirMouseViewSubmenu);
+    } else {
+        view_dispatcher_send_custom_event(calibration->view_dispatcher, 0);
+    }
+
+    return true;
+}
+
+void calibration_exit_callback(void* context) {
+    furi_assert(context);
+    calibration_end();
+}
+
+Calibration* calibration_alloc(ViewDispatcher* view_dispatcher) {
+    Calibration* calibration = malloc(sizeof(Calibration));
+    calibration->view = view_alloc();
+    calibration->view_dispatcher = view_dispatcher;
+    view_set_context(calibration->view, calibration);
+    view_set_draw_callback(calibration->view, calibration_draw_callback);
+    view_set_enter_callback(calibration->view, calibration_enter_callback);
+    view_set_custom_callback(calibration->view, calibration_custom_callback);
+    view_set_exit_callback(calibration->view, calibration_exit_callback);
+    return calibration;
+}
+
+void calibration_free(Calibration* calibration) {
+    furi_assert(calibration);
+    view_free(calibration->view);
+    free(calibration);
+}
+
+View* calibration_get_view(Calibration* calibration) {
+    furi_assert(calibration);
+    return calibration->view;
+}

+ 12 - 0
views/calibration.h

@@ -0,0 +1,12 @@
+#pragma once
+
+#include <gui/view.h>
+#include <gui/view_dispatcher.h>
+
+typedef struct Calibration Calibration;
+
+Calibration* calibration_alloc(ViewDispatcher* view_dispatcher);
+
+void calibration_free(Calibration* calibration);
+
+View* calibration_get_view(Calibration* calibration);

+ 124 - 0
views/usb_mouse.c

@@ -0,0 +1,124 @@
+#include "usb_mouse.h"
+#include "../tracking/main_loop.h"
+
+#include <furi.h>
+#include <furi_hal_usb.h>
+#include <furi_hal_usb_hid.h>
+#include <gui/elements.h>
+
+struct UsbMouse {
+    View* view;
+    ViewDispatcher* view_dispatcher;
+    FuriHalUsbInterface* usb_mode_prev;
+};
+
+static void usb_mouse_draw_callback(Canvas* canvas, void* context) {
+    UNUSED(context);
+    canvas_clear(canvas);
+    canvas_set_font(canvas, FontPrimary);
+    canvas_draw_str(canvas, 0, 10, "USB Mouse mode");
+    canvas_set_font(canvas, FontSecondary);
+    canvas_draw_str(canvas, 0, 63, "Hold [back] to exit");
+}
+
+static void usb_mouse_process(UsbMouse* usb_mouse, InputEvent* event) {
+    with_view_model(
+        usb_mouse->view,
+        void * model,
+        {
+            UNUSED(model);
+            if (event->key == InputKeyUp) {
+                if (event->type == InputTypePress) {
+                    furi_hal_hid_mouse_press(HID_MOUSE_BTN_LEFT);
+                } else if (event->type == InputTypeRelease) {
+                    furi_hal_hid_mouse_release(HID_MOUSE_BTN_LEFT);
+                }
+            } else if (event->key == InputKeyDown) {
+                if (event->type == InputTypePress) {
+                    furi_hal_hid_mouse_press(HID_MOUSE_BTN_RIGHT);
+                } else if (event->type == InputTypeRelease) {
+                    furi_hal_hid_mouse_release(HID_MOUSE_BTN_RIGHT);
+                }
+            } else if (event->key == InputKeyOk) {
+                if (event->type == InputTypePress) {
+                    furi_hal_hid_mouse_press(HID_MOUSE_BTN_WHEEL);
+                } else if (event->type == InputTypeRelease) {
+                    furi_hal_hid_mouse_release(HID_MOUSE_BTN_WHEEL);
+                }
+            }
+        },
+        true);
+}
+
+static bool usb_mouse_input_callback(InputEvent* event, void* context) {
+    furi_assert(context);
+    UsbMouse* usb_mouse = context;
+    bool consumed = false;
+
+    if (event->type == InputTypeLong && event->key == InputKeyBack) {
+        // furi_hal_hid_mouse_release_all();
+    } else {
+        usb_mouse_process(usb_mouse, event);
+        consumed = true;
+    }
+
+    return consumed;
+}
+
+void usb_mouse_enter_callback(void *context) {
+    furi_assert(context);
+    UsbMouse* usb_mouse = context;
+
+    usb_mouse->usb_mode_prev = furi_hal_usb_get_config();
+    furi_hal_usb_unlock();
+    furi_check(furi_hal_usb_set_config(&usb_hid, NULL) == true);
+
+    tracking_begin();
+
+    view_dispatcher_send_custom_event(usb_mouse->view_dispatcher, 0);
+}
+
+bool usb_mouse_custom_callback(uint32_t event, void* context) {
+    UNUSED(event);
+    furi_assert(context);
+    UsbMouse* usb_mouse = context;
+
+    tracking_step(furi_hal_hid_mouse_move);
+    furi_delay_ms(1); // Magic! Removing this will break the buttons
+
+    view_dispatcher_send_custom_event(usb_mouse->view_dispatcher, 0);
+    return true;
+}
+
+void usb_mouse_exit_callback(void *context) {
+    furi_assert(context);
+    UsbMouse* usb_mouse = context;
+
+    tracking_end();
+
+    furi_hal_usb_set_config(usb_mouse->usb_mode_prev, NULL);
+}
+
+UsbMouse* usb_mouse_alloc(ViewDispatcher* view_dispatcher) {
+    UsbMouse* usb_mouse = malloc(sizeof(UsbMouse));
+    usb_mouse->view = view_alloc();
+    usb_mouse->view_dispatcher = view_dispatcher;
+    view_set_context(usb_mouse->view, usb_mouse);
+    view_set_draw_callback(usb_mouse->view, usb_mouse_draw_callback);
+    view_set_input_callback(usb_mouse->view, usb_mouse_input_callback);
+    view_set_enter_callback(usb_mouse->view, usb_mouse_enter_callback);
+    view_set_custom_callback(usb_mouse->view, usb_mouse_custom_callback);
+    view_set_exit_callback(usb_mouse->view, usb_mouse_exit_callback);
+    return usb_mouse;
+}
+
+void usb_mouse_free(UsbMouse* usb_mouse) {
+    furi_assert(usb_mouse);
+    view_free(usb_mouse->view);
+    free(usb_mouse);
+}
+
+View* usb_mouse_get_view(UsbMouse* usb_mouse) {
+    furi_assert(usb_mouse);
+    return usb_mouse->view;
+}

+ 12 - 0
views/usb_mouse.h

@@ -0,0 +1,12 @@
+#pragma once
+
+#include <gui/view.h>
+#include <gui/view_dispatcher.h>
+
+typedef struct UsbMouse UsbMouse;
+
+UsbMouse* usb_mouse_alloc(ViewDispatcher* view_dispatcher);
+
+void usb_mouse_free(UsbMouse* usb_mouse);
+
+View* usb_mouse_get_view(UsbMouse* usb_mouse);