summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJean-François Milants <jf@codingfield.com>2021-03-31 19:47:27 +0200
committerJean-François Milants <jf@codingfield.com>2021-04-04 15:56:04 +0200
commit68bdaee1cc301a2aca1849f38d2596debe7d67d1 (patch)
tree00f3bd9a1554c286aa2d5bd3a86bcfcdf7ba7171 /src
parent04fc33e2d479161ec261f932b908dffbd73e227f (diff)
First integration of the motion sensor (bma 421) : step counting + wake on wrist rotation + app to see the value of the 3 axis in "real time".
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt14
-rw-r--r--src/components/motion/MotionController.cpp33
-rw-r--r--src/components/motion/MotionController.h26
-rw-r--r--src/displayapp/Apps.h3
-rw-r--r--src/displayapp/DisplayApp.cpp15
-rw-r--r--src/displayapp/DisplayApp.h5
-rw-r--r--src/displayapp/DisplayAppRecovery.cpp3
-rw-r--r--src/displayapp/DisplayAppRecovery.h4
-rw-r--r--src/displayapp/lv_pinetime_theme.c13
-rw-r--r--src/displayapp/screens/ApplicationList.cpp4
-rw-r--r--src/displayapp/screens/Clock.cpp9
-rw-r--r--src/displayapp/screens/Clock.h5
-rw-r--r--src/displayapp/screens/Motion.cpp59
-rw-r--r--src/displayapp/screens/Motion.h39
-rw-r--r--src/displayapp/screens/WatchFaceDigital.cpp9
-rw-r--r--src/displayapp/screens/WatchFaceDigital.h5
-rw-r--r--src/drivers/Bma421.cpp122
-rw-r--r--src/drivers/Bma421.h43
-rw-r--r--src/drivers/Bma421_C/bma4.c5689
-rw-r--r--src/drivers/Bma421_C/bma4.h2281
-rw-r--r--src/drivers/Bma421_C/bma423.c1688
-rw-r--r--src/drivers/Bma421_C/bma423.h1115
-rw-r--r--src/drivers/Bma421_C/bma4_defs.h1144
-rw-r--r--src/main.cpp6
-rw-r--r--src/systemtask/SystemTask.cpp28
-rw-r--r--src/systemtask/SystemTask.h6
26 files changed, 12343 insertions, 25 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1183bb3b..89b1bc5a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -490,6 +490,7 @@ list(APPEND SOURCE_FILES
displayapp/screens/Notifications.cpp
displayapp/screens/Twos.cpp
displayapp/screens/HeartRate.cpp
+ displayapp/screens/Motion.cpp
## Watch faces
displayapp/icons/bg_clock.c
@@ -508,11 +509,15 @@ list(APPEND SOURCE_FILES
drivers/DebugPins.cpp
drivers/InternalFlash.cpp
drivers/Hrs3300.cpp
+ drivers/Bma421.cpp
+ drivers/Bma421_C/bma4.c
+ drivers/Bma421_C/bma423.c
components/battery/BatteryController.cpp
components/ble/BleController.cpp
components/ble/NotificationManager.cpp
components/datetime/DateTimeController.cpp
components/brightness/BrightnessController.cpp
+ components/motion/MotionController.cpp
components/ble/NimbleController.cpp
components/ble/DeviceInformationService.cpp
components/ble/CurrentTimeClient.cpp
@@ -563,11 +568,15 @@ list(APPEND RECOVERY_SOURCE_FILES
drivers/DebugPins.cpp
drivers/InternalFlash.cpp
drivers/Hrs3300.cpp
+ drivers/Bma421.cpp
+ drivers/Bma421_C/bma4.c
+ drivers/Bma421_C/bma423.c
components/battery/BatteryController.cpp
components/ble/BleController.cpp
components/ble/NotificationManager.cpp
components/datetime/DateTimeController.cpp
components/brightness/BrightnessController.cpp
+ components/motion/MotionController.cpp
components/ble/NimbleController.cpp
components/ble/DeviceInformationService.cpp
components/ble/CurrentTimeClient.cpp
@@ -651,6 +660,7 @@ set(INCLUDE_FILES
displayapp/Apps.h
displayapp/screens/Notifications.h
displayapp/screens/HeartRate.h
+ displayapp/screens/Motion.h
drivers/St7789.h
drivers/SpiNorFlash.h
drivers/SpiMaster.h
@@ -659,11 +669,15 @@ set(INCLUDE_FILES
drivers/DebugPins.h
drivers/InternalFlash.h
drivers/Hrs3300.h
+ drivers/Bma421.h
+ drivers/Bma421_C/bma4.c
+ drivers/Bma421_C/bma423.c
components/battery/BatteryController.h
components/ble/BleController.h
components/ble/NotificationManager.h
components/datetime/DateTimeController.h
components/brightness/BrightnessController.h
+ components/motion/MotionController.h
components/ble/NimbleController.h
components/ble/DeviceInformationService.h
components/ble/CurrentTimeClient.h
diff --git a/src/components/motion/MotionController.cpp b/src/components/motion/MotionController.cpp
new file mode 100644
index 00000000..bad9d45f
--- /dev/null
+++ b/src/components/motion/MotionController.cpp
@@ -0,0 +1,33 @@
+#include "MotionController.h"
+
+using namespace Pinetime::Controllers;
+
+void MotionController::Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps) {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+ this->nbSteps = nbSteps;
+}
+
+bool MotionController::ShouldWakeUp(bool isSleeping) {
+ if ((x + 335) <= 670 && z < 0) {
+ if (not isSleeping) {
+ if (y <= 0) {
+ return false;
+ } else {
+ lastYForWakeUp = 0;
+ return false;
+ }
+ }
+
+ if (y >= 0) {
+ lastYForWakeUp = 0;
+ return false;
+ }
+ if (y + 230 < lastYForWakeUp) {
+ lastYForWakeUp = y;
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/src/components/motion/MotionController.h b/src/components/motion/MotionController.h
new file mode 100644
index 00000000..dbbbf910
--- /dev/null
+++ b/src/components/motion/MotionController.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <cstdint>
+
+namespace Pinetime {
+ namespace Controllers {
+ class MotionController {
+ public:
+ void Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps);
+
+ uint16_t X() const { return x; }
+ uint16_t Y() const { return y; }
+ uint16_t Z() const { return z; }
+ uint32_t NbSteps() const { return nbSteps; }
+ bool ShouldWakeUp(bool isSleeping);
+
+ private:
+ uint32_t nbSteps;
+ int16_t x;
+ int16_t y;
+ int16_t z;
+ int16_t lastYForWakeUp = 0;
+
+ };
+ }
+} \ No newline at end of file
diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h
index 74b121df..11401c3e 100644
--- a/src/displayapp/Apps.h
+++ b/src/displayapp/Apps.h
@@ -2,6 +2,7 @@
namespace Pinetime {
namespace Applications {
- enum class Apps {None, Launcher, Clock, SysInfo, Meter, Brightness, Music, FirmwareValidation, Paint, Paddle, Notifications, Twos, HeartRate, Navigation, StopWatch};
+ enum class Apps {None, Launcher, Clock, SysInfo, Meter, Brightness, Music, FirmwareValidation,
+ Paint, Paddle, Notifications, Twos, HeartRate, Navigation, StopWatch, Motion};
}
}
diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp
index 3de26991..da398dcf 100644
--- a/src/displayapp/DisplayApp.cpp
+++ b/src/displayapp/DisplayApp.cpp
@@ -1,10 +1,12 @@
#include "DisplayApp.h"
#include <libraries/log/nrf_log.h>
#include <displayapp/screens/HeartRate.h>
+#include <displayapp/screens/Motion.h>
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
#include "components/datetime/DateTimeController.h"
#include "components/ble/NotificationManager.h"
+#include "components/motion/MotionController.h"
#include "displayapp/screens/ApplicationList.h"
#include "displayapp/screens/Brightness.h"
#include "displayapp/screens/Clock.h"
@@ -34,7 +36,8 @@ DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Driver
System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
- Controllers::Settings &settingsController) :
+ Controllers::Settings &settingsController,
+ Pinetime::Controllers::MotionController& motionController) :
lcd{lcd},
lvgl{lvgl},
batteryController{batteryController},
@@ -42,11 +45,12 @@ DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Driver
dateTimeController{dateTimeController},
watchdog{watchdog},
touchPanel{touchPanel},
- currentScreen{new Screens::Clock(this, dateTimeController, batteryController, bleController, notificationManager, settingsController, heartRateController) },
+ currentScreen{new Screens::Clock(this, dateTimeController, batteryController, bleController, notificationManager, settingsController, heartRateController, motionController) },
systemTask{systemTask},
notificationManager{notificationManager},
heartRateController{heartRateController},
- settingsController{settingsController} {
+ settingsController{settingsController},
+ motionController{motionController} {
msgQueue = xQueueCreate(queueSize, itemSize);
onClockApp = true;
}
@@ -178,7 +182,7 @@ void DisplayApp::Refresh() {
break;
case Messages::UpdateDateTime:
// Added to remove warning
- // What should happen here?
+ // What should happen here?
break;
}
}
@@ -204,7 +208,7 @@ void DisplayApp::RunningState() {
case Apps::None:
case Apps::Launcher: currentScreen = std::make_unique<Screens::ApplicationList>(this, settingsController); break;
case Apps::Clock:
- currentScreen = std::make_unique<Screens::Clock>(this, dateTimeController, batteryController, bleController, notificationManager, settingsController, heartRateController);
+ currentScreen = std::make_unique<Screens::Clock>(this, dateTimeController, batteryController, bleController, notificationManager, settingsController, heartRateController, motionController);
onClockApp = true;
break;
case Apps::SysInfo: currentScreen = std::make_unique<Screens::SystemInfo>(this, dateTimeController, batteryController, brightnessController, bleController, watchdog); break;
@@ -219,6 +223,7 @@ void DisplayApp::RunningState() {
case Apps::FirmwareValidation: currentScreen = std::make_unique<Screens::FirmwareValidation>(this, validator); break;
case Apps::Notifications: currentScreen = std::make_unique<Screens::Notifications>(this, notificationManager, systemTask.nimble().alertService(), Screens::Notifications::Modes::Normal); break;
case Apps::HeartRate: currentScreen = std::make_unique<Screens::HeartRate>(this, heartRateController); break;
+ case Apps::Motion: currentScreen = std::make_unique<Screens::Motion>(this, motionController); break;
}
nextApp = Apps::None;
}
diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h
index c22aa1f2..88a5691a 100644
--- a/src/displayapp/DisplayApp.h
+++ b/src/displayapp/DisplayApp.h
@@ -27,6 +27,7 @@ namespace Pinetime {
class DateTime;
class NotificationManager;
class HeartRateController;
+ class MotionController;
}
namespace System {
@@ -45,7 +46,8 @@ namespace Pinetime {
System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
- Controllers::Settings &settingsController
+ Controllers::Settings &settingsController,
+ Pinetime::Controllers::MotionController& motionController
);
void Start();
void PushMessage(Display::Messages msg);
@@ -92,6 +94,7 @@ namespace Pinetime {
TouchModes touchMode = TouchModes::Gestures;
Pinetime::Controllers::HeartRateController& heartRateController;
Pinetime::Controllers::Settings& settingsController;
+ Pinetime::Controllers::MotionController& motionController;
};
}
}
diff --git a/src/displayapp/DisplayAppRecovery.cpp b/src/displayapp/DisplayAppRecovery.cpp
index 57b8aedd..d5723835 100644
--- a/src/displayapp/DisplayAppRecovery.cpp
+++ b/src/displayapp/DisplayAppRecovery.cpp
@@ -13,7 +13,8 @@ DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Driver
System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
- Pinetime::Controllers::Settings& settingsController):
+ Pinetime::Controllers::Settings& settingsController,
+ Pinetime::Controllers::MotionController& motionController):
lcd{lcd}, bleController{bleController} {
msgQueue = xQueueCreate(queueSize, itemSize);
diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h
index a3f27d2c..c35fa729 100644
--- a/src/displayapp/DisplayAppRecovery.h
+++ b/src/displayapp/DisplayAppRecovery.h
@@ -16,6 +16,7 @@
#include <date/date.h>
#include <drivers/Watchdog.h>
#include <components/heartrate/HeartRateController.h>
+#include <components/motion/MotionController.h>
#include <components/settings/Settings.h>
#include "TouchEvents.h"
#include "Apps.h"
@@ -35,7 +36,8 @@ namespace Pinetime {
System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
- Pinetime::Controllers::Settings& settingsController);
+ Pinetime::Controllers::Settings& settingsController,
+ Pinetime::Controllers::MotionController& motionController);
void Start();
void PushMessage(Pinetime::Applications::Display::Messages msg);
diff --git a/src/displayapp/lv_pinetime_theme.c b/src/displayapp/lv_pinetime_theme.c
index 88f77557..1350b0d1 100644
--- a/src/displayapp/lv_pinetime_theme.c
+++ b/src/displayapp/lv_pinetime_theme.c
@@ -53,6 +53,7 @@ static lv_style_t style_table_cell;
static lv_style_t style_pad_small;
static lv_style_t style_bg_grad;
static lv_style_t style_lmeter;
+static lv_style_t style_chart_serie;
static bool inited;
@@ -260,6 +261,11 @@ static void basic_init(void)
lv_style_set_line_width(&style_lmeter, LV_STATE_DEFAULT, LV_DPX(10));
lv_style_set_scale_end_line_width(&style_lmeter, LV_STATE_DEFAULT, LV_DPX(7));
+ style_init_reset(&style_chart_serie);
+ lv_style_set_line_color(&style_chart_serie, LV_STATE_DEFAULT, LV_PINETIME_WHITE);
+ lv_style_set_line_width(&style_chart_serie, LV_STATE_DEFAULT, 4);
+ lv_style_set_size(&style_chart_serie, LV_STATE_DEFAULT, 4);
+ lv_style_set_bg_opa(&style_chart_serie, LV_STATE_DEFAULT, 0);
}
@@ -465,7 +471,12 @@ static void theme_apply(lv_obj_t * obj, lv_theme_style_t name)
_lv_style_list_add_style(list, &style_bg);
_lv_style_list_add_style(list, &style_lmeter);
break;
-
+
+ case LV_THEME_CHART:
+ lv_obj_clean_style_list(obj, LV_CHART_PART_SERIES);
+ list = lv_obj_get_style_list(obj, LV_CHART_PART_SERIES);
+ _lv_style_list_add_style(list, &style_btn);
+ _lv_style_list_add_style(list, &style_chart_serie);
default:
break;
diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp
index 60039045..4083c4b2 100644
--- a/src/displayapp/screens/ApplicationList.cpp
+++ b/src/displayapp/screens/ApplicationList.cpp
@@ -45,7 +45,7 @@ bool ApplicationList::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
std::unique_ptr<Screen> ApplicationList::CreateScreen1() {
std::array<Screens::Tile::Applications, 6> applications {
- {{Symbols::clock, Apps::Clock},
+ {{Symbols::info, Apps::Notifications},
{Symbols::music, Apps::Music},
{Symbols::sun, Apps::Brightness},
{Symbols::list, Apps::SysInfo},
@@ -64,7 +64,7 @@ std::unique_ptr<Screen> ApplicationList::CreateScreen2() {
{{Symbols::map, Apps::Navigation},
{Symbols::stopWatch, Apps::StopWatch},
{Symbols::paintbrush, Apps::Paint},
- {Symbols::info, Apps::Notifications},
+ {Symbols::shoe, Apps::Motion},
{Symbols::paddle, Apps::Paddle},
{"2", Apps::Twos}
}
diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp
index 69180370..1cbd0a91 100644
--- a/src/displayapp/screens/Clock.cpp
+++ b/src/displayapp/screens/Clock.cpp
@@ -8,6 +8,7 @@
#include "NotificationIcon.h"
#include "Symbols.h"
#include "components/battery/BatteryController.h"
+#include "components/motion/MotionController.h"
#include "components/ble/BleController.h"
#include "components/ble/NotificationManager.h"
#include "../DisplayApp.h"
@@ -23,12 +24,14 @@ Clock::Clock(DisplayApp* app,
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings &settingsController,
- Controllers::HeartRateController& heartRateController) : Screen(app),
+ Controllers::HeartRateController& heartRateController,
+ Controllers::MotionController& motionController) : Screen(app),
dateTimeController{dateTimeController}, batteryController{batteryController},
bleController{bleController}, notificatioManager{notificatioManager},
settingsController{settingsController},
heartRateController{heartRateController},
- screens{app,
+ motionController{motionController},
+ screens{app,
settingsController.GetClockFace(),
{
[this]() -> std::unique_ptr<Screen> { return WatchFaceDigitalScreen(); },
@@ -64,7 +67,7 @@ bool Clock::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
}
std::unique_ptr<Screen> Clock::WatchFaceDigitalScreen() {
- return std::make_unique<Screens::WatchFaceDigital>(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController, heartRateController);
+ return std::make_unique<Screens::WatchFaceDigital>(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController, heartRateController, motionController);
}
std::unique_ptr<Screen> Clock::WatchFaceAnalogScreen() {
diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h
index 964ccbf6..95968c5c 100644
--- a/src/displayapp/screens/Clock.h
+++ b/src/displayapp/screens/Clock.h
@@ -17,6 +17,7 @@ namespace Pinetime {
class Battery;
class Ble;
class NotificationManager;
+ class MotionController;
}
namespace Applications {
@@ -29,7 +30,8 @@ namespace Pinetime {
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings &settingsController,
- Controllers::HeartRateController& heartRateController);
+ Controllers::HeartRateController& heartRateController,
+ Controllers::MotionController& motionController);
~Clock() override;
bool Refresh() override;
@@ -44,6 +46,7 @@ namespace Pinetime {
Controllers::NotificationManager& notificatioManager;
Controllers::Settings& settingsController;
Controllers::HeartRateController& heartRateController;
+ Controllers::MotionController& motionController;
ScreenList<2> screens;
diff --git a/src/displayapp/screens/Motion.cpp b/src/displayapp/screens/Motion.cpp
new file mode 100644
index 00000000..ed4b8198
--- /dev/null
+++ b/src/displayapp/screens/Motion.cpp
@@ -0,0 +1,59 @@
+#include <libs/lvgl/lvgl.h>
+#include "Motion.h"
+#include "../DisplayApp.h"
+
+using namespace Pinetime::Applications::Screens;
+extern lv_font_t jetbrains_mono_extrabold_compressed;
+extern lv_font_t jetbrains_mono_bold_20;
+
+
+Motion::Motion(Pinetime::Applications::DisplayApp *app, Controllers::MotionController& motionController) : Screen(app), motionController{motionController} {
+ chart = lv_chart_create(lv_scr_act(), NULL);
+ lv_obj_set_size(chart, 240, 240);
+ lv_obj_align(chart, NULL, LV_ALIGN_IN_TOP_MID, 0, 0);
+ lv_chart_set_type(chart, LV_CHART_TYPE_LINE); /*Show lines and points too*/
+ //lv_chart_set_series_opa(chart, LV_OPA_70); /*Opacity of the data series*/
+ //lv_chart_set_series_width(chart, 4); /*Line width and point radious*/
+
+ lv_chart_set_range(chart, -1100, 1100);
+ lv_chart_set_update_mode(chart, LV_CHART_UPDATE_MODE_SHIFT);
+ lv_chart_set_point_count(chart, 10);
+
+ /*Add 3 data series*/
+ ser1 = lv_chart_add_series(chart, LV_COLOR_RED);
+ ser2 = lv_chart_add_series(chart, LV_COLOR_GREEN);
+ ser3 = lv_chart_add_series(chart, LV_COLOR_YELLOW);
+
+ lv_chart_init_points(chart, ser1, 0);
+ lv_chart_init_points(chart, ser2, 0);
+ lv_chart_init_points(chart, ser3, 0);
+ lv_chart_refresh(chart); /*Required after direct set*/
+
+ labelStep = lv_label_create(lv_scr_act(), NULL);
+ lv_obj_align(labelStep, chart, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
+ lv_label_set_text(labelStep, "Steps: ");
+
+ labelStepValue = lv_label_create(lv_scr_act(), NULL);
+ lv_obj_align(labelStepValue, labelStep, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
+ lv_label_set_text(labelStepValue, "-");
+}
+
+Motion::~Motion() {
+ lv_obj_clean(lv_scr_act());
+}
+
+bool Motion::Refresh() {
+ lv_chart_set_next(chart, ser1, motionController.X());
+ lv_chart_set_next(chart, ser2, motionController.Y());
+ lv_chart_set_next(chart, ser3, motionController.Z());
+
+ snprintf(nbStepsBuffer, nbStepsBufferSize, "%lu", motionController.NbSteps());
+ lv_label_set_text(labelStepValue, nbStepsBuffer);
+
+ return running;
+}
+
+bool Motion::OnButtonPushed() {
+ running = false;
+ return true;
+}
diff --git a/src/displayapp/screens/Motion.h b/src/displayapp/screens/Motion.h
new file mode 100644
index 00000000..ad1341a8
--- /dev/null
+++ b/src/displayapp/screens/Motion.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <cstdint>
+#include <chrono>
+#include "Screen.h"
+#include <bits/unique_ptr.h>
+#include <libs/lvgl/src/lv_core/lv_style.h>
+#include <libs/lvgl/src/lv_core/lv_obj.h>
+#include <components/motion/MotionController.h>
+
+namespace Pinetime {
+ namespace Applications {
+ namespace Screens {
+
+ class Motion : public Screen{
+ public:
+ Motion(DisplayApp* app, Controllers::MotionController& motionController);
+ ~Motion() override;
+
+ bool Refresh() override;
+ bool OnButtonPushed() override;
+
+ private:
+ Controllers::MotionController& motionController;
+ lv_obj_t * chart;
+ lv_chart_series_t * ser1;
+ lv_chart_series_t * ser2;
+ lv_chart_series_t * ser3;
+
+ lv_obj_t* labelStep;
+ lv_obj_t* labelStepValue;
+ static constexpr uint8_t nbStepsBufferSize = 9;
+ char nbStepsBuffer[nbStepsBufferSize+1];
+ bool running = true;
+
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp
index c39fe496..2204e177 100644
--- a/src/displayapp/screens/WatchFaceDigital.cpp
+++ b/src/displayapp/screens/WatchFaceDigital.cpp
@@ -11,6 +11,7 @@
#include "components/ble/BleController.h"
#include "components/ble/NotificationManager.h"
#include "components/heartrate/HeartRateController.h"
+#include "components/motion/MotionController.h"
#include "components/settings/Settings.h"
#include "../DisplayApp.h"
@@ -23,11 +24,13 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings &settingsController,
- Controllers::HeartRateController& heartRateController): Screen(app), currentDateTime{{}},
+ Controllers::HeartRateController& heartRateController,
+ Controllers::MotionController& motionController) : Screen(app), currentDateTime{{}},
dateTimeController{dateTimeController}, batteryController{batteryController},
bleController{bleController}, notificatioManager{notificatioManager},
settingsController{settingsController},
- heartRateController{heartRateController} {
+ heartRateController{heartRateController},
+ motionController{motionController} {
settingsController.SetClockFace(0);
displayedChar[0] = 0;
@@ -236,7 +239,7 @@ bool WatchFaceDigital::Refresh() {
lv_obj_align(heartbeatBpm, heartbeatValue, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
}
- // TODO stepCount = stepController.GetValue();
+ stepCount = motionController.NbSteps();
if(stepCount.IsUpdated()) {
char stepBuffer[5];
sprintf(stepBuffer, "%lu", stepCount.Get());
diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h
index 70a9ce5d..e6514f1e 100644
--- a/src/displayapp/screens/WatchFaceDigital.h
+++ b/src/displayapp/screens/WatchFaceDigital.h
@@ -15,6 +15,7 @@ namespace Pinetime {
class Ble;
class NotificationManager;
class HeartRateController;
+ class MotionController;
}
namespace Applications {
@@ -28,7 +29,8 @@ namespace Pinetime {
Controllers::Ble& bleController,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings &settingsController,
- Controllers::HeartRateController& heartRateController);
+ Controllers::HeartRateController& heartRateController,
+ Controllers::MotionController& motionController);
~WatchFaceDigital() override;
bool Refresh() override;
@@ -73,6 +75,7 @@ namespace Pinetime {
Controllers::NotificationManager& notificatioManager;
Controllers::Settings& settingsController;
Controllers::HeartRateController& heartRateController;
+ Controllers::MotionController& motionController;
bool running = true;
diff --git a/src/drivers/Bma421.cpp b/src/drivers/Bma421.cpp
new file mode 100644
index 00000000..f1dd934a
--- /dev/null
+++ b/src/drivers/Bma421.cpp
@@ -0,0 +1,122 @@
+#include <libraries/delay/nrf_delay.h>
+#include <libraries/log/nrf_log.h>
+#include "Bma421.h"
+#include "TwiMaster.h"
+#include <drivers/Bma421_C/bma423.h>
+
+using namespace Pinetime::Drivers;
+
+int8_t user_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) {
+ auto bma421 = static_cast<Bma421*>(intf_ptr);
+ bma421->Read(reg_addr, reg_data, length);
+ return 0;
+}
+
+int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) {
+ auto bma421 = static_cast<Bma421*>(intf_ptr);
+ bma421->Write(reg_addr, reg_data, length);
+ return 0;
+}
+
+void user_delay(uint32_t period_us, void *intf_ptr) {
+ nrf_delay_us(period_us);
+}
+
+Bma421::Bma421(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster{twiMaster}, twiAddress{twiAddress} {
+ bma.intf = BMA4_I2C_INTF;
+ bma.bus_read = user_i2c_read;
+ bma.bus_write = user_i2c_write;
+ bma.variant = BMA42X_VARIANT;
+ bma.intf_ptr = this;
+ bma.delay_us = user_delay;
+ bma.read_write_len = 8;
+
+ accel_conf.odr = BMA4_OUTPUT_DATA_RATE_100HZ;
+ accel_conf.range = BMA4_ACCEL_RANGE_2G;
+ accel_conf.bandwidth = BMA4_ACCEL_NORMAL_AVG4;
+ accel_conf.perf_mode = BMA4_CIC_AVG_MODE;
+
+
+}
+
+void Bma421::Init() {
+ auto ret = bma4_soft_reset(&bma);
+ ASSERT(ret == BMA4_OK);
+
+ nrf_delay_ms(1);
+
+ ret = bma423_init(&bma);
+ NRF_LOG_INFO("RESET : %d", ret);
+
+ //ret = bma423_init(&bma);
+ //NRF_LOG_INFO("ID : %d", bma.chip_id);
+ ASSERT(ret == BMA4_OK);
+
+ ret = bma423_write_config_file(&bma);
+ ASSERT(ret == BMA4_OK);
+
+ bma4_set_interrupt_mode(BMA4_LATCH_MODE, &bma);
+ struct bma4_int_pin_config int_pin_config;
+ int_pin_config.edge_ctrl = BMA4_LEVEL_TRIGGER;
+ int_pin_config.lvl = BMA4_ACTIVE_LOW;
+ int_pin_config.od = BMA4_PUSH_PULL;
+ int_pin_config.output_en = BMA4_OUTPUT_ENABLE;
+ int_pin_config.input_en = BMA4_INPUT_DISABLE;
+ bma4_set_int_pin_config(&int_pin_config, BMA4_INTR1_MAP, &bma);
+
+ //ret = bma423_feature_enable(BMA423_STEP_CNTR | BMA423_STEP_ACT | BMA423_WRIST_WEAR | BMA423_SINGLE_TAP | BMA423_DOUBLE_TAP, 1, &bma);
+ ret = bma423_feature_enable(0xff, 1, &bma);
+ ASSERT(ret == BMA4_OK);
+
+ //ret = bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_SINGLE_TAP_INT | BMA423_STEP_CNTR_INT | BMA423_ACTIVITY_INT | BMA423_WRIST_WEAR_INT | BMA423_DOUBLE_TAP_INT | BMA423_ANY_MOT_INT | BMA423_NO_MOT_INT| BMA423_ERROR_INT, 1,&bma);
+ ret = bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT, 1,&bma);
+ ASSERT(ret == BMA4_OK);
+
+ bma423_step_detector_enable(0, &bma);
+
+ bma423_any_no_mot_config motConfig;
+ motConfig.threshold = 0xaa;
+ motConfig.axes_en = 3;
+ motConfig.duration = 1;
+ bma423_set_any_mot_config(&motConfig, &bma);
+
+ ret = bma4_set_accel_enable(1, &bma);
+ ASSERT(ret == BMA4_OK);
+
+ ret = bma4_set_accel_config(&accel_conf, &bma);
+ ASSERT(ret == BMA4_OK);
+}
+
+void Bma421::Reset() {
+ uint8_t data = 0xb6;
+ twiMaster.Write(deviceAddress, 0x7E, &data, 1);
+}
+
+void Bma421::Read(uint8_t registerAddress, uint8_t *buffer, size_t size) {
+ twiMaster.Read(deviceAddress, registerAddress, buffer, size);
+}
+
+void Bma421::Write(uint8_t registerAddress, const uint8_t *data, size_t size) {
+ twiMaster.Write(deviceAddress, registerAddress, data, size);
+}
+
+Bma421::Values Bma421::Process() {
+ struct bma4_accel data;
+ bma4_read_accel_xyz(&data, &bma);
+
+ uint32_t steps = 0;
+ bma423_step_counter_output(&steps, &bma);
+
+ int32_t temperature;
+ bma4_get_temperature(&temperature, BMA4_DEG, &bma);
+ temperature = temperature / 1000;
+
+ uint8_t activity = 0;
+ bma423_activity_output(&activity, &bma);
+
+ NRF_LOG_INFO("MOTION : %d - %d/%d/%d", steps, data.x, data.y, data.z);
+
+
+ return {steps, data.x, data.y, data.z};
+}
+
diff --git a/src/drivers/Bma421.h b/src/drivers/Bma421.h
new file mode 100644
index 00000000..bcc06b1c
--- /dev/null
+++ b/src/drivers/Bma421.h
@@ -0,0 +1,43 @@
+#pragma once
+#include <drivers/Bma421_C/bma4_defs.h>
+
+namespace Pinetime {
+ namespace Drivers {
+ class TwiMaster;
+ class Bma421 {
+ public:
+ struct Values {
+ uint32_t steps;
+ int16_t x;
+ int16_t y;
+ int16_t z;
+ };
+ Bma421(TwiMaster& twiMaster, uint8_t twiAddress);
+ Bma421(const Bma421&) = delete;
+ Bma421& operator=(const Bma421&) = delete;
+ Bma421(Bma421&&) = delete;
+ Bma421& operator=(Bma421&&) = delete;
+
+ void Init();
+ void Reset();
+ Values Process();
+
+ void Read(uint8_t registerAddress, uint8_t *buffer, size_t size);
+ void Write(uint8_t registerAddress, const uint8_t *data, size_t size);
+
+ void OnIrq();
+
+ uint32_t GetNbInterrupts() const {return nbInterrupts;}
+
+ private:
+ TwiMaster& twiMaster;
+ uint8_t twiAddress;
+
+ struct bma4_dev bma;
+ struct bma4_accel_config accel_conf;
+ static constexpr uint8_t deviceAddress = 0x18;
+
+ uint32_t nbInterrupts = 0;
+ };
+ }
+} \ No newline at end of file
diff --git a/src/drivers/Bma421_C/bma4.c b/src/drivers/Bma421_C/bma4.c
new file mode 100644
index 00000000..59e2a72e
--- /dev/null
+++ b/src/drivers/Bma421_C/bma4.c
@@ -0,0 +1,5689 @@
+/**
+ * Copyright (c) 2020 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 bma4.c
+ * @date 2020-05-08
+ * @version V2.14.13
+ *
+ */
+
+/*
+ * @file bma4.c
+ * @brief Source file for the BMA4 Sensor API
+ */
+
+/***************************************************************************/
+
+/*!
+ * @defgroup bma4 BMA4
+ */
+
+/**\name Header files
+ ****************************************************************************/
+#include "bma4.h"
+
+/***************************************************************************/
+
+/**\name Local structures
+ ****************************************************************************/
+
+/*!
+ * @brief Accel data deviation from ideal value
+ */
+struct bma4_offset_delta
+{
+ /*! X axis */
+ int16_t x;
+
+ /*! Y axis */
+ int16_t y;
+
+ /*! Z axis */
+ int16_t z;
+};
+
+/*!
+ * @brief Accel offset xyz structure
+ */
+struct bma4_accel_offset
+{
+ /*! Accel offset X data */
+ uint8_t x;
+
+ /*! Accel offset Y data */
+ uint8_t y;
+
+ /*! Accel offset Z data */
+ uint8_t z;
+};
+
+/***************************************************************************/
+
+/*! Static Function Declarations
+ ****************************************************************************/
+
+/*!
+ * @brief This API validates the bandwidth and perfmode
+ * value set by the user.
+ *
+ * param bandwidth[in] : bandwidth value set by the user.
+ * param perf_mode[in] : perf_mode value set by the user.
+ */
+static int8_t validate_bandwidth_perfmode(uint8_t bandwidth, uint8_t perf_mode);
+
+/*!
+ * @brief @brief This API validates the ODR value set by the user.
+ *
+ * param bandwidth[in] : odr for accelerometer
+ */
+static int8_t validate_odr(uint8_t odr);
+
+/*!
+ * @brief This API is used to reset the FIFO related configurations
+ * in the fifo_frame structure.
+ *
+ * @param fifo[in,out] : Structure instance of bma4_fifo_frame
+ *
+ */
+static void reset_fifo_data_structure(struct bma4_fifo_frame *fifo);
+
+/*!
+ * @brief This API computes the number of bytes of accel FIFO data
+ * which is to be parsed in header-less mode
+ *
+ * @param[out] start_idx : The start index for parsing data
+ * @param[out] len : Number of bytes to be parsed
+ * @param[in] acc_count : Number of accelerometer frames to be read
+ * @param[in] fifo : Structure instance of bma4_fifo_frame.
+ *
+ */
+static void get_accel_len_to_parse(uint16_t *start_idx,
+ uint16_t *len,
+ const uint16_t *acc_count,
+ const struct bma4_fifo_frame *fifo);
+
+/*!
+ * @brief This API checks the fifo read data as empty frame, if it
+ * is empty frame then moves the index to last byte.
+ *
+ * @param[in,out] data_index : The index of the current data to
+ * be parsed from fifo data
+ * @param[in] fifo : Structure instance of bma4_fifo_frame.
+ */
+static void check_empty_fifo(uint16_t *data_index, const struct bma4_fifo_frame *fifo);
+
+/*!
+ * @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 bma4_accel where
+ * the accelerometer data in FIFO is stored.
+ * @param[in,out] accel_length : Number of accelerometer frames
+ * (x,y,z axes data)
+ * @param[in,out] fifo : Structure instance of bma4_fifo_frame
+ * @param[in,out] dev : Structure instance of bma4_dev.
+ *
+ */
+static void extract_accel_header_mode(struct bma4_accel *accel_data,
+ uint16_t *accel_length,
+ struct bma4_fifo_frame *fifo,
+ const struct bma4_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 update 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 bma4_accel.
+ * @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) frame to be parsed
+ * @param[in] frm : It consists of either fifo_data_enable
+ * parameter (Accel and/or mag data enabled in FIFO)
+ * in header-less mode or frame header data
+ * in header mode
+ * @param[in] fifo : Structure instance of bma4_fifo_frame.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ */
+static void unpack_acc_frm(struct bma4_accel *acc,
+ uint16_t *idx,
+ uint16_t *acc_idx,
+ uint8_t frm,
+ const struct bma4_fifo_frame *fifo,
+ const struct bma4_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 bma4_accel.
+ *
+ * @param[out] accel_data : Structure instance of bma4_accel where
+ * the parsed accel data bytes are stored.
+ * @param[in] data_start_index : Index value of the accel data bytes
+ * which is to be parsed from the fifo data.
+ * @param[in] fifo : Structure instance of bma4_fifo_frame.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ */
+static void unpack_accel_data(struct bma4_accel *accel_data,
+ uint16_t data_start_index,
+ const struct bma4_fifo_frame *fifo,
+ const struct bma4_dev *dev);
+
+/*!
+ * @brief This API computes the number of bytes of Mag FIFO data which is
+ * to be parsed in header-less mode
+ *
+ * @param[out] start_idx : The start index for parsing data
+ * @param[out] len : Number of bytes to be parsed
+ * @param[in] mag_count : Number of magnetometer frames to be read
+ * @param[in] fifo : Structure instance of bma4_fifo_frame.
+ *
+ */
+static void get_mag_len_to_parse(uint16_t *start_idx,
+ uint16_t *len,
+ const uint16_t *mag_count,
+ const struct bma4_fifo_frame *fifo);
+
+/*!
+ * @brief This API is used to parse the magnetometer data from the
+ * FIFO data in header mode.
+ *
+ * @param[in,out] data : Structure instance of bma4_mag_xyzr where
+ * the magnetometer data in FIFO is extracted
+ * and stored.
+ * @param[in,out] len : Number of magnetometer frames
+ * (x,y,z,r data)
+ * @param[in,out] fifo : Structure instance of bma4_fifo_frame.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+static int8_t extract_mag_header_mode(const struct bma4_mag *data,
+ uint16_t *len,
+ struct bma4_fifo_frame *fifo,
+ const struct bma4_dev *dev);
+
+/*!
+ * @brief This API is used to parse the magnetometer data from the
+ * FIFO data in both header mode and header-less mode and update the
+ * idx value which is used to store the index of the current
+ * data byte which is parsed.
+ *
+ * @param data : Structure instance of bma4_mag_xyzr.
+ * @param idx : Index value of number of bytes parsed
+ * @param mag_idx : Index value magnetometer data frame (x,y,z,r)
+ * to be parsed
+ * @param frm : It consists of either the fifo_data_enable parameter
+ * (Accel and/or mag data enabled in FIFO) in
+ * header-less mode and frame header data in header mode
+ * @param fifo : Structure instance of bma4_fifo_frame.
+ * @param dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+static int8_t unpack_mag_frm(const struct bma4_mag *data,
+ uint16_t *idx,
+ uint16_t *mag_idx,
+ uint8_t frm,
+ const struct bma4_fifo_frame *fifo,
+ const struct bma4_dev *dev);
+
+/*!
+ * @brief This API is used to parse the auxiliary magnetometer data from
+ * the FIFO data and store it in the instance of the structure mag_data.
+ *
+ * @param mag_data : Structure instance of bma4_mag_xyzr where the
+ * parsed magnetometer data bytes are stored.
+ * @param start_idx : Index value of the magnetometer data bytes
+ * which is to be parsed from the FIFO data
+ * @param fifo : Structure instance of bma4_fifo_frame.
+ * @param dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+static int8_t unpack_mag_data(const struct bma4_mag *mag_data,
+ uint16_t start_idx,
+ const struct bma4_fifo_frame *fifo,
+ const struct bma4_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,out] fifo : Structure instance of bma4_fifo_frame.
+ *
+ */
+static void unpack_sensortime_frame(uint16_t *data_index, struct bma4_fifo_frame *fifo);
+
+/*!
+ * @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,out] fifo : Structure instance of bma4_fifo_frame.
+ *
+ */
+static void unpack_skipped_frame(uint16_t *data_index, struct bma4_fifo_frame *fifo);
+
+/*!
+ * @brief This API is used to parse and store the dropped_frame_count from
+ * the FIFO data in the structure instance dev.
+ *
+ * @param[in,out] data_index : Index of the FIFO data which
+ * has the dropped frame data.
+ * @param[in,out] fifo : Structure instance of bma4_fifo_frame.
+ *
+ */
+static void unpack_dropped_frame(uint16_t *data_index, struct bma4_fifo_frame *fifo);
+
+/*!
+ * @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] fifo : Structure instance of bma4_fifo_frame.
+ *
+ */
+static void move_next_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bma4_fifo_frame *fifo);
+
+/*!
+ * @brief This API writes the config stream data in memory using burst mode
+ *
+ * @param[in] stream_data : Pointer to store data of 32 bytes
+ * @param[in] index : Represents value in multiple of 32 bytes
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+static int8_t stream_transfer_write(const uint8_t *stream_data, uint16_t index, struct bma4_dev *dev);
+
+/*!
+ * @brief This API enables or disables the Accel self-test feature in the
+ * sensor.
+ *
+ * @param[in] accel_self-test_enable : Variable used to enable or disable
+ * the Accel self-test feature
+ * Value | Description
+ * --------|---------------
+ * 0x00 | BMA4_DISABLE
+ * 0x01 | BMA4_ENABLE
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+static int8_t set_accel_selftest_enable(uint8_t accel_selftest_axis, struct bma4_dev *dev);
+
+/*!
+ * @brief This API selects the sign of Accel self-test excitation
+ *
+ * @param[in] accel_selftest_sign: Variable used to select the Accel
+ * self-test sign
+ * Value | Description
+ * --------|--------------------------
+ * 0x00 | BMA4_DISABLE (negative)
+ * 0x01 | BMA4_ENABLE (positive)
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+static int8_t set_accel_selftest_sign(uint8_t accel_selftest_sign, struct bma4_dev *dev);
+
+/*!
+ * @brief This API sets the Accel self-test amplitude in the sensor.
+ *
+ * @param[in] accel_selftest_amp : Variable used to specify the Accel self
+ * test amplitude
+ * Value | Description
+ * --------|------------------------------------
+ * 0x00 | BMA4_SELFTEST_AMP_LOW
+ * 0x01 | BMA4_SELFTEST_AMP_HIGH
+ *
+ * @param[in] dev : structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+static int8_t set_accel_selftest_amp(uint8_t accel_selftest_amp, struct bma4_dev *dev);
+
+/*!
+ * @brief This function enables and configures the Accel which is needed
+ * for self-test operation.
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return results of self-test
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+static int8_t set_accel_selftest_config(struct bma4_dev *dev);
+
+/*!
+ * @brief This function validates the Accel self-test data and decides the
+ * result of self-test operation.
+ *
+ * @param[in] accel_data_diff : Pointer to structure variable which holds
+ * the Accel data difference of self-test operation
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return results of self-test operation
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+static int8_t validate_selftest(const struct bma4_selftest_delta_limit *accel_data_diff, const struct bma4_dev *dev);
+
+/*!
+ * @brief This API converts lsb value of axes to mg for self-test
+ *
+ * @param[in] accel_data_diff : Pointer variable used to pass accel difference
+ * values in g
+ * @param[out] accel_data_diff_mg : Pointer variable used to store accel
+ * difference values in mg
+ * @param[out] dev : Structure instance of bma4_dev
+ *
+ */
+static void convert_lsb_g(const struct bma4_selftest_delta_limit *accel_data_diff,
+ struct bma4_selftest_delta_limit *accel_data_diff_mg,
+ const struct bma4_dev *dev);
+
+/*!
+ * @brief This API sets the feature config. data start address in the sensor.
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+static int8_t set_feature_config_start_addr(struct bma4_dev *dev);
+
+/*!
+ * @brief This API increments the feature config. data address according to the user
+ * provided read/write length in the dev structure.
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+static int8_t increment_feature_config_addr(struct bma4_dev *dev);
+
+/*!
+ * @brief This API reads the 8-bit data from the given register
+ * in the sensor.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+static int8_t read_regs(uint8_t addr, uint8_t *data, uint32_t len, struct bma4_dev *dev);
+
+/*!
+ * @brief This API writes the 8-bit data to the given register
+ * in the sensor.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+static int8_t write_regs(uint8_t addr, const uint8_t *data, uint32_t len, struct bma4_dev *dev);
+
+/*!
+ * @brief This API sets the feature config. data start address in the sensor.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+static int8_t get_feature_config_start_addr(struct bma4_dev *dev);
+
+/*!
+ * @brief This API is used to calculate the power of given
+ * base value.
+ *
+ * @param[in] base : value of base
+ * @param[in] resolution : resolution of the sensor
+ *
+ * @return : Return the value of base^resolution
+ */
+static int32_t power(int16_t base, uint8_t resolution);
+
+/*!
+ * @brief This API finds the the null error of the device pointer structure
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval BMA4_OK -> Success
+ * @retval BMA4_E_NULL_PTR -> Null pointer Error
+ */
+static int8_t null_pointer_check(const struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API brings up the secondary interface to access
+ * auxiliary sensor
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+static int8_t set_aux_interface_config(struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API reads the data from the auxiliary sensor
+ * depending on burst length configured
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ * @param[out] aux_data : Pointer variable to store data read
+ * @param[in] aux_reg_addr : Variable to pass address from where
+ * data is to be read
+ *
+ * @return Result of API execution status
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+static int8_t extract_aux_data(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API maps the actual burst read length with user length set.
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ * @param[out] len : Pointer variable to store mapped length
+ *
+ * @return Result of API execution status
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+static int8_t map_read_len(uint8_t *len, const struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API validates accel self-test status from positive and negative axes input
+ *
+ * @param[in] positive : Positive accel data.
+ * @param[in] negative : Negative accel data.
+ * @param[in/out] accel_data_diff_mg : accel data difference data between positive and negative in mg.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+static int8_t get_accel_data_difference_and_validate(struct bma4_accel positive,
+ struct bma4_accel negative,
+ struct bma4_selftest_delta_limit *accel_data_diff_mg,
+ const struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API is used to verify the right position of the sensor before doing accel FOC
+ *
+ * @param[in] accel_en : Variable to store status of accel
+ * @param[in] accel_g_axis : Accel FOC axis and sign input
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ *
+ * @retval BMA4_OK - Success.
+ * @retval BMA4_E_NULL_PTR - Error: Null pointer error
+ */
+static int8_t verify_foc_position(uint8_t accel_en,
+ const struct bma4_accel_foc_g_value *accel_g_axis,
+ struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API reads and provides average for 128 samples of sensor data for accel FOC operation
+ *
+ * @param[in] accel_en : Variable to store status of accel
+ * @param[in] temp_foc_data : Store data samples.
+ * @param[in] bma4_dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ *
+ * @retval BMA4_OK
+ * @retval BMA4_E_NULL_PTR - Error: Null pointer error
+ */
+static int8_t get_average_of_sensor_data(uint8_t accel_en,
+ struct bma4_foc_temp_value *temp_foc_data,
+ struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API validates accel FOC position as per the range
+ *
+ * @param[in] accel_en : Variable to store status of accel
+ * @param[in] accel_g_axis : Accel axis to FOC
+ * @param[in] avg_foc_data : Average value of sensor sample datas
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ *
+ * @retval BMA4_OK - Success.
+ * @retval BMA4_E_FAIL - Fail.
+ */
+static int8_t validate_foc_position(uint8_t accel_en,
+ const struct bma4_accel_foc_g_value *accel_g_axis,
+ struct bma4_accel avg_foc_data,
+ struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API validates accel FOC axis given as input
+ *
+ * @param[in] avg_foc_data : Average value of sensor sample datas
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ *
+ * @retval BMA4_OK - Success.
+ * @retval BMA4_E_FOC_FAIL - Error: FOC fail
+ */
+static int8_t validate_foc_accel_axis(int16_t avg_foc_data, struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API saves the configurations before performing FOC.
+ *
+ * @param[out] acc_cfg : Accelerometer configuration value
+ * @param[out] aps : Advance power mode value
+ * @param[out] acc_en : Accelerometer enable value
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval BMA4_OK - Success.
+ * @retval BMA4_E_COM_FAIL - Error: Communication fail
+ * @retval BMA4_E_INVALID_SENSOR - Error: Invalid sensor
+ */
+static int8_t save_accel_foc_config(struct bma4_accel_config *acc_cfg,
+ uint8_t *aps,
+ uint8_t *acc_en,
+ struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API sets configurations for performing accelerometer FOC.
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval BMA4_OK - Success.
+ * @retval BMA4_E_COM_FAIL - Error: Communication fail
+ * @retval BMA4_E_INVALID_SENSOR - Error: Invalid sensor
+ */
+static int8_t set_accel_foc_config(struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API enables/disables the offset compensation for
+ * filtered and un-filtered accelerometer data.
+ *
+ * @param[in] offset_en : Enables/Disables offset compensation.
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval BMA4_OK - Success.
+ * @retval BMA4_E_COM_FAIL - Error: Communication fail
+ */
+static int8_t set_bma4_accel_offset_comp(uint8_t offset_en, struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API performs Fast Offset Compensation for accelerometer.
+ *
+ * @param[in] accel_g_value : This parameter selects the accel FOC
+ * axis to be performed
+ *
+ * Input format is {x, y, z, sign}. '1' to enable. '0' to disable
+ *
+ * Eg:- To choose x axis {1, 0, 0, 0}
+ * Eg:- To choose -x axis {1, 0, 0, 1}
+ *
+ * @param[in] acc_cfg : Accelerometer configuration value
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ *
+ * @retval BMA4_OK - Success.
+ * @retval BMA4_E_NULL_PTR - Error: Null pointer error
+ * @retval BMA4_E_COM_FAIL - Error: Communication fail
+ */
+static int8_t perform_accel_foc(const struct bma4_accel_foc_g_value *accel_g_value,
+ const struct bma4_accel_config *acc_cfg,
+ struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API converts the range value into accelerometer
+ * corresponding integer value.
+ *
+ * @param[in] range_in : Input range value.
+ * @param[out] range_out : Stores the integer value of range.
+ *
+ * @return None
+ * @retval None
+ */
+static void map_accel_range(uint8_t range_in, uint8_t *range_out);
+
+/*!
+ * @brief This internal API compensate the accelerometer data against gravity.
+ *
+ * @param[in] lsb_per_g : LSB value per 1g.
+ * @param[in] g_val : Gravity reference value of all axes.
+ * @param[in] data : Accelerometer data
+ * @param[out] comp_data : Stores the data that is compensated by taking the
+ * difference in accelerometer data and lsb_per_g
+ * value.
+ *
+ * @return None
+ * @retval None
+ */
+static void comp_for_gravity(uint16_t lsb_per_g,
+ const struct bma4_accel_foc_g_value *g_val,
+ const struct bma4_accel *data,
+ struct bma4_offset_delta *comp_data);
+
+/*!
+ * @brief This internal API scales the compensated accelerometer data according
+ * to the offset register resolution.
+ *
+ * @param[in] range : Gravity range of the accelerometer.
+ * @param[out] comp_data : Data that is compensated by taking the
+ * difference in accelerometer data and lsb_per_g
+ * value.
+ * @param[out] data : Stores offset data
+ *
+ * @return None
+ * @retval None
+ */
+static void scale_bma4_accel_offset(uint8_t range,
+ const struct bma4_offset_delta *comp_data,
+ struct bma4_accel_offset *data);
+
+/*!
+ * @brief This internal API inverts the accelerometer offset data.
+ *
+ * @param[out] offset_data : Stores the inverted offset data
+ *
+ * @return None
+ * @retval None
+ */
+static void invert_bma4_accel_offset(struct bma4_accel_offset *offset_data);
+
+/*!
+ * @brief This internal API writes the offset data in the offset compensation
+ * register.
+ *
+ * @param[in] offset : Offset data
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval BMA4_OK - Success.
+ * @retval BMA4_E_COM_FAIL - Error: Communication fail
+ */
+static int8_t write_bma4_accel_offset(const struct bma4_accel_offset *offset, struct bma4_dev *dev);
+
+/*!
+ * @brief This internal API finds the bit position of 3.9mg according to given
+ * range and resolution.
+ *
+ * @param[in] range : Gravity range of the accelerometer.
+ *
+ * @return Result of API execution status
+ * @retval Bit position of 3.9mg
+ */
+static int8_t get_bit_pos_3_9mg(uint8_t range);
+
+/*!
+ * @brief This internal API restores the configurations saved before performing
+ * accelerometer FOC.
+ *
+ * @param[in] acc_cfg : Accelerometer configuration value
+ * @param[in] aps : Advance power mode value
+ * @param[in] acc_en : Accelerometer enable value
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval BMA4_OK - Success.
+ * @retval BMA4_E_COM_FAIL - Error: Communication fail
+ * @retval BMA4_E_INVALID_SENSOR - Error: Invalid sensor
+ * @retval BMA4_E_SET_APS_FAIL - Error: Set Advance Power Save Fail
+ */
+static int8_t restore_accel_foc_config(const struct bma4_accel_config *acc_cfg,
+ uint8_t aps,
+ uint8_t acc_en,
+ struct bma4_dev *dev);
+
+/***************************************************************************/
+
+/**\name Extern Declarations
+ ****************************************************************************/
+
+/***************************************************************************/
+
+/**\name Globals
+ ****************************************************************************/
+
+/***************************************************************************/
+
+/**\name Function definitions
+ ****************************************************************************/
+
+/*!
+ * @brief This API is the entry point.
+ * Call this API before using all other APIs.
+ * This API reads the chip-id of the sensor which is the first step to
+ * verify the sensor and also it configures the read mechanism of SPI and
+ * I2C interface.
+ */
+int8_t bma4_init(struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+ uint8_t dummy_read = 0;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ if (dev->intf == BMA4_SPI_INTF)
+ {
+ dev->dummy_byte = 1;
+ rslt = bma4_read_regs(BMA4_CHIP_ID_ADDR, &dummy_read, 1, dev);
+ }
+ else
+ {
+ dev->dummy_byte = 0;
+ }
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_read_regs(BMA4_CHIP_ID_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Assign Chip Id */
+ dev->chip_id = data;
+ }
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API is used to write the binary configuration in the sensor
+ */
+int8_t bma4_write_config_file(struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* Config loading disable*/
+ uint8_t config_load = 0;
+ uint16_t index = 0;
+ uint8_t config_stream_status = 0;
+
+ /* Disable advanced power save */
+ rslt = bma4_set_advance_power_save(BMA4_DISABLE, dev);
+
+ /* Wait for sensor time synchronization. Refer the data-sheet for
+ * more information
+ */
+ dev->delay_us(450, dev->intf_ptr);
+ if (rslt == BMA4_OK)
+ {
+ /* Disable config loading*/
+ rslt = bma4_write_regs(BMA4_INIT_CTRL_ADDR, &config_load, 1, dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Write the config stream */
+ for (index = 0; index < dev->config_size; index += dev->read_write_len)
+ {
+ rslt = stream_transfer_write((dev->config_file_ptr + index), index, dev);
+ }
+
+ if (rslt == BMA4_OK)
+ {
+ /* Enable config loading and FIFO mode */
+ config_load = 0x01;
+ rslt = bma4_write_regs(BMA4_INIT_CTRL_ADDR, &config_load, 1, dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Wait till ASIC is initialized. Refer the data-sheet for
+ * more information
+ */
+ dev->delay_us(BMA4_MS_TO_US(150), dev->intf_ptr);
+
+ /* Read the status of config stream operation */
+ rslt = bma4_read_regs(BMA4_INTERNAL_STAT, &config_stream_status, 1, dev);
+ config_stream_status = config_stream_status & BMA4_CONFIG_STREAM_MESSAGE_MSK;
+
+ if (rslt == BMA4_OK)
+ {
+ if (config_stream_status != BMA4_ASIC_INITIALIZED)
+ {
+ rslt = BMA4_E_CONFIG_STREAM_ERROR;
+ }
+ else
+ {
+ /* Enable advanced power save */
+ rslt = bma4_set_advance_power_save(BMA4_ENABLE, dev);
+ if (rslt == BMA4_OK)
+ {
+ rslt = get_feature_config_start_addr(dev);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API checks whether the write operation requested is for feature
+ * config or register write and accordingly writes the data in the sensor.
+ */
+int8_t bma4_write_regs(uint8_t addr, const uint8_t *data, uint32_t len, struct bma4_dev *dev)
+{
+ uint8_t i;
+ uint32_t loop_count;
+ uint16_t overflow;
+ uint16_t index;
+ int8_t rslt;
+ uint8_t adv_pwr_save = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (data != NULL))
+ {
+ if (addr == BMA4_FEATURE_CONFIG_ADDR)
+ {
+ /* Disable APS if enabled before writing the feature
+ * config register
+ */
+ rslt = bma4_get_advance_power_save(&adv_pwr_save, dev);
+ if ((adv_pwr_save == BMA4_ENABLE) && (rslt == BMA4_OK))
+ {
+ rslt = bma4_set_advance_power_save(BMA4_DISABLE, dev);
+
+ /* Wait for sensor time synchronization. Refer
+ * the data-sheet for more information
+ */
+ dev->delay_us(450, dev->intf_ptr);
+ }
+
+ if (((len % 2) == 0) && (len <= dev->feature_len) && (rslt == BMA4_OK))
+ {
+ if (dev->read_write_len < len)
+ {
+ /* Calculate the no of writes to be
+ * performed according to the read/write
+ * length
+ */
+ loop_count = len / dev->read_write_len;
+ overflow = len % dev->read_write_len;
+ index = 0;
+ rslt = set_feature_config_start_addr(dev);
+ if (rslt == BMA4_OK)
+ {
+ for (i = 0; i < loop_count; i++)
+ {
+ rslt = write_regs(BMA4_FEATURE_CONFIG_ADDR, data + index, dev->read_write_len, dev);
+ if (rslt == BMA4_OK)
+ {
+ rslt = increment_feature_config_addr(dev);
+ if (rslt == BMA4_OK)
+ {
+ index = index + dev->read_write_len;
+ }
+ }
+ }
+
+ if ((overflow) && (rslt == BMA4_OK))
+ {
+ rslt = write_regs(BMA4_FEATURE_CONFIG_ADDR, data + index, overflow, dev);
+ }
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = set_feature_config_start_addr(dev);
+ }
+ }
+ }
+ else
+ {
+ rslt = write_regs(BMA4_FEATURE_CONFIG_ADDR, data, len, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_RD_WR_LENGTH_INVALID;
+ }
+
+ if (rslt == BMA4_OK)
+ {
+ /* Enable APS if previously enabled */
+ if (adv_pwr_save == BMA4_ENABLE)
+ {
+ rslt = bma4_set_advance_power_save(BMA4_ENABLE, dev);
+
+ /* Wait for sensor time synchronization.
+ * Refer the data-sheet for more
+ * information
+ */
+ dev->delay_us(450, dev->intf_ptr);
+ }
+ }
+ }
+ else
+ {
+ rslt = write_regs(addr, data, len, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*! @cond DOXYGEN_SUPRESS */
+
+/* Suppressing doxygen warnings triggered for same static function names present across various sensor variant
+ * directories */
+
+/*!
+ * @brief This API writes the 8-bit data to the given register
+ * in the sensor.
+ */
+static int8_t write_regs(uint8_t addr, const uint8_t *data, uint32_t len, struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (data != NULL))
+ {
+ if (dev->intf == BMA4_SPI_INTF)
+ {
+ addr = addr & BMA4_SPI_WR_MASK;
+ }
+
+ /* write data in the register*/
+ dev->intf_rslt = dev->bus_write(addr, data, len, dev->intf_ptr);
+
+ if (dev->intf_rslt == BMA4_INTF_RET_SUCCESS)
+ {
+ /* After write operation 2us delay is required when device operates in performance mode whereas 450us
+ * is required when the device operates in suspend and low power mode.
+ * NOTE: For more information refer datasheet section 6.6 */
+ if (dev->perf_mode_status == BMA4_ENABLE)
+ {
+ dev->delay_us(2, dev->intf_ptr);
+ }
+ else
+ {
+ dev->delay_us(450, dev->intf_ptr);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_COM_FAIL;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the feature config. data start address in the sensor.
+ */
+static int8_t get_feature_config_start_addr(struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t asic_lsb = 0;
+ uint8_t asic_msb = 0;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = read_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ rslt = read_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev);
+ }
+
+ if (rslt == BMA4_OK)
+ {
+ /* Store asic info in dev structure */
+ dev->asic_data.asic_lsb = asic_lsb & 0x0F;
+ dev->asic_data.asic_msb = asic_msb;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the feature config. data start address in the sensor.
+ */
+static int8_t set_feature_config_start_addr(struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = write_regs(BMA4_RESERVED_REG_5B_ADDR, &dev->asic_data.asic_lsb, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ rslt = write_regs(BMA4_RESERVED_REG_5C_ADDR, &dev->asic_data.asic_msb, 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API increments the feature config. data address according to the user
+ * provided read/write length in the dev structure.
+ */
+static int8_t increment_feature_config_addr(struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint16_t asic_addr;
+ uint8_t asic_lsb = 0;
+ uint8_t asic_msb = 0;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Read the asic address from the sensor */
+ rslt = read_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ rslt = read_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev);
+ }
+ else
+ {
+ rslt = BMA4_E_COM_FAIL;
+ }
+
+ if (rslt == BMA4_OK)
+ {
+ /* Get the asic address */
+ asic_addr = (asic_msb << 4) | (asic_lsb & 0x0F);
+
+ /* Sum the asic address with read/write length after converting from
+ * byte to word
+ */
+ asic_addr = asic_addr + (dev->read_write_len / 2);
+
+ /* Split the asic address */
+ asic_lsb = asic_addr & 0x0F;
+ asic_msb = (uint8_t)(asic_addr >> 4);
+
+ /* Write the asic address in the sensor */
+ rslt = write_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ rslt = write_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_COM_FAIL;
+ }
+ }
+
+ return rslt;
+}
+
+/*! @endcond */
+
+/*!
+ * @brief This API checks whether the read operation requested is for feature
+ * or register read and accordingly reads the data from the sensor.
+ */
+int8_t bma4_read_regs(uint8_t addr, uint8_t *data, uint32_t len, struct bma4_dev *dev)
+{
+ uint8_t idx;
+ uint32_t loop_count;
+ uint16_t overflow;
+ uint16_t index;
+ int8_t rslt;
+ uint8_t adv_pwr_save = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (data != NULL))
+ {
+ if (addr == BMA4_FEATURE_CONFIG_ADDR)
+ {
+ /* Disable APS if enabled before reading the feature
+ * config register
+ */
+ rslt = bma4_get_advance_power_save(&adv_pwr_save, dev);
+ if (adv_pwr_save == BMA4_ENABLE)
+ {
+ rslt = bma4_set_advance_power_save(BMA4_DISABLE, dev);
+
+ /* Wait for sensor time synchronization. Refer
+ * the data-sheet for more information
+ */
+ dev->delay_us(450, dev->intf_ptr);
+ }
+
+ if (((len % 2) == 0) && (len <= dev->feature_len) && (rslt == BMA4_OK))
+ {
+ if (dev->read_write_len < len)
+ {
+ /* Calculate the no of writes to be
+ * performed according to the read/write
+ * length
+ */
+ loop_count = len / dev->read_write_len;
+ overflow = len % dev->read_write_len;
+ index = 0;
+ rslt = set_feature_config_start_addr(dev);
+ for (idx = 0; idx < loop_count; idx++)
+ {
+ rslt = read_regs(BMA4_FEATURE_CONFIG_ADDR, data + index, dev->read_write_len, dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = increment_feature_config_addr(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ index = index + dev->read_write_len;
+ }
+ }
+ }
+
+ if ((overflow) && (rslt == BMA4_OK))
+ {
+ rslt = read_regs(BMA4_FEATURE_CONFIG_ADDR, data + index, overflow, dev);
+ }
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = set_feature_config_start_addr(dev);
+ }
+ }
+ else
+ {
+ rslt = read_regs(BMA4_FEATURE_CONFIG_ADDR, data, len, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_RD_WR_LENGTH_INVALID;
+ }
+
+ if (rslt == BMA4_OK)
+ {
+ /* Enable APS if previously enabled */
+ if (adv_pwr_save == BMA4_ENABLE)
+ {
+ rslt = bma4_set_advance_power_save(BMA4_ENABLE, dev);
+
+ /* Wait for sensor time synchronization.
+ * Refer the data-sheet for more
+ * information
+ */
+ dev->delay_us(450, dev->intf_ptr);
+ }
+ }
+ }
+ else
+ {
+ rslt = read_regs(addr, data, len, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*! @cond DOXYGEN_SUPRESS */
+
+/* Suppressing doxygen warnings triggered for same static function names present across various sensor variant
+ * directories */
+
+/*!
+ * @brief This API reads the 8-bit data from the given register
+ * in the sensor.
+ */
+static int8_t read_regs(uint8_t addr, uint8_t *data, uint32_t len, struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (data != NULL))
+ {
+ /* variable used to return the status of communication result*/
+ uint32_t temp_len = len + dev->dummy_byte;
+ uint16_t indx;
+ uint8_t temp_buff[temp_len];
+
+ if (dev->intf == BMA4_SPI_INTF)
+ {
+ /* SPI mask added */
+ addr = addr | BMA4_SPI_RD_MASK;
+ }
+
+ /* Read the data from the register */
+ dev->intf_rslt = dev->bus_read(addr, temp_buff, temp_len, dev->intf_ptr);
+
+ if (dev->intf_rslt == BMA4_INTF_RET_SUCCESS)
+ {
+ for (indx = 0; indx < len; indx++)
+ {
+ /* Parsing and storing the valid data */
+ data[indx] = temp_buff[indx + dev->dummy_byte];
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_COM_FAIL;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*! @endcond */
+
+/*!
+ * @brief This API reads the error status from the sensor.
+ */
+int8_t bma4_get_error_status(struct bma4_err_reg *err_reg, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (err_reg != NULL))
+ {
+ /* Read the error codes*/
+ rslt = bma4_read_regs(BMA4_ERROR_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Fatal error*/
+ err_reg->fatal_err = BMA4_GET_BITS_POS_0(data, BMA4_FATAL_ERR);
+
+ /* Cmd error*/
+ err_reg->cmd_err = BMA4_GET_BITSLICE(data, BMA4_CMD_ERR);
+
+ /* User error*/
+ err_reg->err_code = BMA4_GET_BITSLICE(data, BMA4_ERR_CODE);
+
+ /* FIFO error*/
+ err_reg->fifo_err = BMA4_GET_BITSLICE(data, BMA4_FIFO_ERR);
+
+ /* Mag data ready error*/
+ err_reg->aux_err = BMA4_GET_BITSLICE(data, BMA4_AUX_ERR);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the sensor status from the sensor.
+ */
+int8_t bma4_get_status(uint8_t *status, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (status != NULL))
+ {
+ /* Read the error codes*/
+ rslt = bma4_read_regs(BMA4_STATUS_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *status = data;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the Accel data for x,y and z axis from the sensor.
+ * The data units is in LSB format.
+ */
+int8_t bma4_read_accel_xyz(struct bma4_accel *accel, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint16_t lsb = 0;
+ uint16_t msb = 0;
+ uint8_t data[BMA4_ACCEL_DATA_LENGTH] = { 0 };
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (accel != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_DATA_8_ADDR, data, BMA4_ACCEL_DATA_LENGTH, dev);
+ if (rslt == BMA4_OK)
+ {
+ msb = data[1];
+ lsb = data[0];
+
+ /* Accel data x axis */
+ accel->x = (int16_t)((msb << 8) | lsb);
+ msb = data[3];
+ lsb = data[2];
+
+ /* Accel data y axis */
+ accel->y = (int16_t)((msb << 8) | lsb);
+ msb = data[5];
+ lsb = data[4];
+
+ /* Accel data z axis */
+ accel->z = (int16_t)((msb << 8) | lsb);
+ if (dev->resolution == BMA4_12_BIT_RESOLUTION)
+ {
+ accel->x = (accel->x / 0x10);
+ accel->y = (accel->y / 0x10);
+ accel->z = (accel->z / 0x10);
+ }
+ else if (dev->resolution == BMA4_14_BIT_RESOLUTION)
+ {
+ accel->x = (accel->x / 0x04);
+ accel->y = (accel->y / 0x04);
+ accel->z = (accel->z / 0x04);
+ }
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the sensor time of Sensor time gets updated
+ * with every update of data register or FIFO.
+ */
+int8_t bma4_get_sensor_time(uint32_t *sensor_time, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[BMA4_SENSOR_TIME_LENGTH] = { 0 };
+ uint8_t msb = 0;
+ uint8_t xlsb = 0;
+ uint8_t lsb = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (sensor_time != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_SENSORTIME_0_ADDR, data, BMA4_SENSOR_TIME_LENGTH, dev);
+ if (rslt == BMA4_OK)
+ {
+ msb = data[BMA4_SENSOR_TIME_MSB_BYTE];
+ xlsb = data[BMA4_SENSOR_TIME_XLSB_BYTE];
+ lsb = data[BMA4_SENSOR_TIME_LSB_BYTE];
+ *sensor_time = (uint32_t)((msb << 16) | (xlsb << 8) | lsb);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the chip temperature of sensor.
+ *
+ * @note Using a scaling factor of 1000, to obtain integer values, which
+ * at the user end, are used to get accurate temperature value .
+ * BMA4_FAHREN_SCALED = 1.8 * 1000, BMA4_KELVIN_SCALED = 273.15 * 1000
+ */
+int8_t bma4_get_temperature(int32_t *temp, uint8_t temp_unit, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[BMA4_TEMP_DATA_SIZE] = { 0 };
+ int32_t temp_raw_scaled = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (temp != NULL))
+ {
+ /* Read temperature value from the register */
+ rslt = bma4_read_regs(BMA4_TEMPERATURE_ADDR, data, BMA4_TEMP_DATA_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ temp_raw_scaled = (int32_t)data[BMA4_TEMP_BYTE] * BMA4_SCALE_TEMP;
+ }
+
+ /* '0' value read from the register corresponds to 23 degree C */
+ (*temp) = temp_raw_scaled + (BMA4_OFFSET_TEMP * BMA4_SCALE_TEMP);
+ switch (temp_unit)
+ {
+ case BMA4_DEG:
+ break;
+ case BMA4_FAHREN:
+
+ /* Temperature in degree Fahrenheit */
+ (*temp) = (((*temp) / BMA4_SCALE_TEMP) * BMA4_FAHREN_SCALED) + (32 * BMA4_SCALE_TEMP);
+ break;
+ case BMA4_KELVIN:
+
+ /* Temperature in degree Kelvin */
+ (*temp) = (*temp) + BMA4_KELVIN_SCALED;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the Output data rate, Bandwidth, perf_mode
+ * and Range of accel.
+ */
+int8_t bma4_get_accel_config(struct bma4_accel_config *accel, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[2] = { 0 };
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (accel != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_ACCEL_CONFIG_ADDR, data, BMA4_ACCEL_CONFIG_LENGTH, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* To get the ODR */
+ accel->odr = BMA4_GET_BITS_POS_0(data[0], BMA4_ACCEL_ODR);
+
+ /* To get the bandwidth */
+ accel->bandwidth = BMA4_GET_BITSLICE(data[0], BMA4_ACCEL_BW);
+
+ /* To get the under sampling mode */
+ accel->perf_mode = BMA4_GET_BITSLICE(data[0], BMA4_ACCEL_PERFMODE);
+
+ /* Read the Accel range */
+ accel->range = BMA4_GET_BITS_POS_0(data[1], BMA4_ACCEL_RANGE);
+
+ /* Flag bit to store the performance mode status */
+ dev->perf_mode_status = accel->perf_mode;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the output_data_rate, bandwidth, perf_mode
+ * and range of Accel.
+ */
+int8_t bma4_set_accel_config(const struct bma4_accel_config *accel, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t accel_config_data[2] = { 0, 0 };
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (accel != NULL))
+ {
+ /* check whether the bandwidth and perfmode
+ * settings are valid
+ */
+ rslt = validate_bandwidth_perfmode(accel->bandwidth, accel->perf_mode);
+ if (rslt == BMA4_OK)
+ {
+ /* check ODR is valid */
+ rslt = validate_odr(accel->odr);
+ if (rslt == BMA4_OK)
+ {
+ accel_config_data[0] = accel->odr & BMA4_ACCEL_ODR_MSK;
+ accel_config_data[0] |= (uint8_t)(accel->bandwidth << BMA4_ACCEL_BW_POS);
+ accel_config_data[0] |= (uint8_t)(accel->perf_mode << BMA4_ACCEL_PERFMODE_POS);
+ accel_config_data[1] = accel->range & BMA4_ACCEL_RANGE_MSK;
+
+ /* Flag bit to store the performance mode status */
+ dev->perf_mode_status = ((accel_config_data[0] & BMA4_ACCEL_PERFMODE_MSK) >> BMA4_ACCEL_PERFMODE_POS);
+
+ rslt = bma4_write_regs(BMA4_ACCEL_CONFIG_ADDR, &accel_config_data[0], 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_write_regs((BMA4_ACCEL_CONFIG_ADDR + 1), &accel_config_data[1], 1, dev);
+ }
+ }
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*! @cond DOXYGEN_SUPRESS */
+
+/* Suppressing doxygen warnings triggered for same static function names present across various sensor variant
+ * directories */
+
+/*!
+ * @brief This API validates the bandwidth and perf_mode
+ * value set by the user.
+ */
+static int8_t validate_bandwidth_perfmode(uint8_t bandwidth, uint8_t perf_mode)
+{
+ int8_t rslt = BMA4_OK;
+
+ if (perf_mode == BMA4_CONTINUOUS_MODE)
+ {
+ if (bandwidth > BMA4_ACCEL_NORMAL_AVG4)
+ {
+ /* Invalid bandwidth error for continuous mode */
+ rslt = BMA4_E_OUT_OF_RANGE;
+ }
+ }
+ else if (perf_mode == BMA4_CIC_AVG_MODE)
+ {
+ if (bandwidth > BMA4_ACCEL_RES_AVG128)
+ {
+ /* Invalid bandwidth error for CIC avg. mode */
+ rslt = BMA4_E_OUT_OF_RANGE;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_OUT_OF_RANGE;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API validates the ODR value set by the user.
+ */
+static int8_t validate_odr(uint8_t odr)
+{
+ int8_t rslt = BMA4_OK;
+
+ if ((odr < BMA4_OUTPUT_DATA_RATE_0_78HZ) || (odr > BMA4_OUTPUT_DATA_RATE_1600HZ))
+ {
+ /* If odr is not valid return error */
+ rslt = BMA4_E_OUT_OF_RANGE;
+ }
+
+ return rslt;
+}
+
+/*! @endcond */
+
+/*!
+ * @brief This API sets the advance power save mode in the sensor.
+ */
+int8_t bma4_set_advance_power_save(uint8_t adv_pwr_save, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ data = BMA4_SET_BITS_POS_0(data, BMA4_ADVANCE_POWER_SAVE, adv_pwr_save);
+ rslt = bma4_write_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the status of advance power save mode
+ * from the sensor.
+ */
+int8_t bma4_get_advance_power_save(uint8_t *adv_pwr_save, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (adv_pwr_save != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *adv_pwr_save = BMA4_GET_BITS_POS_0(data, BMA4_ADVANCE_POWER_SAVE);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the FIFO self wake up functionality in the sensor.
+ */
+int8_t bma4_set_fifo_self_wakeup(uint8_t fifo_self_wakeup, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ data = BMA4_SET_BITSLICE(data, BMA4_FIFO_SELF_WAKE_UP, fifo_self_wakeup);
+ rslt = bma4_write_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the status of FIFO self wake up functionality from
+ * the sensor.
+ */
+int8_t bma4_get_fifo_self_wakeup(uint8_t *fifo_self_wake_up, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (fifo_self_wake_up != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_POWER_CONF_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *fifo_self_wake_up = BMA4_GET_BITSLICE(data, BMA4_FIFO_SELF_WAKE_UP);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API enables or disables the Accel in the sensor.
+ */
+int8_t bma4_set_accel_enable(uint8_t accel_en, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ data = BMA4_SET_BITSLICE(data, BMA4_ACCEL_ENABLE, accel_en);
+ rslt = bma4_write_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API checks whether Accel is enabled or not in the sensor.
+ */
+int8_t bma4_get_accel_enable(uint8_t *accel_en, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (accel_en != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *accel_en = BMA4_GET_BITSLICE(data, BMA4_ACCEL_ENABLE);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API is used to enable or disable auxiliary Mag
+ * in the sensor.
+ */
+int8_t bma4_set_mag_enable(uint8_t mag_en, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ data = BMA4_SET_BITS_POS_0(data, BMA4_MAG_ENABLE, mag_en);
+ rslt = bma4_write_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API is used to check whether the auxiliary Mag is enabled
+ * or not in the sensor.
+ */
+int8_t bma4_get_mag_enable(uint8_t *mag_en, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (mag_en != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *mag_en = BMA4_GET_BITS_POS_0(data, BMA4_MAG_ENABLE);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the SPI interface mode which is set for primary
+ * interface.
+ */
+int8_t bma4_get_spi_interface(uint8_t *spi, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (spi != NULL))
+ {
+ /* Read SPI mode */
+ rslt = bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *spi = BMA4_GET_BITS_POS_0(data, BMA4_CONFIG_SPI3);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API configures the SPI interface Mode for primary interface
+ */
+int8_t bma4_set_spi_interface(uint8_t spi, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ if (spi <= BMA4_MAX_VALUE_SPI3)
+ {
+ /* Write SPI mode */
+ rslt = bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ data = BMA4_SET_BITS_POS_0(data, BMA4_CONFIG_SPI3, spi);
+ rslt = bma4_write_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_OUT_OF_RANGE;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API writes the available sensor specific commands
+ * to the sensor.
+ */
+int8_t bma4_set_command_register(uint8_t command_reg, struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Write command register */
+ rslt = bma4_write_regs(BMA4_CMD_ADDR, &command_reg, 1, dev);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the I2C device address of auxiliary sensor
+ */
+int8_t bma4_set_i2c_device_addr(struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0, dev_id = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Write the auxiliary I2C device address */
+ rslt = bma4_read_regs(BMA4_AUX_DEV_ID_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ dev_id = BMA4_SET_BITSLICE(data, BMA4_I2C_DEVICE_ADDR, dev->aux_config.aux_dev_addr);
+ rslt = bma4_write_regs(BMA4_AUX_DEV_ID_ADDR, &dev_id, 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the register access on MAG_IF[2], MAG_IF[3],
+ * MAG_IF[4] in the sensor. This implies that the DATA registers are
+ * not updated with Mag values automatically.
+ */
+int8_t bma4_set_mag_manual_enable(uint8_t mag_manual, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Write the Mag manual*/
+ rslt = bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev);
+ dev->delay_us(BMA4_GEN_READ_WRITE_DELAY, dev->intf_ptr);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Set the bit of Mag manual enable */
+ data = BMA4_SET_BITSLICE(data, BMA4_MAG_MANUAL_ENABLE, mag_manual);
+ rslt = bma4_write_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ dev->aux_config.manual_enable = (uint8_t)mag_manual;
+ }
+ }
+ else
+ {
+ /*dev->mag_manual_enable = 0;*/
+ dev->aux_config.manual_enable = 0;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API checks whether the Mag access is done manually or
+ * automatically in the sensor.
+ * If the Mag access is done through manual mode then Mag data registers
+ * in sensor are not updated automatically.
+ */
+int8_t bma4_get_mag_manual_enable(uint8_t *mag_manual, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (mag_manual != NULL))
+ {
+ /* Read Mag manual */
+ rslt = bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *mag_manual = BMA4_GET_BITSLICE(data, BMA4_MAG_MANUAL_ENABLE);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the I2C interface configuration(if) mode
+ * for auxiliary Mag.
+ */
+int8_t bma4_set_aux_if_mode(uint8_t if_mode, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ data = BMA4_SET_BITSLICE(data, BMA4_IF_CONFIG_IF_MODE, if_mode);
+ rslt = bma4_write_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the address of the register of Aux Mag sensor
+ * where the data to be read.
+ */
+int8_t bma4_get_mag_read_addr(uint8_t *mag_read_addr, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (mag_read_addr != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_AUX_RD_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *mag_read_addr = BMA4_GET_BITS_POS_0(data, BMA4_READ_ADDR);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the address of the register of Aux Mag sensor
+ * where the data to be read.
+ */
+int8_t bma4_set_mag_read_addr(uint8_t mag_read_addr, struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Write the Mag read address*/
+ rslt = bma4_write_regs(BMA4_AUX_RD_ADDR, &mag_read_addr, 1, dev);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the Aux Mag write address from the sensor.
+ * Mag write address is where the Mag data will be written.
+ */
+int8_t bma4_get_mag_write_addr(uint8_t *mag_write_addr, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (mag_write_addr != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_AUX_WR_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *mag_write_addr = BMA4_GET_BITS_POS_0(data, BMA4_WRITE_ADDR);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the Aux Mag write address in the sensor.
+ * Mag write address is where the Mag data will be written.
+ */
+int8_t bma4_set_mag_write_addr(uint8_t mag_write_addr, struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_write_regs(BMA4_AUX_WR_ADDR, &mag_write_addr, 1, dev);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the data from the sensor which is written to the
+ * Mag.
+ */
+int8_t bma4_get_mag_write_data(uint8_t *mag_write_data, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (mag_write_data != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_AUX_WR_DATA_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *mag_write_data = BMA4_GET_BITS_POS_0(data, BMA4_WRITE_DATA);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the data in the sensor which in turn will
+ * be written to Mag.
+ */
+int8_t bma4_set_mag_write_data(uint8_t mag_write_data, struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_write_regs(BMA4_AUX_WR_DATA_ADDR, &mag_write_data, 1, dev);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the x,y,z and r axis data from the auxiliary
+ * Mag BMM150/AKM9916 sensor.
+ */
+int8_t bma4_read_mag_xyzr(struct bma4_mag_xyzr *mag, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint16_t msb = 0;
+ uint16_t lsb = 0;
+ uint8_t data[BMA4_MAG_XYZR_DATA_LENGTH] = { 0 };
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (mag != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_DATA_0_ADDR, data, BMA4_MAG_XYZR_DATA_LENGTH, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Data X */
+ /* X-axis LSB value shifting */
+ lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_X_LSB_BYTE], BMA4_DATA_MAG_X_LSB);
+ msb = data[BMA4_MAG_X_MSB_BYTE];
+ mag->x = (int16_t)((msb << 8) | lsb);
+ mag->x = (mag->x / 0x08);
+
+ /* Data Y */
+ /* Y-axis LSB value shifting */
+ lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_Y_LSB_BYTE], BMA4_DATA_MAG_Y_LSB);
+ msb = data[BMA4_MAG_Y_MSB_BYTE];
+ mag->y = (int16_t)((msb << 8) | lsb);
+ mag->y = (mag->y / 0x08);
+
+ /* Data Z */
+ /* Z-axis LSB value shifting */
+ lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_Z_LSB_BYTE], BMA4_DATA_MAG_Z_LSB);
+ msb = data[BMA4_MAG_Z_MSB_BYTE];
+ mag->z = (int16_t)((msb << 8) | lsb);
+ mag->z = (mag->z / 0x02);
+
+ /* RHall */
+ /* R-axis LSB value shifting */
+ lsb = BMA4_GET_BITSLICE(data[BMA4_MAG_R_LSB_BYTE], BMA4_DATA_MAG_R_LSB);
+ msb = data[BMA4_MAG_R_MSB_BYTE];
+ mag->r = (int16_t)((msb << 8) | lsb);
+ mag->r = (mag->r / 0x04);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the burst data length (1,2,6,8 byte) of auxiliary
+ * Mag sensor.
+ */
+int8_t bma4_set_mag_burst(uint8_t mag_burst, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Write auxiliary burst mode length*/
+ rslt = bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ data = BMA4_SET_BITS_POS_0(data, BMA4_MAG_BURST, mag_burst);
+ rslt = bma4_write_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the burst data length of Mag set in the sensor.
+ */
+int8_t bma4_get_mag_burst(uint8_t *mag_burst, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (mag_burst != NULL))
+ {
+ /* Write Mag burst mode length*/
+ rslt = bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *mag_burst = BMA4_GET_BITS_POS_0(data, BMA4_MAG_BURST);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the FIFO data of Accel and/or Mag sensor
+ */
+int8_t bma4_read_fifo_data(struct bma4_fifo_frame *fifo, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+ uint8_t addr = BMA4_FIFO_DATA_ADDR;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (fifo != NULL))
+ {
+ /* reset the fifo data structure */
+ reset_fifo_data_structure(fifo);
+
+ /* read the fifo data */
+ rslt = bma4_read_regs(addr, fifo->data, fifo->length, dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* read fifo frame content configuration*/
+ rslt = bma4_read_regs(BMA4_FIFO_CONFIG_1_ADDR, &data, 1, dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* filter fifo header enabled status */
+ fifo->fifo_header_enable = data & BMA4_FIFO_HEADER;
+
+ /* filter accel/mag data enabled status */
+ fifo->fifo_data_enable = data & BMA4_FIFO_M_A_ENABLE;
+ }
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API parses and extracts the accelerometer frames from
+ * FIFO data read by the "bma4_read_fifo_data" API and stores it in the
+ * "accel_data" structure instance.
+ */
+int8_t bma4_extract_accel(struct bma4_accel *accel_data,
+ uint16_t *accel_length,
+ struct bma4_fifo_frame *fifo,
+ const struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint16_t data_index = 0;
+ uint16_t accel_index = 0;
+ uint16_t data_read_length = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (accel_data != NULL) && (accel_length != NULL) && (fifo != NULL))
+ {
+ /* Parsing the FIFO data in header-less mode */
+ if (fifo->fifo_header_enable == 0)
+ {
+ get_accel_len_to_parse(&data_index, &data_read_length, accel_length, fifo);
+ for (; data_index < data_read_length;)
+ {
+ unpack_acc_frm(accel_data, &data_index, &accel_index, fifo->fifo_data_enable, fifo, dev);
+
+ /*Check for the availability of next
+ * two bytes of FIFO data
+ */
+ check_empty_fifo(&data_index, fifo);
+ }
+
+ /* update number of accel data read*/
+ *accel_length = accel_index;
+
+ /*update the accel byte index*/
+ fifo->accel_byte_start_idx = data_index;
+ }
+ else
+ {
+ /* Parsing the FIFO data in header mode */
+ extract_accel_header_mode(accel_data, accel_length, fifo, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API parses and extracts the magnetometer frames from
+ * FIFO data read by the "bma4_read_fifo_data" API and stores it in the
+ * "mag_data" structure instance parameter of this API
+ */
+int8_t bma4_extract_mag(const struct bma4_mag *mag_data,
+ uint16_t *mag_length,
+ struct bma4_fifo_frame *fifo,
+ const struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint16_t data_index = 0;
+ uint16_t mag_index = 0;
+ uint16_t data_read_length = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (mag_data != NULL) && (mag_length != NULL) && (fifo != NULL))
+ {
+ /* Parsing the FIFO data in header-less mode */
+ if (fifo->fifo_header_enable == 0)
+ {
+ get_mag_len_to_parse(&data_index, &data_read_length, mag_length, fifo);
+ for (; data_index < data_read_length;)
+ {
+ rslt = unpack_mag_frm(mag_data, &data_index, &mag_index, fifo->fifo_data_enable, fifo, dev);
+
+ /*Check for the availability of next
+ * two bytes of FIFO data
+ */
+ check_empty_fifo(&data_index, fifo);
+ }
+
+ /* update number of Aux. sensor data read*/
+ *mag_length = mag_index;
+
+ /*update the Aux. sensor frame index*/
+ fifo->mag_byte_start_idx = data_index;
+ }
+ else
+ {
+ /* Parsing the FIFO data in header mode */
+ rslt = extract_mag_header_mode(mag_data, mag_length, fifo, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the FIFO water mark level which is set
+ * in the sensor.
+ */
+int8_t bma4_get_fifo_wm(uint16_t *fifo_wm, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[2] = { 0, 0 };
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (fifo_wm != NULL))
+ {
+ /* Read the FIFO water mark level*/
+ rslt = bma4_read_regs(BMA4_FIFO_WTM_0_ADDR, data, BMA4_FIFO_WM_LENGTH, dev);
+ if (rslt == BMA4_OK)
+ {
+ *fifo_wm = (data[1] << 8) | (data[0]);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the FIFO watermark level in the sensor.
+ */
+int8_t bma4_set_fifo_wm(uint16_t fifo_wm, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[2] = { 0, 0 };
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ data[0] = BMA4_GET_LSB(fifo_wm);
+ data[1] = BMA4_GET_MSB(fifo_wm);
+
+ /* consecutive write is not possible in suspend mode hence
+ * separate write is used with delay of 1 ms
+ */
+
+ /* Write the fifo watermark level*/
+ rslt = bma4_write_regs(BMA4_FIFO_WTM_0_ADDR, &data[0], 1, dev);
+
+ if (rslt == BMA4_OK)
+ {
+ dev->delay_us(BMA4_GEN_READ_WRITE_DELAY, dev->intf_ptr);
+ rslt = bma4_write_regs((BMA4_FIFO_WTM_0_ADDR + 1), &data[1], 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API checks whether the Accel FIFO data is set for filtered
+ * or unfiltered mode.
+ */
+int8_t bma4_get_accel_fifo_filter_data(uint8_t *accel_fifo_filter, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (accel_fifo_filter != NULL))
+ {
+ /* Read the Accel FIFO filter data */
+ rslt = bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *accel_fifo_filter = BMA4_GET_BITSLICE(data, BMA4_FIFO_FILTER_ACCEL);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the condition of Accel FIFO data either to
+ * filtered or unfiltered mode.
+ */
+int8_t bma4_set_accel_fifo_filter_data(uint8_t accel_fifo_filter, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ if (accel_fifo_filter <= BMA4_MAX_VALUE_FIFO_FILTER)
+ {
+ rslt = bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Write Accel FIFO filter data */
+ data = BMA4_SET_BITSLICE(data, BMA4_FIFO_FILTER_ACCEL, accel_fifo_filter);
+ rslt = bma4_write_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_OUT_OF_RANGE;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the down sampling rates which is configured
+ * for Accel FIFO data.
+ */
+int8_t bma4_get_fifo_down_accel(uint8_t *fifo_down, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (fifo_down != NULL))
+ {
+ /* Read the Accel FIFO down data */
+ rslt = bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *fifo_down = BMA4_GET_BITSLICE(data, BMA4_FIFO_DOWN_ACCEL);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the down-sampling rates for Accel FIFO.
+ */
+int8_t bma4_set_fifo_down_accel(uint8_t fifo_down, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Write the Accel FIFO down data */
+ rslt = bma4_read_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ data = BMA4_SET_BITSLICE(data, BMA4_FIFO_DOWN_ACCEL, fifo_down);
+ rslt = bma4_write_regs(BMA4_FIFO_DOWN_ADDR, &data, 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the length of FIFO data available in the sensor
+ * in the units of bytes.
+ */
+int8_t bma4_get_fifo_length(uint16_t *fifo_length, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t index = 0;
+ uint8_t data[BMA4_FIFO_DATA_LENGTH] = { 0, 0 };
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (fifo_length != NULL))
+ {
+ /* Read FIFO length*/
+ rslt = bma4_read_regs(BMA4_FIFO_LENGTH_0_ADDR, data, BMA4_FIFO_DATA_LENGTH, dev);
+ if (rslt == BMA4_OK)
+ {
+ index = BMA4_FIFO_LENGTH_MSB_BYTE;
+ data[index] = BMA4_GET_BITS_POS_0(data[index], BMA4_FIFO_BYTE_COUNTER_MSB);
+ *fifo_length = ((data[index] << 8) | data[index - 1]);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API aligns and compensates the Mag data of BMM150/AKM9916
+ * sensor.
+ */
+int8_t bma4_second_if_mag_compensate_xyz(struct bma4_mag_fifo_data mag_fifo_data,
+ uint8_t mag_second_if,
+ const struct bma4_mag *compensated_mag_data)
+{
+ int8_t rslt = BMA4_OK;
+
+#ifdef BMM150
+ int16_t mag_x = 0;
+ int16_t mag_y = 0;
+ int16_t mag_z = 0;
+ uint16_t mag_r = 0;
+#else
+
+ /* Suppress Warnings */
+ (void)(mag_second_if);
+ (void)(mag_fifo_data);
+#endif
+
+ if (compensated_mag_data == NULL)
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+#if defined(BMM150) || defined(AKM9916)
+ switch (mag_second_if)
+ {
+#ifdef BMM150
+ case BMA4_SEC_IF_BMM150:
+
+ /* X data*/
+ mag_x = (int16_t)((mag_fifo_data.mag_x_msb << 8) | (mag_fifo_data.mag_x_lsb));
+ mag_x = (int16_t) (mag_x / 0x08);
+
+ /* Y data*/
+ mag_y = (int16_t)((mag_fifo_data.mag_y_msb << 8) | (mag_fifo_data.mag_y_lsb));
+ mag_y = (int16_t) (mag_y / 0x08);
+
+ /* Z data*/
+ mag_z = (int16_t)((mag_fifo_data.mag_z_msb << 8) | (mag_fifo_data.mag_z_lsb));
+ mag_z = (int16_t) (mag_z / 0x02);
+
+ /* R data*/
+ mag_r = (uint16_t)((mag_fifo_data.mag_r_y2_msb << 8) | (mag_fifo_data.mag_r_y2_lsb));
+ mag_r = (uint16_t) (mag_r >> 2);
+
+ /* Compensated Mag x data */
+ compensated_mag_data->x = bma4_bmm150_mag_compensate_x(mag_x, mag_r);
+
+ /* Compensated Mag y data */
+ compensated_mag_data->y = bma4_bmm150_mag_compensate_y(mag_y, mag_r);
+
+ /* Compensated Mag z data */
+ compensated_mag_data->z = bma4_bmm150_mag_compensate_z(mag_z, mag_r);
+ break;
+#endif
+
+#ifdef AKM9916
+ case BMA4_SEC_IF_AKM09916:
+
+ /* Compensated X data */
+ compensated_mag_data->x = (int16_t)((mag_fifo_data.mag_x_msb << 8) | (mag_fifo_data.mag_x_lsb));
+
+ /* Compensated Y data*/
+ compensated_mag_data->y = (int16_t)((mag_fifo_data.mag_y_msb << 8) | (mag_fifo_data.mag_y_lsb));
+
+ /* Compensated Z data*/
+ compensated_mag_data->z = (int16_t)((mag_fifo_data.mag_z_msb << 8) | (mag_fifo_data.mag_z_lsb));
+ break;
+#endif
+ }
+#endif
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads Mag. x,y and z axis data from either BMM150 or
+ * AKM9916 sensor
+ */
+int8_t bma4_read_mag_xyz(const struct bma4_mag *mag, uint8_t sensor_select, const struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+#if defined(AKM9916) || defined(BMM150)
+ uint8_t index;
+ uint16_t msb = 0;
+ uint16_t lsb = 0;
+ uint8_t data[BMA4_MAG_XYZ_DATA_LENGTH] = { 0 };
+#else
+
+ /* Suppress Warnings */
+ (void)(sensor_select);
+#endif
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((BMA4_OK != rslt) || (mag == NULL))
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+ else
+ {
+#if defined(BMM150) || defined(AKM9916)
+ switch (sensor_select)
+ {
+
+#ifdef BMM150
+ case BMA4_SEC_IF_BMM150:
+ rslt = bma4_read_regs(BMA4_DATA_0_ADDR, data, BMA4_MAG_XYZ_DATA_LENGTH, dev);
+ if (rslt == BMA4_OK)
+ {
+ index = BMA4_MAG_X_LSB_BYTE;
+
+ /*X-axis LSB value shifting*/
+ data[index] = BMA4_GET_BITSLICE(data[index], BMA4_DATA_MAG_X_LSB);
+
+ /* Data X */
+ msb = data[index + 1];
+ lsb = data[index];
+ mag->x = (int16_t)((msb << 8) | lsb);
+ mag->x = (mag->x / 0x08);
+
+ /* Data Y */
+ /*Y-axis LSB value shifting*/
+ data[index + 2] = BMA4_GET_BITSLICE(data[index + 2], BMA4_DATA_MAG_Y_LSB);
+ msb = data[index + 3];
+ lsb = data[index + 2];
+ mag->y = (int16_t)((msb << 8) | lsb);
+ mag->y = (mag->y / 0x08);
+
+ /* Data Z */
+ /*Z-axis LSB value shifting*/
+ data[index + 4] = BMA4_GET_BITSLICE(data[index + 4], BMA4_DATA_MAG_Z_LSB);
+ msb = data[index + 5];
+ lsb = data[index + 4];
+ mag->z = (int16_t)((msb << 8) | lsb);
+ mag->z = (mag->z / 0x02);
+ }
+
+ break;
+#endif
+
+#ifdef AKM9916
+ case BMA4_SEC_IF_AKM09916:
+ if (dev->aux_sensor == AKM9916_SENSOR)
+ {
+ rslt = bma4_read_regs(BMA4_DATA_0_ADDR, data, BMA4_MAG_XYZ_DATA_LENGTH, dev);
+ if (rslt == BMA4_OK)
+ {
+ index = BMA4_MAG_X_LSB_BYTE;
+
+ /* Data X */
+ msb = data[index + 1];
+ lsb = data[index];
+ mag->x = (int16_t)((msb << 8) | lsb);
+
+ /* Data Y */
+ msb = data[index + 3];
+ lsb = data[index + 2];
+ mag->y = (int32_t)((msb << 8) | lsb);
+
+ /* Data Z */
+ msb = data[index + 5];
+ lsb = data[index + 4];
+ mag->z = (int16_t)((msb << 8) | lsb);
+ }
+ }
+
+ break;
+#endif
+ }
+#else
+ rslt = BMA4_E_OUT_OF_RANGE;
+#endif
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the auxiliary I2C interface configuration which
+ * is set in the sensor.
+ */
+int8_t bma4_get_if_mode(uint8_t *if_mode, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (if_mode != NULL))
+ {
+ /* Read auxiliary interface configuration */
+ rslt = bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *if_mode = BMA4_GET_BITSLICE(data, BMA4_IF_CONFIG_IF_MODE);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the auxiliary interface configuration in the
+ * sensor.
+ */
+int8_t bma4_set_if_mode(uint8_t if_mode, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ if (if_mode <= BMA4_MAX_IF_MODE)
+ {
+ /* Write the interface configuration mode */
+ rslt = bma4_read_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ data = BMA4_SET_BITSLICE(data, BMA4_IF_CONFIG_IF_MODE, if_mode);
+ rslt = bma4_write_regs(BMA4_IF_CONFIG_ADDR, &data, 1, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_OUT_OF_RANGE;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the data ready status of Accel from the sensor.
+ */
+int8_t bma4_get_accel_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (data_rdy != NULL))
+ {
+ /*Reads the status of Accel data ready*/
+ rslt = bma4_read_regs(BMA4_STATUS_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *data_rdy = BMA4_GET_BITSLICE(data, BMA4_STAT_DATA_RDY_ACCEL);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the data ready status of Mag from the sensor.
+ * The status get reset when Mag data register is read.
+ */
+int8_t bma4_get_mag_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (data_rdy != NULL))
+ {
+ /*Reads the status of Accel data ready*/
+ rslt = bma4_read_regs(BMA4_STATUS_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *data_rdy = BMA4_GET_BITSLICE(data, BMA4_STAT_DATA_RDY_MAG);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the ASIC status from the sensor.
+ * The status information is mentioned in the below table.
+ */
+int8_t bma4_get_asic_status(struct bma4_asic_status *asic_status, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (asic_status != NULL))
+ {
+ /* Read the Mag I2C device address*/
+ rslt = bma4_read_regs(BMA4_INTERNAL_ERROR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ asic_status->sleep = (data & 0x01);
+ asic_status->irq_ovrn = ((data & 0x02) >> 0x01);
+ asic_status->wc_event = ((data & 0x04) >> 0x02);
+ asic_status->stream_transfer_active = ((data & 0x08) >> 0x03);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API enables the offset compensation for filtered and
+ * unfiltered Accel data.
+ */
+int8_t bma4_set_offset_comp(uint8_t offset_en, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_read_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Write Accel FIFO filter data */
+ data = BMA4_SET_BITSLICE(data, BMA4_NV_ACCEL_OFFSET, offset_en);
+ rslt = bma4_write_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the status of Accel offset compensation
+ */
+int8_t bma4_get_offset_comp(uint8_t *offset_en, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (offset_en != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Write Accel FIFO filter data */
+ *offset_en = BMA4_GET_BITSLICE(data, BMA4_NV_ACCEL_OFFSET);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API checks whether the self-test functionality of the sensor
+ * is working or not.
+ * The following parameter of struct bma4_dev, should have the valid value
+ * before performing the self-test,
+ * 1. Variant and 2. Resolution
+ */
+int8_t bma4_perform_accel_selftest(int8_t *result, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ struct bma4_accel positive = { 0, 0, 0 };
+ struct bma4_accel negative = { 0, 0, 0 };
+
+ /*! Structure for difference of accel values in mg */
+ struct bma4_selftest_delta_limit accel_data_diff_mg = { 0, 0, 0 };
+
+ *result = BMA4_SELFTEST_FAIL;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = set_accel_selftest_config(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Wait for 2ms after accel self-test config please refer data sheet data sheet 4.9. sensor self-test */
+ dev->delay_us(BMA4_MS_TO_US(2), dev->intf_ptr);
+
+ rslt = bma4_selftest_config(BMA4_ENABLE, dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Taking positive data */
+
+ /* User should wait 50ms before interpreting the acceleration data.
+ * please refer data sheet 4.9. sensor self-test
+ */
+ dev->delay_us(BMA4_MS_TO_US(50), dev->intf_ptr);
+ rslt = bma4_read_accel_xyz(&positive, dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_selftest_config(BMA4_DISABLE, dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* User should wait 50ms before interpreting the acceleration data.
+ * please refer data sheet 4.9. sensor self-test
+ */
+ dev->delay_us(BMA4_MS_TO_US(50), dev->intf_ptr);
+ rslt = bma4_read_accel_xyz(&negative, dev);
+ if (rslt == BMA4_OK)
+ {
+ rslt = *result = get_accel_data_difference_and_validate(positive,
+ negative,
+ &accel_data_diff_mg,
+ dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Triggers a soft reset */
+ rslt = bma4_soft_reset(dev);
+ dev->delay_us(BMA4_MS_TO_US(200), dev->intf_ptr);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return rslt;
+}
+
+/*! @cond DOXYGEN_SUPRESS */
+
+/* Suppressing doxygen warnings triggered for same static function names present across various sensor variant
+ * directories */
+
+/*!
+ * @brief This Internal API validates accel self-test status from positive and negative axes input
+ */
+static int8_t get_accel_data_difference_and_validate(struct bma4_accel positive,
+ struct bma4_accel negative,
+ struct bma4_selftest_delta_limit *accel_data_diff_mg,
+ const struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /*! Structure for difference of accel values in g */
+ struct bma4_selftest_delta_limit accel_data_diff = { 0, 0, 0 };
+
+ accel_data_diff.x = ABS(positive.x - negative.x);
+ accel_data_diff.y = ABS(positive.y - negative.y);
+ accel_data_diff.z = ABS(positive.z - negative.z);
+
+ /*! Converting LSB of the differences of accel values to mg */
+ convert_lsb_g(&accel_data_diff, accel_data_diff_mg, dev);
+
+ /*! Validating self-test for accel values in mg */
+ rslt = validate_selftest(accel_data_diff_mg, dev);
+
+ return rslt;
+}
+
+/*! @endcond */
+
+/*!
+ * @brief This API performs the steps needed for self-test operation
+ * before reading the Accel self-test data.
+ */
+int8_t bma4_selftest_config(uint8_t sign, struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = set_accel_selftest_enable(BMA4_ENABLE, dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = set_accel_selftest_sign(sign, dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Set self-test amplitude based on variant */
+ switch (dev->variant)
+ {
+ case BMA42X_VARIANT:
+ case BMA42X_B_VARIANT:
+
+ /* Set self-test amplitude to high for BMA42x */
+ rslt = set_accel_selftest_amp(BMA4_ENABLE, dev);
+ break;
+
+ case BMA45X_VARIANT:
+
+ /* Set self-test amplitude to low for BMA45x */
+ rslt = set_accel_selftest_amp(BMA4_DISABLE, dev);
+ break;
+
+ default:
+ rslt = BMA4_E_INVALID_SENSOR;
+ break;
+ }
+ }
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief API sets the interrupt to either interrupt1 or
+ * interrupt2 pin in the sensor.
+ */
+int8_t bma4_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[3] = { 0, 0, 0 };
+ uint8_t index[2] = { BMA4_INT_MAP_1_ADDR, BMA4_INT_MAP_2_ADDR };
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_read_regs(BMA4_INT_MAP_1_ADDR, data, 3, dev);
+ if (rslt == BMA4_OK)
+ {
+ if (enable == TRUE)
+ {
+ /* Feature interrupt mapping */
+ data[int_line] = (uint8_t)(int_map & (0x00FF));
+
+ /* Hardware interrupt mapping */
+ data[2] = (uint8_t)((int_map & (0xFF00)) >> 8);
+ }
+ else
+ {
+ /* Feature interrupt un-mapping */
+ data[int_line] &= (~(uint8_t)(int_map & (0x00FF)));
+
+ /* Hardware interrupt un-mapping */
+ data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 8));
+ }
+
+ rslt = bma4_write_regs(index[int_line], &data[int_line], 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_write_regs(BMA4_INT_MAP_DATA_ADDR, &data[2], 1, dev);
+ }
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the interrupt mode in the sensor.
+ */
+int8_t bma4_set_interrupt_mode(uint8_t mode, struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ if ((mode == BMA4_NON_LATCH_MODE) || (mode == BMA4_LATCH_MODE))
+ {
+ rslt = bma4_write_regs(BMA4_INTR_LATCH_ADDR, &mode, 1, dev);
+ }
+ else
+ {
+ rslt = BMA4_E_OUT_OF_RANGE;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the interrupt mode which is set in the sensor.
+ */
+int8_t bma4_get_interrupt_mode(uint8_t *mode, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (mode != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_INTR_LATCH_ADDR, &data, 1, dev);
+ *mode = data;
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the auxiliary Mag(BMM150 or AKM9916) output data
+ * rate and offset.
+ */
+int8_t bma4_set_aux_mag_config(const struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (aux_mag != NULL))
+ {
+ if ((aux_mag->odr >= BMA4_OUTPUT_DATA_RATE_0_78HZ) && (aux_mag->odr <= BMA4_OUTPUT_DATA_RATE_1600HZ) &&
+ ((aux_mag->offset & BMA4_MAG_CONFIG_OFFSET_MSK) == 0x00))
+ {
+ data = (uint8_t)(aux_mag->odr | ((aux_mag->offset << BMA4_MAG_CONFIG_OFFSET_POS)));
+ rslt = bma4_write_regs(BMA4_AUX_CONFIG_ADDR, &data, 1, dev);
+ }
+ else
+ {
+ rslt = BMA4_E_OUT_OF_RANGE;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the auxiliary Mag(BMM150 or AKM9916) output data
+ * rate and offset.
+ */
+int8_t bma4_get_aux_mag_config(struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (aux_mag != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_AUX_CONFIG_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ aux_mag->odr = (data & 0x0F);
+ aux_mag->offset = (data & BMA4_MAG_CONFIG_OFFSET_MSK) >> 4;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*! @brief This API sets the FIFO configuration in the sensor. */
+int8_t bma4_set_fifo_config(uint8_t config, uint8_t enable, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[2] = { 0, 0 };
+ uint8_t fifo_config_0 = config & BMA4_FIFO_CONFIG_0_MASK;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_read_regs(BMA4_FIFO_CONFIG_0_ADDR, data, BMA4_FIFO_CONFIG_LENGTH, dev);
+ if (rslt == BMA4_OK)
+ {
+ if (fifo_config_0 > 0)
+ {
+ if (enable == TRUE)
+ {
+ data[0] = data[0] | fifo_config_0;
+ }
+ else
+ {
+ data[0] = data[0] & (~fifo_config_0);
+ }
+ }
+
+ if (enable == TRUE)
+ {
+ data[1] = data[1] | (config & BMA4_FIFO_CONFIG_1_MASK);
+ }
+ else
+ {
+ data[1] = data[1] & (~(config & BMA4_FIFO_CONFIG_1_MASK));
+ }
+
+ /* Burst write is not possible in suspend mode hence
+ * separate write is used with delay of 1 ms
+ */
+ rslt = bma4_write_regs(BMA4_FIFO_CONFIG_0_ADDR, &data[0], 1, dev);
+
+ if (rslt == BMA4_OK)
+ {
+ dev->delay_us(BMA4_GEN_READ_WRITE_DELAY, dev->intf_ptr);
+ rslt = bma4_write_regs((BMA4_FIFO_CONFIG_0_ADDR + 1), &data[1], 1, dev);
+ }
+ }
+ }
+
+ return rslt;
+}
+
+/*! @brief This API reads the FIFO configuration from the sensor.
+ */
+int8_t bma4_get_fifo_config(uint8_t *fifo_config, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[2] = { 0, 0 };
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (fifo_config != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_FIFO_CONFIG_0_ADDR, data, BMA4_FIFO_CONFIG_LENGTH, dev);
+ if (rslt == BMA4_OK)
+ {
+ *fifo_config = ((uint8_t)((data[0] & BMA4_FIFO_CONFIG_0_MASK) | (data[1])));
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*! @brief This function sets the electrical behaviour of interrupt pin1 or
+ * pin2 in the sensor.
+ */
+int8_t bma4_set_int_pin_config(const struct bma4_int_pin_config *int_pin_config, uint8_t int_line, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t interrupt_address_array[2] = { BMA4_INT1_IO_CTRL_ADDR, BMA4_INT2_IO_CTRL_ADDR };
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (int_pin_config != NULL))
+ {
+ if (int_line <= 1)
+ {
+ data =
+ ((uint8_t)((int_pin_config->edge_ctrl & BMA4_INT_EDGE_CTRL_MASK) |
+ ((int_pin_config->lvl << 1) & BMA4_INT_LEVEL_MASK) |
+ ((int_pin_config->od << 2) & BMA4_INT_OPEN_DRAIN_MASK) |
+ ((int_pin_config->output_en << 3) & BMA4_INT_OUTPUT_EN_MASK) |
+ ((int_pin_config->input_en << 4) & BMA4_INT_INPUT_EN_MASK)));
+ rslt = bma4_write_regs(interrupt_address_array[int_line], &data, 1, dev);
+ }
+ else
+ {
+ rslt = BMA4_E_INT_LINE_INVALID;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*! @brief This API reads the electrical behavior of interrupt pin1 or pin2
+ * from the sensor.
+ */
+int8_t bma4_get_int_pin_config(struct bma4_int_pin_config *int_pin_config, uint8_t int_line, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t interrupt_address_array[2] = { BMA4_INT1_IO_CTRL_ADDR, BMA4_INT2_IO_CTRL_ADDR };
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (int_pin_config != NULL))
+ {
+ if (int_line <= 1)
+ {
+ rslt = bma4_read_regs(interrupt_address_array[int_line], &data, 1, dev);
+
+ /* Assign interrupt configurations to the
+ * structure members
+ */
+ if (rslt == BMA4_OK)
+ {
+ int_pin_config->edge_ctrl = data & BMA4_INT_EDGE_CTRL_MASK;
+ int_pin_config->lvl = ((data & BMA4_INT_LEVEL_MASK) >> BMA4_INT_LEVEL_POS);
+ int_pin_config->od = ((data & BMA4_INT_OPEN_DRAIN_MASK) >> BMA4_INT_OPEN_DRAIN_POS);
+ int_pin_config->output_en = ((data & BMA4_INT_OUTPUT_EN_MASK) >> BMA4_INT_OUTPUT_EN_POS);
+ int_pin_config->input_en = ((data & BMA4_INT_INPUT_EN_MASK) >> BMA4_INT_INPUT_EN_POS);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INT_LINE_INVALID;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the Feature and Hardware interrupt status from the sensor.
+ */
+int8_t bma4_read_int_status(uint16_t *int_status, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[2] = { 0 };
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (int_status != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_INT_STAT_0_ADDR, data, 2, dev);
+ if (rslt == BMA4_OK)
+ {
+ *int_status = data[0];
+ *((uint8_t *)int_status + 1) = data[1];
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the Feature interrupt status from the sensor.
+ */
+int8_t bma4_read_int_status_0(uint8_t *int_status_0, struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (int_status_0 != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_INT_STAT_0_ADDR, int_status_0, 1, dev);
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the Hardware interrupt status from the sensor.
+ */
+int8_t bma4_read_int_status_1(uint8_t *int_status_1, struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (int_status_1 != NULL))
+ {
+ rslt = bma4_read_regs(BMA4_INT_STAT_1_ADDR, int_status_1, 1, dev);
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API initializes the auxiliary interface to access
+ * auxiliary sensor
+ */
+int8_t bma4_aux_interface_init(struct bma4_dev *dev)
+{
+ /* Variable to return error codes */
+ int8_t rslt;
+
+ /* Check for Null pointer error */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Set the auxiliary sensor configuration */
+ rslt = set_aux_interface_config(dev);
+ if (rslt != BMA4_OK)
+ {
+ rslt = BMA4_E_AUX_CONFIG_FAIL;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the data from the auxiliary sensor
+ */
+int8_t bma4_aux_read(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev)
+{
+ /* Variable to return error codes */
+ int8_t rslt;
+
+ /* Check for Null pointer error */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (aux_data != NULL))
+ {
+ /* Read the data from the data register in terms of
+ * user defined length
+ */
+ rslt = extract_aux_data(aux_reg_addr, aux_data, len, dev);
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API writes the data into the auxiliary sensor
+ */
+int8_t bma4_aux_write(uint8_t aux_reg_addr, const uint8_t *aux_data, uint16_t len, struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* Check for Null pointer error */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (aux_data != NULL))
+ {
+ /* Write data in terms of user defined length */
+ if (len > 0)
+ {
+ while (len--)
+ {
+ /* First set data to write */
+ rslt = bma4_write_regs(BMA4_AUX_WR_DATA_ADDR, aux_data, 1, dev);
+ dev->delay_us(BMA4_AUX_COM_DELAY, dev->intf_ptr);
+ if (rslt == BMA4_OK)
+ {
+ /* Then set address to write */
+ rslt = bma4_write_regs(BMA4_AUX_WR_ADDR, &aux_reg_addr, 1, dev);
+ dev->delay_us(BMA4_AUX_COM_DELAY, dev->intf_ptr);
+
+ /* Increment data array and register
+ * address until user-defined length is
+ * greater than 0
+ */
+ if ((rslt == BMA4_OK) && (len > 0))
+ {
+ aux_data++;
+ aux_reg_addr++;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_COM_FAIL;
+ }
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_RD_WR_LENGTH_INVALID;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*****************************************************************************/
+/*! @cond DOXYGEN_SUPRESS */
+
+/* Suppressing doxygen warnings triggered for same static function names present across various sensor variant
+ * directories */
+
+/* Static function definition */
+
+/*!
+ * @brief This API converts lsb value of axes to mg for self-test *
+ */
+static void convert_lsb_g(const struct bma4_selftest_delta_limit *accel_data_diff,
+ struct bma4_selftest_delta_limit *accel_data_diff_mg,
+ const struct bma4_dev *dev)
+{
+ uint32_t lsb_per_g;
+
+ /*! Range considered for self-test is 8g */
+ uint8_t range = 8;
+
+ /*! lsb_per_g for the respective resolution and 8g range*/
+ lsb_per_g = (uint32_t)(power(2, dev->resolution) / (2 * range));
+
+ /*! accel x value in mg */
+ accel_data_diff_mg->x = (accel_data_diff->x / (int32_t)lsb_per_g) * 1000;
+
+ /*! accel y value in mg */
+ accel_data_diff_mg->y = (accel_data_diff->y / (int32_t)lsb_per_g) * 1000;
+
+ /*! accel z value in mg */
+ accel_data_diff_mg->z = (accel_data_diff->z / (int32_t)lsb_per_g) * 1000;
+}
+
+/*!
+ * @brief This API writes the config stream data in memory using burst mode
+ * @note index value should be even number.
+ */
+static int8_t stream_transfer_write(const uint8_t *stream_data, uint16_t index, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t asic_msb = (uint8_t)((index / 2) >> 4);
+ uint8_t asic_lsb = ((index / 2) & 0x0F);
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (stream_data != NULL))
+ {
+ rslt = bma4_write_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_write_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ rslt = write_regs(BMA4_FEATURE_CONFIG_ADDR, (uint8_t *)stream_data, dev->read_write_len, dev);
+ }
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API enables or disables the Accel self-test feature in the
+ * sensor.
+ */
+static int8_t set_accel_selftest_enable(uint8_t accel_selftest_enable, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Read the self-test register */
+ rslt = bma4_read_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ data = BMA4_SET_BITS_POS_0(data, BMA4_ACCEL_SELFTEST_ENABLE, accel_selftest_enable);
+ rslt = bma4_write_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API selects the sign of Accel self-test excitation.
+ */
+static int8_t set_accel_selftest_sign(uint8_t accel_selftest_sign, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ if (accel_selftest_sign <= BMA4_MAX_VALUE_SELFTEST_SIGN)
+ {
+ /* Read the Accel self-test sign*/
+ rslt = bma4_read_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ data = BMA4_SET_BITSLICE(data, BMA4_ACCEL_SELFTEST_SIGN, accel_selftest_sign);
+ rslt = bma4_write_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_OUT_OF_RANGE;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the Accel self-test amplitude in the sensor.
+ */
+static int8_t set_accel_selftest_amp(uint8_t accel_selftest_amp, struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ if (accel_selftest_amp <= BMA4_MAX_VALUE_SELFTEST_AMP)
+ {
+ /* Write self-test amplitude*/
+ rslt = bma4_read_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ data = BMA4_SET_BITSLICE(data, BMA4_SELFTEST_AMP, accel_selftest_amp);
+ rslt = bma4_write_regs(BMA4_ACC_SELF_TEST_ADDR, &data, 1, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_OUT_OF_RANGE;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This function enables and configures the Accel which is needed
+ * for self-test operation.
+ */
+static int8_t set_accel_selftest_config(struct bma4_dev *dev)
+{
+ int8_t rslt;
+ struct bma4_accel_config accel = { 0, 0, 0, 0 };
+
+ accel.odr = BMA4_OUTPUT_DATA_RATE_1600HZ;
+ accel.bandwidth = BMA4_ACCEL_NORMAL_AVG4;
+ accel.perf_mode = BMA4_ENABLE;
+ accel.range = BMA4_ACCEL_RANGE_8G;
+
+ rslt = bma4_set_accel_enable(BMA4_ENABLE, dev);
+ dev->delay_us(BMA4_MS_TO_US(1), dev->intf_ptr);
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_set_accel_config(&accel, 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(struct bma4_fifo_frame *fifo)
+{
+ /*Prepare for next FIFO read by resetting FIFO's
+ * internal data structures
+ */
+ fifo->accel_byte_start_idx = 0;
+ fifo->mag_byte_start_idx = 0;
+ fifo->sc_frame_byte_start_idx = 0;
+ fifo->sensor_time = 0;
+ fifo->skipped_frame_count = 0;
+ fifo->accel_dropped_frame_count = 0;
+ fifo->mag_dropped_frame_count = 0;
+}
+
+/*!
+ * @brief This API computes 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 *start_idx,
+ uint16_t *len,
+ const uint16_t *acc_count,
+ const struct bma4_fifo_frame *fifo)
+{
+ /*Data start index*/
+ *start_idx = fifo->accel_byte_start_idx;
+ if (fifo->fifo_data_enable == BMA4_FIFO_A_ENABLE)
+ {
+ /*Len has the number of bytes to loop for */
+ *len = (uint16_t)(((*acc_count) * BMA4_FIFO_A_LENGTH));
+ }
+ else if (fifo->fifo_data_enable == BMA4_FIFO_M_A_ENABLE)
+ {
+ /*Len has the number of bytes to loop for */
+ *len = (uint16_t)(((*acc_count) * BMA4_FIFO_MA_LENGTH));
+ }
+ else
+ {
+ /*Only aux. sensor or no sensor is enabled in FIFO,
+ * so there will be no accel data.
+ * Update the data index as complete
+ */
+ *start_idx = fifo->length;
+ }
+
+ if ((*len) > fifo->length)
+ {
+ /*Handling the case where more data is requested
+ * than available
+ */
+ *len = fifo->length;
+ }
+}
+
+/*!
+ * @brief This API checks the fifo read data as empty frame, if it
+ * is empty frame then moves the index to last byte.
+ */
+static void check_empty_fifo(uint16_t *data_index, const struct bma4_fifo_frame *fifo)
+{
+ if ((*data_index + 2) < fifo->length)
+ {
+ /* Check if FIFO is empty */
+ if ((fifo->data[*data_index] == BMA4_FIFO_MSB_CONFIG_CHECK) &&
+ (fifo->data[*data_index + 1] == BMA4_FIFO_LSB_CONFIG_CHECK))
+ {
+ /*Update the data index as complete*/
+ *data_index = fifo->length;
+ }
+ }
+}
+
+/*!
+ * @brief This API is used to parse the accelerometer data from the
+ * FIFO data in header mode.
+ *
+ */
+static void extract_accel_header_mode(struct bma4_accel *accel_data,
+ uint16_t *accel_length,
+ struct bma4_fifo_frame *fifo,
+ const struct bma4_dev *dev)
+{
+ uint8_t frame_header = 0;
+ uint16_t data_index;
+ uint16_t accel_index = 0;
+ uint16_t frame_to_read = *accel_length;
+
+ /*Check if this is the first iteration of data unpacking
+ * if yes, then consider dummy byte on SPI
+ */
+ if (fifo->accel_byte_start_idx == 0)
+ {
+ fifo->accel_byte_start_idx = dev->dummy_byte;
+ }
+
+ for (data_index = fifo->accel_byte_start_idx; data_index < fifo->length;)
+ {
+ /*Header byte is stored in the variable frame_header*/
+ frame_header = fifo->data[data_index];
+
+ /*Get the frame details from header*/
+ frame_header = frame_header & BMA4_FIFO_TAG_INTR_MASK;
+
+ /*Index is moved to next byte where the data is starting*/
+ data_index++;
+ switch (frame_header)
+ {
+ /* Accel frame */
+ case BMA4_FIFO_HEAD_A:
+ case BMA4_FIFO_HEAD_M_A:
+ unpack_acc_frm(accel_data, &data_index, &accel_index, frame_header, fifo, dev);
+ break;
+
+ /* Aux. sensor frame */
+ case BMA4_FIFO_HEAD_M:
+ move_next_frame(&data_index, BMA4_FIFO_M_LENGTH, fifo);
+ break;
+
+ /* Sensor time frame */
+ case BMA4_FIFO_HEAD_SENSOR_TIME:
+ unpack_sensortime_frame(&data_index, fifo);
+ break;
+
+ /* Skip frame */
+ case BMA4_FIFO_HEAD_SKIP_FRAME:
+ unpack_skipped_frame(&data_index, fifo);
+ break;
+
+ /* Input config frame */
+ case BMA4_FIFO_HEAD_INPUT_CONFIG:
+ move_next_frame(&data_index, 1, fifo);
+ break;
+
+ /* Sample drop frame */
+ case BMA4_FIFO_HEAD_SAMPLE_DROP:
+ unpack_dropped_frame(&data_index, fifo);
+ break;
+
+ /* Over read FIFO data */
+ case BMA4_FIFO_HEAD_OVER_READ_MSB:
+
+ /* Update the data index as complete*/
+ data_index = fifo->length;
+ break;
+ default:
+ break;
+ }
+ if (frame_to_read == accel_index)
+ {
+ /*Number of frames to read completed*/
+ break;
+ }
+ }
+
+ /*Update number of accel data read*/
+ *accel_length = accel_index;
+
+ /*Update the accel frame index*/
+ fifo->accel_byte_start_idx = data_index;
+}
+
+/*!
+ * @brief This API is used to parse the accelerometer data from the
+ * FIFO data in both header mode and header-less mode.
+ * It update the idx value which is used to store the index of
+ * the current data byte which is parsed.
+ */
+static void unpack_acc_frm(struct bma4_accel *acc,
+ uint16_t *idx,
+ uint16_t *acc_idx,
+ uint8_t frm,
+ const struct bma4_fifo_frame *fifo,
+ const struct bma4_dev *dev)
+{
+
+ switch (frm)
+ {
+ case BMA4_FIFO_HEAD_A:
+ case BMA4_FIFO_A_ENABLE:
+
+ /*Partial read, then skip the data*/
+ if ((*idx + BMA4_FIFO_A_LENGTH) > fifo->length)
+ {
+ /*Update the data index as complete*/
+ *idx = fifo->length;
+ break;
+ }
+
+ /*Unpack the data array into the structure instance "acc" */
+ unpack_accel_data(&acc[*acc_idx], *idx, fifo, dev);
+
+ /*Move the data index*/
+ *idx = *idx + BMA4_FIFO_A_LENGTH;
+ (*acc_idx)++;
+ break;
+ case BMA4_FIFO_HEAD_M_A:
+ case BMA4_FIFO_M_A_ENABLE:
+
+ /*Partial read, then skip the data*/
+ if ((*idx + BMA4_FIFO_MA_LENGTH) > fifo->length)
+ {
+ /*Update the data index as complete*/
+ *idx = fifo->length;
+ break;
+ }
+
+ /*Unpack the data array into structure instance "acc"*/
+ unpack_accel_data(&acc[*acc_idx], *idx + BMA4_MA_FIFO_A_X_LSB, fifo, dev);
+
+ /*Move the data index*/
+ *idx = *idx + BMA4_FIFO_MA_LENGTH;
+ (*acc_idx)++;
+ break;
+
+ /* Aux. sensor frame */
+ case BMA4_FIFO_HEAD_M:
+ case BMA4_FIFO_M_ENABLE:
+ (*idx) = (*idx) + BMA4_FIFO_M_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 bma4_accel.
+ */
+static void unpack_accel_data(struct bma4_accel *accel_data,
+ uint16_t data_start_index,
+ const struct bma4_fifo_frame *fifo,
+ const struct bma4_dev *dev)
+{
+ uint16_t data_lsb;
+ uint16_t data_msb;
+
+ /* Accel raw x data */
+ data_lsb = fifo->data[data_start_index++];
+ data_msb = fifo->data[data_start_index++];
+ accel_data->x = (int16_t)((data_msb << 8) | data_lsb);
+
+ /* Accel raw y data */
+ data_lsb = fifo->data[data_start_index++];
+ data_msb = fifo->data[data_start_index++];
+ accel_data->y = (int16_t)((data_msb << 8) | data_lsb);
+
+ /* Accel raw z data */
+ data_lsb = fifo->data[data_start_index++];
+ data_msb = fifo->data[data_start_index++];
+ accel_data->z = (int16_t)((data_msb << 8) | data_lsb);
+ if (dev->resolution == BMA4_12_BIT_RESOLUTION)
+ {
+ accel_data->x = (accel_data->x / 0x10);
+ accel_data->y = (accel_data->y / 0x10);
+ accel_data->z = (accel_data->z / 0x10);
+ }
+ else if (dev->resolution == BMA4_14_BIT_RESOLUTION)
+ {
+ accel_data->x = (accel_data->x / 0x04);
+ accel_data->y = (accel_data->y / 0x04);
+ accel_data->z = (accel_data->z / 0x04);
+ }
+}
+
+/*!
+ * @brief This API computes the number of bytes of Mag FIFO data which is
+ * to be parsed in header-less mode
+ *
+ */
+static void get_mag_len_to_parse(uint16_t *start_idx,
+ uint16_t *len,
+ const uint16_t *mag_count,
+ const struct bma4_fifo_frame *fifo)
+{
+ /*Data start index*/
+ *start_idx = fifo->mag_byte_start_idx;
+ if (fifo->fifo_data_enable == BMA4_FIFO_M_ENABLE)
+ {
+ /*Len has the number of bytes to loop for */
+ *len = (uint16_t)(((*mag_count) * BMA4_FIFO_M_LENGTH));
+ }
+ else if (fifo->fifo_data_enable == BMA4_FIFO_M_A_ENABLE)
+ {
+ /*Len has the number of bytes to loop for */
+ *len = (uint16_t)(((*mag_count) * BMA4_FIFO_MA_LENGTH));
+ }
+ else
+ {
+ /*Only accel sensor or no sensor is enabled in FIFO,
+ * so there will be no mag data.
+ * Update the data index as complete
+ */
+ *start_idx = fifo->length;
+ }
+
+ /*Handling the case where more data is requested than available*/
+ if ((*len) > fifo->length)
+ {
+ /*Len is equal to the FIFO length*/
+ *len = fifo->length;
+ }
+}
+
+/*!
+ * @brief This API is used to parse the magnetometer data from the
+ * FIFO data in header mode.
+ *
+ */
+static int8_t extract_mag_header_mode(const struct bma4_mag *data,
+ uint16_t *len,
+ struct bma4_fifo_frame *fifo,
+ const struct bma4_dev *dev)
+{
+ int8_t rslt = BMA4_OK;
+ uint8_t frame_header = 0;
+ uint16_t data_index;
+ uint16_t mag_index = 0;
+ uint16_t frame_to_read = *len;
+
+ /*Check if this is the first iteration of data unpacking
+ * if yes, then consider dummy byte on SPI
+ */
+ if (fifo->mag_byte_start_idx == 0)
+ {
+ fifo->mag_byte_start_idx = dev->dummy_byte;
+ }
+
+ for (data_index = fifo->mag_byte_start_idx; data_index < fifo->length;)
+ {
+ /*Header byte is stored in the variable frame_header*/
+ frame_header = fifo->data[data_index];
+
+ /*Get the frame details from header*/
+ frame_header = frame_header & BMA4_FIFO_TAG_INTR_MASK;
+
+ /*Index is moved to next byte where the data is starting*/
+ data_index++;
+ switch (frame_header)
+ {
+ /* Aux. sensor frame */
+ case BMA4_FIFO_HEAD_M:
+ case BMA4_FIFO_HEAD_M_A:
+ rslt = unpack_mag_frm(data, &data_index, &mag_index, frame_header, fifo, dev);
+ break;
+
+ /* Aux. sensor frame */
+ case BMA4_FIFO_HEAD_A:
+ move_next_frame(&data_index, BMA4_FIFO_A_LENGTH, fifo);
+ break;
+
+ /* Sensor time frame */
+ case BMA4_FIFO_HEAD_SENSOR_TIME:
+ unpack_sensortime_frame(&data_index, fifo);
+ break;
+
+ /* Skip frame */
+ case BMA4_FIFO_HEAD_SKIP_FRAME:
+ unpack_skipped_frame(&data_index, fifo);
+ break;
+
+ /* Input config frame */
+ case BMA4_FIFO_HEAD_INPUT_CONFIG:
+ move_next_frame(&data_index, 1, fifo);
+ break;
+
+ /* Sample drop frame */
+ case BMA4_FIFO_HEAD_SAMPLE_DROP:
+ unpack_dropped_frame(&data_index, fifo);
+ break;
+ case BMA4_FIFO_HEAD_OVER_READ_MSB:
+
+ /*Update the data index as complete*/
+ data_index = fifo->length;
+ break;
+ default:
+ break;
+ }
+ if (frame_to_read == mag_index)
+ {
+ /*Number of frames to read completed*/
+ break;
+ }
+ }
+
+ /*update number of Aux. sensor data read*/
+ *len = mag_index;
+
+ /*update the Aux. sensor frame index*/
+ fifo->mag_byte_start_idx = data_index;
+
+ return rslt;
+}
+
+/*!
+ * @brief This API is used to parse the magnetometer data from the
+ * FIFO data in both header mode and header-less mode and update the
+ * data_index value which is used to store the index of the current
+ * data byte which is parsed.
+ *
+ */
+static int8_t unpack_mag_frm(const struct bma4_mag *data,
+ uint16_t *idx,
+ uint16_t *mag_idx,
+ uint8_t frm,
+ const struct bma4_fifo_frame *fifo,
+ const struct bma4_dev *dev)
+{
+ int8_t rslt = BMA4_OK;
+
+ switch (frm)
+ {
+ case BMA4_FIFO_HEAD_M:
+ case BMA4_FIFO_M_ENABLE:
+
+ /*partial read, then skip the data*/
+ if ((*idx + BMA4_FIFO_M_LENGTH) > fifo->length)
+ {
+ /*update the data index as complete*/
+ *idx = fifo->length;
+ break;
+ }
+
+ /*unpack the data array into Aux. sensor data structure*/
+ rslt = unpack_mag_data(&data[*mag_idx], *idx, fifo, dev);
+
+ /*move the data index*/
+ *idx = *idx + BMA4_FIFO_M_LENGTH;
+ (*mag_idx)++;
+ break;
+ case BMA4_FIFO_HEAD_M_A:
+ case BMA4_FIFO_M_A_ENABLE:
+
+ /*partial read, then skip the data*/
+ if ((*idx + BMA4_FIFO_MA_LENGTH) > fifo->length)
+ {
+ /*update the data index as complete*/
+ *idx = fifo->length;
+ break;
+ }
+
+ /*unpack the data array into Aux. sensor data structure*/
+ rslt = unpack_mag_data(&data[*mag_idx], *idx, fifo, dev);
+
+ /*move the data index to next frame*/
+ *idx = *idx + BMA4_FIFO_MA_LENGTH;
+ (*mag_idx)++;
+ break;
+
+ /* aux. sensor frame */
+ case BMA4_FIFO_HEAD_A:
+ case BMA4_FIFO_A_ENABLE:
+ (*idx) = (*idx) + BMA4_FIFO_A_LENGTH;
+ break;
+ default:
+ break;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API is used to parse the auxiliary magnetometer data from
+ * the FIFO data and store it in the instance of the structure mag_data.
+ *
+ */
+static int8_t unpack_mag_data(const struct bma4_mag *mag_data,
+ uint16_t start_idx,
+ const struct bma4_fifo_frame *fifo,
+ const struct bma4_dev *dev)
+{
+ int8_t rslt;
+ struct bma4_mag_fifo_data mag_fifo_data;
+
+ /* Aux. mag sensor raw x data */
+ mag_fifo_data.mag_x_lsb = fifo->data[start_idx++];
+ mag_fifo_data.mag_x_msb = fifo->data[start_idx++];
+
+ /* Aux. mag sensor raw y data */
+ mag_fifo_data.mag_y_lsb = fifo->data[start_idx++];
+ mag_fifo_data.mag_y_msb = fifo->data[start_idx++];
+
+ /* Aux. mag sensor raw z data */
+ mag_fifo_data.mag_z_lsb = fifo->data[start_idx++];
+ mag_fifo_data.mag_z_msb = fifo->data[start_idx++];
+
+ /* Aux. mag sensor raw r data */
+ mag_fifo_data.mag_r_y2_lsb = fifo->data[start_idx++];
+ mag_fifo_data.mag_r_y2_msb = fifo->data[start_idx++];
+
+ /*Compensated FIFO data output*/
+ rslt = bma4_second_if_mag_compensate_xyz(mag_fifo_data, dev->aux_sensor, mag_data);
+
+ return rslt;
+}
+
+/*!
+ * @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, struct bma4_fifo_frame *fifo)
+{
+ 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 + BMA4_SENSOR_TIME_LENGTH) > fifo->length)
+ {
+ /*Update the data index as complete*/
+ *data_index = fifo->length;
+ }
+ else
+ {
+ sensor_time_byte3 = fifo->data[(*data_index) + BMA4_SENSOR_TIME_MSB_BYTE] << 16;
+ sensor_time_byte2 = fifo->data[(*data_index) + BMA4_SENSOR_TIME_XLSB_BYTE] << 8;
+ sensor_time_byte1 = fifo->data[(*data_index)];
+
+ /* Sensor time */
+ fifo->sensor_time = (uint32_t)(sensor_time_byte3 | sensor_time_byte2 | sensor_time_byte1);
+ *data_index = (*data_index) + BMA4_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, struct bma4_fifo_frame *fifo)
+{
+ /*Partial read, then move the data index to last data*/
+ if (*data_index >= fifo->length)
+ {
+ /*Update the data index as complete*/
+ *data_index = fifo->length;
+ }
+ else
+ {
+ fifo->skipped_frame_count = fifo->data[*data_index];
+
+ /*Move the data index*/
+ *data_index = (*data_index) + 1;
+ }
+}
+
+/*!
+ * @brief This API is used to parse and store the dropped_frame_count from
+ * the FIFO data in the structure instance dev.
+ */
+static void unpack_dropped_frame(uint16_t *data_index, struct bma4_fifo_frame *fifo)
+{
+ uint8_t dropped_frame = 0;
+
+ /*Partial read, then move the data index to last data*/
+ if (*data_index >= fifo->length)
+ {
+ /*Update the data index as complete*/
+ *data_index = fifo->length;
+ }
+ else
+ {
+ /*Extract accel and mag dropped frame count*/
+ dropped_frame = fifo->data[*data_index] & BMA4_ACCEL_AUX_FIFO_DROP;
+
+ /*Move the data index and update the dropped frame count*/
+ switch (dropped_frame)
+ {
+ case BMA4_ACCEL_FIFO_DROP:
+ *data_index = (*data_index) + BMA4_FIFO_A_LENGTH;
+ fifo->accel_dropped_frame_count = fifo->accel_dropped_frame_count + 1;
+ break;
+ case BMA4_AUX_FIFO_DROP:
+ *data_index = (*data_index) + BMA4_FIFO_M_LENGTH;
+ fifo->mag_dropped_frame_count = fifo->mag_dropped_frame_count + 1;
+ break;
+ case BMA4_ACCEL_AUX_FIFO_DROP:
+ *data_index = (*data_index) + BMA4_FIFO_MA_LENGTH;
+ fifo->accel_dropped_frame_count = fifo->accel_dropped_frame_count + 1;
+ fifo->mag_dropped_frame_count = fifo->mag_dropped_frame_count + 1;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/*!
+ * @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 bma4_fifo_frame *fifo)
+{
+ /*Partial read, then move the data index to last data*/
+ if ((*data_index + current_frame_length) > fifo->length)
+ {
+ /*Update the data index as complete*/
+ *data_index = fifo->length;
+ }
+ else
+ {
+ /*Move the data index to next frame*/
+ *data_index = *data_index + current_frame_length;
+ }
+}
+
+/*!
+ * @brief This function validates the Accel self-test data and decides the
+ * result of self-test operation.
+ */
+static int8_t validate_selftest(const struct bma4_selftest_delta_limit *accel_data_diff, const struct bma4_dev *dev)
+{
+ int8_t rslt = 0;
+ uint16_t x_axis_signal_diff = 0;
+ uint16_t y_axis_signal_diff = 0;
+ uint16_t z_axis_signal_diff = 0;
+
+ /* Set self-test amplitude based on variant */
+ switch (dev->variant)
+ {
+ case BMA42X_VARIANT:
+ x_axis_signal_diff = BMA42X_ST_ACC_X_AXIS_SIGNAL_DIFF;
+ y_axis_signal_diff = BMA42X_ST_ACC_Y_AXIS_SIGNAL_DIFF;
+ z_axis_signal_diff = BMA42X_ST_ACC_Z_AXIS_SIGNAL_DIFF;
+ break;
+
+ case BMA42X_B_VARIANT:
+ x_axis_signal_diff = BMA42X_B_ST_ACC_X_AXIS_SIGNAL_DIFF;
+ y_axis_signal_diff = BMA42X_B_ST_ACC_Y_AXIS_SIGNAL_DIFF;
+ z_axis_signal_diff = BMA42X_B_ST_ACC_Z_AXIS_SIGNAL_DIFF;
+ break;
+
+ case BMA45X_VARIANT:
+ x_axis_signal_diff = BMA45X_ST_ACC_X_AXIS_SIGNAL_DIFF;
+ y_axis_signal_diff = BMA45X_ST_ACC_X_AXIS_SIGNAL_DIFF;
+ z_axis_signal_diff = BMA45X_ST_ACC_X_AXIS_SIGNAL_DIFF;
+ break;
+
+ default:
+ rslt = BMA4_E_INVALID_SENSOR;
+ break;
+ }
+
+ if (rslt != BMA4_E_INVALID_SENSOR)
+ {
+ if ((accel_data_diff->x <= x_axis_signal_diff) && (accel_data_diff->y <= y_axis_signal_diff) &&
+ (accel_data_diff->z <= z_axis_signal_diff))
+ {
+ rslt = BMA4_SELFTEST_DIFF_X_Y_AND_Z_AXIS_FAILED;
+ }
+ else if ((accel_data_diff->x <= x_axis_signal_diff) && (accel_data_diff->y <= y_axis_signal_diff))
+ {
+ rslt = BMA4_SELFTEST_DIFF_X_AND_Y_AXIS_FAILED;
+ }
+ else if ((accel_data_diff->x <= x_axis_signal_diff) && (accel_data_diff->z <= z_axis_signal_diff))
+ {
+ rslt = BMA4_SELFTEST_DIFF_X_AND_Z_AXIS_FAILED;
+ }
+ else if ((accel_data_diff->y <= y_axis_signal_diff) && (accel_data_diff->z <= z_axis_signal_diff))
+ {
+ rslt = BMA4_SELFTEST_DIFF_Y_AND_Z_AXIS_FAILED;
+ }
+ else if (accel_data_diff->x <= x_axis_signal_diff)
+ {
+ rslt = BMA4_SELFTEST_DIFF_X_AXIS_FAILED;
+ }
+ else if (accel_data_diff->y <= y_axis_signal_diff)
+ {
+ rslt = BMA4_SELFTEST_DIFF_Y_AXIS_FAILED;
+ }
+ else if (accel_data_diff->z <= z_axis_signal_diff)
+ {
+ rslt = BMA4_SELFTEST_DIFF_Z_AXIS_FAILED;
+ }
+ else
+ {
+ rslt = BMA4_SELFTEST_PASS;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API is used to calculate the power of 2
+ */
+static int32_t power(int16_t base, uint8_t resolution)
+{
+ uint8_t i = 1;
+
+ /* Initialize variable to store the power of 2 value */
+ int32_t value = 1;
+
+ for (; i <= resolution; i++)
+ {
+ value = (int32_t)(value * base);
+ }
+
+ return value;
+}
+
+/*!
+ * @brief This internal API brings up the secondary interface to access
+ * auxiliary sensor *
+ */
+static int8_t set_aux_interface_config(struct bma4_dev *dev)
+{
+ /* Variable to return error codes */
+ int8_t rslt;
+
+ /* Check for null pointer error */
+ rslt = null_pointer_check(dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Enable the auxiliary sensor */
+ rslt = bma4_set_mag_enable(0x01, dev);
+ dev->delay_us(BMA4_AUX_COM_DELAY, dev->intf_ptr);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Disable advance power save */
+ rslt = bma4_set_advance_power_save(0x00, dev);
+ dev->delay_us(BMA4_AUX_COM_DELAY, dev->intf_ptr);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Set the I2C device address of auxiliary device */
+ rslt = bma4_set_i2c_device_addr(dev);
+ dev->delay_us(BMA4_AUX_COM_DELAY, dev->intf_ptr);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Set auxiliary interface to manual mode */
+ rslt = bma4_set_mag_manual_enable(dev->aux_config.manual_enable, dev);
+ dev->delay_us(BMA4_AUX_COM_DELAY, dev->intf_ptr);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Set the number of bytes for burst read */
+ rslt = bma4_set_mag_burst(dev->aux_config.burst_read_length, dev);
+ dev->delay_us(BMA4_AUX_COM_DELAY, dev->intf_ptr);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Switch on the the auxiliary interface mode */
+ rslt = bma4_set_if_mode(dev->aux_config.if_mode, dev);
+ dev->delay_us(BMA4_AUX_COM_DELAY, dev->intf_ptr);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API reads the data from the auxiliary sensor
+ * depending on burst length configured
+ */
+static int8_t extract_aux_data(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev)
+{
+ /* Variable to return error codes */
+ int8_t rslt;
+
+ /* Pointer variable to read data from the register */
+ uint8_t data[15] = { 0 };
+
+ /* Variable to define length counts */
+ uint8_t len_count = 0;
+
+ /* Variable to define burst read length */
+ uint8_t burst_len = 0;
+
+ /* Variable to define read length */
+ uint8_t read_length = 0;
+
+ /* Variable to define the number of burst reads */
+ uint8_t burst_count;
+
+ /* Variable to define address of the data register*/
+ uint8_t aux_read_addr = BMA4_DATA_0_ADDR;
+
+ /* Extract burst read length in a variable */
+ rslt = map_read_len(&burst_len, dev);
+ if ((rslt == BMA4_OK) && (aux_data != NULL))
+ {
+ for (burst_count = 0; burst_count < len; burst_count += burst_len)
+ {
+ /* Set the address whose data is to be read */
+ rslt = bma4_set_mag_read_addr(aux_reg_addr, dev);
+ dev->delay_us(BMA4_AUX_COM_DELAY, dev->intf_ptr);
+ if (rslt == BMA4_OK)
+ {
+ /* If user defined length is valid */
+ if (len > 0)
+ {
+ /* Read the data from the data register */
+ rslt = bma4_read_regs(aux_read_addr, data, (uint8_t)burst_len, dev);
+ dev->delay_us(BMA4_AUX_COM_DELAY, dev->intf_ptr);
+ if (rslt == BMA4_OK)
+ {
+ /* If defined user length or remaining
+ * length after a burst read is less than
+ * burst length
+ */
+ if ((len - burst_count) < burst_len)
+ {
+ /* Read length is equal to burst
+ * length or remaining length
+ */
+ read_length = (uint8_t)(len - burst_count);
+ }
+ else
+ {
+ /* Read length is equal to burst
+ * length
+ */
+ read_length = burst_len;
+ }
+
+ /* Copy the read data in terms of given
+ * read length
+ */
+ for (len_count = 0; len_count < read_length; len_count++)
+ {
+ aux_data[burst_count + len_count] = data[len_count];
+ }
+
+ /* Increment the register address by
+ * burst read length
+ */
+ aux_reg_addr += burst_len;
+ }
+ else
+ {
+ rslt = BMA4_E_RD_WR_LENGTH_INVALID;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_COM_FAIL;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_COM_FAIL;
+ }
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API maps the actual burst read length with user
+ * length set.
+ */
+static int8_t map_read_len(uint8_t *len, const struct bma4_dev *dev)
+{
+ /* Variable to return error codes */
+ int8_t rslt = BMA4_OK;
+
+ switch (dev->aux_config.burst_read_length)
+ {
+ case BMA4_AUX_READ_LEN_0:
+ *len = 1;
+ break;
+ case BMA4_AUX_READ_LEN_1:
+ *len = 2;
+ break;
+ case BMA4_AUX_READ_LEN_2:
+ *len = 6;
+ break;
+ case BMA4_AUX_READ_LEN_3:
+ *len = 8;
+ break;
+ default:
+ rslt = BMA4_E_OUT_OF_RANGE;
+ break;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API checks null pointer error
+ */
+static int8_t null_pointer_check(const struct bma4_dev *dev)
+{
+ int8_t rslt = BMA4_OK;
+
+ if ((dev == NULL) || (dev->bus_read == NULL) || (dev->bus_write == NULL) || (dev->intf_ptr == NULL))
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+ else
+ {
+ rslt = BMA4_OK;
+ }
+
+ return rslt;
+}
+
+/*! @endcond */
+
+/*!
+ * @brief This API does soft reset
+ */
+int8_t bma4_soft_reset(struct bma4_dev *dev)
+{
+ int8_t rslt;
+ uint8_t command_reg = BMA4_SOFT_RESET;
+
+ /* Check the dev structure as NULL */
+ rslt = null_pointer_check(dev);
+
+ /* Check the bma4 structure as NULL */
+ if (rslt == BMA4_OK)
+ {
+ /* Write command register */
+ rslt = bma4_write_regs(BMA4_CMD_ADDR, &command_reg, 1, dev);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API performs Fast Offset Compensation for accelerometer.
+ */
+int8_t bma4_perform_accel_foc(const struct bma4_accel_foc_g_value *accel_g_value, struct bma4_dev *dev)
+{
+ /* Variable to define error */
+ int8_t rslt;
+
+ /* Structure to define the accelerometer configurations */
+ struct bma4_accel_config acc_cfg = { 0, 0, 0, 0 };
+
+ /* Variable to store status of advance power save */
+ uint8_t aps = 0;
+
+ /* Variable to store status of accelerometer enable */
+ uint8_t acc_en = 0;
+
+ /* Variable to get the accel status */
+ uint8_t accel_status = 0;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (accel_g_value != NULL))
+ {
+ /* Check for input validity */
+ if (((ABS(accel_g_value->x) + ABS(accel_g_value->y) + ABS(accel_g_value->z)) == 1) &&
+ ((accel_g_value->sign == 1) || (accel_g_value->sign == 0)))
+ {
+ /* Enable the accelerometer */
+ rslt = bma4_set_accel_enable(BMA4_ENABLE, dev);
+
+ /* Get the accel status */
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_get_accel_enable(&accel_status, dev);
+ }
+
+ /* Verify FOC position */
+ if (rslt == BMA4_OK)
+ {
+ rslt = verify_foc_position(accel_status, accel_g_value, dev);
+ }
+
+ if (rslt == BMA4_OK)
+ {
+ /* Save accelerometer configurations, accelerometer
+ * enable status and advance power save status
+ */
+ rslt = save_accel_foc_config(&acc_cfg, &aps, &acc_en, dev);
+ }
+
+ /* Set configurations for FOC */
+ if (rslt == BMA4_OK)
+ {
+ rslt = set_accel_foc_config(dev);
+ }
+
+ /* Perform accelerometer FOC */
+ if (rslt == BMA4_OK)
+ {
+ rslt = perform_accel_foc(accel_g_value, &acc_cfg, dev);
+ }
+
+ /* Restore the saved configurations */
+ if (rslt == BMA4_OK)
+ {
+ rslt = restore_accel_foc_config(&acc_cfg, aps, acc_en, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_OUT_OF_RANGE;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API verifies and allows only the correct position to do Fast Offset Compensation for
+ * accelerometer.
+ */
+static int8_t verify_foc_position(uint8_t accel_en,
+ const struct bma4_accel_foc_g_value *accel_g_axis,
+ struct bma4_dev *dev)
+{
+ int8_t rslt;
+ struct bma4_accel avg_foc_data = { 0 };
+ struct bma4_foc_temp_value temp_foc_data = { 0 };
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (accel_g_axis != NULL))
+ {
+ rslt = get_average_of_sensor_data(accel_en, &temp_foc_data, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Taking modulus to make negative values as positive */
+ if ((accel_g_axis->x == 1) && (accel_g_axis->sign == 1))
+ {
+ temp_foc_data.x = temp_foc_data.x * -1;
+ }
+ else if ((accel_g_axis->y == 1) && (accel_g_axis->sign == 1))
+ {
+ temp_foc_data.y = temp_foc_data.y * -1;
+ }
+ else if ((accel_g_axis->z == 1) && (accel_g_axis->sign == 1))
+ {
+ temp_foc_data.z = temp_foc_data.z * -1;
+ }
+
+ /* Typecasting into 16 bit */
+ avg_foc_data.x = (int16_t)(temp_foc_data.x);
+ avg_foc_data.y = (int16_t)(temp_foc_data.y);
+ avg_foc_data.z = (int16_t)(temp_foc_data.z);
+
+ rslt = validate_foc_position(accel_en, accel_g_axis, avg_foc_data, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API reads and provides average for 128 samples of sensor data for accel FOC operation.
+ */
+static int8_t get_average_of_sensor_data(uint8_t accel_en,
+ struct bma4_foc_temp_value *temp_foc_data,
+ struct bma4_dev *dev)
+{
+ int8_t rslt;
+ struct bma4_accel sensor_data = { 0 };
+ uint8_t sample_count = 0;
+ uint8_t datardy_try_cnt;
+ uint8_t drdy_status = 0;
+ uint8_t sensor_drdy = 0;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (temp_foc_data != NULL))
+ {
+ if (accel_en == BMA4_ENABLE)
+ {
+ sensor_drdy = BMA4_STAT_DATA_RDY_ACCEL_MSK;
+ }
+
+ /* Read sensor values before FOC */
+ while (sample_count < BMA4_FOC_SAMPLE_LIMIT)
+ {
+ datardy_try_cnt = 5;
+ do
+ {
+ dev->delay_us(BMA4_MS_TO_US(20), dev->intf_ptr);
+ rslt = bma4_get_status(&drdy_status, dev);
+ datardy_try_cnt--;
+ } while ((rslt == BMA4_OK) && (!(drdy_status & sensor_drdy)) && (datardy_try_cnt));
+
+ if ((rslt != BMA4_OK) || (datardy_try_cnt == 0))
+ {
+ rslt = BMA4_E_COM_FAIL;
+ break;
+ }
+
+ rslt = bma4_read_accel_xyz(&sensor_data, dev);
+ if (rslt == BMA4_OK)
+ {
+ temp_foc_data->x += sensor_data.x;
+ temp_foc_data->y += sensor_data.y;
+ temp_foc_data->z += sensor_data.z;
+ }
+ else
+ {
+ return rslt;
+ }
+
+ sample_count++;
+ }
+
+ if (rslt == BMA4_OK)
+ {
+ temp_foc_data->x = (temp_foc_data->x / BMA4_FOC_SAMPLE_LIMIT);
+ temp_foc_data->y = (temp_foc_data->y / BMA4_FOC_SAMPLE_LIMIT);
+ temp_foc_data->z = (temp_foc_data->z / BMA4_FOC_SAMPLE_LIMIT);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API validates accel FOC position as per the range
+ */
+static int8_t validate_foc_position(uint8_t accel_en,
+ const struct bma4_accel_foc_g_value *accel_g_axis,
+ struct bma4_accel avg_foc_data,
+ struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (accel_g_axis != NULL))
+ {
+ if (accel_en == BMA4_ENABLE)
+ {
+ if (accel_g_axis->x == 1)
+ {
+ rslt = validate_foc_accel_axis(avg_foc_data.x, dev);
+ }
+ else if (accel_g_axis->y == 1)
+ {
+ rslt = validate_foc_accel_axis(avg_foc_data.y, dev);
+ }
+ else
+ {
+ rslt = validate_foc_accel_axis(avg_foc_data.z, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_COM_FAIL;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API validates depends on accel FOC access input
+ */
+static int8_t validate_foc_accel_axis(int16_t avg_foc_data, struct bma4_dev *dev)
+{
+ struct bma4_accel_config sens_cfg = { 0 };
+ uint8_t range;
+ int8_t rslt;
+ uint16_t range_2g = 0;
+ uint16_t range_4g = 0;
+ uint16_t range_8g = 0;
+ uint16_t range_16g = 0;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Get configurations for accel */
+ rslt = bma4_get_accel_config(&sens_cfg, dev);
+ range = sens_cfg.range;
+
+ /* Calculation. Eg. Range = 2G, Resolution = 12 bit.
+ * Value(i.e range_2g) = 2^(Resolution - 1) / Range
+ * = 2^(12-1) / 2 = 1024
+ */
+ if (dev->resolution == BMA4_12_BIT_RESOLUTION)
+ {
+ range_2g = 1024;
+ range_4g = 512;
+ range_8g = 256;
+ range_16g = 128;
+ }
+ else if (dev->resolution == BMA4_14_BIT_RESOLUTION)
+ {
+ range_2g = 4096;
+ range_4g = 2048;
+ range_8g = 1024;
+ range_16g = 512;
+ }
+ else if (dev->resolution == BMA4_16_BIT_RESOLUTION)
+ {
+ range_2g = 16384;
+ range_4g = 8192;
+ range_8g = 4096;
+ range_16g = 2048;
+ }
+
+ /* Reference LSB value of 2G */
+ if ((range == BMA4_ACCEL_RANGE_2G) && (avg_foc_data > BMA4_MIN_NOISE_LIMIT(range_2g)) &&
+ (avg_foc_data < BMA4_MAX_NOISE_LIMIT(range_2g)))
+ {
+ rslt = BMA4_OK;
+ }
+ /* Reference LSB value of 4G */
+ else if ((range == BMA4_ACCEL_RANGE_4G) && (avg_foc_data > BMA4_MIN_NOISE_LIMIT(range_4g)) &&
+ (avg_foc_data < BMA4_MAX_NOISE_LIMIT(range_4g)))
+ {
+ rslt = BMA4_OK;
+ }
+ /* Reference LSB value of 8G */
+ else if ((range == BMA4_ACCEL_RANGE_8G) && (avg_foc_data > BMA4_MIN_NOISE_LIMIT(range_8g)) &&
+ (avg_foc_data < BMA4_MAX_NOISE_LIMIT(range_8g)))
+ {
+ rslt = BMA4_OK;
+ }
+ /* Reference LSB value of 16G */
+ else if ((range == BMA4_ACCEL_RANGE_16G) && (avg_foc_data > BMA4_MIN_NOISE_LIMIT(range_16g)) &&
+ (avg_foc_data < BMA4_MAX_NOISE_LIMIT(range_16g)))
+ {
+ rslt = BMA4_OK;
+ }
+ else
+ {
+ rslt = BMA4_E_FOC_FAIL;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API saves the configurations before performing FOC.
+ */
+static int8_t save_accel_foc_config(struct bma4_accel_config *acc_cfg,
+ uint8_t *aps,
+ uint8_t *acc_en,
+ struct bma4_dev *dev)
+{
+ /* Variable to define error */
+ int8_t rslt;
+
+ /* Variable to get the status from PWR_CTRL register */
+ uint8_t pwr_ctrl_data = 0;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (acc_cfg != NULL) && (aps != NULL) && (acc_en != NULL))
+ {
+ /* Get accelerometer configurations to be saved */
+ rslt = bma4_get_accel_config(acc_cfg, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Get accelerometer enable status to be saved */
+ rslt = bma4_read_regs(BMA4_POWER_CTRL_ADDR, &pwr_ctrl_data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *acc_en = BMA4_GET_BITSLICE(pwr_ctrl_data, BMA4_ACCEL_ENABLE);
+ }
+
+ /* Get advance power save mode to be saved */
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_get_advance_power_save(aps, dev);
+ }
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API sets configurations for performing accelerometer FOC.
+ */
+static int8_t set_accel_foc_config(struct bma4_dev *dev)
+{
+ /* Variable to define error */
+ int8_t rslt;
+
+ /* Variable to set the accelerometer configuration value */
+ uint8_t acc_conf_data = BMA4_FOC_ACC_CONF_VAL;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Disabling offset compensation */
+ rslt = set_bma4_accel_offset_comp(BMA4_DISABLE, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Set accelerometer configurations to 50Hz, continuous mode, CIC mode */
+ rslt = bma4_write_regs(BMA4_ACCEL_CONFIG_ADDR, &acc_conf_data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Set accelerometer to normal mode by enabling it */
+ rslt = bma4_set_accel_enable(BMA4_ENABLE, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Disable advance power save mode */
+ rslt = bma4_set_advance_power_save(BMA4_DISABLE, dev);
+ }
+ }
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API enables/disables the offset compensation for
+ * filtered and un-filtered accelerometer data.
+ */
+static int8_t set_bma4_accel_offset_comp(uint8_t offset_en, struct bma4_dev *dev)
+{
+ /* Variable to define error */
+ int8_t rslt;
+
+ /* Variable to store data */
+ uint8_t data = 0;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Enable/Disable offset compensation */
+ rslt = bma4_read_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ data = BMA4_SET_BITSLICE(data, BMA4_NV_ACCEL_OFFSET, offset_en);
+ rslt = bma4_write_regs(BMA4_NV_CONFIG_ADDR, &data, 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API performs Fast Offset Compensation for accelerometer.
+ */
+static int8_t perform_accel_foc(const struct bma4_accel_foc_g_value *accel_g_value,
+ const struct bma4_accel_config *acc_cfg,
+ struct bma4_dev *dev)
+{
+ /* Variable to define error */
+ int8_t rslt;
+
+ /* Variable to define count */
+ uint8_t loop;
+
+ /* Variable to store status read from the status register */
+ uint8_t reg_status = 0;
+
+ /* Array of structure to store accelerometer data */
+ struct bma4_accel accel_value[128] = { { 0 } };
+
+ /* Structure to store accelerometer data temporarily */
+ struct bma4_foc_temp_value temp = { 0, 0, 0 };
+
+ /* Structure to store the average of accelerometer data */
+ struct bma4_accel accel_avg = { 0, 0, 0 };
+
+ /* Variable to define LSB per g value */
+ uint16_t lsb_per_g = 0;
+
+ /* Variable to define range */
+ uint8_t range = 0;
+
+ /* Variable to set limit for FOC sample */
+ uint8_t limit = 128;
+
+ /* Structure to store accelerometer data deviation from ideal value */
+ struct bma4_offset_delta delta = { 0, 0, 0 };
+
+ /* Structure to store accelerometer offset values */
+ struct bma4_accel_offset offset = { 0, 0, 0 };
+
+ /* Variable tries max 5 times for interrupt then generates timeout */
+ uint8_t try_cnt;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (accel_g_value != NULL) && (acc_cfg != NULL))
+ {
+ for (loop = 0; loop < limit; loop++)
+ {
+ try_cnt = 5;
+ while (try_cnt && (!(reg_status & BMA4_STAT_DATA_RDY_ACCEL_MSK)))
+ {
+ /* 20ms delay for 50Hz ODR */
+ dev->delay_us(BMA4_MS_TO_US(20), dev->intf_ptr);
+ rslt = bma4_get_status(&reg_status, dev);
+ try_cnt--;
+ }
+
+ if ((rslt == BMA4_OK) && (reg_status & BMA4_STAT_DATA_RDY_ACCEL_MSK))
+ {
+ rslt = bma4_read_accel_xyz(&accel_value[loop], dev);
+ }
+
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_read_accel_xyz(&accel_value[loop], dev);
+ }
+
+ if (rslt == BMA4_OK)
+ {
+ /* Store the data in a temporary structure */
+ temp.x = temp.x + (int32_t)accel_value[loop].x;
+ temp.y = temp.y + (int32_t)accel_value[loop].y;
+ temp.z = temp.z + (int32_t)accel_value[loop].z;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (rslt == BMA4_OK)
+ {
+ /* Take average of x, y and z data for lesser noise */
+ accel_avg.x = (int16_t)(temp.x / 128);
+ accel_avg.y = (int16_t)(temp.y / 128);
+ accel_avg.z = (int16_t)(temp.z / 128);
+
+ /* Get the exact range value */
+ map_accel_range(acc_cfg->range, &range);
+
+ /* Get the smallest possible measurable acceleration level given the range and
+ * resolution */
+ lsb_per_g = (uint16_t)(power(2, dev->resolution) / (2 * range));
+
+ /* Compensate acceleration data against gravity */
+ comp_for_gravity(lsb_per_g, accel_g_value, &accel_avg, &delta);
+
+ /* Scale according to offset register resolution */
+ scale_bma4_accel_offset(range, &delta, &offset);
+
+ /* Invert the accelerometer offset data */
+ invert_bma4_accel_offset(&offset);
+
+ /* Write offset data in the offset compensation register */
+ rslt = write_bma4_accel_offset(&offset, dev);
+
+ /* Enable offset compensation */
+ if (rslt == BMA4_OK)
+ {
+ rslt = set_bma4_accel_offset_comp(BMA4_ENABLE, dev);
+ }
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API converts the accelerometer range value into
+ * corresponding integer value.
+ */
+static void map_accel_range(uint8_t range_in, uint8_t *range_out)
+{
+ switch (range_in)
+ {
+ case BMA4_ACCEL_RANGE_2G:
+ *range_out = 2;
+ break;
+ case BMA4_ACCEL_RANGE_4G:
+ *range_out = 4;
+ break;
+ case BMA4_ACCEL_RANGE_8G:
+ *range_out = 8;
+ break;
+ case BMA4_ACCEL_RANGE_16G:
+ *range_out = 16;
+ break;
+ default:
+
+ /* By default RANGE 4G is set */
+ *range_out = 4;
+ break;
+ }
+}
+
+/*!
+ * @brief This internal API compensate the accelerometer data against gravity.
+ */
+static void comp_for_gravity(uint16_t lsb_per_g,
+ const struct bma4_accel_foc_g_value *g_val,
+ const struct bma4_accel *data,
+ struct bma4_offset_delta *comp_data)
+{
+ /* Array to store the accelerometer values in LSB */
+ int16_t accel_value_lsb[3] = { 0 };
+
+ /* Convert g-value to LSB */
+ accel_value_lsb[BMA4_X_AXIS] = (int16_t)(lsb_per_g * g_val->x);
+ accel_value_lsb[BMA4_Y_AXIS] = (int16_t)(lsb_per_g * g_val->y);
+ accel_value_lsb[BMA4_Z_AXIS] = (int16_t)(lsb_per_g * g_val->z);
+
+ /* Get the compensated values for X, Y and Z axis */
+ comp_data->x = (data->x - accel_value_lsb[BMA4_X_AXIS]);
+ comp_data->y = (data->y - accel_value_lsb[BMA4_Y_AXIS]);
+ comp_data->z = (data->z - accel_value_lsb[BMA4_Z_AXIS]);
+}
+
+/*!
+ * @brief This internal API scales the compensated accelerometer data according
+ * to the offset register resolution.
+ */
+static void scale_bma4_accel_offset(uint8_t range,
+ const struct bma4_offset_delta *comp_data,
+ struct bma4_accel_offset *data)
+{
+ /* Variable to store the position of bit having 3.9mg resolution */
+ int8_t bit_pos_3_9mg;
+
+ /* Variable to store the position previous of bit having 3.9mg resolution */
+ int8_t bit_pos_3_9mg_prev_bit;
+
+ /* Variable to store the round-off value */
+ uint8_t round_off;
+
+ /* Find the bit position of 3.9mg */
+ bit_pos_3_9mg = get_bit_pos_3_9mg(range);
+
+ /* Round off, consider if the next bit is high */
+ bit_pos_3_9mg_prev_bit = bit_pos_3_9mg - 1;
+ round_off = (uint8_t)(power(2, ((uint8_t) bit_pos_3_9mg_prev_bit)));
+
+ /* Scale according to offset register resolution */
+ data->x = (uint8_t)((comp_data->x + round_off) / power(2, ((uint8_t) bit_pos_3_9mg)));
+ data->y = (uint8_t)((comp_data->y + round_off) / power(2, ((uint8_t) bit_pos_3_9mg)));
+ data->z = (uint8_t)((comp_data->z + round_off) / power(2, ((uint8_t) bit_pos_3_9mg)));
+}
+
+/*!
+ * @brief This internal API inverts the accelerometer offset data.
+ */
+static void invert_bma4_accel_offset(struct bma4_accel_offset *offset_data)
+{
+ /* Get the offset data */
+ offset_data->x = (uint8_t)((offset_data->x) * (-1));
+ offset_data->y = (uint8_t)((offset_data->y) * (-1));
+ offset_data->z = (uint8_t)((offset_data->z) * (-1));
+}
+
+/*!
+ * @brief This internal API writes the offset data in the offset compensation
+ * register.
+ */
+static int8_t write_bma4_accel_offset(const struct bma4_accel_offset *offset, struct bma4_dev *dev)
+{
+ /* Variable to define error */
+ int8_t rslt;
+
+ /* Array to store the offset data */
+ uint8_t data_array[3] = { 0 };
+
+ data_array[0] = offset->x;
+ data_array[1] = offset->y;
+ data_array[2] = offset->z;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Offset values are written in the offset register */
+ rslt = bma4_write_regs(BMA4_OFFSET_0_ADDR, data_array, 3, dev);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API finds the bit position of 3.9mg according to given
+ * range and resolution.
+ */
+static int8_t get_bit_pos_3_9mg(uint8_t range)
+{
+ /* Variable to store the bit position of 3.9mg resolution */
+ int8_t bit_pos_3_9mg;
+
+ /* Variable to shift the bits according to the resolution */
+ uint32_t divisor = 1;
+
+ /* Scaling factor to get the bit position of 3.9 mg resolution */
+ int16_t scale_factor = -1;
+
+ /* Variable to store temporary value */
+ uint16_t temp;
+
+ /* Shift left by the times of resolution */
+ divisor = divisor << 16;
+
+ /* Get the bit position to be shifted */
+ temp = (uint16_t)(divisor / (range * 256));
+
+ /* Get the scaling factor until bit position is shifted to last bit */
+ while (temp != 1)
+ {
+ scale_factor++;
+ temp = temp >> 1;
+ }
+
+ /* Scaling factor is the bit position of 3.9 mg resolution */
+ bit_pos_3_9mg = (int8_t) scale_factor;
+
+ return bit_pos_3_9mg;
+}
+
+/*!
+ * @brief This internal API restores the configurations saved before performing
+ * accelerometer FOC.
+ */
+static int8_t restore_accel_foc_config(const struct bma4_accel_config *acc_cfg,
+ uint8_t aps,
+ uint8_t acc_en,
+ struct bma4_dev *dev)
+{
+ /* Variable to define error */
+ int8_t rslt;
+
+ /* Variable to get the status from PWR_CTRL register */
+ uint8_t pwr_ctrl_data = 0;
+
+ /* NULL pointer check */
+ rslt = null_pointer_check(dev);
+
+ if ((rslt == BMA4_OK) && (acc_cfg != NULL))
+ {
+ /* Restore the saved accelerometer configurations */
+ rslt = bma4_set_accel_config(acc_cfg, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Restore the saved accelerometer enable status */
+ rslt = bma4_read_regs(BMA4_POWER_CTRL_ADDR, &pwr_ctrl_data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ pwr_ctrl_data = BMA4_SET_BITSLICE(pwr_ctrl_data, BMA4_ACCEL_ENABLE, acc_en);
+ rslt = bma4_write_regs(BMA4_POWER_CTRL_ADDR, &pwr_ctrl_data, 1, dev);
+
+ /* Restore the saved advance power save */
+ if (rslt == BMA4_OK)
+ {
+ rslt = bma4_set_advance_power_save(aps, dev);
+ }
+ }
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
diff --git a/src/drivers/Bma421_C/bma4.h b/src/drivers/Bma421_C/bma4.h
new file mode 100644
index 00000000..081dd4d8
--- /dev/null
+++ b/src/drivers/Bma421_C/bma4.h
@@ -0,0 +1,2281 @@
+/**
+ * Copyright (c) 2020 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 bma4.h
+ * @date 2020-05-08
+ * @version V2.14.13
+ *
+ */
+
+/*
+ * @file bma4.h
+ * @brief Source file for the BMA4 Sensor API
+ */
+
+/*!
+ * @defgroup bma4xy BMA4XY
+ */
+
+/**
+ * \ingroup bma4xy
+ * \defgroup bma4 BMA4
+ * @brief Sensor driver for BMA4 sensor
+ */
+
+#ifndef BMA4_H__
+#define BMA4_H__
+
+/*********************************************************************/
+/* header files */
+
+#include "bma4_defs.h"
+#ifdef AKM9916
+#include "aux_akm9916.h"
+#endif
+
+#ifdef BMM150
+#include "aux_bmm150.h"
+#endif
+
+/*********************************************************************/
+/* (extern) variable declarations */
+/*********************************************************************/
+/* function prototype declarations */
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiInit Initialization
+ * @brief Initialize the sensor and device structure
+ */
+
+/*!
+ * \ingroup bma4ApiInit
+ * \page bma4_api_bma4_init bma4_init
+ * \code
+ * int8_t bma4_init(struct bma4_dev *dev);
+ * \endcode
+ * @details This API is the entry point.
+ * Call this API before using all other APIs.
+ * This API reads the chip-id of the sensor which is the first step to
+ * verify the sensor and also it configures the read mechanism of SPI and
+ * I2C interface.
+ *
+ * @param[in,out] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ * @note
+ * While changing the parameter of the bma4
+ * consider the following point:
+ * Changing the reference value of the parameter
+ * will changes the local copy or local reference
+ * make sure your changes will not
+ * affect the reference value of the parameter
+ * (Better case don't change the reference value of the parameter)
+ */
+int8_t bma4_init(struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiConfig ConfigFile
+ * @brief Write binary configuration in the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiConfig
+ * \page bma4_api_bma4_write_config_file bma4_write_config_file
+ * \code
+ * int8_t bma4_write_config_file(struct bma4_dev *dev);
+ * \endcode
+ * @details This API is used to write the binary configuration in the sensor
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_write_config_file(struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiRegisters Registers
+ * @brief Perform read / write operation to registers of the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiRegisters
+ * \page bma4_api_bma4_write_regs bma4_write_regs
+ * \code
+ * int8_t bma4_write_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev);
+ * \endcode
+ * @details This API checks whether the write operation requested is for
+ * feature config or register write and accordingly writes the data in the
+ * sensor.
+ *
+ * @note user has to disable the advance power save mode in the sensor when
+ * using this API in burst write mode.
+ * bma4_set_advance_power_save(BMA4_DISABLE, dev);
+ *
+ * @param[in] addr : Register address.
+ * @param[in] data : Write data buffer
+ * @param[in] len : No of bytes to write
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_write_regs(uint8_t addr, const uint8_t *data, uint32_t len, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiRegisters
+ * \page bma4_api_bma4_read_regs bma4_read_regs
+ * \code
+ * int8_t bma4_write_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev);
+ * \endcode
+ * @details This API checks whether the read operation requested is for
+ * feature or register read and accordingly reads the data from the sensor.
+ *
+ * @param[in] addr : Register address.
+ * @param[in] data : Read data buffer.
+ * @param[in] len : No of bytes to read.
+ * @param[in] dev : Structure instance of bma4_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 - 0x26, 0x5E.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_read_regs(uint8_t addr, uint8_t *data, uint32_t len, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiErrorStatus Error Status
+ * @brief Read error status of the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiErrorStatus
+ * \page bma4_api_bma4_get_error_status bma4_get_error_status
+ * \code
+ * int8_t bma4_get_error_status(struct bma4_err_reg *err_reg, struct bma4_dev *dev);;
+ * \endcode
+ * @details This API reads the error status from the sensor.
+ *
+ * Below table mention the types of error which can occur in the sensor
+ *
+ *@verbatim
+ *************************************************************************
+ * Error | Description
+ *************************|***********************************************
+ * | Fatal Error, chip is not in operational
+ * fatal | state (Boot-, power-system).
+ * | This flag will be reset only by
+ * | power-on-reset or soft reset.
+ *************************|***********************************************
+ * cmd | Command execution failed.
+ *************************|***********************************************
+ * | Value Name Description
+ * error_code | 000 no_error no error
+ * | 001 acc_err error in
+ * | ACC_CONF
+ *************************|***********************************************
+ * | Error in FIFO detected: Input data was
+ * fifo | discarded in stream mode. This flag
+ * | will be reset when read.
+ *************************|***********************************************
+ * mag | Error in I2C-Master detected.
+ * | This flag will be reset when read.
+ *************************************************************************
+ *@endverbatim
+ *
+ * @param[in,out] err_reg : Pointer to structure variable which stores the
+ * error status read from the sensor.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_error_status(struct bma4_err_reg *err_reg, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiStatus Status
+ * @brief Read sensor status
+ */
+
+/*!
+ * \ingroup bma4ApiStatus
+ * \page bma4_api_bma4_get_status bma4_get_status
+ * \code
+ * int8_t bma4_get_status(uint8_t *status, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the sensor status from the dev sensor.
+ *
+ * Below table lists the sensor status flags
+ *
+ * @verbatim
+ * Status | Description
+ * ----------------------------|----------------------------------------
+ * BMA4_MAG_MAN_OP_ONGOING | Manual Mag. interface operation ongoing
+ * BMA4_CMD_RDY | Command decoder is ready.
+ * BMA4_MAG_DATA_RDY | Data ready for Mag.
+ * BMA4_ACC_DATA_RDY | Data ready for Accel.
+ *@endverbatim
+ *
+ * @param[in] status : Variable used to store the sensor status flags
+ * which is read from the sensor.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_status(uint8_t *status, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiAccelxyz Accel XYZ Data
+ * @brief Read accel xyz data from the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiAccelxyz
+ * \page bma4_api_bma4_read_accel_xyz bma4_read_accel_xyz
+ * \code
+ * int8_t bma4_read_accel_xyz(struct bma4_accel *accel, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the Accel data for x,y and z axis from the sensor.
+ * The data units is in LSB format.
+ *
+ * @param[in] accel : Variable used to store the Accel data which is read
+ * from the sensor.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @note For setting the Accel configuration use the below function
+ * bma4_set_accel_config
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_read_accel_xyz(struct bma4_accel *accel, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiSensorTime Sensor Time
+ * @brief Read sensor time of the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiSensorTime
+ * \page bma4_api_bma4_get_sensor_time bma4_get_sensor_time
+ * \code
+ * int8_t bma4_get_sensor_time(uint32_t *sensor_time, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the sensor time of Sensor time gets updated
+ * with every update of data register or FIFO.
+ *
+ * @param[in] sensor_time : Pointer variable which stores sensor time
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_sensor_time(uint32_t *sensor_time, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiTemperature Temperature
+ * @brief Read chip temperature of the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiTemperature
+ * \page bma4_api_bma4_get_temperature bma4_get_temperature
+ * \code
+ * int8_t bma4_get_temperature(int32_t *temp, uint8_t temp_unit, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the chip temperature of sensor.
+ * @note If Accel and Mag are disabled, the temperature value will be set
+ * to invalid.
+ *
+ * @param[out] temp : Pointer variable which stores the temperature value.
+ * @param[in] temp_unit : indicates the unit of temperature
+ *
+ * @verbatim
+ * temp_unit | description
+ * ------------|-------------------
+ * BMA4_DEG | degrees Celsius
+ * BMA4_FAHREN | degrees fahrenheit
+ * BMA4_KELVIN | degrees kelvin
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @note Using a scaling factor of 1000, to obtain integer values, which
+ * at the user end, are used to get accurate temperature value.
+ * BMA4_SCALE_FARHAN = 1.8 * 1000, BMA4_SCALE_KELVIN = 273.15 * 1000
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_temperature(int32_t *temp, uint8_t temp_unit, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiAccel Accel Configuration
+ * @brief Read / Write configurations of accel sensor
+ */
+
+/*!
+ * \ingroup bma4ApiAccel
+ * \page bma4_api_bma4_get_accel_config bma4_get_accel_config
+ * \code
+ * int8_t bma4_get_accel_config(struct bma4_accel_config *accel, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the Output data rate, Bandwidth, perf_mode
+ * and Range of accel.
+ *
+ * @param[in,out] accel : Address of user passed structure which is used
+ * to store the Accel configurations read from the sensor.
+ *
+ * @note Enums and corresponding values for structure parameters like
+ * Odr, Bandwidth and Range are mentioned in the below tables.
+ *
+ *@verbatim
+ * Value | Odr
+ * -----------|------------------------------------
+ * 1 | BMA4_OUTPUT_DATA_RATE_0_78HZ
+ * 2 | BMA4_OUTPUT_DATA_RATE_1_56HZ
+ * 3 | BMA4_OUTPUT_DATA_RATE_3_12HZ
+ * 4 | BMA4_OUTPUT_DATA_RATE_6_25HZ
+ * 5 | BMA4_OUTPUT_DATA_RATE_12_5HZ
+ * 6 | BMA4_OUTPUT_DATA_RATE_25HZ
+ * 7 | BMA4_OUTPUT_DATA_RATE_50HZ
+ * 8 | BMA4_OUTPUT_DATA_RATE_100HZ
+ * 9 | BMA4_OUTPUT_DATA_RATE_200HZ
+ * 10 | BMA4_OUTPUT_DATA_RATE_400HZ
+ * 11 | BMA4_OUTPUT_DATA_RATE_800HZ
+ * 12 | BMA4_OUTPUT_DATA_RATE_1600HZ
+ *@endverbatim
+ *
+ *@verbatim
+ * Value | accel_bw
+ * ------|--------------------------
+ * 0 | BMA4_ACCEL_OSR4_AVG1
+ * 1 | BMA4_ACCEL_OSR2_AVG2
+ * 2 | BMA4_ACCEL_NORMAL_AVG4
+ * 3 | BMA4_ACCEL_CIC_AVG8
+ * 4 | BMA4_ACCEL_RES_AVG16
+ * 5 | BMA4_ACCEL_RES_AVG32
+ * 6 | BMA4_ACCEL_RES_AVG64
+ * 7 | BMA4_ACCEL_RES_AVG128
+ *@endverbatim
+ *
+ *@verbatim
+ * Value | g_range
+ * --------|---------------------
+ * 0x00 | BMA4_ACCEL_RANGE_2G
+ * 0x01 | BMA4_ACCEL_RANGE_4G
+ * 0x02 | BMA4_ACCEL_RANGE_8G
+ * 0x03 | BMA4_ACCEL_RANGE_16G
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_accel_config(struct bma4_accel_config *accel, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiAccel
+ * \page bma4_api_bma4_set_accel_config bma4_set_accel_config
+ * \code
+ * int8_t bma4_set_accel_config(struct bma4_accel_config *accel, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the output_data_rate, bandwidth, perf_mode
+ * and range of Accel.
+ *
+ * @param[in] accel : Pointer to structure variable which specifies the
+ * Accel configurations.
+ *
+ * @note Enums and corresponding values for structure parameters like
+ * Odr, Bandwidth and Range are mentioned in the below tables.
+ *
+ * @verbatim
+ * Value | ODR
+ * --------|-----------------------------------------
+ * 1 | BMA4_OUTPUT_DATA_RATE_0_78HZ
+ * 2 | BMA4_OUTPUT_DATA_RATE_1_56HZ
+ * 3 | BMA4_OUTPUT_DATA_RATE_3_12HZ
+ * 4 | BMA4_OUTPUT_DATA_RATE_6_25HZ
+ * 5 | BMA4_OUTPUT_DATA_RATE_12_5HZ
+ * 6 | BMA4_OUTPUT_DATA_RATE_25HZ
+ * 7 | BMA4_OUTPUT_DATA_RATE_50HZ
+ * 8 | BMA4_OUTPUT_DATA_RATE_100HZ
+ * 9 | BMA4_OUTPUT_DATA_RATE_200HZ
+ * 10 | BMA4_OUTPUT_DATA_RATE_400HZ
+ * 11 | BMA4_OUTPUT_DATA_RATE_800HZ
+ * 12 | BMA4_OUTPUT_DATA_RATE_1600HZ
+ *
+ *@endverbatim
+ *
+ *@verbatim
+ * Value | accel_bw
+ * ------|--------------------------
+ * 0 | BMA4_ACCEL_OSR4_AVG1
+ * 1 | BMA4_ACCEL_OSR2_AVG2
+ * 2 | BMA4_ACCEL_NORMAL_AVG4
+ * 3 | BMA4_ACCEL_CIC_AVG8
+ * 4 | BMA4_ACCEL_RES_AVG16
+ * 5 | BMA4_ACCEL_RES_AVG32
+ * 6 | BMA4_ACCEL_RES_AVG64
+ * 7 | BMA4_ACCEL_RES_AVG128
+ *@endverbatim
+ *
+ *@verbatim
+ * Value | g_range
+ * --------|---------------------
+ * 0x00 | BMA4_ACCEL_RANGE_2G
+ * 0x01 | BMA4_ACCEL_RANGE_4G
+ * 0x02 | BMA4_ACCEL_RANGE_8G
+ * 0x03 | BMA4_ACCEL_RANGE_16G
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_set_accel_config(const struct bma4_accel_config *accel, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiAdvancedPowerMode Advanced Power Mode
+ * @brief Read / Write advance power mode of accel sensor
+ */
+
+/*!
+ * \ingroup bma4ApiAdvancedPowerMode
+ * \page bma4_api_bma4_set_advance_power_save bma4_set_advance_power_save
+ * \code
+ * int8_t bma4_set_advance_power_save(uint8_t adv_pwr_save, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the advance power save mode in the sensor.
+ *
+ * @note If advanced power save is enabled and the Accel and/or
+ * magnetometer operate in duty cycling mode, the length of the unlatched
+ * DRDY interrupt pulse is longer than 1/3.2 kHz (312.5 us).
+ *
+ * @param[in] adv_pwr_save : The value of advance power save mode
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_advance_power_save(uint8_t adv_pwr_save, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiAdvancedPowerMode
+ * \page bma4_api_bma4_get_advance_power_save bma4_get_advance_power_save
+ * \code
+ * int8_t bma4_get_advance_power_save(uint8_t adv_pwr_save, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the status of advance power save mode
+ * from the sensor.
+ *
+ * @note If the advanced power save is enabled and the Accel and/or
+ * magnetometer operate in duty cycling mode, the length of the unlatched
+ * DRDY interrupt pulse is longer than 1/3.2 kHz (312.5 us).
+ *
+ * @param[out] adv_pwr_save : The value of advance power save mode
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_advance_power_save(uint8_t *adv_pwr_save, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiFIFOSelfWakeUp FIFO Self Wake up
+ * @brief Read / Write FIFO self wake up functionality in the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiFIFOSelfWakeUp
+ * \page bma4_api_bma4_set_fifo_self_wakeup bma4_set_fifo_self_wakeup
+ * \code
+ * int8_t bma4_set_fifo_self_wakeup(uint8_t fifo_self_wakeup, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the FIFO self wake up functionality in the sensor.
+ *
+ * @note Functionality related to FIFO self wake up depends upon the
+ * advance power save mode. for more info. refer data sheet.
+ *
+ * @param[in] fifo_self_wakeup : Variable used to enable or disable
+ * FIFO self wake up functionality.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_fifo_self_wakeup(uint8_t fifo_self_wakeup, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiFIFOSelfWakeUp
+ * \page bma4_api_bma4_get_fifo_self_wakeup bma4_get_fifo_self_wakeup
+ * \code
+ * int8_t bma4_get_fifo_self_wakeup(uint8_t *fifo_self_wakeup, struct bma4_dev *dev);
+ * \endcode
+ * @details This API gets the status of FIFO self wake up functionality from
+ * the sensor.
+ *
+ * @note Functionality related to FIFO self wake up depends upon the
+ * advance power save mode. for more info. refer data sheet.
+ *
+ * @param[out] fifo_self_wake_up : Pointer variable used to store the
+ * fifo self wake up status.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_fifo_self_wakeup(uint8_t *fifo_self_wake_up, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiAccelEnable Accel Enable
+ * @brief Enables / Disables accelerometer in the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiAccelEnable
+ * \page bma4_api_bma4_set_accel_enable bma4_set_accel_enable
+ * \code
+ * int8_t bma4_set_accel_enable(uint8_t accel_en, struct bma4_dev *dev);
+ * \endcode
+ * @details This API enables or disables the Accel in the sensor.
+ *
+ * @note Before reading Accel data, user should call this API.
+ *
+ * @param[in] accel_en : Variable used to enable or disable the Accel.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_accel_enable(uint8_t accel_en, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiAccelEnable
+ * \page bma4_api_bma4_get_accel_enable bma4_get_accel_enable
+ * \code
+ * int8_t bma4_get_accel_enable(uint8_t *accel_en, struct bma4_dev *dev);
+ * \endcode
+ * @details This API checks whether Accel is enabled or not in the sensor.
+ *
+ * @param[out] accel_en : Pointer variable used to store the Accel enable
+ * status
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_accel_enable(uint8_t *accel_en, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiMagEnable Magnetometer Enable
+ * @brief Enables / Disables Auxiliary Magnetometer in the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiMagEnable
+ * \page bma4_api_bma4_set_mag_enable bma4_set_mag_enable
+ * \code
+ * int8_t bma4_set_mag_enable(uint8_t mag_en, struct bma4_dev *dev);
+ * \endcode
+ * @details This API is used to enable or disable auxiliary Mag
+ * in the sensor.
+ *
+ * @note Before reading Mag data, user should call this API.
+ *
+ * @param[in] mag_en : Variable used to enable or disable the Mag.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_mag_enable(uint8_t mag_en, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiMagEnable
+ * \page bma4_api_bma4_get_mag_enable bma4_get_mag_enable
+ * \code
+ * int8_t bma4_get_mag_enable(uint8_t *mag_en, struct bma4_dev *dev);
+ * \endcode
+ * @details This API is used to check whether the auxiliary Mag is enabled
+ * or not in the sensor.
+ *
+ * @param[out] mag_en : Pointer variable used to store the enable status of
+ * Mag in the sensor.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_mag_enable(uint8_t *mag_en, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiSpiInterface SPI interface
+ * @brief Read / Write SPI interface mode set for primary interface
+ */
+
+/*!
+ * \ingroup bma4AiSpiInterface
+ * \page bma4_api_bma4_set_spi_interface bma4_set_spi_interface
+ * \code
+ * int8_t bma4_set_spi_interface(uint8_t *spi, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the SPI interface mode which is set for primary
+ * interface.
+ *
+ * @param[out] spi : Pointer variable which stores the SPI mode selection
+ *
+ * @verbatim
+ * Value | Description
+ * --------|------------------
+ * 0 | SPI 4-wire mode
+ * 1 | SPI 3-wire mode
+ *
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_spi_interface(uint8_t *spi, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiSpiInterface
+ * \page bma4_api_bma4_get_spi_interface bma4_get_spi_interface
+ * \code
+ * int8_t bma4_get_spi_interface(uint8_t spi, struct bma4_dev *dev);
+ * \endcode
+ * @details This API configures the SPI interface Mode for primary interface
+ *
+ * @param[in] spi : The value of SPI mode selection
+ *
+ *@verbatim
+ * Value | Description
+ * --------|------------------
+ * 0 | SPI 4-wire mode
+ * 1 | SPI 3-wire mode
+ *
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_spi_interface(uint8_t spi, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiCommandReg Command Register
+ * @brief Write available sensor specific commands to the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiCommandReg
+ * \page bma4_api_bma4_set_command_register bma4_set_command_register
+ * \code
+ * int8_t bma4_set_command_register(uint8_t command_reg, struct bma4_dev *dev);
+ * \endcode
+ * @details This API writes the available sensor specific commands
+ * to the sensor.
+ *
+ * @param[in] command_reg : The command to write to the command register
+ *
+ *@verbatim
+ * value | Description
+ * --------|------------------------------------------------------
+ * 0xB6 | Triggers a soft reset
+ * 0xB0 | Clears all data in the FIFO, does not change
+ * | FIFO_CONFIG and FIFO_DOWNS registers
+ * 0xF0 | Reset acceleration data path
+ *@endverbatim
+ *
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @note Register will always read as 0x00
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_command_register(uint8_t command_reg, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiI2CAddr i2C Device Address
+ * @brief Write I2C device address of auxiliary sensor
+ */
+
+/*!
+ * \ingroup bma4ApiI2CAddr
+ * \page bma4_api_bma4_set_i2c_device_addr bma4_set_i2c_device_addr
+ * \code
+ * int8_t bma4_set_i2c_device_addr(struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the I2C device address of auxiliary sensor
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_i2c_device_addr(struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiMagManualEnable Mag Manual Enable
+ * @brief Read / Write register access on magnetometer manually
+ */
+
+/*!
+ * \ingroup bma4ApiMagManualEnable
+ * \page bma4_api_bma4_set_mag_manual_enable bma4_set_mag_manual_enable
+ * \code
+ * int8_t bma4_set_mag_manual_enable(uint8_t mag_manual, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the register access on MAG_IF[2], MAG_IF[3],
+ * MAG_IF[4] in the sensor. This implies that the DATA registers are
+ * not updated with Mag values automatically.
+ *
+ * @param[in] mag_manual : Variable used to specify the Mag manual
+ * enable status.
+ *
+ *@verbatim
+ * value | mag manual
+ * ---------|--------------------
+ * 0x01 | BMA4_ENABLE
+ * 0x00 | BMA4_DISABLE
+ *@endverbatim
+ *
+ * @param[out] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_mag_manual_enable(uint8_t mag_manual, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiMagManualEnable
+ * \page bma4_api_bma4_get_mag_manual_enable bma4_get_mag_manual_enable
+ * \code
+ * int8_t bma4_get_mag_manual_enable(uint8_t *mag_manual, struct bma4_dev *dev);
+ * \endcode
+ * @details This API checks whether the Mag access is done manually or
+ * automatically in the sensor.
+ * If the Mag access is done through manual mode then Mag data registers
+ * in sensor are not updated automatically.
+ *
+ * @param[out] mag_manual : Mag manual enable value
+ *
+ *@verbatim
+ * value | mag_manual
+ * --------|-------------------
+ * 0x01 | BMA4_ENABLE
+ * 0x00 | BMA4_DISABLE
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_mag_manual_enable(uint8_t *mag_manual, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiMagIFMode Mag Interface Mode
+ * @brief Set I2C interface configuration mode for auxiliary magnetometer
+ */
+
+/*!
+ * \ingroup bma4ApiMagIFMode
+ * \page bma4_api_bma4_set_aux_if_mode bma4_set_aux_if_mode
+ * \code
+ * int8_t bma4_set_aux_if_mode(uint8_t if_mode, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the I2C interface configuration(if) mode
+ * for auxiliary Mag.
+ *
+ * @param[in] if_mode : The value of interface configuration mode
+ *
+ *@verbatim
+ * Value | Description
+ * ------------|-------------------------------------------
+ * 0 | p_auto_s_off Auxiliary interface:off
+ * 1 | p_auto_s_mag Auxiliary interface:on
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_aux_if_mode(uint8_t if_mode, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiMagRead Mag Read
+ * @brief Set / Get address of register of Aux Mag sensor to read data
+ */
+
+/*!
+ * \ingroup bma4ApiMagRead
+ * \page bma4_api_bma4_get_mag_read_addr bma4_get_mag_read_addr
+ * \code
+ * int8_t bma4_get_mag_read_addr(uint8_t *mag_read_addr, struct bma4_dev *dev);
+ * \endcode
+ * @details This API gets the address of the register of Aux Mag sensor
+ * where the data to be read.
+ *
+ * @param[out] mag_read_addr : Pointer variable used to store the
+ * mag read address.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_mag_read_addr(uint8_t *mag_read_addr, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiMagRead
+ * \page bma4_api_bma4_set_mag_read_addr bma4_set_mag_read_addr
+ * \code
+ * int8_t bma4_set_mag_read_addr(uint8_t mag_read_addr, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the address of the register of Aux Mag sensor
+ * where the data to be read.
+ *
+ * @param[in] mag_read_addr: Value of Mag. read address in order to read
+ * the data from the auxiliary Mag.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_mag_read_addr(uint8_t mag_read_addr, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiMagWrite Mag Write
+ * @brief Set / Get address of register of Aux Mag sensor to write data
+ */
+
+/*!
+ * \ingroup bma4ApiMagWrite
+ * \page bma4_api_bma4_get_mag_write_addr bma4_get_mag_write_addr
+ * \code
+ * int8_t bma4_get_mag_write_addr(uint8_t *mag_write_addr, struct bma4_dev *dev);
+ * \endcode
+ * @details This API gets the Aux Mag write address from the sensor.
+ * Mag write address is where the Mag data will be written.
+ *
+ * @param[out] mag_write_addr: Pointer used to store the Mag write address
+ * which is read from the sensor.
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_mag_write_addr(uint8_t *mag_write_addr, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiMagWrite
+ * \page bma4_api_bma4_set_mag_write_addr bma4_set_mag_write_addr
+ * \code
+ * int8_t bma4_set_mag_write_addr(uint8_t mag_write_addr, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the Aux Mag write address in the sensor.
+ * Mag write address is where the Mag data will be written.
+ *
+ * @param[in] mag_write_addr: Write address of Mag where the data will
+ * be written.
+ * @param[out] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_mag_write_addr(uint8_t mag_write_addr, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiMagData Mag Data
+ * @brief Read / Write data from the Mag sensor
+ */
+
+/*!
+ * \ingroup bma4ApiMagData
+ * \page bma4_api_bma4_get_mag_write_data bma4_get_mag_write_data
+ * \code
+ * int8_t bma4_get_mag_write_data(uint8_t *mag_write_data, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the data from the sensor which is written to the
+ * Mag.
+ *
+ * @param[out] mag_write_data: Pointer variable which stores the
+ * data which is written in Mag through sensor.
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_mag_write_data(uint8_t *mag_write_data, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiMagData
+ * \page bma4_api_bma4_set_mag_write_data bma4_set_mag_write_data
+ * \code
+ * int8_t bma4_set_mag_write_data(uint8_t mag_write_data, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the data in the sensor which in turn will
+ * be written to Mag.
+ *
+ * @param[in] mag_write_data: variable which specify the data which is to
+ * be written in Mag.
+ * @param[out] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_mag_write_data(uint8_t mag_write_data, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiReadMagXYZR Mag xyzr Data
+ * @brief Read xyzr axes data from auxiliary Mag sensor
+ */
+
+/*!
+ * \ingroup bma4ApiReadMagXYZR
+ * \page bma4_api_bma4_read_mag_xyzr bma4_read_mag_xyzr
+ * \code
+ * int8_t bma4_read_mag_xyzr(struct bma4_mag_xyzr *mag, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the x,y,z and r axis data from the auxiliary
+ * Mag BMM150/AKM9916 sensor.
+ *
+ * @param[out] mag : Pointer variable to store the auxiliary Mag x,y,z
+ * and r axis data read from the sensor.
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_read_mag_xyzr(struct bma4_mag_xyzr *mag, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiMagBurst Mag Burst
+ * @brief Set / Get burst data length of auxiliary Mag Sensor
+ */
+
+/*!
+ * \ingroup bma4ApiMagBurst
+ * \page bma4_api_bma4_set_mag_burst bma4_set_mag_burst
+ * \code
+ * int8_t bma4_set_mag_burst(uint8_t mag_burst, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the burst data length (1,2,6,8 byte) of auxiliary
+ * Mag sensor.
+ *
+ * @param[in] mag_burst : Variable used to specify the Mag burst read length
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_mag_burst(uint8_t mag_burst, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiMagBurst
+ * \page bma4_api_bma4_get_mag_burst bma4_get_mag_burst
+ * \code
+ * int8_t bma4_get_mag_burst(uint8_t *mag_burst, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the burst data length of Mag set in the sensor.
+ *
+ * @param[out] mag_burst : Pointer variable used to store the burst length
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_mag_burst(uint8_t *mag_burst, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiReadFIFO Read FIFO Data
+ * @brief Read FIFO data of accel and/or Mag sensor
+ */
+
+/*!
+ * \ingroup bma4ApiReadFIFO
+ * \page bma4_api_bma4_read_fifo_data bma4_read_fifo_data
+ * \code
+ * int8_t bma4_read_fifo_data(struct bma4_fifo_frame *fifo, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the FIFO data of Accel and/or Mag sensor
+ *
+ * @param dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_read_fifo_data(struct bma4_fifo_frame *fifo, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiFIFOWM FIFO Watermark level
+ * @brief Read / Write FIFO watermark level in the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiFIFOWM
+ * \page bma4_api_bma4_get_fifo_wm bma4_get_fifo_wm
+ * \code
+ * int8_t bma4_get_fifo_wm(uint16_t *fifo_wm, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the FIFO water mark level which is set
+ * in the sensor.
+ *
+ * @note The FIFO watermark is issued when the FIFO fill level is
+ * equal or above the watermark level.
+ *
+ * @param[out] fifo_wm : Pointer variable to store FIFO water mark level
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_fifo_wm(uint16_t *fifo_wm, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiFIFOWM
+ * \page bma4_api_bma4_set_fifo_wm bma4_set_fifo_wm
+ * \code
+ * int8_t bma4_set_fifo_wm(uint16_t fifo_wm, struct bma4_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.
+ *
+ * @param[in] fifo_wm : Variable used to set the FIFO water mark level
+ * @param[out] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_fifo_wm(uint16_t fifo_wm, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiAccelFIFOFilterData Accel FIFO Filter data
+ * @brief Set / Get Filtered or unfiltered mode of Accel FIFO data
+ */
+
+/*!
+ * \ingroup bma4ApiAccelFIFOFilterData
+ * \page bma4_api_bma4_get_accel_fifo_filter_data bma4_get_accel_fifo_filter_data
+ * \code
+ * int8_t bma4_get_accel_fifo_filter_data(uint8_t *accel_fifo_filter, struct bma4_dev *dev);
+ * \endcode
+ * @details This API checks whether the Accel FIFO data is set for filtered
+ * or unfiltered mode.
+ *
+ * @param[out] accel_fifo_filter : Variable used to check whether the Accel
+ * data is filtered or unfiltered.
+ *
+ *@verbatim
+ * Value | accel_fifo_filter
+ * ---------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *@endverbatim
+ *
+ * @param[in] dev : structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_accel_fifo_filter_data(uint8_t *accel_fifo_filter, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiAccelFIFOFilterData
+ * \page bma4_api_bma4_set_accel_fifo_filter_data bma4_set_accel_fifo_filter_data
+ * \code
+ * int8_t bma4_set_accel_fifo_filter_data(uint8_t accel_fifo_filter, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the condition of Accel FIFO data either to
+ * filtered or unfiltered mode.
+ *
+ * @param[in] accel_fifo_filter : Variable used to set the filtered or
+ * unfiltered condition of Accel FIFO data.
+ *
+ *@verbatim
+ * value | accel_fifo_filter_data
+ * -----------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ *@endverbatim
+ *
+ * @param[out] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_accel_fifo_filter_data(uint8_t accel_fifo_filter, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiAccelFIFODown Accel FIFO Down Sampling
+ * @brief Read / Write Down sampling rates configured for Accel FIFO Data
+ */
+
+/*!
+ * \ingroup bma4ApiAccelFIFOFilterData
+ * \page bma4_api_bma4_get_fifo_down_accel bma4_get_fifo_down_accel
+ * \code
+ * int8_t bma4_get_fifo_down_accel(uint8_t *fifo_down, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the down sampling rates which is configured
+ * for Accel FIFO data.
+ *
+ * @param[out] fifo_down : Variable used to specify the Accel FIFO
+ * down-sampling rates
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_fifo_down_accel(uint8_t *fifo_down, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiAccelFIFOFilterData
+ * \page bma4_api_bma4_set_fifo_down_accel bma4_set_fifo_down_accel
+ * \code
+ * int8_t bma4_set_fifo_down_accel(uint8_t fifo_down, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the down-sampling rates for Accel FIFO.
+ *
+ * @param[in] fifo_down : Variable used to specify the Accel FIFO
+ * down-sampling rates.
+ * @param[in] dev : structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_fifo_down_accel(uint8_t fifo_down, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiFIFOLength FIFO Length
+ * @brief Read length of FIFO data available in the sensor (unit of bytes)
+ */
+
+/*!
+ * \ingroup bma4ApiAccelFIFOFilterData
+ * \page bma4_api_bma4_get_fifo_length bma4_get_fifo_length
+ * \code
+ * int8_t bma4_get_fifo_length(uint16_t *fifo_length, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the length of FIFO data available in the sensor
+ * in the units of bytes.
+ *
+ * @note This byte counter is updated each time a complete frame was read
+ * or written
+ *
+ * @param[in] fifo_length : Pointer variable used to store the value of
+ * fifo byte counter
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_get_fifo_length(uint16_t *fifo_length, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiMagCompensate Compensate Mag data
+ * @brief Aligns and Compensates Mag Data of BMM150 / AKM9916
+ */
+
+/*!
+ * \ingroup bma4ApiAccelFIFOFilterData
+ * \page bma4_api_bma4_second_if_mag_compensate_xyz bma4_second_if_mag_compensate_xyz
+ * \code
+ * int8_t bma4_second_if_mag_compensate_xyz(struct bma4_mag_fifo_data mag_fifo_data,
+ * uint8_t mag_second_if,
+ * const struct bma4_mag *compensated_mag_data);
+ *
+ * \endcode
+ * @details This API aligns and compensates the Mag data of BMM150/AKM9916
+ * sensor.
+ *
+ * @param[in] mag_fifo_data: Structure object which stores the Mag x,yand z
+ * axis FIFO data which is to be aligned and/or compensated.
+ * @param[in] mag_second_if: Variable used to select the Mag sensor.
+ *
+ *@verbatim
+ * Value | mag_second_if
+ * --------|----------------------
+ * 1 | BMA4_SEC_IF_BMM150
+ * 2 | BMA4_SEC_IF_AKM09916
+ *@endverbatim
+ *
+ * @param[out] compensated_mag_data: Pointer variable used to store the
+ * compensated Mag xyz axis data
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_second_if_mag_compensate_xyz(struct bma4_mag_fifo_data mag_fifo_data,
+ uint8_t mag_second_if,
+ const struct bma4_mag *compensated_mag_data);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiMagXYZ Mag XYZ
+ * @brief Read x, y and z axes data from either BMM150 or AKM9916 sensor
+ */
+
+/*!
+ * \ingroup bma4ApiMagXYZ
+ * \page bma4_api_bma4_read_mag_xyz bma4_read_mag_xyz
+ * \code
+ * int8_t bma4_read_mag_xyz(const struct bma4_mag *mag, uint8_t sensor_select, const struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads Mag. x,y and z axis data from either BMM150 or
+ * AKM9916 sensor
+ *
+ * @param[out] mag : Structure pointer used to store the Mag x,y, and z axis
+ * data read from the sensor.
+ *
+ * @param[in] sensor_select : Variable used to select the Mag sensor
+ *
+ *@verbatim
+ * Value | Sensor
+ * ---------|----------------------
+ * 0 | BMA4_SEC_IF_NULL
+ * 1 | BMA4_SEC_IF_BMM150
+ * 2 | BMA4_SEC_IF_AKM09916
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_read_mag_xyz(const struct bma4_mag *mag, uint8_t sensor_select, const struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiIFMode I2C interface configuration
+ * @brief Set / Get auxiliary I2C interface configuration set in the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiIFMode
+ * \page bma4_api_bma4_get_if_mode bma4_get_if_mode
+ * \code
+ * int8_t bma4_get_if_mode(uint8_t *if_mode, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the auxiliary I2C interface configuration which
+ * is set in the sensor.
+ *
+ * @param[out] if_mode : Pointer variable used to store the auxiliary
+ * interface configuration.
+ *
+ *@verbatim
+ * Value | Description
+ * ----- |----------------------------------
+ * 0x00 | auxiliary interface:off
+ * 0x01 | auxiliary interface:on
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_if_mode(uint8_t *if_mode, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiIFMode
+ * \page bma4_api_bma4_set_if_mode bma4_set_if_mode
+ * \code
+ * int8_t bma4_set_if_mode(uint8_t if_mode, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the auxiliary interface configuration in the sensor.
+ *
+ * @param[in] if_mode : Variable used to select the auxiliary interface
+ * configuration.
+ *
+ *@verbatim
+ * Value | Description
+ * ----- |--------------------------
+ * 0x00 | auxiliary interface:off
+ * 0x01 | auxiliary interface:on
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_if_mode(uint8_t if_mode, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiAccelDataRdy Accel Data Ready
+ * @brief Get accel data ready status from the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiAccelDataRdy
+ * \page bma4_api_bma4_get_accel_data_rdy bma4_get_accel_data_rdy
+ * \code
+ * int8_t bma4_get_accel_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the data ready status of Accel from the sensor.
+ * @note The status get reset when Accel data register is read.
+ *
+ * @param[out] data_rdy : Pointer variable to store the data ready status
+ * @param[in] dev : structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_accel_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiMagDataRdy Mag Data Ready
+ * @brief Get Mag data ready status from the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiMagDataRdy
+ * \page bma4_api_bma4_get_mag_data_rdy bma4_get_mag_data_rdy
+ * \code
+ * int8_t bma4_get_mag_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the data ready status of Mag from the sensor.
+ * The status get reset when Mag data register is read.
+ *
+ * @param[out] data_rdy : Pointer variable to store the data ready status
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_mag_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiASICStatus ASIC status
+ * @brief Read ASIC status from the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiASICStatus
+ * \page bma4_api_bma4_get_asic_status bma4_get_asic_status
+ * \code
+ * int8_t bma4_get_asic_status(struct bma4_asic_status *asic_status, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the ASIC status from the sensor.
+ * The status information is mentioned in the below table.
+ *
+ *@verbatim
+ *******************************************************************************
+ * Status | Description
+ **************************|****************************************************
+ * sleep | ASIC is in sleep/halt state.
+ * irq_ovrn | Dedicated interrupt is set again before previous
+ * | interrupt was acknowledged.
+ * wc_event | Watchcell event detected (ASIC stopped).
+ * stream_transfer_active | stream transfer has started.
+ *******************************************************************************
+ *@endverbatim
+ *
+ * @param[out] asic_status : Structure pointer used to store the ASIC
+ * status read from the sensor.
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_asic_status(struct bma4_asic_status *asic_status, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiOffsetComp Accel Offset Compensation
+ * @brief Set / Get Accel Offset Compensation
+ */
+
+/*!
+ * \ingroup bma4ApiOffsetComp
+ * \page bma4_api_bma4_set_offset_comp bma4_set_offset_comp
+ * \code
+ * int8_t bma4_set_offset_comp(uint8_t offset_en, struct bma4_dev *dev);
+ * \endcode
+ * @details This API enables the offset compensation for filtered and
+ * unfiltered Accel data.
+ *
+ * @param[in] offset_en : Variable used to enable or disable offset
+ * compensation
+ *
+ *@verbatim
+ * offset_en | Description
+ * ------------|----------------------
+ * 0 | BMA4_DISABLE
+ * 1 | BMA4_ENABLE
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_offset_comp(uint8_t offset_en, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiOffsetComp
+ * \page bma4_api_bma4_get_offset_comp bma4_get_offset_comp
+ * \code
+ * int8_t bma4_get_offset_comp(uint8_t *offset_en, struct bma4_dev *dev);
+ * \endcode
+ * @details This API gets the status of Accel offset compensation
+ *
+ * @param[out] offset_en : Pointer variable used to store the Accel offset
+ * enable or disable status.
+ *
+ *@verbatim
+ * offset_en | Description
+ * ----------|--------------
+ * 0 | BMA4_DISABLE
+ * 1 | BMA4_ENABLE
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_get_offset_comp(uint8_t *offset_en, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiExtractAccel Accel Extract and Parse Frames
+ * @brief Parse and Extract Accel frames from FIFO data read
+ */
+
+/*!
+ * \ingroup bma4ApiExtractAccel
+ * \page bma4_api_bma4_extract_accel bma4_extract_accel
+ * \code
+ * int8_t bma4_extract_accel(struct bma4_accel *accel_data,
+ * uint16_t *accel_length,
+ * struct bma4_fifo_frame *fifo,
+ * const struct bma4_dev *dev);
+ * \endcode
+ * @details This API parses and extracts the accelerometer frames from
+ * FIFO data read by the "bma4_read_fifo_data" API and stores it in the
+ * "accel_data" structure instance.
+ *
+ * @note The bma4_extract_accel API should be called only after reading
+ * the FIFO data by calling the bma4_read_fifo_data() API
+ *
+ * @param[in,out] accel_data : Structure instance of bma4_accel where
+ * the accelerometer data in FIFO is stored.
+ * @param[in,out] accel_length : Number of accelerometer frames
+ * (x,y,z axes data)
+ * @param[in,out] dev : Structure instance of bma4_dev.
+ *
+ * @note accel_length has the number of accelerometer frames
+ * (1 accel frame = 6 bytes) which the user needs to extract and store is
+ * provided as input parameter by the user and the Number of valid
+ * accelerometer frames extracted and stored is updated in
+ * "accel_length" at the end of execution of this API.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_extract_accel(struct bma4_accel *accel_data,
+ uint16_t *accel_length,
+ struct bma4_fifo_frame *fifo,
+ const struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiExtractMag Mag Extract and Parse Frames
+ * @brief Parse and Extract Accel frames from FIFO data read
+ */
+
+/*!
+ * \ingroup bma4ApiExtractMag
+ * \page bma4_api_bma4_extract_mag bma4_extract_mag
+ * \code
+ * int8_t bma4_extract_mag(const struct bma4_mag *mag_data,
+ * uint16_t *mag_length,
+ * struct bma4_fifo_frame *fifo,
+ * const struct bma4_dev *dev);
+ * \endcode
+ * @details This API parses and extracts the magnetometer frames from
+ * FIFO data read by the "bma4_read_fifo_data" API and stores it in the
+ * "mag_data" structure instance parameter of this API
+ *
+ * @note The bma4_extract_mag API should be called only after reading
+ * the FIFO data by calling the bma4_read_fifo_data() API
+ *
+ * @param[in,out] mag_data : Structure instance of bma4_mag_xyzr where
+ * the magnetometer data in FIFO is stored.
+ * @param[in,out] mag_length : Number of magnetometer frames (x,y,z,r data)
+ * @param[in,out] dev : Structure instance of bma4_dev.
+ *
+ * @note mag_length has the number of magnetometer frames(x,y,z,r data)
+ * (1 mag frame = 8 bytes) which the user needs to extract and store,It is
+ * provided as input parameter by the user and the number of valid
+ * magnetometer frames extracted and stored is updated in
+ * "mag_length" at the end of execution of this API.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_extract_mag(const struct bma4_mag *mag_data,
+ uint16_t *mag_length,
+ struct bma4_fifo_frame *fifo,
+ const struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiAccelSelftest Accel Self test
+ * @brief Self test for accel
+ */
+
+/*!
+ * \ingroup bma4ApiAccelSelftest
+ * \page bma4_api_bma4_perform_accel_selftest bma4_perform_accel_selftest
+ * \code
+ * int8_t bma4_perform_accel_selftest(int8_t *result, struct bma4_dev *dev);
+ * \endcode
+ * @details This API checks whether the self test functionality of the sensor
+ * is working or not
+ *
+ * @param[in] result : Pointer variable used to store the result of self test
+ * operation
+ *
+ *@verbatim
+ * result | Description
+ * ---------|--------------------
+ * 0x00 | BMA4_SELFTEST_PASS
+ * 0x01 | BMA4_SELFTEST_FAIL
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_perform_accel_selftest(int8_t *result, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiAccelSelftest
+ * \page bma4_api_bma4_selftest_config bma4_selftest_config
+ * \code
+ * int8_t bma4_selftest_config(uint8_t sign, struct bma4_dev *dev);
+ * \endcode
+ * @details This API performs the steps needed for Self test operation
+ * before reading the Accel Self test data.
+ *
+ * @param[in] sign: Variable used to specify the self test sign
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_selftest_config(uint8_t sign, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiInterrupt Interrupt Functions
+ * @brief Interrupt mapping and set/get interrupt mode
+ */
+
+/*!
+ * \ingroup bma4ApiInterrupt
+ * \page bma4_api_bma4_map_interrupt bma4_map_interrupt
+ * \code
+ * int8_t bma4_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev);
+ * \endcode
+ * @details API sets the interrupt to either interrupt1 or
+ * interrupt2 pin in the sensor.
+ *
+ * @param[in] int_line: Variable used to select interrupt pin1 or pin2
+ *
+ *@verbatim
+ * int_line | interrupt selection
+ * ---------|-------------------
+ * 0 | BMA4_INTR1_MAP
+ * 1 | BMA4_INTR2_MAP
+ *@endverbatim
+ *
+ * @param[in] int_map: Variable used to select a particular interrupt
+ * in the sensor
+ *
+ * @param[in] enable : Variable used to enable or disable the interrupt
+ *
+ *@verbatim
+ * Value | Behaviour
+ * ---------|-------------------
+ * 0x01 | BMA4_ENABLE
+ * 0x00 | BMA4_DISABLE
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiInterrupt
+ * \page bma4_api_bma4_set_interrupt_mode bma4_set_interrupt_mode
+ * \code
+ * int8_t bma4_set_interrupt_mode(uint8_t mode, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the interrupt mode in the sensor.
+ *
+ * @param[in] mode: Variable used to specify the interrupt mode which
+ * is to be set in the sensor.
+ *
+ *@verbatim
+ * Mode | Value
+ * ----------------------- |---------
+ * BMA4_NON_LATCH_MODE | 0
+ * BMA4_LATCH_MODE | 1
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_set_interrupt_mode(uint8_t mode, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiInterrupt
+ * \page bma4_api_bma4_get_interrupt_mode bma4_get_interrupt_mode
+ * \code
+ * int8_t bma4_get_interrupt_mode(uint8_t *mode, struct bma4_dev *dev);
+ * \endcode
+ * @details This API gets the interrupt mode which is set in the sensor.
+ *
+ * @param[out] mode: Pointer variable used to store the interrupt mode set in
+ * in the sensor.
+ *
+ *@verbatim
+ * Mode | Value
+ * ---------------------|---------------
+ * BMA4_NON_LATCH_MODE | 0
+ * BMA4_LATCH_MODE | 1
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_get_interrupt_mode(uint8_t *mode, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiAuxMagConfig Auxiliary Mag Config
+ * @brief Set / Get Auxiliary Mag(BMM150 or AKM9916) output data rate and offset
+ */
+
+/*!
+ * \ingroup bma4ApiAuxMagConfig
+ * \page bma4_api_bma4_set_aux_mag_config bma4_set_aux_mag_config
+ * \code
+ * int8_t bma4_set_aux_mag_config(const struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the auxiliary Mag(BMM150 or AKM9916) output data
+ * rate and offset.
+ *
+ * @param[in] aux_mag : Pointer to structure variable used to specify
+ * the auxiliary Mag configuration.
+ *
+ *@verbatim
+ *------------------------------------------------------------------------------
+ * Odr | Value
+ *----------------------------------------|---------------------------------
+ * BMA4_OUTPUT_DATA_RATE_0_78HZ | 0x01
+ * BMA4_OUTPUT_DATA_RATE_1_56HZ | 0x02
+ * BMA4_OUTPUT_DATA_RATE_3_12HZ | 0x03
+ * BMA4_OUTPUT_DATA_RATE_6_25HZ | 0x04
+ * BMA4_OUTPUT_DATA_RATE_12_5HZ | 0x05
+ * BMA4_OUTPUT_DATA_RATE_25HZ | 0x06
+ * BMA4_OUTPUT_DATA_RATE_50HZ | 0x07
+ * BMA4_OUTPUT_DATA_RATE_100HZ | 0x08
+ * BMA4_OUTPUT_DATA_RATE_200HZ | 0x09
+ * BMA4_OUTPUT_DATA_RATE_400HZ | 0x0A
+ * BMA4_OUTPUT_DATA_RATE_800HZ | 0x0B
+ * BMA4_OUTPUT_DATA_RATE_1600HZ | 0x0C
+ *------------------------------------------------------------------------------
+ * Offset | Value
+ *--------------------------------------------|---------------------------------
+ * BMA4_MAG_OFFSET_MAX | 0x00
+ *--------------------------------------------|---------------------------------
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_set_aux_mag_config(const struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiAuxMagConfig
+ * \page bma4_api_bma4_get_aux_mag_config bma4_get_aux_mag_config
+ * \code
+ * int8_t bma4_get_aux_mag_config(struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the auxiliary Mag(BMM150 or AKM9916) output data
+ * rate and offset.
+ * @note : Valid output data rates are mentioned in the below table
+ *
+ * @param[out] aux_mag : Pointer to structure variable used to store the
+ * auxiliary Mag configuration read from the sensor
+ *
+ *@verbatim
+ *------------------------------------------------------------------------
+ * Odr | Value
+ *----------------------------------------|-------------------------------
+ * BMA4_OUTPUT_DATA_RATE_0_78HZ | 0x01
+ * BMA4_OUTPUT_DATA_RATE_1_56HZ | 0x02
+ * BMA4_OUTPUT_DATA_RATE_3_12HZ | 0x03
+ * BMA4_OUTPUT_DATA_RATE_6_25HZ | 0x04
+ * BMA4_OUTPUT_DATA_RATE_12_5HZ | 0x05
+ * BMA4_OUTPUT_DATA_RATE_25HZ | 0x06
+ * BMA4_OUTPUT_DATA_RATE_50HZ | 0x07
+ * BMA4_OUTPUT_DATA_RATE_100HZ | 0x08
+ * BMA4_OUTPUT_DATA_RATE_200HZ | 0x09
+ * BMA4_OUTPUT_DATA_RATE_400HZ | 0x0A
+ * BMA4_OUTPUT_DATA_RATE_800HZ | 0x0B
+ * BMA4_OUTPUT_DATA_RATE_1600HZ | 0x0C
+ *-------------------------------------------------------------------------
+ * Offset | Value
+ *----------------------------------------|--------------------------------
+ * BMA4_MAG_OFFSET_MAX | 0x00
+ *-------------------------------------------------------------------------
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_get_aux_mag_config(struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiFIFOConfig FIFO Configuration
+ * @brief Set / Get FIFO Configuration in the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiFIFOConfig
+ * \page bma4_api_bma4_set_fifo_config bma4_set_fifo_config
+ * \code
+ * int8_t bma4_set_fifo_config(uint8_t config, uint8_t enable, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the FIFO configuration in the sensor.
+ *
+ * @param[in] config : Enum variable used to specify the FIFO
+ * configurations which are to be enabled or disabled in the sensor.
+ *
+ * @note : User can set either one or more or all FIFO configurations
+ * by ORing the below mentioned enums.
+ *
+ *@verbatim
+ * config | Value
+ * ------------------------|---------------------------
+ * BMA4_FIFO_STOP_ON_FULL | 0x01
+ * BMA4_FIFO_TIME | 0x02
+ * BMA4_FIFO_TAG_INTR2 | 0x04
+ * BMA4_FIFO_TAG_INTR1 | 0x08
+ * BMA4_FIFO_HEADER | 0x10
+ * BMA4_FIFO_MAG | 0x20
+ * BMA4_FIFO_ACCEL | 0x40
+ * BMA4_FIFO_ALL | 0x7F
+ *@endverbatim
+ *
+ * @param[in] enable : Parameter used to enable or disable the above
+ * FIFO configuration
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_set_fifo_config(uint8_t config, uint8_t enable, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiFIFOConfig
+ * \page bma4_api_bma4_get_fifo_config bma4_get_fifo_config
+ * \code
+ * int8_t bma4_get_fifo_config(uint8_t *fifo_config, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the FIFO configuration from the sensor.
+ *
+ * @param[in] fifo_config : Enum variable used to get the below fifo
+ * configuration from the sensor.
+ *
+ * @note After calling this function user should do the AND operation with
+ * the enum value populated by this function to know which FIFO
+ * configuration is enabled.
+ *
+ *@verbatim
+ * fifo_config | Value
+ * -------------------------|--------------------------
+ * BMA4_FIFO_STOP_ON_FULL | 0x01
+ * BMA4_FIFO_TIME | 0x02
+ * BMA4_FIFO_TAG_INTR2 | 0x04
+ * BMA4_FIFO_TAG_INTR1 | 0x08
+ * BMA4_FIFO_HEADER | 0x10
+ * BMA4_FIFO_MAG | 0x20
+ * BMA4_FIFO_ACCEL | 0x40
+ * BMA4_FIFO_ALL | 0x7F
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_get_fifo_config(uint8_t *fifo_config, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiIntConfig Interrupt Pin Config
+ * @brief Set / Get Electrical behavior of interrupt pin1 or pin2 of the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiIntConfig
+ * \page bma4_api_bma4_set_int_pin_config bma4_set_int_pin_config
+ * \code
+ * int8_t bma4_set_int_pin_config(const struct bma4_int_pin_config *int_pin_config,
+ * uint8_t int_line,
+ * struct bma4_dev *dev);
+ *
+ * \endcode
+ * @details This function sets the electrical behaviour of interrupt pin1 or
+ * pin2 in the sensor.
+ *
+ * @param[in] int_pin_config : Pointer to structure variable which specifies
+ * the configuration data of either interrupt pin1 or 2.
+ *
+ *@verbatim
+ * ************************************************************************
+ * Structure field members | Macros
+ * ********************************|***************************************
+ * edge_ctrl | BMA4_LEVEL_TRIGGER(0)
+ * | BMA4_EDGE_TRIGGER(1)
+ * ********************************|***************************************
+ * lvl | BMA4_ACTIVE_LOW(0)
+ * | BMA4_ACTIVE_HIGH(1)
+ * ********************************|***************************************
+ * od | BMA4_PUSH_PULL(0)
+ * | BMA4_OPEN_DRAIN(1)
+ * ********************************|***************************************
+ * output_en | BMA4_OUTPUT_DISABLE(0)
+ * | BMA4_OUTPUT_ENABLE(1)
+ * ********************************|***************************************
+ * input_en | BMA4_INPUT_DISABLE(0)
+ * | BMA4_INPUT_ENABLE(1)
+ * ************************************************************************
+ *@endverbatim
+ *
+ * @param[in] int_line : Variable used to select the interrupt pin1 or
+ * pin2 for interrupt configuration.
+ *
+ *@verbatim
+ * int_line | Value
+ * ----------------|----------------------
+ * BMA4_INTR1_MAP | 0
+ * BMA4_INTR2_MAP | 1
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma4_set_int_pin_config(const struct bma4_int_pin_config *int_pin_config, uint8_t int_line,
+ struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiIntConfig
+ * \page bma4_api_bma4_get_int_pin_config bma4_get_int_pin_config
+ * \code
+ * int8_t bma4_get_int_pin_config(struct bma4_int_pin_config *int_pin_config, uint8_t int_line, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the electrical behavior of interrupt pin1 or pin2
+ * from the sensor.
+ *
+ * @param[out] int_pin_config : Pointer to structure variable which stores the
+ * configuration data of either interrupt pin1 or pin2 read from the sensor
+ *
+ *@verbatim
+ * ************************************************************************
+ * Structure field members | Macros
+ * ************************|***********************************************
+ * edge_ctrl | BMA4_LEVEL_TRIGGER(0)
+ * | BMA4_EDGE_TRIGGER(1)
+ * ************************|***********************************************
+ * lvl | BMA4_ACTIVE_LOW(0)
+ * | BMA4_ACTIVE_HIGH(1)
+ * ************************|***********************************************
+ * od | BMA4_PUSH_PULL(0)
+ * | BMA4_OPEN_DRAIN(1)
+ * ************************|***********************************************
+ * output_en | BMA4_OUTPUT_DISABLE(0)
+ * | BMA4_OUTPUT_ENABLE(1)
+ * ************************|***********************************************
+ * input_en | BMA4_INPUT_DISABLE(0)
+ * | BMA4_INPUT_ENABLE(1)
+ * ************************************************************************
+ *@endverbatim
+ *
+ * @param[in] int_line : Variable used to select the interrupt pin1 or
+ * pin2 for interrupt configuration.
+ *
+ *@verbatim
+ * int_line | Value
+ * -------------------|---------------
+ * BMA4_INTR1_MAP | 0
+ * BMA4_INTR2_MAP | 1
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_get_int_pin_config(struct bma4_int_pin_config *int_pin_config, uint8_t int_line, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiIntStatus Interrupt Status
+ * @brief Read Feature interrupt and/or Hardware interrupt status from the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiIntStatus
+ * \page bma4_api_bma4_read_int_status bma4_read_int_status
+ * \code
+ * int8_t bma4_read_int_status(uint16_t *int_status, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the Feature and Hardware interrupt status from the sensor.
+ *
+ * @param[out] int_status : Variable used to get the interrupt status.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_read_int_status(uint16_t *int_status, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiIntStatus
+ * \page bma4_api_bma4_read_int_status_0 bma4_read_int_status_0
+ * \code
+ * int8_t bma4_read_int_status_0(uint8_t *int_status_0, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the Feature interrupt status from the sensor.
+ *
+ * @param[out] int_status_0 : Variable used to get the interrupt status.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_read_int_status_0(uint8_t *int_status_0, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiIntStatus
+ * \page bma4_api_bma4_read_int_status_1 bma4_read_int_status_1
+ * \code
+ * int8_t bma4_read_int_status_1(uint8_t *int_status_1, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the Hardware interrupt status from the sensor.
+ *
+ * @param[out] int_status_1 : Variable used to get the interrupt status.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_read_int_status_1(uint8_t *int_status_1, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiAux Auxiliary interface
+ * @brief Initialize and read/write data to auxiliary interface
+ */
+
+/*!
+ * \ingroup bma4ApiAux
+ * \page bma4_api_bma4_aux_interface_init bma4_aux_interface_init
+ * \code
+ * int8_t bma4_aux_interface_init(struct bma4_dev *dev);
+ * \endcode
+ * @details This API initializes the auxiliary interface to access
+ * auxiliary sensor
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_aux_interface_init(struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiAux
+ * \page bma4_api_bma4_aux_read bma4_aux_read
+ * \code
+ * int8_t bma4_aux_read(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the data from the auxiliary sensor
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ * @param[in] len : User specified data length
+ * @param[out] aux_data : Pointer variable to store data read
+ * @param[in] aux_reg_addr : Variable to pass address from where
+ * data is to be read
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_aux_read(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma4ApiAux
+ * \page bma4_api_bma4_aux_write bma4_aux_write
+ * \code
+ * int8_t bma4_aux_write(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev);
+ * \endcode
+ * @details This API writes the data into the auxiliary sensor
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ * @param[in] len : User specified data length
+ * @param[out] aux_data : Pointer variable to store data read
+ * @param[in] aux_reg_addr : Variable to pass address from where
+ * data is to be written
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_aux_write(uint8_t aux_reg_addr, const uint8_t *aux_data, uint16_t len, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiSoftReset Soft Reset
+ * @brief Perform Soft Reset of the sensor
+ */
+
+/*!
+ * \ingroup bma4ApiSoftReset
+ * \page bma4_api_bma4_soft_reset bma4_soft_reset
+ * \code
+ * int8_t bma4_soft_reset(struct bma4_dev *dev);
+ * \endcode
+ * @details This API commands to do soft reset
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ *
+ */
+int8_t bma4_soft_reset(struct bma4_dev *dev);
+
+/**
+ * \ingroup bma4
+ * \defgroup bma4ApiAccelFoc Accel FOC
+ * @brief Performs Fast Offset Compensation for accel
+ */
+
+/*!
+ * \ingroup bma4ApiAccelFoc
+ * \page bma4_api_bma4_perform_accel_foc bma4_perform_accel_foc
+ * \code
+ * int8_t bma4_perform_accel_foc(const struct bma4_accel_foc_g_value *accel_g_value, struct bma4_dev *dev);
+ * \endcode
+ * @details This API performs Fast Offset Compensation for Accel.
+ * @param[in] accel_g_value : Array which stores the Accel g units
+ * for x,y and z-axis.
+ *
+ *@verbatim
+ * accel_g_value | Description
+ * --------------------------|---------------------------------------
+ * accel_g_value[0] | x-axis g units
+ * accel_g_value[1] | y-axis g units
+ * accel_g_value[2] | z-axis g units
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of dev.
+ *
+ * @return Result of API execution status.
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+int8_t bma4_perform_accel_foc(const struct bma4_accel_foc_g_value *accel_g_value, struct bma4_dev *dev);
+
+#endif
+
+/* End of __BMA4_H__ */
diff --git a/src/drivers/Bma421_C/bma423.c b/src/drivers/Bma421_C/bma423.c
new file mode 100644
index 00000000..1d782705
--- /dev/null
+++ b/src/drivers/Bma421_C/bma423.c
@@ -0,0 +1,1688 @@
+/**
+ * Copyright (c) 2020 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 bma423.c
+ * @date 2020-05-08
+ * @version V2.14.13
+ *
+ */
+
+/*! \file bma423.c
+ * \brief Sensor Driver for BMA423 sensor
+ */
+
+#include "bma423.h"
+
+/**\name Feature configuration file */
+const uint8_t bma423_config_file[] = {
+ 0x80, 0x2e, 0xfe, 0x00, 0x80, 0x2e, 0xf1, 0x01, 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0xfc, 0x00, 0x80, 0x2e, 0xfb,
+ 0x00, 0x80, 0x2e, 0xff, 0x00, 0x80, 0x2e, 0xfd, 0x00, 0x80, 0x2e, 0x42, 0xb0, 0x50, 0x39, 0x21, 0x2e, 0xb0, 0xf0,
+ 0x10, 0x30, 0x21, 0x2e, 0x16, 0xf0, 0x80, 0x2e, 0xf2, 0x01, 0x5d, 0x50, 0x5b, 0x52, 0x01, 0x42, 0x3b, 0x80, 0x41,
+ 0x30, 0x01, 0x42, 0x3c, 0x80, 0x00, 0x2e, 0x01, 0x40, 0x01, 0x42, 0x21, 0x2e, 0xff, 0xaf, 0xb8, 0x2e, 0x03, 0xb7,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x2e, 0x84, 0x01,
+ 0x20, 0x26, 0x98, 0x2e, 0xf7, 0x00, 0x10, 0x30, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, 0xae, 0x00, 0x98, 0x2e, 0xab,
+ 0xb3, 0x98, 0x2e, 0xba, 0xb3, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x98, 0x2e, 0xd4, 0x01, 0x01, 0x2e, 0x5a, 0x00,
+ 0x00, 0xb2, 0x10, 0x2f, 0x00, 0x30, 0x21, 0x2e, 0x5a, 0x00, 0x41, 0x50, 0x98, 0x2e, 0x00, 0xb0, 0x41, 0x50, 0x98,
+ 0x2e, 0xf2, 0xb0, 0x41, 0x50, 0x43, 0x52, 0x98, 0x2e, 0xd5, 0xb3, 0x41, 0x50, 0x45, 0x52, 0x98, 0x2e, 0xd5, 0xb3,
+ 0x98, 0x2e, 0xae, 0x00, 0xe3, 0x2d, 0x01, 0x2e, 0x55, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0x55, 0xf0, 0x30, 0x50, 0x00,
+ 0x30, 0x47, 0x56, 0x05, 0x30, 0x05, 0x2c, 0xfb, 0x7f, 0x3e, 0xbe, 0xd2, 0xba, 0xb2, 0xb9, 0x6c, 0x0b, 0x53, 0x0e,
+ 0xf9, 0x2f, 0x53, 0x1a, 0x01, 0x2f, 0x4d, 0x0e, 0xf5, 0x2f, 0xd2, 0x7f, 0x04, 0x30, 0x1f, 0x2c, 0xe1, 0x7f, 0xc5,
+ 0x01, 0xa3, 0x03, 0x72, 0x0e, 0x03, 0x2f, 0x72, 0x1a, 0x0f, 0x2f, 0x79, 0x0f, 0x0d, 0x2f, 0xe1, 0x6f, 0x4f, 0x04,
+ 0x5f, 0xb9, 0xb1, 0xbf, 0xfa, 0x0b, 0xd2, 0x6f, 0x96, 0x06, 0xb1, 0x25, 0x51, 0xbf, 0xeb, 0x7f, 0x06, 0x00, 0xb2,
+ 0x25, 0x27, 0x03, 0xdb, 0x7f, 0xcf, 0xbf, 0x3e, 0xbf, 0x01, 0xb8, 0xd2, 0xba, 0x41, 0xba, 0xb2, 0xb9, 0x07, 0x0a,
+ 0x6e, 0x0b, 0xc0, 0x90, 0xdf, 0x2f, 0x40, 0x91, 0xdd, 0x2f, 0xfb, 0x6f, 0xd0, 0x5f, 0xb8, 0x2e, 0x10, 0x50, 0xfb,
+ 0x7f, 0x21, 0x25, 0x98, 0x2e, 0x65, 0x01, 0xfb, 0x6f, 0x21, 0x25, 0xf0, 0x5f, 0x10, 0x25, 0x80, 0x2e, 0xb3, 0x00,
+ 0x00, 0x31, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0xc8, 0x2e, 0xc8, 0x2e, 0xc8, 0x2e, 0xc8, 0x2e, 0xc8, 0x2e, 0xaa,
+ 0x00, 0x05, 0x00, 0xaa, 0x00, 0x05, 0x00, 0x2d, 0x01, 0xd4, 0x7b, 0x3b, 0x01, 0xdb, 0x7a, 0x04, 0x00, 0x3f, 0x7b,
+ 0xcd, 0x6c, 0xc3, 0x04, 0x85, 0x09, 0xc3, 0x04, 0xec, 0xe6, 0x0c, 0x46, 0x01, 0x00, 0x27, 0x00, 0x19, 0x00, 0x96,
+ 0x00, 0xa0, 0x00, 0x01, 0x00, 0x0c, 0x00, 0xf0, 0x3c, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x0e, 0x00,
+ 0x00, 0x00, 0x4e, 0x14, 0x88, 0x00, 0x57, 0x00, 0x71, 0x00, 0x7a, 0x00, 0x00, 0x40, 0xff, 0x7f, 0x00, 0x80, 0xaf,
+ 0x00, 0xff, 0x00, 0xff, 0xb7, 0x00, 0x02, 0x00, 0xb0, 0x05, 0x80, 0xb1, 0xf0, 0x80, 0x00, 0x5e, 0xf0, 0xc0, 0x00,
+ 0x59, 0xf0, 0x89, 0xf0, 0x5a, 0x00, 0x00, 0x20, 0x5c, 0x00, 0x50, 0x00, 0x54, 0x00, 0x5b, 0x00, 0xff, 0xfb, 0x52,
+ 0xf0, 0x56, 0xf0, 0x33, 0x09, 0x33, 0x07, 0x00, 0x08, 0x90, 0x01, 0x00, 0xf8, 0x00, 0x01, 0x02, 0x01, 0x94, 0x01,
+ 0xdd, 0x03, 0xc0, 0xad, 0x0b, 0x2f, 0xc0, 0xa8, 0x03, 0x2f, 0xc0, 0x90, 0x07, 0x2f, 0x80, 0xa6, 0x05, 0x2f, 0x40,
+ 0xa9, 0x12, 0x2f, 0x40, 0x91, 0x01, 0x2f, 0x00, 0xab, 0x0e, 0x2f, 0xc0, 0xac, 0x00, 0x30, 0x4b, 0x52, 0x07, 0x2f,
+ 0xc0, 0xa9, 0x03, 0x2f, 0xc0, 0x91, 0x03, 0x2f, 0x80, 0xa7, 0x01, 0x2f, 0x40, 0xa1, 0x05, 0x2f, 0xc0, 0x2e, 0x17,
+ 0x25, 0x06, 0x25, 0xc0, 0x2e, 0xf0, 0x3f, 0x49, 0x52, 0xb8, 0x2e, 0x83, 0x86, 0x01, 0x30, 0x00, 0x30, 0x94, 0x40,
+ 0x24, 0x18, 0x06, 0x00, 0x53, 0x0e, 0x4f, 0x02, 0xf9, 0x2f, 0xb8, 0x2e, 0x80, 0xa8, 0x03, 0x25, 0x10, 0x2f, 0x80,
+ 0x90, 0x01, 0x2f, 0x41, 0x0e, 0x0c, 0x2f, 0xf3, 0x3f, 0x18, 0x05, 0x05, 0x30, 0x5d, 0x07, 0x15, 0x0e, 0x03, 0x2f,
+ 0x55, 0x1a, 0x02, 0x2f, 0xcc, 0x0f, 0x00, 0x2f, 0x58, 0x04, 0x01, 0x25, 0xb8, 0x2e, 0xb8, 0x2e, 0x59, 0x50, 0x41,
+ 0x30, 0x02, 0x40, 0x51, 0x0a, 0x01, 0x42, 0x18, 0x82, 0x4d, 0x50, 0x60, 0x42, 0x70, 0x3c, 0x4f, 0x54, 0x42, 0x42,
+ 0x69, 0x82, 0x82, 0x32, 0x43, 0x40, 0x18, 0x08, 0x02, 0x0a, 0x40, 0x42, 0x42, 0x80, 0x02, 0x3f, 0x01, 0x40, 0x10,
+ 0x50, 0x4a, 0x08, 0xfb, 0x7f, 0x11, 0x42, 0x0b, 0x31, 0x0b, 0x42, 0x3e, 0x80, 0x01, 0x32, 0x01, 0x42, 0x00, 0x2e,
+ 0x01, 0x2e, 0x40, 0xf0, 0x11, 0x90, 0x20, 0x2f, 0x03, 0x30, 0x53, 0x50, 0x51, 0x54, 0x04, 0x35, 0x06, 0x30, 0x57,
+ 0x52, 0x55, 0x32, 0x1d, 0x1a, 0xe3, 0x22, 0x18, 0x1a, 0x55, 0x58, 0xe3, 0x22, 0x04, 0x30, 0xd5, 0x40, 0xb5, 0x0d,
+ 0xe1, 0xbe, 0x6f, 0xbb, 0x80, 0x91, 0xa9, 0x0d, 0x01, 0x89, 0xb5, 0x23, 0x10, 0xa1, 0xf7, 0x2f, 0xda, 0x0e, 0x04,
+ 0x35, 0xeb, 0x2f, 0x01, 0x2e, 0x25, 0x00, 0x70, 0x1a, 0x00, 0x30, 0x21, 0x30, 0x02, 0x2c, 0x08, 0x22, 0x30, 0x30,
+ 0x00, 0xb2, 0x06, 0x2f, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, 0xae, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0xfb,
+ 0x6f, 0xf0, 0x5f, 0xb8, 0x2e, 0x61, 0x50, 0x05, 0x2e, 0x00, 0xf0, 0x5b, 0x56, 0xd3, 0x0f, 0x01, 0x40, 0xf4, 0x33,
+ 0xcc, 0x08, 0x0d, 0x2f, 0xf4, 0x30, 0x94, 0x08, 0xb9, 0x88, 0x02, 0xa3, 0x04, 0x2f, 0x5f, 0x58, 0x4c, 0x0a, 0x87,
+ 0xa2, 0x05, 0x2c, 0xcb, 0x22, 0x5b, 0x54, 0x4a, 0x0a, 0xf2, 0x3b, 0xca, 0x08, 0x3c, 0x80, 0x27, 0x2e, 0x59, 0xf0,
+ 0x01, 0x40, 0x01, 0x42, 0xb8, 0x2e, 0xc8, 0x2e, 0x1a, 0x24, 0x26, 0x00, 0x80, 0x2e, 0x83, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x70, 0x50,
+ 0x03, 0x2e, 0x1f, 0x01, 0xf1, 0x7f, 0x2a, 0x25, 0xb9, 0x82, 0xe0, 0x7f, 0xdb, 0x7f, 0x00, 0x30, 0x45, 0x30, 0x32,
+ 0x30, 0x03, 0x30, 0x04, 0x30, 0xf6, 0x6f, 0xf2, 0x09, 0xfc, 0x13, 0xc2, 0xab, 0xb5, 0x09, 0xc7, 0x23, 0x80, 0xb3,
+ 0xe6, 0x6f, 0xb7, 0x01, 0x00, 0x2e, 0x8b, 0x41, 0x4b, 0x42, 0x05, 0x2f, 0xc5, 0x7f, 0x05, 0x30, 0x46, 0x40, 0xae,
+ 0x05, 0xc5, 0x6f, 0x46, 0x42, 0x01, 0x80, 0x23, 0xbd, 0xd3, 0xbe, 0x03, 0x89, 0x41, 0x82, 0xdf, 0x0c, 0x03, 0xa2,
+ 0xe4, 0x2f, 0xe0, 0x6f, 0x91, 0x6f, 0x11, 0x42, 0xc3, 0xb2, 0xa1, 0x6f, 0x11, 0x42, 0x00, 0x2e, 0xb1, 0x6f, 0x01,
+ 0x42, 0x06, 0x2f, 0x00, 0x32, 0x03, 0x2e, 0x59, 0xf0, 0x08, 0x0a, 0x21, 0x2e, 0x59, 0xf0, 0x06, 0x2d, 0xf1, 0x3d,
+ 0x01, 0x2e, 0x59, 0xf0, 0x01, 0x08, 0x21, 0x2e, 0x59, 0xf0, 0xdb, 0x6f, 0x90, 0x5f, 0xb8, 0x2e, 0x60, 0x50, 0xc3,
+ 0x7f, 0xd4, 0x7f, 0xe7, 0x7f, 0xf6, 0x7f, 0xb2, 0x7f, 0xa5, 0x7f, 0x36, 0x30, 0x07, 0x2e, 0x01, 0xf0, 0xbe, 0xbd,
+ 0xbe, 0xbb, 0x63, 0x58, 0x77, 0x05, 0x41, 0x56, 0x65, 0x54, 0x27, 0x41, 0x06, 0x41, 0xf8, 0xbf, 0xbe, 0x0b, 0xb5,
+ 0x11, 0xd6, 0x42, 0x03, 0x89, 0x5a, 0x0e, 0xf6, 0x2f, 0x12, 0x30, 0x25, 0x2e, 0x5a, 0x00, 0x02, 0x31, 0x25, 0x2e,
+ 0xb8, 0xf0, 0xd4, 0x6f, 0xc3, 0x6f, 0xe7, 0x6f, 0xb2, 0x6f, 0xa5, 0x6f, 0xf6, 0x6f, 0xa0, 0x5f, 0xc8, 0x2e, 0x70,
+ 0x50, 0x42, 0x8e, 0xd4, 0x7f, 0xf6, 0x7f, 0x47, 0x25, 0x1a, 0x18, 0x67, 0x52, 0xf1, 0x00, 0x64, 0x25, 0x01, 0x30,
+ 0x39, 0x02, 0x94, 0x41, 0x81, 0x41, 0xe2, 0x7f, 0xbe, 0xbb, 0xbd, 0x8d, 0x02, 0xbd, 0xb5, 0x7f, 0x8e, 0xb5, 0xba,
+ 0x0a, 0xc6, 0x7f, 0xab, 0x7f, 0x51, 0x25, 0x98, 0x2e, 0x42, 0x01, 0xd5, 0x6f, 0xe2, 0x6f, 0x2a, 0x18, 0x67, 0x54,
+ 0xb2, 0x01, 0x02, 0x30, 0xc4, 0x6f, 0x7a, 0x03, 0x12, 0x41, 0x74, 0x25, 0xd0, 0x7f, 0x52, 0xbc, 0xd3, 0x41, 0x6e,
+ 0xba, 0xde, 0xb6, 0x20, 0x0b, 0xc7, 0x7f, 0x91, 0x7f, 0x98, 0x2e, 0x42, 0x01, 0xf2, 0x6f, 0xd5, 0x6f, 0xca, 0x16,
+ 0x55, 0x18, 0xdd, 0x18, 0x95, 0x6f, 0xea, 0x18, 0x67, 0x5a, 0x31, 0x25, 0x75, 0x01, 0x01, 0x30, 0x20, 0x25, 0x39,
+ 0x02, 0x5e, 0xba, 0x82, 0xbc, 0x8e, 0xb6, 0x21, 0x0b, 0x98, 0x2e, 0x42, 0x01, 0xe2, 0x6f, 0xb5, 0x6f, 0x2a, 0x18,
+ 0xe0, 0x7f, 0xf1, 0x7f, 0x04, 0x30, 0x67, 0x54, 0xf2, 0x00, 0x7c, 0x02, 0x85, 0x6f, 0xd0, 0x6f, 0x0d, 0x17, 0x68,
+ 0x18, 0xe0, 0x18, 0x90, 0x6f, 0xc4, 0x6f, 0xc5, 0x18, 0xeb, 0x6f, 0xb2, 0x01, 0x1b, 0x43, 0x02, 0x30, 0x7a, 0x03,
+ 0xfb, 0x6f, 0x3d, 0x8f, 0x0b, 0x43, 0x3e, 0xba, 0x12, 0xbd, 0x52, 0xbc, 0x6e, 0xbb, 0xa2, 0x0a, 0x9e, 0xb5, 0xde,
+ 0xb6, 0x30, 0x0b, 0xf7, 0x7f, 0x98, 0x2e, 0x42, 0x01, 0xf5, 0x6f, 0x31, 0x25, 0xd1, 0x6f, 0x92, 0x6f, 0xab, 0x6f,
+ 0x50, 0x43, 0x43, 0x43, 0x90, 0x5f, 0x49, 0x56, 0x80, 0x2e, 0x6f, 0x01, 0x10, 0x50, 0x03, 0x40, 0x19, 0x18, 0x4b,
+ 0x56, 0x19, 0x05, 0x36, 0x25, 0xf7, 0x7f, 0x4a, 0x17, 0x54, 0x18, 0xec, 0x18, 0x09, 0x17, 0x01, 0x30, 0x0c, 0x07,
+ 0xe2, 0x18, 0xde, 0x00, 0xf2, 0x6f, 0x97, 0x02, 0x47, 0x58, 0xdc, 0x00, 0x91, 0x02, 0xbf, 0xb8, 0x21, 0xbd, 0x8a,
+ 0x0a, 0xc0, 0x2e, 0x02, 0x42, 0xf0, 0x5f, 0x09, 0x2e, 0x1d, 0x01, 0x05, 0x2e, 0x1d, 0x01, 0xa3, 0xbc, 0x44, 0xbe,
+ 0x90, 0x50, 0x4f, 0xb9, 0x07, 0x2e, 0x1d, 0x01, 0x4a, 0x25, 0x9f, 0xb8, 0x39, 0x8f, 0xb2, 0xbd, 0xf2, 0x7f, 0xbf,
+ 0xb9, 0xeb, 0x7f, 0x8a, 0x0a, 0x37, 0x89, 0x0b, 0x30, 0x93, 0x0a, 0x8b, 0x7f, 0xcb, 0x43, 0x0b, 0x43, 0x80, 0xb2,
+ 0xd3, 0x7f, 0xc1, 0x7f, 0x90, 0x2e, 0x9d, 0xb1, 0x20, 0x25, 0x01, 0x2e, 0x56, 0x00, 0x01, 0x90, 0x0e, 0x2f, 0x69,
+ 0x52, 0x01, 0x2e, 0x53, 0x00, 0xb4, 0x7f, 0xa2, 0x7f, 0x98, 0x2e, 0xa3, 0xb1, 0x00, 0x30, 0x21, 0x2e, 0x56, 0x00,
+ 0xc1, 0x6f, 0xd3, 0x6f, 0xa2, 0x6f, 0xb4, 0x6f, 0x0b, 0x30, 0x01, 0x2e, 0x1d, 0x01, 0x06, 0xbc, 0x06, 0xbb, 0x57,
+ 0x25, 0x01, 0x2e, 0x1d, 0x01, 0x94, 0xb1, 0x05, 0xbc, 0xb6, 0x7f, 0x0f, 0xbb, 0x6d, 0x50, 0x80, 0xb3, 0x0f, 0x2f,
+ 0x0d, 0x2e, 0x1d, 0x01, 0x71, 0x5e, 0xb7, 0x09, 0x2d, 0x2e, 0x1d, 0x01, 0x73, 0x5c, 0x6b, 0x5e, 0x9b, 0x43, 0x9b,
+ 0x43, 0xdb, 0x43, 0x9b, 0x43, 0x1b, 0x42, 0xcb, 0x43, 0x0b, 0x42, 0x8b, 0x43, 0x40, 0xb2, 0x05, 0x2f, 0x6b, 0x50,
+ 0x00, 0x2e, 0x16, 0x40, 0x0b, 0x40, 0x76, 0x7f, 0x8b, 0x7f, 0xcb, 0x0a, 0x01, 0x2e, 0x53, 0x00, 0x69, 0x52, 0x6f,
+ 0x5c, 0x98, 0x2e, 0xef, 0xb1, 0x90, 0x6f, 0x00, 0xb2, 0x0b, 0x2f, 0xf0, 0x6f, 0x00, 0xb2, 0x08, 0x2f, 0x6b, 0x58,
+ 0x6d, 0x50, 0x12, 0x41, 0x12, 0x42, 0x21, 0x30, 0x04, 0x41, 0x04, 0x42, 0x23, 0x2e, 0x5e, 0xf0, 0xc0, 0x6f, 0x00,
+ 0xb2, 0x26, 0x2f, 0x74, 0x6f, 0x80, 0x6f, 0x73, 0x54, 0x88, 0xbd, 0xc8, 0xb8, 0x4b, 0x0a, 0x94, 0x42, 0x91, 0x42,
+ 0x90, 0x42, 0x88, 0xba, 0x6b, 0x52, 0xf3, 0x6f, 0x54, 0x42, 0x85, 0x42, 0xc0, 0x90, 0x40, 0x42, 0x15, 0x2f, 0x6d,
+ 0x52, 0x00, 0x2e, 0x52, 0x40, 0x41, 0x40, 0xa2, 0x04, 0x41, 0x06, 0x40, 0xaa, 0x04, 0x2f, 0x40, 0x90, 0x0b, 0x2f,
+ 0xb1, 0x6f, 0x4a, 0x0f, 0x08, 0x2f, 0xb2, 0x6f, 0x80, 0xb2, 0x05, 0x2f, 0x6d, 0x54, 0x21, 0x30, 0x94, 0x42, 0x80,
+ 0x42, 0x23, 0x2e, 0x5e, 0xf0, 0xd0, 0x6f, 0x00, 0xb2, 0x13, 0x2f, 0x01, 0x2e, 0x52, 0x00, 0x09, 0x2e, 0x5b, 0x00,
+ 0x04, 0x1a, 0x0d, 0x2f, 0x75, 0x50, 0x29, 0x2e, 0x52, 0x00, 0x24, 0x42, 0x44, 0x30, 0x02, 0x40, 0x02, 0x42, 0x09,
+ 0x80, 0x00, 0x2e, 0x04, 0x42, 0x03, 0x2d, 0x10, 0x30, 0x21, 0x2e, 0x56, 0x00, 0xeb, 0x6f, 0x70, 0x5f, 0xb8, 0x2e,
+ 0x09, 0x86, 0x47, 0x54, 0xe4, 0x40, 0xc3, 0x80, 0x94, 0x04, 0xc3, 0x40, 0x13, 0x05, 0x05, 0x40, 0x25, 0x05, 0x8a,
+ 0x17, 0x73, 0x30, 0x73, 0x09, 0x8c, 0x17, 0xf3, 0x08, 0xe3, 0x00, 0x4c, 0x82, 0x15, 0x01, 0xb3, 0xb5, 0x53, 0x42,
+ 0x8b, 0x16, 0x43, 0xb6, 0x52, 0x42, 0x4c, 0x17, 0x54, 0x42, 0x55, 0x42, 0x53, 0x42, 0x52, 0x42, 0x54, 0x42, 0x45,
+ 0x42, 0x6d, 0x82, 0x77, 0x54, 0x52, 0x42, 0x10, 0x50, 0x79, 0x54, 0x52, 0x42, 0xfb, 0x7f, 0x22, 0x30, 0x7b, 0x56,
+ 0x43, 0x42, 0x44, 0x82, 0x0b, 0x30, 0x52, 0x42, 0x5b, 0x42, 0x7c, 0x84, 0x4b, 0x42, 0x35, 0x82, 0x90, 0x80, 0x8b,
+ 0x42, 0x0b, 0x42, 0x35, 0x80, 0x04, 0x30, 0x0b, 0x42, 0x37, 0x80, 0x15, 0x30, 0x60, 0x25, 0x98, 0x2e, 0xe2, 0xb1,
+ 0x8b, 0x83, 0xfb, 0x6f, 0x65, 0x42, 0xc0, 0x2e, 0x44, 0x42, 0xf0, 0x5f, 0x05, 0x80, 0x02, 0x30, 0x51, 0x82, 0x02,
+ 0x42, 0x13, 0x30, 0x41, 0x40, 0x4b, 0x08, 0x7d, 0x54, 0x3e, 0x80, 0x51, 0x14, 0xc0, 0x2e, 0x01, 0x42, 0x00, 0x2e,
+ 0x40, 0x51, 0xd1, 0x7f, 0x12, 0x25, 0x02, 0x30, 0x42, 0x43, 0x32, 0x30, 0x82, 0x43, 0xc6, 0x7f, 0xe5, 0x7f, 0xb4,
+ 0x7f, 0xa3, 0x7f, 0x90, 0x7f, 0x8b, 0x7f, 0x98, 0x2e, 0xec, 0x00, 0xc0, 0x7e, 0x00, 0xac, 0x01, 0x2f, 0x49, 0x50,
+ 0xc0, 0x7e, 0x00, 0x2e, 0x90, 0x6f, 0x09, 0x8a, 0xd1, 0x6f, 0x75, 0x7f, 0x4c, 0x82, 0x63, 0x41, 0x65, 0x7f, 0x11,
+ 0x7f, 0x00, 0x2e, 0x64, 0x41, 0x44, 0x85, 0x52, 0x7f, 0x45, 0x7f, 0x00, 0x2e, 0xa6, 0x40, 0x80, 0x40, 0x32, 0x7f,
+ 0x82, 0x8e, 0xc2, 0x6e, 0x45, 0x41, 0xf0, 0x7f, 0x27, 0x7f, 0x02, 0x7f, 0x98, 0x2e, 0x69, 0xb0, 0x23, 0x6f, 0xd1,
+ 0x6f, 0xc2, 0x40, 0xf9, 0x86, 0x23, 0x7f, 0x80, 0xb2, 0xe0, 0x7e, 0x0f, 0x2f, 0x32, 0x6f, 0x64, 0x6f, 0x82, 0x40,
+ 0xf2, 0x7f, 0x50, 0x82, 0x42, 0x6f, 0x50, 0x6f, 0x73, 0x6f, 0x85, 0x40, 0xc3, 0x40, 0x04, 0x41, 0x06, 0x40, 0xe2,
+ 0x6e, 0x98, 0x2e, 0x69, 0xb0, 0xe0, 0x7e, 0xf3, 0x31, 0x10, 0x6f, 0x36, 0x80, 0xe1, 0x6e, 0x02, 0x40, 0x71, 0x7f,
+ 0x51, 0x04, 0x02, 0x30, 0x40, 0xa8, 0x91, 0x04, 0x4a, 0x22, 0x89, 0x16, 0x93, 0x08, 0x4a, 0x00, 0x95, 0xb4, 0x09,
+ 0x18, 0x8e, 0x16, 0x13, 0x30, 0x93, 0x08, 0x21, 0x6f, 0x60, 0x7f, 0x4d, 0x86, 0x02, 0x80, 0xb2, 0x00, 0x41, 0x40,
+ 0x21, 0xb5, 0x50, 0x7f, 0x43, 0x7f, 0x98, 0x2e, 0xd8, 0xb0, 0x40, 0x6f, 0x62, 0x6f, 0x55, 0x6f, 0x13, 0x40, 0x84,
+ 0x40, 0x01, 0x40, 0x45, 0x41, 0x42, 0xbe, 0x1d, 0x18, 0x4c, 0x04, 0x31, 0x0f, 0x04, 0x8a, 0xc0, 0x6f, 0x11, 0x30,
+ 0x02, 0x2f, 0x00, 0x2e, 0x03, 0x2c, 0x01, 0x42, 0x23, 0x30, 0x03, 0x42, 0x00, 0x2e, 0xd6, 0x6f, 0x44, 0x41, 0x8a,
+ 0x87, 0x76, 0x8b, 0x00, 0xb3, 0x53, 0x7f, 0x15, 0x2f, 0x04, 0x6f, 0x7f, 0x5e, 0x8b, 0x8d, 0xe7, 0x01, 0xc0, 0xa5,
+ 0x84, 0x41, 0x01, 0x2f, 0x00, 0xa1, 0x03, 0x2f, 0xc0, 0xad, 0x08, 0x2f, 0x00, 0xa5, 0x06, 0x2f, 0xc6, 0x40, 0x81,
+ 0x8d, 0x07, 0x30, 0x3c, 0x05, 0xd6, 0x42, 0x04, 0x2c, 0xc4, 0x42, 0x02, 0x2c, 0x07, 0x30, 0x07, 0x30, 0x86, 0x86,
+ 0x94, 0x6f, 0xd7, 0x7e, 0x0e, 0x8d, 0x00, 0x40, 0x74, 0x89, 0xc7, 0x40, 0x02, 0xb2, 0xf9, 0x29, 0x45, 0x41, 0x86,
+ 0x41, 0xbe, 0x80, 0x21, 0x41, 0x75, 0x23, 0x82, 0x40, 0xc7, 0x42, 0x45, 0x7f, 0x34, 0x7f, 0x20, 0x7f, 0x98, 0x2e,
+ 0xd8, 0xb0, 0x31, 0x6f, 0x60, 0x6f, 0x24, 0x6f, 0x22, 0x40, 0x05, 0x41, 0x43, 0x40, 0x13, 0x01, 0x43, 0x86, 0xac,
+ 0x0f, 0xd1, 0x6f, 0x30, 0x7f, 0x00, 0x2f, 0x44, 0x42, 0x48, 0x8a, 0x41, 0x88, 0xe1, 0x40, 0x13, 0x7f, 0x04, 0x7f,
+ 0xf5, 0x7e, 0x98, 0x2e, 0xd8, 0xb0, 0x11, 0x6f, 0x60, 0x6f, 0x34, 0x6f, 0x42, 0x40, 0x03, 0x40, 0x9a, 0x04, 0x04,
+ 0x41, 0x43, 0x82, 0xa2, 0x0e, 0x03, 0x6f, 0x00, 0x2f, 0xc2, 0x42, 0x00, 0x2e, 0x41, 0x40, 0x72, 0x6f, 0x98, 0x2e,
+ 0xd8, 0xb0, 0x25, 0x6f, 0x72, 0x6f, 0x53, 0x41, 0x93, 0x0e, 0xd1, 0x6f, 0x46, 0x80, 0x1b, 0x30, 0x03, 0x30, 0x0c,
+ 0x2f, 0x04, 0x40, 0x00, 0x91, 0x42, 0x42, 0x08, 0x2f, 0xf6, 0x6e, 0x44, 0x6f, 0x86, 0x41, 0xb4, 0x0e, 0x03, 0x2f,
+ 0x02, 0x88, 0xdb, 0x7e, 0x03, 0x43, 0x0b, 0x42, 0x46, 0x8d, 0x44, 0x41, 0x47, 0x80, 0x05, 0x6f, 0x94, 0x0f, 0x76,
+ 0x7f, 0x60, 0x7f, 0x02, 0x2f, 0x45, 0x89, 0x42, 0x43, 0x03, 0x43, 0x49, 0x88, 0xa5, 0x6f, 0x40, 0x91, 0xa4, 0x7f,
+ 0x15, 0x30, 0xe2, 0x6f, 0xd3, 0x6e, 0x03, 0x2f, 0x04, 0x30, 0x83, 0x42, 0x80, 0x2e, 0x93, 0xb3, 0x04, 0x40, 0x25,
+ 0x29, 0x04, 0x42, 0x83, 0x42, 0x45, 0x82, 0x94, 0x6f, 0x04, 0x85, 0xc0, 0xb2, 0x90, 0x2e, 0x7f, 0xb3, 0x15, 0x87,
+ 0x3c, 0x8c, 0xc4, 0x40, 0x46, 0x7f, 0xc2, 0x86, 0x07, 0x40, 0x86, 0x41, 0xf4, 0xbf, 0x00, 0xb3, 0x0c, 0x2f, 0x90,
+ 0x6f, 0x16, 0x80, 0x46, 0x25, 0x00, 0x40, 0x57, 0x25, 0x04, 0x18, 0xae, 0x0e, 0x10, 0x30, 0x06, 0x30, 0x75, 0x25,
+ 0x46, 0x23, 0x60, 0x6f, 0x64, 0x25, 0xc4, 0x40, 0xfa, 0x86, 0x00, 0xb3, 0x33, 0x7f, 0x09, 0x2f, 0x93, 0x6f, 0xd8,
+ 0x88, 0x53, 0x6f, 0x04, 0x41, 0xc3, 0x40, 0xdc, 0x0e, 0x13, 0x30, 0x04, 0x30, 0xdc, 0x22, 0xb3, 0x25, 0x40, 0xb3,
+ 0x02, 0x2f, 0x3b, 0x25, 0xc0, 0x90, 0x05, 0x2f, 0x91, 0x6f, 0xd0, 0x6f, 0x98, 0x2e, 0xe2, 0xb1, 0x4d, 0x2c, 0x04,
+ 0x30, 0x8d, 0x88, 0x43, 0x40, 0x82, 0x40, 0x54, 0x7f, 0xda, 0x0f, 0x04, 0x30, 0x08, 0x2f, 0xc1, 0x80, 0x40, 0x42,
+ 0xc2, 0x0f, 0x02, 0x2f, 0x00, 0x30, 0xc0, 0x7e, 0x1b, 0x2d, 0xc0, 0x7e, 0x19, 0x2d, 0xe1, 0xbc, 0x92, 0x6f, 0x4f,
+ 0x04, 0x90, 0x84, 0x40, 0xa8, 0x21, 0x05, 0x83, 0x40, 0x4c, 0x22, 0x4b, 0x0e, 0xb6, 0x84, 0x21, 0x30, 0x02, 0x2f,
+ 0x11, 0x30, 0x04, 0x2c, 0xc1, 0x7e, 0xe3, 0x6f, 0xc1, 0x7e, 0xc1, 0x42, 0x00, 0x2e, 0x00, 0x40, 0x81, 0x40, 0x04,
+ 0xbd, 0x40, 0x6f, 0x98, 0x2e, 0xd8, 0xb0, 0x50, 0x6f, 0x11, 0x30, 0x02, 0x40, 0x51, 0x08, 0xc3, 0x6e, 0x03, 0x80,
+ 0x99, 0x15, 0x0b, 0x40, 0xb1, 0x6f, 0xd0, 0x6f, 0xb6, 0x7f, 0x5b, 0x7f, 0x04, 0x30, 0x4f, 0x54, 0x03, 0x30, 0x11,
+ 0x2c, 0x14, 0x80, 0x55, 0x6f, 0x06, 0x40, 0x75, 0x01, 0x58, 0xbb, 0x6a, 0x09, 0x05, 0x42, 0xc1, 0x86, 0x47, 0x40,
+ 0x51, 0x25, 0xbe, 0x01, 0x56, 0x43, 0x00, 0x2e, 0x46, 0x41, 0xf4, 0x03, 0xb6, 0x6f, 0x47, 0x43, 0x5e, 0x0e, 0xed,
+ 0x2f, 0x31, 0x6f, 0x60, 0x6f, 0x42, 0x40, 0x15, 0x30, 0x02, 0x82, 0x95, 0x08, 0x04, 0x42, 0x52, 0x42, 0x02, 0x2c,
+ 0x44, 0x42, 0x04, 0x30, 0x3e, 0x8e, 0x91, 0x6f, 0x4f, 0x8c, 0x02, 0x40, 0x83, 0x41, 0xb5, 0x8d, 0x93, 0x0e, 0xd0,
+ 0x6f, 0x01, 0x2f, 0x98, 0x2e, 0xe2, 0xb1, 0x00, 0x2e, 0xc0, 0x41, 0x81, 0x41, 0xc1, 0x0f, 0xc0, 0x6f, 0x01, 0x2f,
+ 0x04, 0x42, 0x00, 0x2e, 0x70, 0x6f, 0x3c, 0x82, 0x00, 0x40, 0x41, 0x40, 0x89, 0x16, 0x95, 0x08, 0x4a, 0x00, 0x04,
+ 0xbc, 0x91, 0xb4, 0x01, 0x0e, 0xe0, 0x6f, 0x07, 0x2f, 0xa1, 0x6f, 0x00, 0x2e, 0x41, 0x40, 0x40, 0xb2, 0x02, 0x2f,
+ 0xa1, 0x6f, 0x05, 0x42, 0x44, 0x42, 0x00, 0x2e, 0x8b, 0x6f, 0xc0, 0x5e, 0xb8, 0x2e, 0x10, 0x50, 0x81, 0x52, 0x43,
+ 0x50, 0xfb, 0x7f, 0x98, 0x2e, 0xc9, 0xb3, 0x43, 0x52, 0x45, 0x82, 0x10, 0x30, 0x50, 0x42, 0x60, 0x30, 0xfb, 0x6f,
+ 0xc0, 0x2e, 0x40, 0x42, 0xf0, 0x5f, 0x10, 0x50, 0x83, 0x52, 0x45, 0x50, 0xfb, 0x7f, 0x98, 0x2e, 0xc9, 0xb3, 0x45,
+ 0x52, 0x45, 0x82, 0x00, 0x30, 0x50, 0x42, 0x70, 0x30, 0xfb, 0x6f, 0xc0, 0x2e, 0x40, 0x42, 0xf0, 0x5f, 0x12, 0x30,
+ 0x12, 0x42, 0x02, 0x30, 0x12, 0x42, 0x12, 0x42, 0x12, 0x42, 0x02, 0x42, 0x03, 0x80, 0x41, 0x84, 0x11, 0x42, 0x02,
+ 0x42, 0xb8, 0x2e, 0x48, 0x84, 0xbe, 0x8a, 0x84, 0x40, 0x70, 0x50, 0x02, 0x41, 0x2d, 0xbb, 0x63, 0x41, 0x42, 0x84,
+ 0x45, 0x41, 0xc2, 0x7f, 0xb5, 0x7f, 0x80, 0xb3, 0xe6, 0x7f, 0xd0, 0x7f, 0xf3, 0x7f, 0x12, 0x30, 0x5e, 0x2f, 0x31,
+ 0x25, 0x55, 0x40, 0x41, 0x91, 0xa1, 0x7f, 0x0f, 0x2f, 0x01, 0x30, 0xc1, 0x42, 0x00, 0x2e, 0xc2, 0x6f, 0x13, 0x40,
+ 0x93, 0x42, 0x00, 0x2e, 0x13, 0x40, 0x93, 0x42, 0x00, 0x2e, 0x00, 0x40, 0x80, 0x42, 0xbd, 0x80, 0xc0, 0x2e, 0x01,
+ 0x42, 0x90, 0x5f, 0xc7, 0x86, 0x01, 0x30, 0xc5, 0x40, 0xfb, 0x86, 0x45, 0x41, 0x04, 0x41, 0x43, 0xbe, 0xc3, 0xbb,
+ 0xd5, 0xbe, 0x55, 0xba, 0x97, 0x7f, 0x05, 0x30, 0xd1, 0x15, 0xf7, 0x09, 0xc0, 0xb3, 0x09, 0x2f, 0x06, 0x40, 0xc7,
+ 0x40, 0xb7, 0x05, 0x07, 0x30, 0x80, 0xa9, 0xfe, 0x05, 0xb7, 0x23, 0x74, 0x0f, 0x55, 0x23, 0xe6, 0x6f, 0x41, 0x82,
+ 0x01, 0x80, 0xc1, 0x86, 0x43, 0xa2, 0xec, 0x2f, 0xb0, 0x6f, 0xa4, 0x6f, 0x28, 0x1a, 0xd1, 0x6f, 0xc3, 0x6f, 0x02,
+ 0x2f, 0x02, 0x30, 0x18, 0x2c, 0x02, 0x43, 0x05, 0x41, 0x6a, 0x29, 0x96, 0x6f, 0x05, 0x43, 0x6e, 0x0e, 0x10, 0x2f,
+ 0xf4, 0x6f, 0x00, 0xb3, 0x03, 0x2f, 0x3f, 0x89, 0x94, 0x14, 0x25, 0x2e, 0x5e, 0xf0, 0x41, 0x25, 0x23, 0x25, 0x15,
+ 0x41, 0x95, 0x42, 0x00, 0x2e, 0x15, 0x41, 0x95, 0x42, 0x00, 0x2e, 0x04, 0x41, 0x84, 0x42, 0x00, 0x90, 0x09, 0x2f,
+ 0x50, 0x40, 0xd0, 0x42, 0x00, 0x2e, 0x50, 0x40, 0xd0, 0x42, 0x00, 0x2e, 0x40, 0x40, 0x02, 0x2c, 0xc0, 0x42, 0x42,
+ 0x42, 0x90, 0x5f, 0xb8, 0x2e, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18,
+ 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e,
+ 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80,
+ 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00
+};
+
+/***************************************************************************/
+
+/*! Static Function Declarations
+ ****************************************************************************/
+
+/*!
+ * @brief This API enables the features of sensor.
+ *
+ * @param[in] feature : Variable to specify the features which are to be set
+ * in the sensor.
+ * @param[in] len : Length for read and write
+ * @param[in] feature_config : Array address which stores the feature
+ * configuration data
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+static int8_t feature_enable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev);
+
+/*!
+ * @brief This API disables the features of sensor.
+ *
+ * @param[in] feature : Variable to specify the features which are to be unset
+ * in the sensor.
+ * @param[in] len : Length for read and write
+ * @param[in] feature_config : Array address which stores the feature
+ * configuration data
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+static int8_t feature_disable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev);
+
+/*!
+ * @brief This API update the settings of step counter into write array.
+ *
+ * @param[in] setting : Pointer to structure variable which stores the
+ * settings parameter1 to parameter25.
+ * @param[in] index : value for array traversing.
+ * @param[out] feature_config : Pointer to store the settings
+ *
+ * @return none
+ */
+static void update_stepcounter_parameter(const struct bma423_stepcounter_settings *setting,
+ uint8_t index,
+ uint8_t *feature_config);
+
+/*!
+ * @brief This API copy the settings of step counter into the
+ * structure of bma423_stepcounter_settings, which is read from sensor.
+ *
+ * @param[out] setting : Pointer to structure variable which stores the
+ * settings parameter1 to parameter25 read from sensor.
+ * @param[in] data_p : Pointer of array which stores the parameters.
+ *
+ * @return none
+ */
+static void extract_stepcounter_parameter(struct bma423_stepcounter_settings *setting, const uint16_t *data_p);
+
+/***************************************************************************/
+
+/**\name Function definitions
+ ****************************************************************************/
+
+/*!
+ * @brief This API is the entry point.
+ * Call this API before using all other APIs.
+ * This API reads the chip-id of the sensor and sets the resolution.
+ */
+int8_t bma423_init(struct bma4_dev *dev)
+{
+ int8_t rslt;
+
+ rslt = bma4_init(dev);
+ if (rslt == BMA4_OK)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ /* Resolution of BMA423 sensor is 12 bit */
+ dev->resolution = 12;
+
+ dev->feature_len = BMA423_FEATURE_SIZE;
+
+ dev->config_size = sizeof(bma423_config_file);
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API is used to upload the configuration file to enable the
+ * features of the sensor.
+ */
+int8_t bma423_write_config_file(struct bma4_dev *dev)
+{
+ int8_t rslt = BMA4_OK;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ /* Configuration stream read/write length boundary
+ * check
+ */
+ if ((dev->read_write_len >= BMA423_RD_WR_MIN_LEN) && (dev->read_write_len <= BMA423_FEATURE_SIZE))
+ {
+ /* Even or odd check */
+ if ((dev->read_write_len % 2) != 0)
+ {
+ dev->read_write_len = dev->read_write_len - 1;
+ }
+
+ /*Assign stream data */
+ dev->config_file_ptr = bma423_config_file;
+ rslt = bma4_write_config_file(dev);
+ }
+ else
+ {
+ rslt = BMA4_E_RD_WR_LENGTH_INVALID;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API is used to get the configuration id of the sensor.
+ */
+int8_t bma423_get_config_id(uint16_t *config_id, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+ uint8_t index = BMA423_CONFIG_ID_OFFSET;
+ int8_t rslt = BMA4_OK;
+ uint16_t config_id_lsb = 0;
+ uint16_t config_id_msb = 0;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ config_id_lsb = (uint16_t)feature_config[index];
+ config_id_msb = ((uint16_t)feature_config[index + 1]) << 8;
+ *config_id = config_id_lsb | config_id_msb;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets/un-sets the user provided interrupt to either interrupt
+ * pin1 or pin2 in the sensor.
+ */
+int8_t bma423_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev)
+{
+ int8_t rslt = BMA4_OK;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ if (int_line <= 1)
+ {
+ /* Map/Unmap the interrupt */
+ rslt = bma4_map_interrupt(int_line, int_map, enable, dev);
+ }
+ else
+ {
+ rslt = BMA4_E_INT_LINE_INVALID;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the bma423 interrupt status from the sensor.
+ */
+int8_t bma423_read_int_status(uint16_t *int_status, struct bma4_dev *dev)
+{
+ int8_t rslt = BMA4_OK;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ /* Read the interrupt status */
+ rslt = bma4_read_int_status(int_status, dev);
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API enables/disables the features of the sensor.
+ */
+int8_t bma423_feature_enable(uint8_t feature, uint8_t enable, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+ int8_t rslt = BMA4_OK;
+ uint8_t len = BMA423_FEATURE_SIZE;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ /* Read feature configuration data */
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, len, dev);
+ if (rslt == BMA4_OK)
+ {
+ if (enable == TRUE)
+ {
+ /* Enables the feature */
+ rslt = feature_enable(feature, len, feature_config, dev);
+ }
+ else
+ {
+ /* Disables the feature */
+ rslt = feature_disable(feature, len, feature_config, dev);
+ }
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API performs x, y and z axis remapping in the sensor.
+ */
+int8_t bma423_set_remap_axes(const struct bma423_axes_remap *remap_data, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+ uint8_t index = BMA423_AXES_REMAP_OFFSET;
+ int8_t rslt = BMA4_OK;
+ uint8_t x_axis = 0;
+ uint8_t x_axis_sign = 0;
+ uint8_t y_axis = 0;
+ uint8_t y_axis_sign = 0;
+ uint8_t z_axis = 0;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ x_axis = remap_data->x_axis & BMA423_X_AXIS_MASK;
+ x_axis_sign = (remap_data->x_axis_sign << 2) & BMA423_X_AXIS_SIGN_MASK;
+ y_axis = (remap_data->y_axis << 3) & BMA423_Y_AXIS_MASK;
+ y_axis_sign = (remap_data->y_axis_sign << 5) & BMA423_Y_AXIS_SIGN_MASK;
+ z_axis = (remap_data->z_axis << 6) & BMA423_Z_AXIS_MASK;
+ feature_config[index] = x_axis | x_axis_sign | y_axis | y_axis_sign | z_axis;
+ feature_config[index + 1] = remap_data->z_axis_sign & BMA423_Z_AXIS_SIGN_MASK;
+ rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the x, y and z axis remap data from the sensor.
+ */
+int8_t bma423_get_remap_axes(struct bma423_axes_remap *remap_data, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+ uint8_t index = BMA423_AXES_REMAP_OFFSET;
+ int8_t rslt = BMA4_OK;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ remap_data->x_axis = feature_config[index] & BMA423_X_AXIS_MASK;
+ remap_data->x_axis_sign = (feature_config[index] & BMA423_X_AXIS_SIGN_MASK) >> 2;
+ remap_data->y_axis = (feature_config[index] & BMA423_Y_AXIS_MASK) >> 3;
+ remap_data->y_axis_sign = (feature_config[index] & BMA423_Y_AXIS_SIGN_MASK) >> 5;
+ remap_data->z_axis = (feature_config[index] & BMA423_Z_AXIS_MASK) >> 6;
+ remap_data->z_axis_sign = (feature_config[index + 1] & BMA423_Z_AXIS_SIGN_MASK);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the configuration of any-motion feature in the sensor.
+ * This API enables/disables the any-motion feature according to the axis set.
+ */
+int8_t bma423_set_any_mot_config(const struct bma423_any_no_mot_config *any_mot, struct bma4_dev *dev)
+{
+ /* Variable to define error */
+ int8_t rslt = BMA4_OK;
+
+ /* Initialize configuration file */
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+
+ /* Update index to configure any-motion axes */
+ uint8_t index = BMA423_ANY_MOT_OFFSET;
+
+ /* Variable to define LSB */
+ uint16_t lsb = 0;
+
+ /* Variable to define MSB */
+ uint16_t msb = 0;
+
+ /* Variable to define LSB and MSB */
+ uint16_t lsb_msb = 0;
+
+ if ((dev != NULL) && (any_mot != NULL))
+ {
+ /* Get any-motion configuration from the sensor */
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_ANY_MOT_LEN, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Set threshold value in feature configuration array */
+ feature_config[index++] = BMA4_GET_LSB(any_mot->threshold);
+ feature_config[index++] = BMA4_GET_MSB(any_mot->threshold);
+
+ /* Extract the word where duration and axes enable
+ * resides
+ */
+ lsb = feature_config[index];
+ msb = feature_config[index + 1] << 8;
+ lsb_msb = lsb | msb;
+
+ /* Set the duration in the same word */
+ lsb_msb = BMA4_SET_BITS_POS_0(lsb_msb, BMA423_ANY_NO_MOT_DUR, any_mot->duration);
+
+ /* Set the axes in the same word */
+ lsb_msb = BMA4_SET_BITSLICE(lsb_msb, BMA423_ANY_NO_MOT_AXIS_EN, any_mot->axes_en);
+
+ /* Assign the word with set duration and axes enable
+ * value back to feature configuration array
+ */
+ feature_config[index++] = BMA4_GET_LSB(lsb_msb);
+ feature_config[index] = BMA4_GET_MSB(lsb_msb);
+
+ /* Set any-motion configuration to the sensor */
+ rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_ANY_MOT_LEN, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the configuration of any-motion feature from the
+ * sensor.
+ */
+int8_t bma423_get_any_mot_config(struct bma423_any_no_mot_config *any_mot, struct bma4_dev *dev)
+{
+ /* Variable to define error */
+ int8_t rslt = BMA4_OK;
+
+ /* Initialize configuration file */
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+
+ /* Update index to configure any-motion axes */
+ uint8_t index = BMA423_ANY_MOT_OFFSET;
+
+ /* Variable to define LSB */
+ uint16_t lsb = 0;
+
+ /* Variable to define MSB */
+ uint16_t msb = 0;
+
+ /* Variable to define LSB and MSB */
+ uint16_t lsb_msb = 0;
+
+ if ((dev != NULL) && (any_mot != NULL))
+ {
+ /* Get any-motion configuration from the sensor */
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_ANY_MOT_LEN, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Get word to calculate threshold and any-motion
+ * select
+ */
+ lsb = (uint16_t)feature_config[index++];
+ msb = ((uint16_t)feature_config[index++] << 8);
+ lsb_msb = lsb | msb;
+
+ /* Extract threshold value */
+ any_mot->threshold = lsb_msb & BMA423_ANY_NO_MOT_THRES_MSK;
+
+ /* Get word to calculate duration and axes enable */
+ lsb = (uint16_t)feature_config[index++];
+ msb = ((uint16_t)feature_config[index] << 8);
+ lsb_msb = lsb | msb;
+
+ /* Extract duration value */
+ any_mot->duration = lsb_msb & BMA423_ANY_NO_MOT_DUR_MSK;
+
+ /* Extract axes enable value */
+ any_mot->axes_en = (uint8_t)((lsb_msb & BMA423_ANY_NO_MOT_AXIS_EN_MSK) >> BMA423_ANY_NO_MOT_AXIS_EN_POS);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the configuration of no-motion feature in the sensor.
+ * This API enables/disables the no-motion feature according to the axis set.
+ */
+int8_t bma423_set_no_mot_config(const struct bma423_any_no_mot_config *no_mot, struct bma4_dev *dev)
+{
+ /* Variable to define error */
+ int8_t rslt = BMA4_OK;
+
+ /* Initialize configuration file */
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+
+ /* Update index to configure no-motion axes */
+ uint8_t index = BMA423_NO_MOT_OFFSET;
+
+ /* Variable to define LSB */
+ uint16_t lsb = 0;
+
+ /* Variable to define MSB */
+ uint16_t msb = 0;
+
+ /* Variable to define LSB and MSB */
+ uint16_t lsb_msb = 0;
+
+ if ((dev != NULL) && (no_mot != NULL))
+ {
+ /* Get no-motion configuration from the sensor */
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_NO_MOT_RD_WR_LEN, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Set threshold value in feature configuration array */
+ feature_config[index++] = BMA4_GET_LSB(no_mot->threshold);
+ feature_config[index++] = BMA4_GET_MSB(no_mot->threshold);
+
+ /* Extract the word where duration and axes enable
+ * resides
+ */
+ lsb = feature_config[index];
+ msb = feature_config[index + 1] << 8;
+ lsb_msb = lsb | msb;
+
+ /* Set the duration in the same word */
+ lsb_msb = BMA4_SET_BITS_POS_0(lsb_msb, BMA423_ANY_NO_MOT_DUR, no_mot->duration);
+
+ /* Set the axes in the same word */
+ lsb_msb = BMA4_SET_BITSLICE(lsb_msb, BMA423_ANY_NO_MOT_AXIS_EN, no_mot->axes_en);
+
+ /* Assign the word with set duration and axes enable
+ * value back to feature configuration array
+ */
+ feature_config[index++] = BMA4_GET_LSB(lsb_msb);
+ feature_config[index] = BMA4_GET_MSB(lsb_msb);
+
+ /* Set no-motion configuration to the sensor */
+ rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_NO_MOT_RD_WR_LEN, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the configuration of no-motion feature from the
+ * sensor.
+ */
+int8_t bma423_get_no_mot_config(struct bma423_any_no_mot_config *no_mot, struct bma4_dev *dev)
+{
+ /* Variable to define error */
+ int8_t rslt = BMA4_OK;
+
+ /* Initialize configuration file */
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+
+ /* Update index to configure no-motion axes */
+ uint8_t index = BMA423_NO_MOT_OFFSET;
+
+ /* Variable to define LSB */
+ uint16_t lsb = 0;
+
+ /* Variable to define MSB */
+ uint16_t msb = 0;
+
+ /* Variable to define LSB and MSB */
+ uint16_t lsb_msb = 0;
+
+ if ((dev != NULL) && (no_mot != NULL))
+ {
+ /* Get no-motion configuration from the sensor */
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_NO_MOT_RD_WR_LEN, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Get word to calculate threshold and no-motion
+ * select
+ */
+ lsb = (uint16_t)feature_config[index++];
+ msb = ((uint16_t)feature_config[index++] << 8);
+ lsb_msb = lsb | msb;
+
+ /* Extract threshold value */
+ no_mot->threshold = lsb_msb & BMA423_ANY_NO_MOT_THRES_MSK;
+
+ /* Get word to calculate duration and axes enable */
+ lsb = (uint16_t)feature_config[index++];
+ msb = ((uint16_t)feature_config[index] << 8);
+ lsb_msb = lsb | msb;
+
+ /* Extract duration value */
+ no_mot->duration = lsb_msb & BMA423_ANY_NO_MOT_DUR_MSK;
+
+ /* Extract axes enable value */
+ no_mot->axes_en = (uint8_t)((lsb_msb & BMA423_ANY_NO_MOT_AXIS_EN_MSK) >> BMA423_ANY_NO_MOT_AXIS_EN_POS);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API enables or disables the step detector feature in the sensor.
+ */
+int8_t bma423_step_detector_enable(uint8_t enable, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+ int8_t rslt = BMA4_OK;
+
+ /* Step detector enable bit position is 1 byte ahead of the base address */
+ uint8_t index = BMA423_STEP_CNTR_OFFSET + 1;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], BMA423_STEP_DETECTOR_EN, enable);
+ rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the watermark level for step counter interrupt in the
+ * sensor.
+ */
+int8_t bma423_step_counter_set_watermark(uint16_t step_counter_wm, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+ uint8_t index = BMA423_STEP_CNTR_OFFSET;
+ uint16_t wm_lsb = 0;
+ uint16_t wm_msb = 0;
+ int8_t rslt = BMA4_OK;
+ uint16_t data = 0;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ wm_lsb = feature_config[index];
+ wm_msb = feature_config[index + 1] << 8;
+ data = wm_lsb | wm_msb;
+
+ /* Sets only watermark bits in the complete
+ * 16 bits of data
+ */
+ data = BMA4_SET_BITS_POS_0(data, BMA423_STEP_CNTR_WM, step_counter_wm);
+
+ /* Splits 16 bits of data to individual
+ * 8 bits data
+ */
+ feature_config[index] = BMA4_GET_LSB(data);
+ feature_config[index + 1] = BMA4_GET_MSB(data);
+
+ /* Writes stepcounter watermark settings
+ * in the sensor
+ */
+ rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the water mark level set for step counter interrupt
+ * in the sensor.
+ */
+int8_t bma423_step_counter_get_watermark(uint16_t *step_counter_wm, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+ uint8_t index = BMA423_STEP_CNTR_OFFSET;
+ uint16_t wm_lsb = 0;
+ uint16_t wm_msb = 0;
+ int8_t rslt = BMA4_OK;
+ uint16_t data = 0;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ wm_lsb = feature_config[index];
+ wm_msb = feature_config[index + 1] << 8;
+ data = wm_lsb | wm_msb;
+ *step_counter_wm = BMA4_GET_BITS_POS_0(data, BMA423_STEP_CNTR_WM);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API resets the counted steps of step counter.
+ */
+int8_t bma423_reset_step_counter(struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+
+ /* Reset bit is 1 byte ahead of base address */
+ uint8_t index = BMA423_STEP_CNTR_OFFSET + 1;
+ int8_t rslt = BMA4_OK;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], BMA423_STEP_CNTR_RST, 1);
+ rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the number of counted steps of the step counter
+ * feature from the sensor.
+ */
+int8_t bma423_step_counter_output(uint32_t *step_count, struct bma4_dev *dev)
+{
+ uint8_t data[BMA423_STEP_CNTR_DATA_SIZE] = { 0 };
+ int8_t rslt = BMA4_OK;
+ uint32_t step_count_0 = 0;
+ uint32_t step_count_1 = 0;
+ uint32_t step_count_2 = 0;
+ uint32_t step_count_3 = 0;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ /* Reads the step counter output data from the
+ * gpio register
+ */
+ rslt = bma4_read_regs(BMA4_STEP_CNT_OUT_0_ADDR, data, BMA423_STEP_CNTR_DATA_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ step_count_0 = (uint32_t)data[0];
+ step_count_1 = (uint32_t)data[1] << 8;
+ step_count_2 = (uint32_t)data[2] << 16;
+ step_count_3 = (uint32_t)data[3] << 24;
+ *step_count = step_count_0 | step_count_1 | step_count_2 | step_count_3;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the output for activity feature.
+ */
+int8_t bma423_activity_output(uint8_t *activity, struct bma4_dev *dev)
+{
+ uint8_t data = 0;
+ int8_t rslt = BMA4_OK;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ /* Reads the activity output from the gpio register */
+ rslt = bma4_read_regs(BMA4_ACTIVITY_OUT_ADDR, &data, 1, dev);
+ if (rslt == BMA4_OK)
+ {
+ *activity = data;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the parameter1 to parameter7 settings of the step
+ * counter feature.
+ */
+int8_t bma423_stepcounter_get_parameter(struct bma423_stepcounter_settings *setting, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+ uint16_t *data_p = (uint16_t *)(void *)feature_config;
+ int8_t rslt = BMA4_OK;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* To convert 8bit to 16 bit address */
+ data_p = data_p + BMA423_STEP_CNTR_PARAM_OFFSET / 2;
+ extract_stepcounter_parameter(setting, data_p);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the parameter1 to parameter7 settings of the step
+ * counter feature in the sensor.
+ */
+int8_t bma423_stepcounter_set_parameter(const struct bma423_stepcounter_settings *setting, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+ uint8_t index = BMA423_STEP_CNTR_PARAM_OFFSET;
+ int8_t rslt = BMA4_OK;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ update_stepcounter_parameter(setting, index, feature_config);
+
+ /* Writes step counter parameter settings
+ * in the sensor
+ */
+ rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the sensitivity of single tap feature in the sensor.
+ */
+int8_t bma423_single_tap_set_sensitivity(uint8_t sensitivity, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+ uint8_t index = BMA423_SINGLE_TAP_OFFSET;
+ int8_t rslt = BMA4_OK;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], BMA423_TAP_SENS, sensitivity);
+
+ /* Writes sensitivity settings in the sensor */
+ rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the sensitivity of double tap feature in the sensor.
+ */
+int8_t bma423_double_tap_set_sensitivity(uint8_t sensitivity, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+ uint8_t index = BMA423_DOUBLE_TAP_OFFSET;
+ int8_t rslt = BMA4_OK;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ feature_config[index] = BMA4_SET_BITSLICE(feature_config[index], BMA423_TAP_SENS, sensitivity);
+
+ /* Writes sensitivity settings in the sensor */
+ rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the sensitivity of single tap feature in the sensor
+ */
+int8_t bma423_single_tap_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+ uint8_t index = BMA423_SINGLE_TAP_OFFSET;
+ int8_t rslt = BMA4_OK;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Extracts sensitivity data */
+ *sensitivity = BMA4_GET_BITSLICE(feature_config[index], BMA423_TAP_SENS);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the sensitivity of double tap feature in the sensor
+ */
+int8_t bma423_double_tap_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+ uint8_t index = BMA423_DOUBLE_TAP_OFFSET;
+ int8_t rslt = BMA4_OK;
+
+ if (dev != NULL)
+ {
+ if (dev->chip_id == BMA423_CHIP_ID)
+ {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+ if (rslt == BMA4_OK)
+ {
+ /* Extracts sensitivity data */
+ *sensitivity = BMA4_GET_BITSLICE(feature_config[index], BMA423_TAP_SENS);
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*! @cond DOXYGEN_SUPRESS */
+
+/* Suppressing doxygen warnings triggered for same static function names present across various sensor variant
+ * directories */
+
+/*!
+ * @brief This API enables the features of the sensor.
+ */
+static int8_t feature_enable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev)
+{
+ uint8_t index = 0;
+ int8_t rslt;
+
+ /* Enable step counter */
+ if ((feature & BMA423_STEP_CNTR) > 0)
+ {
+ index = BMA423_STEP_CNTR_OFFSET + 1;
+ feature_config[index] = feature_config[index] | BMA423_STEP_CNTR_EN_MSK;
+ }
+
+ /* Enable step activity */
+ if ((feature & BMA423_STEP_ACT) > 0)
+ {
+ index = BMA423_STEP_CNTR_OFFSET + 1;
+ feature_config[index] = feature_config[index] | BMA423_STEP_ACT_EN_MSK;
+ }
+
+ /* Enable wrist wear wakeup */
+ if ((feature & BMA423_WRIST_WEAR) > 0)
+ {
+ index = BMA423_WRIST_WEAR_OFFSET;
+ feature_config[index] = feature_config[index] | BMA423_WRIST_WEAR_EN_MSK;
+ }
+
+ /* Enable single - tap */
+ if ((feature & BMA423_SINGLE_TAP) > 0)
+ {
+ index = BMA423_SINGLE_TAP_OFFSET;
+ feature_config[index] = feature_config[index] | BMA423_SINGLE_TAP_EN_MSK;
+ }
+
+ /* Enable double- tap */
+ if ((feature & BMA423_DOUBLE_TAP) > 0)
+ {
+ index = BMA423_DOUBLE_TAP_OFFSET;
+ feature_config[index] = feature_config[index] | BMA423_DOUBLE_TAP_EN_MSK;
+ }
+
+ /* Write the feature enable settings in the sensor */
+ rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, len, dev);
+
+ return rslt;
+}
+
+/*!
+ * @brief This API disables the features of the sensor.
+ */
+static int8_t feature_disable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev)
+{
+ uint8_t index = 0;
+ int8_t rslt;
+
+ /* Disable step counter */
+ if ((feature & BMA423_STEP_CNTR) > 0)
+ {
+ index = BMA423_STEP_CNTR_OFFSET + 1;
+ feature_config[index] = feature_config[index] & (~BMA423_STEP_CNTR_EN_MSK);
+ }
+
+ /* Disable step activity */
+ if ((feature & BMA423_STEP_ACT) > 0)
+ {
+ index = BMA423_STEP_CNTR_OFFSET + 1;
+ feature_config[index] = feature_config[index] & (~BMA423_STEP_ACT_EN_MSK);
+ }
+
+ /* Disable wrist wear wakeup */
+ if ((feature & BMA423_WRIST_WEAR) > 0)
+ {
+ index = BMA423_WRIST_WEAR_OFFSET;
+ feature_config[index] = feature_config[index] & (~BMA423_WRIST_WEAR_EN_MSK);
+ }
+
+ /* Disable single-tap */
+ if ((feature & BMA423_SINGLE_TAP) > 0)
+ {
+ index = BMA423_SINGLE_TAP_OFFSET;
+ feature_config[index] = feature_config[index] & (~BMA423_SINGLE_TAP_EN_MSK);
+ }
+
+ /* Disable double-tap */
+ if ((feature & BMA423_DOUBLE_TAP) > 0)
+ {
+ index = BMA423_DOUBLE_TAP_OFFSET;
+ feature_config[index] = feature_config[index] & (~BMA423_DOUBLE_TAP_EN_MSK);
+ }
+
+ /* Write the configured settings in the sensor */
+ rslt = bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, len, dev);
+
+ return rslt;
+}
+
+/*!
+ * @brief This API update the settings of step counter.
+ */
+static void update_stepcounter_parameter(const struct bma423_stepcounter_settings *setting,
+ uint8_t index,
+ uint8_t *feature_config)
+{
+ feature_config[index++] = BMA4_GET_LSB(setting->param1);
+ feature_config[index++] = BMA4_GET_MSB(setting->param1);
+ feature_config[index++] = BMA4_GET_LSB(setting->param2);
+ feature_config[index++] = BMA4_GET_MSB(setting->param2);
+ feature_config[index++] = BMA4_GET_LSB(setting->param3);
+ feature_config[index++] = BMA4_GET_MSB(setting->param3);
+ feature_config[index++] = BMA4_GET_LSB(setting->param4);
+ feature_config[index++] = BMA4_GET_MSB(setting->param4);
+ feature_config[index++] = BMA4_GET_LSB(setting->param5);
+ feature_config[index++] = BMA4_GET_MSB(setting->param5);
+ feature_config[index++] = BMA4_GET_LSB(setting->param6);
+ feature_config[index++] = BMA4_GET_MSB(setting->param6);
+ feature_config[index++] = BMA4_GET_LSB(setting->param7);
+ feature_config[index++] = BMA4_GET_MSB(setting->param7);
+ feature_config[index++] = BMA4_GET_LSB(setting->param8);
+ feature_config[index++] = BMA4_GET_MSB(setting->param8);
+ feature_config[index++] = BMA4_GET_LSB(setting->param9);
+ feature_config[index++] = BMA4_GET_MSB(setting->param9);
+ feature_config[index++] = BMA4_GET_LSB(setting->param10);
+ feature_config[index++] = BMA4_GET_MSB(setting->param10);
+ feature_config[index++] = BMA4_GET_LSB(setting->param11);
+ feature_config[index++] = BMA4_GET_MSB(setting->param11);
+ feature_config[index++] = BMA4_GET_LSB(setting->param12);
+ feature_config[index++] = BMA4_GET_MSB(setting->param12);
+ feature_config[index++] = BMA4_GET_LSB(setting->param13);
+ feature_config[index++] = BMA4_GET_MSB(setting->param13);
+ feature_config[index++] = BMA4_GET_LSB(setting->param14);
+ feature_config[index++] = BMA4_GET_MSB(setting->param14);
+ feature_config[index++] = BMA4_GET_LSB(setting->param15);
+ feature_config[index++] = BMA4_GET_MSB(setting->param15);
+ feature_config[index++] = BMA4_GET_LSB(setting->param16);
+ feature_config[index++] = BMA4_GET_MSB(setting->param16);
+ feature_config[index++] = BMA4_GET_LSB(setting->param17);
+ feature_config[index++] = BMA4_GET_MSB(setting->param17);
+ feature_config[index++] = BMA4_GET_LSB(setting->param18);
+ feature_config[index++] = BMA4_GET_MSB(setting->param18);
+ feature_config[index++] = BMA4_GET_LSB(setting->param19);
+ feature_config[index++] = BMA4_GET_MSB(setting->param19);
+ feature_config[index++] = BMA4_GET_LSB(setting->param20);
+ feature_config[index++] = BMA4_GET_MSB(setting->param20);
+ feature_config[index++] = BMA4_GET_LSB(setting->param21);
+ feature_config[index++] = BMA4_GET_MSB(setting->param21);
+ feature_config[index++] = BMA4_GET_LSB(setting->param22);
+ feature_config[index++] = BMA4_GET_MSB(setting->param22);
+ feature_config[index++] = BMA4_GET_LSB(setting->param23);
+ feature_config[index++] = BMA4_GET_MSB(setting->param23);
+ feature_config[index++] = BMA4_GET_LSB(setting->param24);
+ feature_config[index++] = BMA4_GET_MSB(setting->param24);
+ feature_config[index++] = BMA4_GET_LSB(setting->param25);
+ feature_config[index] = BMA4_GET_MSB(setting->param25);
+}
+
+/*!
+ * @brief This API copy the settings of step counter into the structure of
+ * bma423_stepcounter_settings, which is read from sensor.
+ */
+static void extract_stepcounter_parameter(struct bma423_stepcounter_settings *setting, const uint16_t *data_p)
+{
+ setting->param1 = *(data_p++);
+ setting->param2 = *(data_p++);
+ setting->param3 = *(data_p++);
+ setting->param4 = *(data_p++);
+ setting->param5 = *(data_p++);
+ setting->param6 = *(data_p++);
+ setting->param7 = *(data_p++);
+ setting->param8 = *(data_p++);
+ setting->param9 = *(data_p++);
+ setting->param10 = *(data_p++);
+ setting->param11 = *(data_p++);
+ setting->param12 = *(data_p++);
+ setting->param13 = *(data_p++);
+ setting->param14 = *(data_p++);
+ setting->param15 = *(data_p++);
+ setting->param16 = *(data_p++);
+ setting->param17 = *(data_p++);
+ setting->param18 = *(data_p++);
+ setting->param19 = *(data_p++);
+ setting->param20 = *(data_p++);
+ setting->param21 = *(data_p++);
+ setting->param22 = *(data_p++);
+ setting->param23 = *(data_p++);
+ setting->param24 = *(data_p++);
+ setting->param25 = *data_p;
+}
+
+/*!
+ * @brief This API is used to get the config file major and minor information.
+ */
+int8_t bma423_get_version_config(uint16_t *config_major, uint16_t *config_minor, struct bma4_dev *dev)
+{
+ /* Initialize configuration file */
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = { 0 };
+
+ /* Update index to config file version */
+ uint8_t index = BMA423_CONFIG_ID_START_ADDR;
+
+ /* Variable to define LSB */
+ uint8_t lsb = 0;
+
+ /* Variable to define MSB */
+ uint8_t msb = 0;
+
+ /* Variable to define LSB and MSB */
+ uint16_t lsb_msb = 0;
+
+ /* Result of api are returned to this variable */
+ int8_t rslt = BMA4_OK;
+
+ if ((dev != NULL) && (config_major != NULL) && (config_minor != NULL))
+ {
+ rslt = bma4_set_advance_power_save(BMA4_DISABLE, dev);
+
+ /* Wait for sensor time synchronization. Refer the data-sheet for
+ * more information
+ */
+ dev->delay_us(450, dev->intf_ptr);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Get config file identification from the sensor */
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
+
+ if (rslt == BMA4_OK)
+ {
+ /* Get word to calculate config file identification */
+ lsb = feature_config[index++];
+ msb = feature_config[index++];
+
+ lsb_msb = (uint16_t)(msb << 8 | lsb);
+
+ /* Get major and minor version */
+ *config_major = BMA4_GET_BITSLICE(lsb_msb, BMA423_CONFIG_MAJOR);
+ *config_minor = BMA4_GET_BITS_POS_0(lsb, BMA423_CONFIG_MINOR);
+ }
+ }
+ }
+ else
+ {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*! @endcond */
diff --git a/src/drivers/Bma421_C/bma423.h b/src/drivers/Bma421_C/bma423.h
new file mode 100644
index 00000000..96e5d8e3
--- /dev/null
+++ b/src/drivers/Bma421_C/bma423.h
@@ -0,0 +1,1115 @@
+/**
+ * Copyright (c) 2020 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 bma423.h
+ * @date 2020-05-08
+ * @version V2.14.13
+ *
+ */
+
+/**
+ * \ingroup bma4xy
+ * \defgroup bma423 BMA423
+ * @brief Sensor driver for BMA423 sensor
+ */
+
+#ifndef BMA423_H
+#define BMA423_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "bma4.h"
+
+/**\name Chip ID of BMA423 sensor */
+#define BMA423_CHIP_ID UINT8_C(0x11)
+
+/**\ Configuration ID start position of BMA423 sensor */
+#define BMA423_CONFIG_ID_START_ADDR UINT8_C(66)
+
+/**\name Sensor feature size */
+#define BMA423_FEATURE_SIZE UINT8_C(70)
+#define BMA423_ANY_MOT_LEN UINT8_C(4)
+
+/**\name Feature offset address */
+#define BMA423_ANY_MOT_OFFSET UINT8_C(0x00)
+#define BMA423_NO_MOT_OFFSET UINT8_C(0x04)
+#define BMA423_STEP_CNTR_PARAM_OFFSET UINT8_C(0x08)
+#define BMA423_STEP_CNTR_OFFSET UINT8_C(0x3A)
+#define BMA423_SINGLE_TAP_OFFSET UINT8_C(0x3C)
+#define BMA423_DOUBLE_TAP_OFFSET UINT8_C(0x3E)
+#define BMA423_WRIST_WEAR_OFFSET UINT8_C(0x40)
+#define BMA423_CONFIG_ID_OFFSET UINT8_C(0x42)
+#define BMA423_AXES_REMAP_OFFSET UINT8_C(0x44)
+
+/**\name Read/Write Lengths */
+#define BMA423_RD_WR_MIN_LEN UINT8_C(2)
+#define BMA423_NO_MOT_RD_WR_LEN (BMA423_ANY_MOT_LEN + BMA423_NO_MOT_OFFSET)
+
+/*! @name Mask definitions for major and minor config */
+#define BMA423_CONFIG_MAJOR_MSK UINT16_C(0X3C0)
+#define BMA423_CONFIG_MINOR_MSK UINT8_C(0X1F)
+
+/*! @name Bit position for major config */
+#define BMA423_CONFIG_MAJOR_POS UINT8_C(0X06)
+
+/**************************************************************/
+/**\name Re-map Axes */
+/**************************************************************/
+#define BMA423_X_AXIS_MASK UINT8_C(0x03)
+#define BMA423_X_AXIS_SIGN_MASK UINT8_C(0x04)
+#define BMA423_Y_AXIS_MASK UINT8_C(0x18)
+#define BMA423_Y_AXIS_SIGN_MASK UINT8_C(0x20)
+#define BMA423_Z_AXIS_MASK UINT8_C(0xC0)
+#define BMA423_Z_AXIS_SIGN_MASK UINT8_C(0x01)
+
+/**************************************************************/
+/**\name Step Counter/Detector/Activity */
+/**************************************************************/
+/**\name Step counter/activity enable macros */
+#define BMA423_STEP_CNTR_EN_MSK UINT8_C(0x10)
+#define BMA423_STEP_ACT_EN_MSK UINT8_C(0x20)
+
+/**\name Step counter water-mark macros */
+#define BMA423_STEP_CNTR_WM_MSK UINT16_C(0x03FF)
+
+/**\name Step counter reset macros */
+#define BMA423_STEP_CNTR_RST_POS UINT8_C(2)
+#define BMA423_STEP_CNTR_RST_MSK UINT8_C(0x04)
+
+/**\name Step detector enable macros */
+#define BMA423_STEP_DETECTOR_EN_POS UINT8_C(3)
+#define BMA423_STEP_DETECTOR_EN_MSK UINT8_C(0x08)
+
+/**\name Wrist-wear enable macros */
+#define BMA423_WRIST_WEAR_EN_MSK UINT8_C(0x01)
+
+/**\name Step count output length*/
+#define BMA423_STEP_CNTR_DATA_SIZE UINT16_C(4)
+
+/**\name single tap enable macros */
+#define BMA423_SINGLE_TAP_EN_MSK UINT8_C(0x01)
+
+/**\name double tap enable macros */
+#define BMA423_DOUBLE_TAP_EN_MSK UINT8_C(0x01)
+
+/**\name tap sensitivity macros */
+#define BMA423_TAP_SENS_POS UINT8_C(1)
+#define BMA423_TAP_SENS_MSK UINT8_C(0x0E)
+
+/**\name Tap selection macro */
+#define BMA423_TAP_SEL_POS UINT8_C(4)
+#define BMA423_TAP_SEL_MSK UINT8_C(0x10)
+
+/**************************************************************/
+/**\name Any/no Motion */
+/**************************************************************/
+/**\name Any/No motion threshold macros */
+#define BMA423_ANY_NO_MOT_THRES_MSK UINT16_C(0x07FF)
+
+/**\name Any/No motion duration macros */
+#define BMA423_ANY_NO_MOT_DUR_MSK UINT16_C(0x1FFF)
+
+/**\name Any/No motion enable macros */
+#define BMA423_ANY_NO_MOT_AXIS_EN_POS UINT8_C(0x0D)
+#define BMA423_ANY_NO_MOT_AXIS_EN_MSK UINT16_C(0xE000)
+
+/**************************************************************/
+/**\name User macros */
+/**************************************************************/
+/**\name Any-motion/No-motion axis enable macros */
+#define BMA423_X_AXIS_EN UINT8_C(0x01)
+#define BMA423_Y_AXIS_EN UINT8_C(0x02)
+#define BMA423_Z_AXIS_EN UINT8_C(0x04)
+#define BMA423_EN_ALL_AXIS UINT8_C(0x07)
+#define BMA423_DIS_ALL_AXIS UINT8_C(0x00)
+
+/**\name Feature enable macros for the sensor */
+#define BMA423_STEP_CNTR UINT8_C(0x01)
+#define BMA423_STEP_ACT UINT8_C(0x02)
+#define BMA423_WRIST_WEAR UINT8_C(0x04)
+#define BMA423_SINGLE_TAP UINT8_C(0x08)
+#define BMA423_DOUBLE_TAP UINT8_C(0x10)
+
+/**\name Interrupt status macros */
+#define BMA423_SINGLE_TAP_INT UINT8_C(0x01)
+#define BMA423_STEP_CNTR_INT UINT8_C(0x02)
+#define BMA423_ACTIVITY_INT UINT8_C(0x04)
+#define BMA423_WRIST_WEAR_INT UINT8_C(0x08)
+#define BMA423_DOUBLE_TAP_INT UINT8_C(0x10)
+#define BMA423_ANY_MOT_INT UINT8_C(0x20)
+#define BMA423_NO_MOT_INT UINT8_C(0x40)
+#define BMA423_ERROR_INT UINT8_C(0x80)
+
+/**\name Activity recognition macros */
+#define BMA423_USER_STATIONARY UINT8_C(0x00)
+#define BMA423_USER_WALKING UINT8_C(0x01)
+#define BMA423_USER_RUNNING UINT8_C(0x02)
+#define BMA423_STATE_INVALID UINT8_C(0x03)
+
+/******************************************************************************/
+/*! @name Structure Declarations */
+/******************************************************************************/
+
+/*!
+ * @brief Any/No motion configuration
+ */
+struct bma423_any_no_mot_config
+{
+ /*! Expressed in 50 Hz samples (20 ms) */
+ uint16_t duration;
+
+ /*! Threshold value for Any-motion/No-motion detection in
+ * 5.11g format
+ */
+ uint16_t threshold;
+
+ /*! To enable selected axes */
+ uint8_t axes_en;
+};
+
+/*!
+ * @brief Axes re-mapping configuration
+ */
+struct bma423_axes_remap
+{
+ /*! Re-mapped x-axis */
+ uint8_t x_axis;
+
+ /*! Re-mapped y-axis */
+ uint8_t y_axis;
+
+ /*! Re-mapped z-axis */
+ uint8_t z_axis;
+
+ /*! Re-mapped x-axis sign */
+ uint8_t x_axis_sign;
+
+ /*! Re-mapped y-axis sign */
+ uint8_t y_axis_sign;
+
+ /*! Re-mapped z-axis sign */
+ uint8_t z_axis_sign;
+};
+
+/*!
+ * @brief Step counter param settings
+ */
+struct bma423_stepcounter_settings
+{
+ /*! Step Counter param 1 */
+ uint16_t param1;
+
+ /*! Step Counter param 2 */
+ uint16_t param2;
+
+ /*! Step Counter param 3 */
+ uint16_t param3;
+
+ /*! Step Counter param 4 */
+ uint16_t param4;
+
+ /*! Step Counter param 5 */
+ uint16_t param5;
+
+ /*! Step Counter param 6 */
+ uint16_t param6;
+
+ /*! Step Counter param 7 */
+ uint16_t param7;
+
+ /*! Step Counter param 8 */
+ uint16_t param8;
+
+ /*! Step Counter param 9 */
+ uint16_t param9;
+
+ /*! Step Counter param 10 */
+ uint16_t param10;
+
+ /*! Step Counter param 11 */
+ uint16_t param11;
+
+ /*! Step Counter param 12 */
+ uint16_t param12;
+
+ /*! Step Counter param 13 */
+ uint16_t param13;
+
+ /*! Step Counter param 14 */
+ uint16_t param14;
+
+ /*! Step Counter param 15 */
+ uint16_t param15;
+
+ /*! Step Counter param 16 */
+ uint16_t param16;
+
+ /*! Step Counter param 17 */
+ uint16_t param17;
+
+ /*! Step Counter param 18 */
+ uint16_t param18;
+
+ /*! Step Counter param 19 */
+ uint16_t param19;
+
+ /*! Step Counter param 20 */
+ uint16_t param20;
+
+ /*! Step Counter param 21 */
+ uint16_t param21;
+
+ /*! Step Counter param 22 */
+ uint16_t param22;
+
+ /*! Step Counter param 23 */
+ uint16_t param23;
+
+ /*! Step Counter param 24 */
+ uint16_t param24;
+
+ /*! Step Counter param 25 */
+ uint16_t param25;
+};
+
+/***************************************************************************/
+
+/*! BMA423 User Interface function prototypes
+ ****************************************************************************/
+
+/**
+ * \ingroup bma423
+ * \defgroup bma423ApiInit Initialization
+ * @brief Initialize the sensor and device structure
+ */
+
+/*!
+ * \ingroup bma423ApiInit
+ * \page bma423_api_bma423_init bma423_init
+ * \code
+ * int8_t bma423_init(struct bma4_dev *dev);
+ * \endcode
+ * @details This API is the entry point.
+ * Call this API before using all other APIs.
+ * This API reads the chip-id of the sensor and sets the resolution.
+ *
+ * @param[in,out] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_init(struct bma4_dev *dev);
+
+/**
+ * \ingroup bma423
+ * \defgroup bma423ApiConfig ConfigFile
+ * @brief Write binary configuration in the sensor
+ */
+
+/*!
+ * \ingroup bma423ApiConfig
+ * \page bma423_api_bma423_write_config_file bma423_write_config_file
+ * \code
+ * int8_t bma423_write_config_file(struct bma4_dev *dev);
+ * \endcode
+ * @details This API is used to upload the config file to enable the features of
+ * the sensor.
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_write_config_file(struct bma4_dev *dev);
+
+/**
+ * \ingroup bma423
+ * \defgroup bma423ApiConfigId ConfigId
+ * @brief Get Configuration ID of the sensor
+ */
+
+/*!
+ * \ingroup bma423ApiConfig
+ * \page bma423_api_bma423_get_config_id bma423_get_config_id
+ * \code
+ * int8_t bma423_get_config_id(uint16_t *config_id, struct bma4_dev *dev);
+ * \endcode
+ * @details This API is used to get the configuration id of the sensor.
+ *
+ * @param[out] config_id : Pointer variable used to store the configuration id.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_get_config_id(uint16_t *config_id, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma423
+ * \defgroup bma423ApiMapInt Map / Unmap Interrupt
+ * @brief Map / Unmap user provided interrupt to interrupt pin1 or pin2 of the sensor
+ */
+
+/*!
+ * \ingroup bma423ApiMapInt
+ * \page bma423_api_bma423_map_interrupt bma423_map_interrupt
+ * \code
+ * int8_t bma423_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets/unsets the user provided interrupt to either
+ * interrupt pin1 or pin2 in the sensor.
+ *
+ * @param[in] int_line: Variable to select either interrupt pin1 or pin2.
+ *
+ *@verbatim
+ * int_line | Macros
+ * ------------|-------------------
+ * 0x00 | BMA4_INTR1_MAP
+ * 0x01 | BMA4_INTR2_MAP
+ *@endverbatim
+ *
+ * @param[in] int_map : Variable to specify the interrupts.
+ * @param[in] enable : Variable to specify mapping or unmapping of interrupts.
+ *
+ *@verbatim
+ * enable | Macros
+ * --------|-------------------
+ * 0x00 | BMA4_DISABLE
+ * 0x01 | BMA4_ENABLE
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @note Below macros specify the interrupts.
+ *
+ * Feature Interrupts
+ * - BMA423_STEP_CNTR_INT
+ * - BMA423_ACTIVITY_INT
+ * - BMA423_WRIST_WEAR_INT
+ * - BMA423_WAKEUP_INT
+ * - BMA423_ANY_MOT_INT
+ * - BMA423_NO_MOT_INT
+ * - BMA423_ERROR_INT
+ *
+ * Hardware Interrupts
+ * - BMA4_FIFO_FULL_INT
+ * - BMA4_FIFO_WM_INT
+ * - BMA4_DATA_RDY_INT
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma423
+ * \defgroup bma423ApiIntS Interrupt Status
+ * @brief Read interrupt status of the sensor
+ */
+
+/*!
+ * \ingroup bma423ApiIntS
+ * \page bma423_api_bma423_read_int_status bma423_read_int_status
+ * \code
+ * int8_t bma423_read_int_status(uint16_t *int_status, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the bma423 interrupt status from the sensor.
+ *
+ * @param[out] int_status : Variable to store the interrupt status read from
+ * the sensor.
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @note Below macros are used to check the interrupt status.
+ *
+ * Feature Interrupts
+ * - BMA423_STEP_CNTR_INT
+ * - BMA423_ACTIVITY_INT
+ * - BMA423_WRIST_WEAR_INT
+ * - BMA423_WAKEUP_INT
+ * - BMA423_ANY_MOT_INT
+ * - BMA423_NO_MOT_INT
+ * - BMA423_ERROR_INT
+ *
+ * Hardware Interrupts
+ * - BMA4_FIFO_FULL_INT
+ * - BMA4_FIFO_WM_INT
+ * - BMA4_DATA_RDY_INT
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_read_int_status(uint16_t *int_status, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma423
+ * \defgroup bma423ApiFeat Sensor Feature
+ * @brief Enables / Disables features of the sensor
+ */
+
+/*!
+ * \ingroup bma423ApiFeat
+ * \page bma423_api_bma423_feature_enable bma423_feature_enable
+ * \code
+ * int8_t bma423_feature_enable(uint8_t feature, uint8_t enable, struct bma4_dev *dev);
+ * \endcode
+ * @details This API enables/disables the features of the sensor.
+ *
+ * @param[in] feature : Variable to specify the features which are to be set in
+ * bma423 sensor.
+ * @param[in] enable : Variable which specifies whether to enable or disable the
+ * features in the bma456 sensor.
+ *
+ *@verbatim
+ * enable | Macros
+ * --------|-------------------
+ * 0x00 | BMA4_DISABLE
+ * 0x01 | BMA4_ENABLE
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @note User should use the below macros to enable or disable the
+ * features of bma423 sensor
+ *
+ * - BMA423_STEP_CNTR
+ * - BMA423_ACTIVITY
+ * - BMA423_WAKEUP
+ * - BMA423_WRIST_WEAR
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_feature_enable(uint8_t feature, uint8_t enable, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma423
+ * \defgroup bma423ApiRemap Remap Axes
+ * @brief Set / Get x, y and z axis re-mapping in the sensor
+ */
+
+/*!
+ * \ingroup bma423ApiRemap
+ * \page bma423_api_bma423_set_remap_axes bma423_set_remap_axes
+ * \code
+ * int8_t bma423_set_remap_axes(const struct bma423_axes_remap *remap_data, struct bma4_dev *dev);
+ * \endcode
+ * @details This API performs x, y and z axis remapping in the sensor.
+ *
+ * @param[in] remap_data : Pointer to store axes remapping data.
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_set_remap_axes(const struct bma423_axes_remap *remap_data, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma423ApiRemap
+ * \page bma423_api_bma423_get_remap_axes bma423_get_remap_axes
+ * \code
+ * int8_t bma423_get_remap_axes(struct bma423_axes_remap *remap_data, struct bma4_dev *dev);
+ * \endcode
+ * @details This API reads the x, y and z axis remap data from the sensor.
+ *
+ * @param[out] remap_data : Pointer to store axis remap data which is read
+ * from the bma423 sensor.
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_get_remap_axes(struct bma423_axes_remap *remap_data, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma423
+ * \defgroup bma423ApiStepC Step counter
+ * @brief Operations of step counter feature of the sensor
+ */
+
+/*!
+ * \ingroup bma423ApiStepC
+ * \page bma423_api_bma423_step_counter_set_watermark bma423_step_counter_set_watermark
+ * \code
+ * int8_t bma423_step_counter_set_watermark(uint16_t step_counter_wm, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the watermark level for step counter interrupt in
+ * the sensor.
+ *
+ * @param[in] step_counter_wm : Variable which specifies watermark level
+ * count
+ * @note Valid values are from 1 to 1023
+ * @note Value 0 is used for step detector interrupt
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_step_counter_set_watermark(uint16_t step_counter_wm, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma423ApiStepC
+ * \page bma423_api_bma423_step_counter_get_watermark bma423_step_counter_get_watermark
+ * \code
+ * int8_t bma423_step_counter_get_watermark(uint16_t *step_counter_wm, struct bma4_dev *dev);
+ * \endcode
+ * @details This API gets the water mark level set for step counter interrupt
+ * in the sensor
+ *
+ * @param[out] step_counter_wm : Pointer variable which stores the water mark
+ * level read from the sensor.
+ * @note valid values are from 1 to 1023
+ * @note value 0 is used for step detector interrupt
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_step_counter_get_watermark(uint16_t *step_counter_wm, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma423ApiStepC
+ * \page bma423_api_bma423_reset_step_counter bma423_reset_step_counter
+ * \code
+ * int8_t bma423_reset_step_counter(struct bma4_dev *dev);
+ * \endcode
+ * @details This API resets the counted steps of step counter.
+ *
+ * @param[in] dev : structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_reset_step_counter(struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma423ApiStepC
+ * \page bma423_api_bma423_step_counter_output bma423_step_counter_output
+ * \code
+ * int8_t bma423_step_counter_output(uint32_t *step_count, struct bma4_dev *dev);
+ * \endcode
+ * @details This API gets the number of counted steps of the step counter
+ * feature from the sensor.
+ *
+ * @param[out] step_count : Pointer variable which stores counted steps
+ * read from the sensor.
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_step_counter_output(uint32_t *step_count, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma423
+ * \defgroup bma423ApiAct Activity Feature
+ * @brief Get output for activity feature of the sensor
+ */
+
+/*!
+ * \ingroup bma423ApiAct
+ * \page bma423_api_bma423_activity_output bma423_activity_output
+ * \code
+ * int8_t bma423_activity_output(uint8_t *activity, struct bma4_dev *dev);
+ * \endcode
+ * @details This API gets the output for activity feature.
+ *
+ * @param[out] activity : Pointer variable which stores activity output read
+ * from the sensor.
+ *
+ *@verbatim
+ * activity | State
+ * --------------|------------------------
+ * 0x00 | BMA423_USER_STATIONARY
+ * 0x01 | BMA423_USER_WALKING
+ * 0x02 | BMA423_USER_RUNNING
+ * 0x03 | BMA423_STATE_INVALID
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_activity_output(uint8_t *activity, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma423ApiStepC
+ * \page bma423_api_bma423_stepcounter_get_parameter bma423_stepcounter_get_parameter
+ * \code
+ * int8_t bma423_stepcounter_get_parameter(struct bma423_stepcounter_settings *setting, struct bma4_dev *dev);
+ * \endcode
+ * @details This API gets the parameter1 to parameter7 settings of the step
+ * counter feature.
+ *
+ * @param[out] setting : Pointer to structure variable which stores the
+ * parameter1 to parameter7 read from the sensor.
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_stepcounter_get_parameter(struct bma423_stepcounter_settings *setting, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma423ApiStepC
+ * \page bma423_api_bma423_stepcounter_set_parameter bma423_stepcounter_set_parameter
+ * \code
+ * int8_t bma423_stepcounter_set_parameter(const struct bma423_stepcounter_settings *setting, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the parameter1 to parameter7 settings of the step
+ * counter feature in the sensor.
+ *
+ * @param[in] setting : Pointer to structure variable which stores the
+ * parameter1 to parameter7 settings read from the sensor.
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_stepcounter_set_parameter(const struct bma423_stepcounter_settings *setting, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma421
+ * \defgroup bma421ApiStepD Step detector
+ * @brief Operations of step detector feature of the sensor
+ */
+
+/*!
+ * \ingroup bma421ApiStepD
+ * \page bma421_api_bma421_step_detector_enable bma421_step_detector_enable
+ * \code
+ * int8_t bma421_step_detector_enable(uint8_t enable, struct bma4_dev *dev);
+ * \endcode
+ * @details This API enables or disables the step detector feature in the
+ * sensor.
+ *
+ * @param[in] enable : Variable used to enable or disable step detector
+ *
+ *@verbatim
+ * enable | Macros
+ * --------|-------------------
+ * 0x00 | BMA4_DISABLE
+ * 0x01 | BMA4_ENABLE
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_step_detector_enable(uint8_t enable, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma423
+ * \defgroup bma423ApiAnyMot Any motion Feature
+ * @brief Functions of Any motion feature of the sensor
+ */
+
+/*!
+ * \ingroup bma423ApiAnyMot
+ * \page bma423_api_bma423_set_any_motion_config bma423_set_any_motion_config
+ * \code
+ * int8_t bma423_set_any_motion_config(const struct bma423_anymotion_config *any_motion, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the configuration of any-motion feature in the sensor
+ * This API enables/disables the any-motion feature according to the axis set.
+ *
+ * @param[in] any_mot : Pointer to structure variable to configure
+ * any-motion.
+ *
+ * @verbatim
+ * -------------------------------------------------------------------------
+ * Structure parameters | Description
+ * --------------------------------|----------------------------------------
+ * | Defines the number of
+ * | consecutive data points for
+ * | which the threshold condition
+ * duration | must be respected, for interrupt
+ * | assertion. It is expressed in
+ * | 50 Hz samples (20 ms).
+ * | Range is 0 to 163sec.
+ * | Default value is 5 = 100ms.
+ * --------------------------------|----------------------------------------
+ * | Slope threshold value for
+ * | Any-motion detection
+ * threshold | in 5.11g format.
+ * | Range is 0 to 1g.
+ * | Default value is 0xAA = 83mg.
+ * --------------------------------|----------------------------------------
+ * | Enables the feature on a per-axis
+ * axis_en | basis.
+ * ---------------------------------------------------------------------------
+ * @endverbatim
+ *
+ *@verbatim
+ * Value | axis_en
+ * ---------|-------------------------
+ * 0x00 | BMA423_DIS_ALL_AXIS
+ * 0x01 | BMA423_X_AXIS_EN
+ * 0x02 | BMA423_Y_AXIS_EN
+ * 0x04 | BMA423_Z_AXIS_EN
+ * 0x07 | BMA423_EN_ALL_AXIS
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_set_any_mot_config(const struct bma423_any_no_mot_config *any_mot, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma423ApiAnyMot
+ * \page bma423_api_bma423_get_any_motion_config bma423_get_any_motion_config
+ * \code
+ * int8_t bma423_get_any_motion_config(struct bma423_anymotion_config *any_motion, struct bma4_dev *dev);
+ * \endcode
+ * @details This API gets the configuration of any-motion feature from the
+ * sensor.
+ *
+ * @param[out] any_mot : Pointer to structure variable to configure
+ * any-motion.
+ *
+ * @verbatim
+ * -------------------------------------------------------------------------
+ * Structure parameters | Description
+ * --------------------------------|----------------------------------------
+ * | Defines the number of
+ * | consecutive data points for
+ * | which the threshold condition
+ * duration | must be respected, for interrupt
+ * | assertion. It is expressed in
+ * | 50 Hz samples (20 ms).
+ * | Range is 0 to 163sec.
+ * | Default value is 5 = 100ms.
+ * --------------------------------|----------------------------------------
+ * | Slope threshold value for
+ * | Any-motion detection
+ * threshold | in 5.11g format.
+ * | Range is 0 to 1g.
+ * | Default value is 0xAA = 83mg.
+ * --------------------------------|-----------------------------------------
+ * | Enables the feature on a per-axis
+ * axis_en | basis.
+ * ---------------------------------------------------------------------------
+ * @endverbatim
+ *
+ *@verbatim
+ * Value | axis_en
+ * ---------|-------------------------
+ * 0x00 | BMA423_DIS_ALL_AXIS
+ * 0x01 | BMA423_X_AXIS_EN
+ * 0x02 | BMA423_Y_AXIS_EN
+ * 0x04 | BMA423_Z_AXIS_EN
+ * 0x07 | BMA423_EN_ALL_AXIS
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_get_any_mot_config(struct bma423_any_no_mot_config *any_mot, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma423
+ * \defgroup bma423ApiNomot No-Motion Feature
+ * @brief Operations of no-motion feature of the sensor
+ */
+
+/*!
+ * \ingroup bma423ApiNomot
+ * \page bma423_api_bma423_set_no_motion_config bma423_set_no_motion_config
+ * \code
+ * int8_t bma423_set_no_motion_config(const struct bma423_nomotion_config *no_motion, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the configuration of no-motion feature in the sensor
+ * This API enables/disables the no-motion feature according to the axis set.
+ *
+ * @param[in] no_mot : Pointer to structure variable to configure
+ * no-motion.
+ *
+ * @verbatim
+ * -------------------------------------------------------------------------
+ * Structure parameters | Description
+ * --------------------------------|----------------------------------------
+ * | Defines the number of
+ * | consecutive data points for
+ * | which the threshold condition
+ * duration | must be respected, for interrupt
+ * | assertion. It is expressed in
+ * | 50 Hz samples (20 ms).
+ * | Range is 0 to 163sec.
+ * | Default value is 5 = 100ms.
+ * --------------------------------|----------------------------------------
+ * | Slope threshold value for
+ * | No-motion detection
+ * threshold | in 5.11g format.
+ * | Range is 0 to 1g.
+ * | Default value is 0xAA = 83mg.
+ * --------------------------------|----------------------------------------
+ * | Enables the feature on a per-axis
+ * axis_en | basis.
+ * ---------------------------------------------------------------------------
+ * @endverbatim
+ *
+ *@verbatim
+ * Value | axis_en
+ * ---------|-------------------------
+ * 0x00 | BMA423_DIS_ALL_AXIS
+ * 0x01 | BMA423_X_AXIS_EN
+ * 0x02 | BMA423_Y_AXIS_EN
+ * 0x04 | BMA423_Z_AXIS_EN
+ * 0x07 | BMA423_EN_ALL_AXIS
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_set_no_mot_config(const struct bma423_any_no_mot_config *no_mot, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma423ApiNomot
+ * \page bma423_api_bma423_get_no_motion_config bma423_get_no_motion_config
+ * \code
+ * int8_t bma423_get_no_motion_config(struct bma423_nomotion_config *no_motion, struct bma4_dev *dev);
+ * \endcode
+ * @details This API gets the configuration of no-motion feature from the
+ * sensor.
+ *
+ * @param[out] no_mot : Pointer to structure variable to configure
+ * no-motion.
+ *
+ * @verbatim
+ * -------------------------------------------------------------------------
+ * Structure parameters | Description
+ * --------------------------------|----------------------------------------
+ * | Defines the number of
+ * | consecutive data points for
+ * | which the threshold condition
+ * duration | must be respected, for interrupt
+ * | assertion. It is expressed in
+ * | 50 Hz samples (20 ms).
+ * | Range is 0 to 163sec.
+ * | Default value is 5 = 100ms.
+ * --------------------------------|----------------------------------------
+ * | Slope threshold value for
+ * | No-motion detection
+ * threshold | in 5.11g format.
+ * | Range is 0 to 1g.
+ * | Default value is 0xAA = 83mg.
+ * --------------------------------|-----------------------------------------
+ * | Enables the feature on a per-axis
+ * axis_en | basis.
+ * ---------------------------------------------------------------------------
+ * @endverbatim
+ *
+ *@verbatim
+ * Value | axis_en
+ * ---------|-------------------------
+ * 0x00 | BMA423_DIS_ALL_AXIS
+ * 0x01 | BMA423_X_AXIS_EN
+ * 0x02 | BMA423_Y_AXIS_EN
+ * 0x04 | BMA423_Z_AXIS_EN
+ * 0x07 | BMA423_EN_ALL_AXIS
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_get_no_mot_config(struct bma423_any_no_mot_config *no_mot, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma423
+ * \defgroup bma423ApiTap Single Tap and Double tap
+ * @brief Single and Double tap feature operations
+ */
+
+/*!
+ * \ingroup bma423ApiTap
+ * \page bma423_api_bma423_single_tap_set_sensitivity bma423_single_tap_set_sensitivity
+ * \code
+ * int8_t bma423_single_tap_set_sensitivity(uint8_t sensitivity, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the sensitivity of single tap wake-up feature in the sensor
+ *
+ * @param[in] sensitivity : Variable used to specify the sensitivity of the
+ * Wake up feature.
+ *
+ *@verbatim
+ * Value | Sensitivity
+ * --------|-------------------------
+ * 0x00 | MOST SENSITIVE
+ * 0x07 | LEAST SENSITIVE
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_single_tap_set_sensitivity(uint8_t sensitivity, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma423ApiTap
+ * \page bma423_api_bma423_double_tap_set_sensitivity bma423_double_tap_set_sensitivity
+ * \code
+ * int8_t bma423_double_tap_set_sensitivity(uint8_t sensitivity, struct bma4_dev *dev);
+ * \endcode
+ * @details This API sets the sensitivity of double tap wake-up feature in the sensor
+ *
+ * @param[in] sensitivity : Variable used to specify the sensitivity of the
+ * Wake up feature.
+ *
+ *@verbatim
+ * Value | Sensitivity
+ * --------|-------------------------
+ * 0x00 | MOST SENSITIVE
+ * 0x07 | LEAST SENSITIVE
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_double_tap_set_sensitivity(uint8_t sensitivity, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma423ApiTap
+ * \page bma423_api_bma423_single_tap_get_sensitivity bma423_single_tap_get_sensitivity
+ * \code
+ * int8_t bma423_single_tap_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *dev);
+ * \endcode
+ * @details This API gets the sensitivity of single tap wake up feature in the sensor
+ *
+ * @param[out] sensitivity : Pointer variable which stores the sensitivity
+ * value read from the sensor.
+ *
+ * @verbatim
+ * Value | Sensitivity
+ * --------|-------------------------
+ * 0x00 | MOST SENSITIVE
+ * 0x07 | LEAST SENSITIVE
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_single_tap_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *dev);
+
+/*!
+ * \ingroup bma423ApiTap
+ * \page bma423_api_bma423_double_tap_get_sensitivity bma423_double_tap_get_sensitivity
+ * \code
+ * int8_t bma423_double_tap_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *dev);
+ * \endcode
+ * @details This API gets the sensitivity of double tap wake up feature in the sensor
+ *
+ * @param[out] sensitivity : Pointer variable which stores the sensitivity
+ * value read from the sensor.
+ *
+ *@verbatim
+ * Value | Sensitivity
+ * --------|-------------------------
+ * 0x00 | MOST SENSITIVE
+ * 0x07 | LEAST SENSITIVE
+ *@endverbatim
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval < 0 -> Fail
+ */
+int8_t bma423_double_tap_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *dev);
+
+/**
+ * \ingroup bma423
+ * \defgroup bma423ApiVersionConfig Version Config
+ * @brief Get version configuration of the sensor
+ */
+
+/*!
+ * \ingroup bma423ApiVersionConfig
+ * \page bma423_api_bma422_huawei_get_version_config bma423_get_version_config
+ * \code
+ * int8_t bma423_get_version_config(uint16_t *config_major, uint16_t *config_minor, struct bma4_dev *dev);
+ * \endcode
+ * @details This API is used to get the config file major and minor information.
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ * @param[out] config_major : Pointer to data buffer to store the config major.
+ * @param[out] config_minor : Pointer to data buffer to store the config minor.
+ *
+ * @retval BMA4_OK - Success.
+ * @retval BMA4_E_NULL_PTR - Error: Null pointer error
+ */
+int8_t bma423_get_version_config(uint16_t *config_major, uint16_t *config_minor, struct bma4_dev *dev);
+
+#ifdef __cplusplus
+}
+#endif /*End of CPP guard */
+
+#endif /*End of header guard macro */
diff --git a/src/drivers/Bma421_C/bma4_defs.h b/src/drivers/Bma421_C/bma4_defs.h
new file mode 100644
index 00000000..2db99c00
--- /dev/null
+++ b/src/drivers/Bma421_C/bma4_defs.h
@@ -0,0 +1,1144 @@
+/**
+ * Copyright (c) 2020 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 bma4_defs.h
+ * @date 2020-05-08
+ * @version V2.14.13
+ *
+ */
+
+/*! \file bma4_defs.h
+ * \brief Sensor Driver for BMA4 family of sensors
+ */
+#ifndef BMA4_DEFS_H__
+#define BMA4_DEFS_H__
+
+/*********************************************************************/
+/**\ header files */
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#include <stddef.h>
+#include <math.h>
+#endif
+
+/*********************************************************************/
+/* macro definitions */
+
+#ifdef __KERNEL__
+
+#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
+
+#else /* __KERNEL__ */
+
+#if (!defined(UINT8_C) && !defined(INT8_C))
+#define INT8_C(x) (x)
+#define UINT8_C(x) (x##U)
+#endif
+
+#if (!defined(UINT16_C) && !defined(INT16_C))
+#define INT16_C(x) (x)
+#define UINT16_C(x) (x##U)
+#endif
+
+#if (!defined(INT32_C) && !defined(UINT32_C))
+#define INT32_C(x) (x)
+#define UINT32_C(x) (x##U)
+#endif
+
+#if (!defined(INT64_C) && !defined(UINT64_C))
+#define INT64_C(x) (x##LL)
+#define UINT64_C(x) (x##ULL)
+#endif
+
+#endif /* __KERNEL__ */
+
+/**\name CHIP ID ADDRESS*/
+#define BMA4_CHIP_ID_ADDR UINT8_C(0x00)
+
+/**\name ERROR STATUS*/
+#define BMA4_ERROR_ADDR UINT8_C(0X02)
+
+/**\name STATUS REGISTER FOR SENSOR STATUS FLAG*/
+#define BMA4_STATUS_ADDR UINT8_C(0X03)
+
+/**\name AUX/ACCEL DATA BASE ADDRESS REGISTERS*/
+#define BMA4_DATA_0_ADDR UINT8_C(0X0A)
+#define BMA4_DATA_8_ADDR UINT8_C(0X12)
+
+/**\name SENSOR TIME REGISTERS*/
+#define BMA4_SENSORTIME_0_ADDR UINT8_C(0X18)
+
+/**\name INTERRUPT/FEATURE STATUS REGISTERS*/
+#define BMA4_INT_STAT_0_ADDR UINT8_C(0X1C)
+
+/**\name INTERRUPT/FEATURE STATUS REGISTERS*/
+#define BMA4_INT_STAT_1_ADDR UINT8_C(0X1D)
+
+/**\name TEMPERATURE REGISTERS*/
+#define BMA4_TEMPERATURE_ADDR UINT8_C(0X22)
+
+/**\name FIFO REGISTERS*/
+#define BMA4_FIFO_LENGTH_0_ADDR UINT8_C(0X24)
+#define BMA4_FIFO_DATA_ADDR UINT8_C(0X26)
+
+/**\name ACCEL CONFIG REGISTERS*/
+#define BMA4_ACCEL_CONFIG_ADDR UINT8_C(0X40)
+
+/**\name ACCEL RANGE ADDRESS*/
+#define BMA4_ACCEL_RANGE_ADDR UINT8_C(0X41)
+
+/**\name AUX CONFIG REGISTERS*/
+#define BMA4_AUX_CONFIG_ADDR UINT8_C(0X44)
+
+/**\name FIFO DOWN SAMPLING REGISTER ADDRESS FOR ACCEL*/
+#define BMA4_FIFO_DOWN_ADDR UINT8_C(0X45)
+
+/**\name FIFO WATERMARK REGISTER ADDRESS*/
+#define BMA4_FIFO_WTM_0_ADDR UINT8_C(0X46)
+
+/**\name FIFO CONFIG REGISTERS*/
+#define BMA4_FIFO_CONFIG_0_ADDR UINT8_C(0X48)
+#define BMA4_FIFO_CONFIG_1_ADDR UINT8_C(0X49)
+
+/**\name MAG INTERFACE REGISTERS*/
+#define BMA4_AUX_DEV_ID_ADDR UINT8_C(0X4B)
+#define BMA4_AUX_IF_CONF_ADDR UINT8_C(0X4C)
+#define BMA4_AUX_RD_ADDR UINT8_C(0X4D)
+#define BMA4_AUX_WR_ADDR UINT8_C(0X4E)
+#define BMA4_AUX_WR_DATA_ADDR UINT8_C(0X4F)
+
+/**\name INTERRUPT ENABLE REGISTERS*/
+#define BMA4_INT1_IO_CTRL_ADDR UINT8_C(0X53)
+#define BMA4_INT2_IO_CTRL_ADDR UINT8_C(0X54)
+
+/**\name LATCH DURATION REGISTERS*/
+#define BMA4_INTR_LATCH_ADDR UINT8_C(0X55)
+
+/**\name MAP INTERRUPT 1 and 2 REGISTERS*/
+#define BMA4_INT_MAP_1_ADDR UINT8_C(0X56)
+#define BMA4_INT_MAP_2_ADDR UINT8_C(0X57)
+#define BMA4_INT_MAP_DATA_ADDR UINT8_C(0x58)
+#define BMA4_INIT_CTRL_ADDR UINT8_C(0x59)
+
+/**\name FEATURE CONFIG RELATED */
+#define BMA4_RESERVED_REG_5B_ADDR UINT8_C(0x5B)
+#define BMA4_RESERVED_REG_5C_ADDR UINT8_C(0x5C)
+#define BMA4_FEATURE_CONFIG_ADDR UINT8_C(0x5E)
+#define BMA4_INTERNAL_ERROR UINT8_C(0x5F)
+
+/**\name SERIAL INTERFACE SETTINGS REGISTER*/
+#define BMA4_IF_CONFIG_ADDR UINT8_C(0X6B)
+
+/**\name SELF_TEST REGISTER*/
+#define BMA4_ACC_SELF_TEST_ADDR UINT8_C(0X6D)
+
+/**\name Macro to define accelerometer configuration value for FOC */
+#define BMA4_FOC_ACC_CONF_VAL UINT8_C(0xB7)
+
+/**\name SPI,I2C SELECTION REGISTER*/
+#define BMA4_NV_CONFIG_ADDR UINT8_C(0x70)
+
+/**\name ACCEL OFFSET REGISTERS*/
+#define BMA4_OFFSET_0_ADDR UINT8_C(0X71)
+#define BMA4_OFFSET_1_ADDR UINT8_C(0X72)
+#define BMA4_OFFSET_2_ADDR UINT8_C(0X73)
+
+/**\name POWER_CTRL REGISTER*/
+#define BMA4_POWER_CONF_ADDR UINT8_C(0x7C)
+#define BMA4_POWER_CTRL_ADDR UINT8_C(0x7D)
+
+/**\name COMMAND REGISTER*/
+#define BMA4_CMD_ADDR UINT8_C(0X7E)
+
+/**\name GPIO REGISTERS*/
+#define BMA4_STEP_CNT_OUT_0_ADDR UINT8_C(0x1E)
+#define BMA4_HIGH_G_OUT_ADDR UINT8_C(0x1F)
+#define BMA4_ACTIVITY_OUT_ADDR UINT8_C(0x27)
+#define BMA4_ORIENTATION_OUT_ADDR UINT8_C(0x28)
+#define BMA4_INTERNAL_STAT UINT8_C(0x2A)
+
+/*!
+ * @brief Block size for config write
+ */
+#define BMA4_BLOCK_SIZE UINT8_C(32)
+
+/**\name I2C slave address */
+#define BMA4_I2C_ADDR_PRIMARY UINT8_C(0x18)
+#define BMA4_I2C_ADDR_SECONDARY UINT8_C(0x19)
+#define BMA4_I2C_BMM150_ADDR UINT8_C(0x10)
+
+/**\name Interface selection macro */
+#define BMA4_SPI_WR_MASK UINT8_C(0x7F)
+#define BMA4_SPI_RD_MASK UINT8_C(0x80)
+
+/**\name Chip ID macros */
+#define BMA4_CHIP_ID_MIN UINT8_C(0x10)
+#define BMA4_CHIP_ID_MAX UINT8_C(0x15)
+
+/**\name Auxiliary sensor selection macro */
+#define BMM150_SENSOR UINT8_C(1)
+#define AKM9916_SENSOR UINT8_C(2)
+#define BMA4_ASIC_INITIALIZED UINT8_C(0x01)
+
+/**\name Auxiliary sensor chip id macros */
+#define BMM150_CHIP_ID UINT8_C(0x32)
+
+/**\name Auxiliary sensor other macros */
+#define BMM150_POWER_CONTROL_REG UINT8_C(0x4B)
+#define BMM150_POWER_MODE_REG UINT8_C(0x4C)
+
+/**\name CONSTANTS */
+#define BMA4_FIFO_CONFIG_LENGTH UINT8_C(2)
+#define BMA4_ACCEL_CONFIG_LENGTH UINT8_C(2)
+#define BMA4_FIFO_WM_LENGTH UINT8_C(2)
+#define BMA4_NON_LATCH_MODE UINT8_C(0)
+#define BMA4_LATCH_MODE UINT8_C(1)
+#define BMA4_OPEN_DRAIN UINT8_C(1)
+#define BMA4_PUSH_PULL UINT8_C(0)
+#define BMA4_ACTIVE_HIGH UINT8_C(1)
+#define BMA4_ACTIVE_LOW UINT8_C(0)
+#define BMA4_EDGE_TRIGGER UINT8_C(1)
+#define BMA4_LEVEL_TRIGGER UINT8_C(0)
+#define BMA4_OUTPUT_ENABLE UINT8_C(1)
+#define BMA4_OUTPUT_DISABLE UINT8_C(0)
+#define BMA4_INPUT_ENABLE UINT8_C(1)
+#define BMA4_INPUT_DISABLE UINT8_C(0)
+
+/**\name ACCEL RANGE CHECK*/
+#define BMA4_ACCEL_RANGE_2G UINT8_C(0)
+#define BMA4_ACCEL_RANGE_4G UINT8_C(1)
+#define BMA4_ACCEL_RANGE_8G UINT8_C(2)
+#define BMA4_ACCEL_RANGE_16G UINT8_C(3)
+
+/**\name CONDITION CHECK FOR READING AND WRTING DATA*/
+#define BMA4_MAX_VALUE_FIFO_FILTER UINT8_C(1)
+#define BMA4_MAX_VALUE_SPI3 UINT8_C(1)
+#define BMA4_MAX_VALUE_SELFTEST_AMP UINT8_C(1)
+#define BMA4_MAX_IF_MODE UINT8_C(3)
+#define BMA4_MAX_VALUE_SELFTEST_SIGN UINT8_C(1)
+
+/**\name BUS READ AND WRITE LENGTH FOR MAG & ACCEL*/
+#define BMA4_MAG_TRIM_DATA_SIZE UINT8_C(16)
+#define BMA4_MAG_XYZ_DATA_LENGTH UINT8_C(6)
+#define BMA4_MAG_XYZR_DATA_LENGTH UINT8_C(8)
+#define BMA4_ACCEL_DATA_LENGTH UINT8_C(6)
+#define BMA4_FIFO_DATA_LENGTH UINT8_C(2)
+#define BMA4_TEMP_DATA_SIZE UINT8_C(1)
+
+/**\name TEMPERATURE CONSTANT */
+#define BMA4_OFFSET_TEMP UINT8_C(23)
+#define BMA4_DEG UINT8_C(1)
+#define BMA4_FAHREN UINT8_C(2)
+#define BMA4_KELVIN UINT8_C(3)
+
+/**\name DELAY DEFINITION IN MSEC*/
+#define BMA4_AUX_IF_DELAY UINT8_C(5)
+#define BMA4_BMM150_WAKEUP_DELAY1 UINT8_C(2)
+#define BMA4_BMM150_WAKEUP_DELAY2 UINT8_C(3)
+#define BMA4_BMM150_WAKEUP_DELAY3 UINT8_C(1)
+#define BMA4_GEN_READ_WRITE_DELAY UINT16_C(1000)
+#define BMA4_AUX_COM_DELAY UINT16_C(10000)
+
+/**\name ARRAY PARAMETER DEFINITIONS*/
+#define BMA4_SENSOR_TIME_MSB_BYTE UINT8_C(2)
+#define BMA4_SENSOR_TIME_XLSB_BYTE UINT8_C(1)
+#define BMA4_SENSOR_TIME_LSB_BYTE UINT8_C(0)
+#define BMA4_MAG_X_LSB_BYTE UINT8_C(0)
+#define BMA4_MAG_X_MSB_BYTE UINT8_C(1)
+#define BMA4_MAG_Y_LSB_BYTE UINT8_C(2)
+#define BMA4_MAG_Y_MSB_BYTE UINT8_C(3)
+#define BMA4_MAG_Z_LSB_BYTE UINT8_C(4)
+#define BMA4_MAG_Z_MSB_BYTE UINT8_C(5)
+#define BMA4_MAG_R_LSB_BYTE UINT8_C(6)
+#define BMA4_MAG_R_MSB_BYTE UINT8_C(7)
+#define BMA4_TEMP_BYTE UINT8_C(0)
+#define BMA4_FIFO_LENGTH_MSB_BYTE UINT8_C(1)
+
+/*! @name To define success code */
+#define BMA4_OK INT8_C(0)
+
+/*! @name To define error codes */
+#define BMA4_E_NULL_PTR INT8_C(-1)
+#define BMA4_E_COM_FAIL INT8_C(-2)
+#define BMA4_E_DEV_NOT_FOUND INT8_C(-3)
+#define BMA4_E_INVALID_SENSOR INT8_C(-4)
+#define BMA4_E_CONFIG_STREAM_ERROR INT8_C(-5)
+#define BMA4_E_SELF_TEST_FAIL INT8_C(-6)
+#define BMA4_E_FOC_FAIL INT8_C(-7)
+#define BMA4_E_OUT_OF_RANGE INT8_C(-8)
+#define BMA4_E_INT_LINE_INVALID INT8_C(-9)
+#define BMA4_E_RD_WR_LENGTH_INVALID INT8_C(-10)
+#define BMA4_E_AUX_CONFIG_FAIL INT8_C(-11)
+#define BMA4_E_SC_FIFO_HEADER_ERR INT8_C(-12)
+#define BMA4_E_SC_FIFO_CONFIG_ERR INT8_C(-13)
+
+/**\name UTILITY MACROS */
+#define BMA4_SET_LOW_BYTE UINT16_C(0x00FF)
+#define BMA4_SET_HIGH_BYTE UINT16_C(0xFF00)
+#define BMA4_SET_LOW_NIBBLE UINT8_C(0x0F)
+
+/* Macros used for Self test (BMA42X_VARIANT) */
+/* Self-test: Resulting minimum difference signal in mg for BMA42X */
+#define BMA42X_ST_ACC_X_AXIS_SIGNAL_DIFF UINT16_C(400)
+#define BMA42X_ST_ACC_Y_AXIS_SIGNAL_DIFF UINT16_C(800)
+#define BMA42X_ST_ACC_Z_AXIS_SIGNAL_DIFF UINT16_C(400)
+
+/* Macros used for Self test (BMA42X_B_VARIANT) */
+/* Self-test: Resulting minimum difference signal in mg for BMA42X_B */
+#define BMA42X_B_ST_ACC_X_AXIS_SIGNAL_DIFF UINT16_C(1800)
+#define BMA42X_B_ST_ACC_Y_AXIS_SIGNAL_DIFF UINT16_C(1800)
+#define BMA42X_B_ST_ACC_Z_AXIS_SIGNAL_DIFF UINT16_C(1800)
+
+/* Macros used for Self test (BMA45X_VARIANT) */
+/* Self-test: Resulting minimum difference signal in mg for BMA45X */
+#define BMA45X_ST_ACC_X_AXIS_SIGNAL_DIFF UINT16_C(1800)
+#define BMA45X_ST_ACC_Y_AXIS_SIGNAL_DIFF UINT16_C(1800)
+#define BMA45X_ST_ACC_Z_AXIS_SIGNAL_DIFF UINT16_C(1800)
+
+/**\name BOOLEAN TYPES*/
+#ifndef TRUE
+#define TRUE UINT8_C(0x01)
+#endif
+
+#ifndef FALSE
+#define FALSE UINT8_C(0x00)
+#endif
+
+#ifndef NULL
+#define NULL UINT8_C(0x00)
+#endif
+
+/**\name ERROR STATUS POSITION AND MASK*/
+#define BMA4_FATAL_ERR_MSK UINT8_C(0x01)
+#define BMA4_CMD_ERR_POS UINT8_C(1)
+#define BMA4_CMD_ERR_MSK UINT8_C(0x02)
+#define BMA4_ERR_CODE_POS UINT8_C(2)
+#define BMA4_ERR_CODE_MSK UINT8_C(0x1C)
+#define BMA4_FIFO_ERR_POS UINT8_C(6)
+#define BMA4_FIFO_ERR_MSK UINT8_C(0x40)
+#define BMA4_AUX_ERR_POS UINT8_C(7)
+#define BMA4_AUX_ERR_MSK UINT8_C(0x80)
+
+/**\name NV_CONFIG POSITION AND MASK*/
+/* NV_CONF Description - Reg Addr --> (0x70), Bit --> 3 */
+#define BMA4_NV_ACCEL_OFFSET_POS UINT8_C(3)
+#define BMA4_NV_ACCEL_OFFSET_MSK UINT8_C(0x08)
+
+/**\name MAG DATA XYZ POSITION AND MASK*/
+#define BMA4_DATA_MAG_X_LSB_POS UINT8_C(3)
+#define BMA4_DATA_MAG_X_LSB_MSK UINT8_C(0xF8)
+#define BMA4_DATA_MAG_Y_LSB_POS UINT8_C(3)
+#define BMA4_DATA_MAG_Y_LSB_MSK UINT8_C(0xF8)
+#define BMA4_DATA_MAG_Z_LSB_POS UINT8_C(1)
+#define BMA4_DATA_MAG_Z_LSB_MSK UINT8_C(0xFE)
+#define BMA4_DATA_MAG_R_LSB_POS UINT8_C(2)
+#define BMA4_DATA_MAG_R_LSB_MSK UINT8_C(0xFC)
+
+/**\name ACCEL DATA READY POSITION AND MASK*/
+#define BMA4_STAT_DATA_RDY_ACCEL_POS UINT8_C(7)
+#define BMA4_STAT_DATA_RDY_ACCEL_MSK UINT8_C(0x80)
+
+/**\name MAG DATA READY POSITION AND MASK*/
+#define BMA4_STAT_DATA_RDY_MAG_POS UINT8_C(5)
+#define BMA4_STAT_DATA_RDY_MAG_MSK UINT8_C(0x20)
+
+/**\name ADVANCE POWER SAVE POSITION AND MASK*/
+#define BMA4_ADVANCE_POWER_SAVE_MSK UINT8_C(0x01)
+
+/**\name ACCELEROMETER ENABLE POSITION AND MASK*/
+#define BMA4_ACCEL_ENABLE_POS UINT8_C(2)
+#define BMA4_ACCEL_ENABLE_MSK UINT8_C(0x04)
+
+/**\name MAGNETOMETER ENABLE POSITION AND MASK*/
+#define BMA4_MAG_ENABLE_MSK UINT8_C(0x01)
+
+/**\name ACCEL CONFIGURATION POSITION AND MASK*/
+#define BMA4_ACCEL_ODR_MSK UINT8_C(0x0F)
+#define BMA4_ACCEL_BW_POS UINT8_C(4)
+#define BMA4_ACCEL_BW_MSK UINT8_C(0x70)
+#define BMA4_ACCEL_RANGE_MSK UINT8_C(0x03)
+#define BMA4_ACCEL_PERFMODE_POS UINT8_C(7)
+#define BMA4_ACCEL_PERFMODE_MSK UINT8_C(0x80)
+
+/**\name MAG CONFIGURATION POSITION AND MASK*/
+#define BMA4_MAG_CONFIG_OFFSET_POS UINT8_C(4)
+#define BMA4_MAG_CONFIG_OFFSET_LEN UINT8_C(4)
+#define BMA4_MAG_CONFIG_OFFSET_MSK UINT8_C(0xF0)
+#define BMA4_MAG_CONFIG_OFFSET_REG (BMA4_AUX_CONFIG_ADDR)
+
+/**\name FIFO SELF WAKE UP POSITION AND MASK*/
+#define BMA4_FIFO_SELF_WAKE_UP_POS UINT8_C(1)
+#define BMA4_FIFO_SELF_WAKE_UP_MSK UINT8_C(0x02)
+
+/**\name FIFO BYTE COUNTER POSITION AND MASK*/
+#define BMA4_FIFO_BYTE_COUNTER_MSB_MSK UINT8_C(0x3F)
+
+/**\name FIFO DATA POSITION AND MASK*/
+#define BMA4_FIFO_DATA_POS UINT8_C(0)
+#define BMA4_FIFO_DATA_MSK UINT8_C(0xFF)
+
+/**\name FIFO FILTER FOR ACCEL POSITION AND MASK*/
+#define BMA4_FIFO_DOWN_ACCEL_POS UINT8_C(4)
+#define BMA4_FIFO_DOWN_ACCEL_MSK UINT8_C(0x70)
+#define BMA4_FIFO_FILTER_ACCEL_POS UINT8_C(7)
+#define BMA4_FIFO_FILTER_ACCEL_MSK UINT8_C(0x80)
+
+/**\name FIFO HEADER DATA DEFINITIONS */
+#define BMA4_FIFO_HEAD_A UINT8_C(0x84)
+#define BMA4_FIFO_HEAD_M UINT8_C(0x90)
+#define BMA4_FIFO_HEAD_M_A UINT8_C(0x94)
+#define BMA4_FIFO_HEAD_SENSOR_TIME UINT8_C(0x44)
+#define BMA4_FIFO_HEAD_INPUT_CONFIG UINT8_C(0x48)
+#define BMA4_FIFO_HEAD_SKIP_FRAME UINT8_C(0x40)
+#define BMA4_FIFO_HEAD_OVER_READ_MSB UINT8_C(0x80)
+#define BMA4_FIFO_HEAD_SAMPLE_DROP UINT8_C(0x50)
+
+/**\name FIFO HEADERLESS MODE DATA ENABLE DEFINITIONS */
+#define BMA4_FIFO_M_A_ENABLE UINT8_C(0x60)
+#define BMA4_FIFO_A_ENABLE UINT8_C(0x40)
+#define BMA4_FIFO_M_ENABLE UINT8_C(0x20)
+
+/**\name FIFO CONFIGURATION SELECTION */
+#define BMA4_FIFO_STOP_ON_FULL UINT8_C(0x01)
+#define BMA4_FIFO_TIME UINT8_C(0x02)
+#define BMA4_FIFO_TAG_INTR2 UINT8_C(0x04)
+#define BMA4_FIFO_TAG_INTR1 UINT8_C(0x08)
+#define BMA4_FIFO_HEADER UINT8_C(0x10)
+#define BMA4_FIFO_MAG UINT8_C(0x20)
+#define BMA4_FIFO_ACCEL UINT8_C(0x40)
+#define BMA4_FIFO_ALL UINT8_C(0x7F)
+#define BMA4_FIFO_CONFIG_0_MASK UINT8_C(0x03)
+#define BMA4_FIFO_CONFIG_1_MASK UINT8_C(0xFC)
+
+/**\name FIFO FRAME COUNT DEFINITION */
+#define BMA4_FIFO_LSB_CONFIG_CHECK UINT8_C(0x00)
+#define BMA4_FIFO_MSB_CONFIG_CHECK UINT8_C(0x80)
+#define BMA4_FIFO_TAG_INTR_MASK UINT8_C(0xFC)
+
+/**\name FIFO DROPPED FRAME DEFINITION */
+#define BMA4_AUX_FIFO_DROP UINT8_C(0x04)
+#define BMA4_ACCEL_AUX_FIFO_DROP UINT8_C(0x05)
+#define BMA4_ACCEL_FIFO_DROP UINT8_C(0x01)
+
+/**\name FIFO MAG DEFINITION*/
+#define BMA4_MA_FIFO_A_X_LSB UINT8_C(8)
+
+/**\name FIFO sensor time length definitions*/
+#define BMA4_SENSOR_TIME_LENGTH UINT8_C(3)
+
+/**\name FIFO LENGTH DEFINITION*/
+#define BMA4_FIFO_A_LENGTH UINT8_C(6)
+#define BMA4_FIFO_M_LENGTH UINT8_C(8)
+#define BMA4_FIFO_MA_LENGTH UINT8_C(14)
+
+/**\name MAG I2C ADDRESS SELECTION POSITION AND MASK*/
+#define BMA4_I2C_DEVICE_ADDR_POS UINT8_C(1)
+#define BMA4_I2C_DEVICE_ADDR_MSK UINT8_C(0xFE)
+
+/**\name MAG CONFIGURATION FOR SECONDARY INTERFACE POSITION AND MASK*/
+#define BMA4_MAG_BURST_MSK UINT8_C(0x03)
+#define BMA4_MAG_MANUAL_ENABLE_POS UINT8_C(7)
+#define BMA4_MAG_MANUAL_ENABLE_MSK UINT8_C(0x80)
+#define BMA4_READ_ADDR_MSK UINT8_C(0xFF)
+#define BMA4_WRITE_ADDR_MSK UINT8_C(0xFF)
+#define BMA4_WRITE_DATA_MSK UINT8_C(0xFF)
+
+/**\name OUTPUT TYPE ENABLE POSITION AND MASK*/
+#define BMA4_INT_EDGE_CTRL_MASK UINT8_C(0x01)
+#define BMA4_INT_EDGE_CTRL_POS UINT8_C(0x00)
+#define BMA4_INT_LEVEL_MASK UINT8_C(0x02)
+#define BMA4_INT_LEVEL_POS UINT8_C(0x01)
+#define BMA4_INT_OPEN_DRAIN_MASK UINT8_C(0x04)
+#define BMA4_INT_OPEN_DRAIN_POS UINT8_C(0x02)
+#define BMA4_INT_OUTPUT_EN_MASK UINT8_C(0x08)
+#define BMA4_INT_OUTPUT_EN_POS UINT8_C(0x03)
+#define BMA4_INT_INPUT_EN_MASK UINT8_C(0x10)
+#define BMA4_INT_INPUT_EN_POS UINT8_C(0x04)
+
+/**\name IF CONFIG POSITION AND MASK*/
+#define BMA4_CONFIG_SPI3_MSK UINT8_C(0x01)
+#define BMA4_IF_CONFIG_IF_MODE_POS UINT8_C(4)
+#define BMA4_IF_CONFIG_IF_MODE_MSK UINT8_C(0x10)
+
+/**\name ACCEL SELF TEST POSITION AND MASK*/
+#define BMA4_ACCEL_SELFTEST_ENABLE_MSK UINT8_C(0x01)
+#define BMA4_ACCEL_SELFTEST_SIGN_POS UINT8_C(2)
+#define BMA4_ACCEL_SELFTEST_SIGN_MSK UINT8_C(0x04)
+#define BMA4_SELFTEST_AMP_POS UINT8_C(3)
+#define BMA4_SELFTEST_AMP_MSK UINT8_C(0x08)
+
+/**\name ACCEL ODR */
+#define BMA4_OUTPUT_DATA_RATE_0_78HZ UINT8_C(0x01)
+#define BMA4_OUTPUT_DATA_RATE_1_56HZ UINT8_C(0x02)
+#define BMA4_OUTPUT_DATA_RATE_3_12HZ UINT8_C(0x03)
+#define BMA4_OUTPUT_DATA_RATE_6_25HZ UINT8_C(0x04)
+#define BMA4_OUTPUT_DATA_RATE_12_5HZ UINT8_C(0x05)
+#define BMA4_OUTPUT_DATA_RATE_25HZ UINT8_C(0x06)
+#define BMA4_OUTPUT_DATA_RATE_50HZ UINT8_C(0x07)
+#define BMA4_OUTPUT_DATA_RATE_100HZ UINT8_C(0x08)
+#define BMA4_OUTPUT_DATA_RATE_200HZ UINT8_C(0x09)
+#define BMA4_OUTPUT_DATA_RATE_400HZ UINT8_C(0x0A)
+#define BMA4_OUTPUT_DATA_RATE_800HZ UINT8_C(0x0B)
+#define BMA4_OUTPUT_DATA_RATE_1600HZ UINT8_C(0x0C)
+
+/**\name ACCEL BANDWIDTH PARAMETER */
+#define BMA4_ACCEL_OSR4_AVG1 UINT8_C(0)
+#define BMA4_ACCEL_OSR2_AVG2 UINT8_C(1)
+#define BMA4_ACCEL_NORMAL_AVG4 UINT8_C(2)
+#define BMA4_ACCEL_CIC_AVG8 UINT8_C(3)
+#define BMA4_ACCEL_RES_AVG16 UINT8_C(4)
+#define BMA4_ACCEL_RES_AVG32 UINT8_C(5)
+#define BMA4_ACCEL_RES_AVG64 UINT8_C(6)
+#define BMA4_ACCEL_RES_AVG128 UINT8_C(7)
+
+/**\name ACCEL PERFMODE PARAMETER */
+#define BMA4_CIC_AVG_MODE UINT8_C(0)
+#define BMA4_CONTINUOUS_MODE UINT8_C(1)
+
+/**\name MAG OFFSET */
+#define BMA4_MAG_OFFSET_MAX UINT8_C(0x00)
+
+/**\name ENABLE/DISABLE SELECTIONS */
+#define BMA4_X_AXIS UINT8_C(0)
+#define BMA4_Y_AXIS UINT8_C(1)
+#define BMA4_Z_AXIS UINT8_C(2)
+
+/**\name SELF TEST*/
+#define BMA4_SELFTEST_PASS INT8_C(0)
+#define BMA4_SELFTEST_FAIL INT8_C(1)
+
+#define BMA4_SELFTEST_DIFF_X_AXIS_FAILED INT8_C(1)
+#define BMA4_SELFTEST_DIFF_Y_AXIS_FAILED INT8_C(2)
+#define BMA4_SELFTEST_DIFF_Z_AXIS_FAILED INT8_C(3)
+#define BMA4_SELFTEST_DIFF_X_AND_Y_AXIS_FAILED INT8_C(4)
+#define BMA4_SELFTEST_DIFF_X_AND_Z_AXIS_FAILED INT8_C(5)
+#define BMA4_SELFTEST_DIFF_Y_AND_Z_AXIS_FAILED INT8_C(6)
+#define BMA4_SELFTEST_DIFF_X_Y_AND_Z_AXIS_FAILED INT8_C(7)
+
+/**\name INTERRUPT MAPS */
+#define BMA4_INTR1_MAP UINT8_C(0)
+#define BMA4_INTR2_MAP UINT8_C(1)
+
+/**\name INTERRUPT MASKS */
+#define BMA4_FIFO_FULL_INT UINT16_C(0x0100)
+#define BMA4_FIFO_WM_INT UINT16_C(0x0200)
+#define BMA4_DATA_RDY_INT UINT16_C(0x0400)
+#define BMA4_MAG_DATA_RDY_INT UINT16_C(0x2000)
+#define BMA4_ACCEL_DATA_RDY_INT UINT16_C(0x8000)
+
+/**\name AKM POWER MODE SELECTION */
+#define BMA4_AKM_POWER_DOWN_MODE UINT8_C(0)
+#define BMA4_AKM_SINGLE_MEAS_MODE UINT8_C(1)
+
+/**\name SECONDARY_MAG POWER MODE SELECTION */
+#define BMA4_MAG_FORCE_MODE UINT8_C(0)
+#define BMA4_MAG_SUSPEND_MODE UINT8_C(1)
+
+/**\name MAG POWER MODE SELECTION */
+#define BMA4_FORCE_MODE UINT8_C(0)
+#define BMA4_SUSPEND_MODE UINT8_C(1)
+
+/**\name ACCEL POWER MODE */
+#define BMA4_ACCEL_MODE_NORMAL UINT8_C(0x11)
+
+/**\name MAG POWER MODE */
+#define BMA4_MAG_MODE_SUSPEND UINT8_C(0x18)
+
+/**\name ENABLE/DISABLE BIT VALUES */
+#define BMA4_ENABLE UINT8_C(0x01)
+#define BMA4_DISABLE UINT8_C(0x00)
+
+/**\name DEFINITION USED FOR DIFFERENT WRITE */
+#define BMA4_MANUAL_DISABLE UINT8_C(0x00)
+#define BMA4_MANUAL_ENABLE UINT8_C(0x01)
+#define BMA4_ENABLE_MAG_IF_MODE UINT8_C(0x01)
+#define BMA4_MAG_DATA_READ_REG UINT8_C(0x0A)
+#define BMA4_BMM_POWER_MODE_REG UINT8_C(0x06)
+#define BMA4_SEC_IF_NULL UINT8_C(0)
+#define BMA4_SEC_IF_BMM150 UINT8_C(1)
+#define BMA4_SEC_IF_AKM09916 UINT8_C(2)
+#define BMA4_ENABLE_AUX_IF_MODE UINT8_C(0x01)
+
+/**\name SENSOR RESOLUTION */
+#define BMA4_12_BIT_RESOLUTION UINT8_C(12)
+#define BMA4_14_BIT_RESOLUTION UINT8_C(14)
+#define BMA4_16_BIT_RESOLUTION UINT8_C(16)
+
+/**\name FOC MACROS */
+#define BMA4_FOC_SAMPLE_LIMIT UINT8_C(128)
+#define BMA4_MAX_NOISE_LIMIT(RANGE_VALUE) (RANGE_VALUE + UINT16_C(255))
+#define BMA4_MIN_NOISE_LIMIT(RANGE_VALUE) (RANGE_VALUE - UINT16_C(255))
+
+/*! for handling float temperature values */
+#define BMA4_SCALE_TEMP INT32_C(1000)
+
+/* BMA4_FAHREN_SCALED = 1.8 * 1000 */
+#define BMA4_FAHREN_SCALED INT32_C(1800)
+
+/* BMA4_KELVIN_SCALED = 273.15 * 1000 */
+#define BMA4_KELVIN_SCALED INT32_C(273150)
+
+/**\name MAP BURST READ LENGTHS */
+#define BMA4_AUX_READ_LEN_0 UINT8_C(0)
+#define BMA4_AUX_READ_LEN_1 UINT8_C(1)
+#define BMA4_AUX_READ_LEN_2 UINT8_C(2)
+#define BMA4_AUX_READ_LEN_3 UINT8_C(3)
+
+#define BMA4_CONFIG_STREAM_MESSAGE_MSK UINT8_C(0x0F)
+
+#define BMA4_SOFT_RESET UINT8_C(0XB6)
+
+#define BMA4_MS_TO_US(X) (X * 1000)
+
+#ifndef ABS
+#define ABS(a) ((a) > 0 ? (a) : -(a)) /*!< Absolute value */
+#endif
+
+/**\name BIT SLICE GET AND SET FUNCTIONS */
+#define BMA4_GET_BITSLICE(regvar, bitname) \
+ ((regvar & bitname##_MSK) >> bitname##_POS)
+
+#define BMA4_SET_BITSLICE(regvar, bitname, val) \
+ ((regvar & ~bitname##_MSK) | \
+ ((val << bitname##_POS) & bitname##_MSK))
+
+#define BMA4_GET_DIFF(x, y) ((x) - (y))
+
+#define BMA4_GET_LSB(var) (uint8_t)(var & BMA4_SET_LOW_BYTE)
+#define BMA4_GET_MSB(var) (uint8_t)((var & BMA4_SET_HIGH_BYTE) >> 8)
+
+#define BMA4_SET_BIT_VAL_0(reg_data, bitname) (reg_data & ~(bitname##_MSK))
+
+#define BMA4_SET_BITS_POS_0(reg_data, bitname, data) \
+ ((reg_data & ~(bitname##_MSK)) | \
+ (data & bitname##_MSK))
+
+#define BMA4_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK))
+
+/**
+ * BMA4_INTF_RET_TYPE is the read/write interface return type which can be overwritten by the build system.
+ * The default is set to int8_t.
+ */
+#ifndef BMA4_INTF_RET_TYPE
+#define BMA4_INTF_RET_TYPE int8_t
+#endif
+
+/**
+ * BST_INTF_RET_SUCCESS is the success return value read/write interface return type which can be
+ * overwritten by the build system. The default is set to 0. It is used to check for a successful
+ * execution of the read/write functions
+ */
+#ifndef BMA4_INTF_RET_SUCCESS
+#define BMA4_INTF_RET_SUCCESS INT8_C(0)
+#endif
+
+/******************************************************************************/
+/*! @name TYPEDEF DEFINITIONS */
+/******************************************************************************/
+
+/*!
+ * @brief Bus communication function pointer which should be mapped to
+ * the platform specific read functions of the user
+ *
+ * @param[in] reg_addr : Register address from which data is read.
+ * @param[out] read_data : Pointer to data buffer where read data is stored.
+ * @param[in] len : Number of bytes of data to be read.
+ * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors
+ * for interface related call backs.
+ *
+ * @retval = BMA4_INTF_RET_SUCCESS -> Success
+ * @retval != BMA4_INTF_RET_SUCCESS -> Failure Info
+ *
+ */
+typedef BMA4_INTF_RET_TYPE (*bma4_read_fptr_t)(uint8_t reg_addr, uint8_t *read_data, uint32_t len, void *intf_ptr);
+
+/*!
+ * @brief Bus communication function pointer which should be mapped to
+ * the platform specific write functions of the user
+ *
+ * @param[in] reg_addr : Register address to which the data is written.
+ * @param[in] read_data : Pointer to data buffer in which data to be written
+ * is stored.
+ * @param[in] len : Number of bytes of data to be written.
+ * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors
+ * for interface related call backs
+ *
+ * @retval = BMA4_INTF_RET_SUCCESS -> Success
+ * @retval != BMA4_INTF_RET_SUCCESS -> Failure Info
+ *
+ */
+typedef BMA4_INTF_RET_TYPE (*bma4_write_fptr_t)(uint8_t reg_addr, const uint8_t *read_data, uint32_t len,
+ void *intf_ptr);
+
+/*!
+ * @brief Delay function pointer which should be mapped to
+ * delay function of the user
+ *
+ * @param[in] period : Delay in microseconds.
+ * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors
+ * for interface related call backs
+ *
+ */
+typedef void (*bma4_delay_us_fptr_t)(uint32_t period, void *intf_ptr);
+
+/******************************************************************************/
+/*! @name Enum Declarations */
+/******************************************************************************/
+/*! @name Enum to define BMA4 variants */
+enum bma4_variant {
+ BMA42X_VARIANT = 1,
+ BMA42X_B_VARIANT,
+ BMA45X_VARIANT
+};
+
+/* Enumerator describing interfaces */
+enum bma4_intf {
+ BMA4_SPI_INTF,
+ BMA4_I2C_INTF
+};
+
+/**\name STRUCTURE DEFINITIONS*/
+
+/*!
+ * @brief
+ * This structure holds asic info. for feature configuration.
+ */
+struct bma4_asic_data
+{
+ /* Feature config start addr (0-3 bits)*/
+ uint8_t asic_lsb;
+
+ /* Feature config start addr (4-11 bits)*/
+ uint8_t asic_msb;
+};
+
+/*!
+ * @brief Auxiliary configuration structure for user settings
+ */
+struct bma4_aux_config
+{
+ /*! Device address of auxiliary sensor */
+ uint8_t aux_dev_addr;
+
+ /*! To enable manual or auto mode */
+ uint8_t manual_enable;
+
+ /*! No of bytes to be read at a time */
+ uint8_t burst_read_length;
+
+ /*! Variable to set the auxiliary interface */
+ uint8_t if_mode;
+};
+
+/*!
+ * @brief
+ * This structure holds all relevant information about BMA4
+ */
+struct bma4_dev
+{
+ /*! Chip id of BMA4 */
+ uint8_t chip_id;
+
+ /*! Chip id of auxiliary sensor */
+ uint8_t aux_chip_id;
+
+ /*! Interface pointer */
+ void *intf_ptr;
+
+ /*! Interface detail */
+ enum bma4_intf intf;
+
+ /*! Variable that holds error code */
+ BMA4_INTF_RET_TYPE intf_rslt;
+
+ /*! Auxiliary sensor information */
+ uint8_t aux_sensor;
+
+ /*! Decide SPI or I2C read mechanism */
+ uint8_t dummy_byte;
+
+ /*! Resolution for FOC */
+ uint8_t resolution;
+
+ /*! Define the BMA4 variant BMA42X or BMA45X */
+ enum bma4_variant variant;
+
+ /*! Used to check mag manual/auto mode status
+ * int8_t mag_manual_enable;
+ */
+
+ /*! Config stream data buffer address will be assigned*/
+ const uint8_t *config_file_ptr;
+
+ /*! Read/write length */
+ uint16_t read_write_len;
+
+ /*! Feature len */
+ uint8_t feature_len;
+
+ /*! Contains asic information */
+ struct bma4_asic_data asic_data;
+
+ /*! Contains aux configuration settings */
+ struct bma4_aux_config aux_config;
+
+ /*! Bus read function pointer */
+ bma4_read_fptr_t bus_read;
+
+ /*! Bus write function pointer */
+ bma4_write_fptr_t bus_write;
+
+ /*! Delay(in microsecond) function pointer */
+ bma4_delay_us_fptr_t delay_us;
+
+ /*! Variable to store the size of config file */
+ uint16_t config_size;
+
+ /*! Variable to store the status of performance mode */
+ uint8_t perf_mode_status;
+};
+
+/*!
+ * @brief This structure holds the information for usage of
+ * FIFO by the user.
+ */
+struct bma4_fifo_frame
+{
+ /*! Data buffer of user defined length is to be mapped here */
+ uint8_t *data;
+
+ /*! Number of bytes of FIFO to be read as specified by the user */
+ uint16_t length;
+
+ /*! Enabling of the FIFO header to stream in header mode */
+ uint8_t fifo_header_enable;
+
+ /*! Streaming of the Accelerometer, Auxiliary
+ * 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 mag_byte_start_idx;
+
+ /*! Will be equal to length when no more frames are there to parse */
+ uint16_t sc_frame_byte_start_idx;
+
+ /*! Value of FIFO sensor time time */
+ uint32_t sensor_time;
+
+ /*! Value of Skipped frame counts */
+ uint8_t skipped_frame_count;
+
+ /*! Value of accel dropped frame count */
+ uint8_t accel_dropped_frame_count;
+
+ /*! Value of mag dropped frame count */
+ uint8_t mag_dropped_frame_count;
+};
+
+/*!
+ * @brief Error Status structure
+ */
+struct bma4_err_reg
+{
+ /*! Indicates fatal error */
+ uint8_t fatal_err;
+
+ /*! Indicates command error */
+ uint8_t cmd_err;
+
+ /*! Indicates error code */
+ uint8_t err_code;
+
+ /*! Indicates fifo error */
+ uint8_t fifo_err;
+
+ /*! Indicates mag error */
+ uint8_t aux_err;
+};
+
+/*!
+ * @brief Asic Status structure
+ */
+struct bma4_asic_status
+{
+ /*! Asic is in sleep/halt state */
+ uint8_t sleep;
+
+ /*! Dedicated interrupt is set again before previous interrupt
+ * was acknowledged
+ */
+ uint8_t irq_ovrn;
+
+ /*! Watchcell event detected (asic stopped) */
+ uint8_t wc_event;
+
+ /*! Stream transfer has started and transactions are ongoing */
+ uint8_t stream_transfer_active;
+};
+
+/*!
+ * @brief Interrupt Pin Configuration structure
+ */
+struct bma4_int_pin_config
+{
+ /*! Trigger condition of interrupt pin */
+ uint8_t edge_ctrl;
+
+ /*! Level of interrupt pin */
+ uint8_t lvl;
+
+ /*! Behaviour of interrupt pin to open drain */
+ uint8_t od;
+
+ /*! Output enable for interrupt pin */
+ uint8_t output_en;
+
+ /*! Input enable for interrupt pin */
+ uint8_t input_en;
+};
+
+/*!
+ * @brief Accelerometer configuration structure
+ */
+struct bma4_accel_config
+{
+ /*! Output data rate in Hz */
+ uint8_t odr;
+
+ /*! Bandwidth parameter, determines filter configuration */
+ uint8_t bandwidth;
+
+ /*! Filter performance mode */
+ uint8_t perf_mode;
+
+ /*! G-range */
+ uint8_t range;
+};
+
+/*!
+ * @brief Auxiliary magnetometer configuration structure
+ */
+struct bma4_aux_mag_config
+{
+ /*! Poll rate for the sensor attached to the Magnetometer interface */
+ uint8_t odr;
+
+ /*! Trigger-readout offset in units of 2.5 ms.
+ * If set to zero, the offset is maximum, i.e. after readout a trigger
+ * is issued immediately
+ */
+ uint8_t offset;
+};
+
+/*!
+ * @brief ASIC Config structure
+ */
+struct bma4_asic_config
+{
+ /*! Enable/Disable ASIC Wake Up */
+ uint8_t asic_en;
+
+ /*! Configure stream_transfer/FIFO mode */
+ uint8_t fifo_mode_en;
+
+ /*! Mapping of instance RAM1 */
+ uint8_t mem_conf_ram1;
+
+ /*! Mapping of instance RAM2 */
+ uint8_t mem_conf_ram2;
+
+ /*! Mapping of instance RAM3 */
+ uint8_t mem_conf_ram3;
+};
+
+/*!
+ * @brief bmm150 or akm09916
+ * magnetometer values structure
+ */
+struct bma4_mag
+{
+ /*! BMM150 and AKM09916 X raw data */
+ int32_t x;
+
+ /*! BMM150 and AKM09916 Y raw data */
+ int32_t y;
+
+ /*! BMM150 and AKM09916 Z raw data */
+ int32_t z;
+};
+
+/*!
+ * @brief bmm150 xyz data structure
+ */
+struct bma4_mag_xyzr
+{
+ /*! BMM150 X raw data */
+ int16_t x;
+
+ /*! BMM150 Y raw data */
+ int16_t y;
+
+ /*! BMM150 Z raw data */
+ int16_t z;
+
+ /*! BMM150 R raw data */
+ uint16_t r;
+};
+
+/*!
+ * @brief Accel xyz data structure
+ */
+struct bma4_accel
+{
+ /*! Accel X data */
+ int16_t x;
+
+ /*! Accel Y data */
+ int16_t y;
+
+ /*! Accel Z data */
+ int16_t z;
+};
+
+/*!
+ * @brief FIFO mag data structure
+ */
+struct bma4_mag_fifo_data
+{
+ /*! The value of mag x LSB data */
+ uint8_t mag_x_lsb;
+
+ /*! The value of mag x MSB data */
+ uint8_t mag_x_msb;
+
+ /*! The value of mag y LSB data */
+ uint8_t mag_y_lsb;
+
+ /*! The value of mag y MSB data */
+ uint8_t mag_y_msb;
+
+ /*! The value of mag z LSB data */
+ uint8_t mag_z_lsb;
+
+ /*! The value of mag z MSB data */
+ uint8_t mag_z_msb;
+
+ /*! The value of mag r for BMM150 Y2 for YAMAHA LSB data */
+ uint8_t mag_r_y2_lsb;
+
+ /*! The value of mag r for BMM150 Y2 for YAMAHA MSB data */
+ uint8_t mag_r_y2_msb;
+};
+
+/*!
+ * @brief Accel self test difference data structure
+ */
+struct bma4_selftest_delta_limit
+{
+ /*! Accel X data */
+ int32_t x;
+
+ /*! Accel Y data */
+ int32_t y;
+
+ /*! Accel Z data */
+ int32_t z;
+};
+
+/*! @name Structure to enable an accel axis for FOC */
+struct bma4_accel_foc_g_value
+{
+ /* '0' to disable x-axis and '1' to enable x-axis */
+ uint8_t x;
+
+ /* '0' to disable y-axis and '1' to enable y-axis */
+ uint8_t y;
+
+ /* '0' to disable z-axis and '1' to enable z-axis */
+ uint8_t z;
+
+ /* '0' for positive input and '1' for negative input */
+ uint8_t sign;
+};
+
+/*! @name Structure to store temporary accelerometer values */
+struct bma4_foc_temp_value
+{
+ /*! X data */
+ int32_t x;
+
+ /*! Y data */
+ int32_t y;
+
+ /*! Z data */
+ int32_t z;
+};
+
+/* Structure to store temporary axes data values */
+struct bma4_temp_axes_val
+{
+ /* X data */
+ int32_t x;
+
+ /* Y data */
+ int32_t y;
+
+ /* Z data */
+ int32_t z;
+};
+
+#endif /* End of BMA4_DEFS_H__ */
diff --git a/src/main.cpp b/src/main.cpp
index bd4bbe79..f1d1bcf7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -26,6 +26,7 @@
#include <task.h>
#include <timers.h>
#include <drivers/Hrs3300.h>
+#include <drivers/Bma421.h>
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
@@ -60,6 +61,7 @@ static constexpr uint8_t pinLcdDataCommand = 18;
static constexpr uint8_t pinTwiScl = 7;
static constexpr uint8_t pinTwiSda = 6;
static constexpr uint8_t touchPanelTwiAddress = 0x15;
+static constexpr uint8_t motionSensorTwiAddress = 0x18;
static constexpr uint8_t heartRateSensorTwiAddress = 0x44;
Pinetime::Drivers::SpiMaster spi{Pinetime::Drivers::SpiMaster::SpiModule::SPI0, {
@@ -98,7 +100,7 @@ static constexpr bool isFactory = false;
Pinetime::Components::LittleVgl lvgl {lcd, touchPanel};
#endif
-
+Pinetime::Drivers::Bma421 motionSensor{twiMaster, motionSensorTwiAddress};
Pinetime::Drivers::Hrs3300 heartRateSensor {twiMaster, heartRateSensorTwiAddress};
@@ -257,7 +259,7 @@ int main(void) {
debounceTimer = xTimerCreate ("debounceTimer", 200, pdFALSE, (void *) 0, DebounceTimerCallback);
systemTask = std::make_unique<Pinetime::System::SystemTask>(spi, lcd, spiNorFlash, twiMaster, touchPanel, lvgl, batteryController, bleController,
- dateTimeController, motorController, heartRateSensor, settingsController);
+ dateTimeController, motorController, heartRateSensor, motionSensor, settingsController);
systemTask->Start();
nimble_port_init();
diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp
index 7b137f55..bf1839c7 100644
--- a/src/systemtask/SystemTask.cpp
+++ b/src/systemtask/SystemTask.cpp
@@ -43,13 +43,14 @@ SystemTask::SystemTask(Drivers::SpiMaster &spi, Drivers::St7789 &lcd,
Controllers::DateTime &dateTimeController,
Pinetime::Controllers::MotorController& motorController,
Pinetime::Drivers::Hrs3300& heartRateSensor,
+ Pinetime::Drivers::Bma421& motionSensor,
Controllers::Settings &settingsController) :
spi{spi}, lcd{lcd}, spiNorFlash{spiNorFlash},
twiMaster{twiMaster}, touchPanel{touchPanel}, lvgl{lvgl}, batteryController{batteryController},
heartRateController{*this},
bleController{bleController}, dateTimeController{dateTimeController},
watchdog{}, watchdogView{watchdog},
- motorController{motorController}, heartRateSensor{heartRateSensor},
+ motorController{motorController}, heartRateSensor{heartRateSensor}, motionSensor{motionSensor},
settingsController{settingsController},
nimbleController(*this, bleController,dateTimeController, notificationManager, batteryController, spiNorFlash, heartRateController) {
systemTasksMsgQueue = xQueueCreate(10, 1);
@@ -84,13 +85,14 @@ void SystemTask::Work() {
touchPanel.Init();
batteryController.Init();
motorController.Init();
+ motionSensor.Init();
settingsController.Init();
displayApp = std::make_unique<Pinetime::Applications::DisplayApp>(lcd, lvgl, touchPanel, batteryController, bleController,
dateTimeController, watchdogView, *this, notificationManager,
- heartRateController, settingsController);
+ heartRateController, settingsController, motionController);
displayApp->Start();
batteryController.Update();
@@ -132,8 +134,10 @@ void SystemTask::Work() {
#pragma clang diagnostic push
#pragma ide diagnostic ignored "EndlessLoop"
while(true) {
+ UpdateMotion();
+
uint8_t msg;
- if (xQueueReceive(systemTasksMsgQueue, &msg, isSleeping ? 2500 : 1000)) {
+ if (xQueueReceive(systemTasksMsgQueue, &msg, 100)) {
batteryController.Update();
Messages message = static_cast<Messages >(msg);
switch(message) {
@@ -230,6 +234,23 @@ void SystemTask::Work() {
// Clear diagnostic suppression
#pragma clang diagnostic pop
}
+void SystemTask::UpdateMotion() {
+ if(isGoingToSleep or isWakingUp) return;
+
+ if(isSleeping)
+ twiMaster.Wakeup();
+ auto motionValues = motionSensor.Process();
+ if(isSleeping)
+ twiMaster.Sleep();
+
+ motionController.Update(motionValues.y,
+ motionValues.x,
+ motionValues.z,
+ motionValues.steps);
+ if (motionController.ShouldWakeUp(isSleeping)) {
+ GoToRunning();
+ }
+}
void SystemTask::OnButtonPushed() {
if(isGoingToSleep) return;
@@ -247,6 +268,7 @@ void SystemTask::OnButtonPushed() {
}
void SystemTask::GoToRunning() {
+ if(isGoingToSleep or (not isSleeping) or isWakingUp) return;
isWakingUp = true;
PushMessage(Messages::GoToRunning);
}
diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h
index cc693735..2b70d19a 100644
--- a/src/systemtask/SystemTask.h
+++ b/src/systemtask/SystemTask.h
@@ -8,6 +8,8 @@
#include <heartratetask/HeartRateTask.h>
#include <components/heartrate/HeartRateController.h>
#include <components/settings/Settings.h>
+#include <drivers/Bma421.h>
+#include <components/motion/MotionController.h>
#include "SystemMonitor.h"
#include "components/battery/BatteryController.h"
@@ -49,6 +51,7 @@ namespace Pinetime {
Controllers::DateTime &dateTimeController,
Pinetime::Controllers::MotorController& motorController,
Pinetime::Drivers::Hrs3300& heartRateSensor,
+ Pinetime::Drivers::Bma421& motionSensor,
Controllers::Settings &settingsController);
@@ -87,9 +90,11 @@ namespace Pinetime {
Pinetime::Controllers::NotificationManager notificationManager;
Pinetime::Controllers::MotorController& motorController;
Pinetime::Drivers::Hrs3300& heartRateSensor;
+ Pinetime::Drivers::Bma421& motionSensor;
Pinetime::Controllers::Settings& settingsController;
Pinetime::Controllers::NimbleController nimbleController;
Controllers::BrightnessController brightnessController;
+ Pinetime::Controllers::MotionController motionController;
static constexpr uint8_t pinSpiSck = 2;
static constexpr uint8_t pinSpiMosi = 3;
@@ -109,6 +114,7 @@ namespace Pinetime {
bool doNotGoToSleep = false;
void GoToRunning();
+ void UpdateMotion();
#if configUSE_TRACE_FACILITY == 1
SystemMonitor<FreeRtosMonitor> monitor;