diff --git a/libesp32/TTGO_TWatch_Library/LICENSE b/libesp32/TTGO_TWatch_Library/LICENSE
new file mode 100755
index 000000000..630942bc6
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 TTGO
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/libesp32/TTGO_TWatch_Library/README.MD b/libesp32/TTGO_TWatch_Library/README.MD
new file mode 100755
index 000000000..9e8d6ed0e
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/README.MD
@@ -0,0 +1,62 @@
+
🌟LilyGO T-Watch🌟
+
+**English | [中文](docs/details_cn.md)**
+
+
+⭐ News
+
+1. In order to be compatible with multiple versions of T-Watch, all examples include a `config.h` file. For the first use, you need to define the **T-Watch** model you use in the `config.h` file
+2. In the `config.h` file, you can also see similar definitions, such as **LILYGO_WATCH_LVGL**, **LILYGO_WATCH_HAS_MOTOR**, this type of definition, it will be responsible for opening the defined module function, all definitions Will be available here [View](./docs/defined_en.md)
+3. Most of the examples are only used as hardware function demonstrations. This library only completes some initialization work and some demonstrations. For more advanced gameplay, please see [TTGO.h](https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library/blob/master/src/TTGO.h), to understand how to initialize, after being familiar with it, you can completely leave this library for more advanced gameplay
+- About API, please check the source code
+
+🚀 Characteristics
+
+1. The library already contains all the hardware drivers for `T-Watch`
+2. Using **TFT_eSPI** as the display driver, you can directly call **TFT_eSPI** through the construction object.
+3. Using **lvgl 7.0.0** as the display graphics framework, the driver method has been implemented, you only need to call lvgl api according to your own needs.
+4. For the use of lvgl please refer to **[lvgl docs](https://docs.lvgl.io/v7/en/html/)**
+
+
+🔷 Install
+
+- Download a zipfile from github using the "Download ZIP" button and install it using the IDE ("Sketch" -> "Include Library" -> "Add .ZIP Library..."
+- Clone this git repository into your sketchbook/libraries folder.
+For more info, see https://www.arduino.cc/en/Guide/Libraries
+
+
+🔶 How to find the sample program
+
+- In the Arduino board select `TTGO T-Watch`
+- In the Arduino File -> Examples -> TTGO T-Watch
+
+🔷 Note
+
+- If you don't have the `TTGO T-Watch` option in your board manager, please update the esp32 board as follows:
+ - Using Arduino IDE Boards Manager (preferred)
+ + [Instructions for Boards Manager](docs/arduino-ide/boards_manager.md)
+ - Using Arduino IDE with the development repository
+ + [Instructions for Windows](docs/arduino-ide/windows.md)
+ + [Instructions for Mac](docs/arduino-ide/mac.md)
+ + [Instructions for Debian/Ubuntu Linux](docs/arduino-ide/debian_ubuntu.md)
+ + [Instructions for Fedora](docs/arduino-ide/fedora.md)
+ + [Instructions for openSUSE](docs/arduino-ide/opensuse.md)
+
+ 🔶 Precautions
+
+- T-Watch-2019 : Since Twatch uses a special IO as the SD interface, please remove the SD card when downloading the program.
+
+
+ 🔷 Other
+
+- [Click for details of power consumption](docs/power.md)
+- [Pin Map Click to View](docs/pinmap.md)
+- [3D Shell](https://github.com/Xinyuan-LilyGO/LilyGo-TWatch-DataSheet/tree/master/3DSHELL)
+- [Hardware Resource](https://github.com/Xinyuan-LilyGO/LilyGo-TWatch-DataSheet)
+- [Acsip S76/78 Library&Examples](https://github.com/lewisxhe/Acsip-S7xG-Library)
+
+ 🔶 More interesting projects
+
+- [Flight Recorder](https://github.com/lyusupov/SoftRF/wiki/Flight-Recorder)
+- [TTGO_T_Watch_Baidu_Rec](https://github.com/lixy123/TTGO_T_Watch_Baidu_Rec)
+- [TTGO_T_Watch_Alarm_Clock](https://github.com/lixy123/TTGO_T_Watch_Alarm_Clock)
diff --git a/libesp32/TTGO_TWatch_Library/library.json b/libesp32/TTGO_TWatch_Library/library.json
new file mode 100755
index 000000000..b56343ca9
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/library.json
@@ -0,0 +1,25 @@
+{
+ "name": "TTGO TWatch Library",
+ "keywords": "Device Conterl,TWatch,Watch,TTGO",
+ "description": "Arduino Library for TTGO T-Watch development kit",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library.git"
+ },
+ "authors": [
+ {
+ "name": "Xinyuan Electronics",
+ "email": "lily@lilygo.cc",
+ "url": "https://github.com/Xinyuan-LilyGO",
+ "maintainer": true
+ },
+ {
+ "name": "lewishe",
+ "email": "lewishe@outlook.com",
+ "url": "https://github.com/lewisxhe"
+ }
+ ],
+ "version": "1.2.0",
+ "frameworks": "arduino",
+ "platforms": "esp32"
+}
\ No newline at end of file
diff --git a/libesp32/TTGO_TWatch_Library/library.properties b/libesp32/TTGO_TWatch_Library/library.properties
new file mode 100755
index 000000000..ec44a9e27
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/library.properties
@@ -0,0 +1,10 @@
+name=TTGO TWatch Library
+version=1.2.0
+author=TTGO
+maintainer=lewis he
+sentence=Library for TTGO T-Watch development kit
+paragraph=twatch library
+category=Device Control
+url=https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library
+architectures=esp32
+includes=*
diff --git a/libesp32/TTGO_TWatch_Library/src/axp20x.cpp b/libesp32/TTGO_TWatch_Library/src/axp20x.cpp
new file mode 100755
index 000000000..0adf4faf3
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/src/axp20x.cpp
@@ -0,0 +1,1800 @@
+/////////////////////////////////////////////////////////////////
+/*
+MIT License
+
+Copyright (c) 2019 lewis he
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+axp20x.cpp - Arduino library for X-Power AXP202 chip.
+Created by Lewis he on April 1, 2019.
+github:https://github.com/lewisxhe/AXP202X_Libraries
+*/
+/////////////////////////////////////////////////////////////////
+
+#include "axp20x.h"
+#include
+
+const uint8_t AXP20X_Class::startupParams[] = {
+ 0b00000000,
+ 0b01000000,
+ 0b10000000,
+ 0b11000000
+};
+
+const uint8_t AXP20X_Class::longPressParams[] = {
+ 0b00000000,
+ 0b00010000,
+ 0b00100000,
+ 0b00110000
+};
+
+const uint8_t AXP20X_Class::shutdownParams[] = {
+ 0b00000000,
+ 0b00000001,
+ 0b00000010,
+ 0b00000011
+};
+
+const uint8_t AXP20X_Class::targetVolParams[] = {
+ 0b00000000,
+ 0b00100000,
+ 0b01000000,
+ 0b01100000
+};
+
+
+
+// Power Output Control register
+uint8_t AXP20X_Class::_outputReg;
+
+int AXP20X_Class::_axp_probe()
+{
+ uint8_t data;
+ if (_isAxp173) {
+ //!Axp173 does not have a chip ID, read the status register to see if it reads normally
+ _readByte(0x01, 1, &data);
+ if (data == 0 || data == 0xFF) {
+ return AXP_FAIL;
+ }
+ _chip_id = AXP173_CHIP_ID;
+ _readByte(AXP202_LDO234_DC23_CTL, 1, &_outputReg);
+ AXP_DEBUG("OUTPUT Register 0x%x\n", _outputReg);
+ _init = true;
+ return AXP_PASS;
+ }
+ _readByte(AXP202_IC_TYPE, 1, &_chip_id);
+ AXP_DEBUG("chip id detect 0x%x\n", _chip_id);
+ if (_chip_id == AXP202_CHIP_ID || _chip_id == AXP192_CHIP_ID) {
+ AXP_DEBUG("Detect CHIP :%s\n", _chip_id == AXP202_CHIP_ID ? "AXP202" : "AXP192");
+ _readByte(AXP202_LDO234_DC23_CTL, 1, &_outputReg);
+ AXP_DEBUG("OUTPUT Register 0x%x\n", _outputReg);
+ _init = true;
+ return AXP_PASS;
+ }
+ return AXP_FAIL;
+}
+
+int AXP20X_Class::begin(TwoWire &port, uint8_t addr, bool isAxp173)
+{
+ _i2cPort = &port; //Grab which port the user wants us to use
+ _address = addr;
+ _isAxp173 = isAxp173;
+
+ return _axp_probe();
+}
+
+int AXP20X_Class::begin(axp_com_fptr_t read_cb, axp_com_fptr_t write_cb, uint8_t addr, bool isAxp173)
+{
+ if (read_cb == nullptr || write_cb == nullptr)return AXP_FAIL;
+ _read_cb = read_cb;
+ _write_cb = write_cb;
+ _address = addr;
+ _isAxp173 = isAxp173;
+ return _axp_probe();
+}
+
+//Only axp192 chip
+bool AXP20X_Class::isDCDC1Enable()
+{
+ if (_chip_id == AXP192_CHIP_ID)
+ return IS_OPEN(_outputReg, AXP192_DCDC1);
+ else if (_chip_id == AXP173_CHIP_ID)
+ return IS_OPEN(_outputReg, AXP173_DCDC1);
+ return false;
+}
+
+bool AXP20X_Class::isExtenEnable()
+{
+ if (_chip_id == AXP192_CHIP_ID)
+ return IS_OPEN(_outputReg, AXP192_EXTEN);
+ else if (_chip_id == AXP202_CHIP_ID)
+ return IS_OPEN(_outputReg, AXP202_EXTEN);
+ else if (_chip_id == AXP173_CHIP_ID) {
+ uint8_t data;
+ _readByte(AXP173_EXTEN_DC2_CTL, 1, &data);
+ return IS_OPEN(data, AXP173_CTL_EXTEN_BIT);
+ }
+ return false;
+}
+
+bool AXP20X_Class::isLDO2Enable()
+{
+ if (_chip_id == AXP173_CHIP_ID) {
+ return IS_OPEN(_outputReg, AXP173_LDO2);
+ }
+ //axp192 same axp202 ldo2 bit
+ return IS_OPEN(_outputReg, AXP202_LDO2);
+}
+
+bool AXP20X_Class::isLDO3Enable()
+{
+ if (_chip_id == AXP192_CHIP_ID)
+ return IS_OPEN(_outputReg, AXP192_LDO3);
+ else if (_chip_id == AXP202_CHIP_ID)
+ return IS_OPEN(_outputReg, AXP202_LDO3);
+ else if (_chip_id == AXP173_CHIP_ID)
+ return IS_OPEN(_outputReg, AXP173_LDO3);
+ return false;
+}
+
+bool AXP20X_Class::isLDO4Enable()
+{
+ if (_chip_id == AXP202_CHIP_ID)
+ return IS_OPEN(_outputReg, AXP202_LDO4);
+ if (_chip_id == AXP173_CHIP_ID)
+ return IS_OPEN(_outputReg, AXP173_LDO4);
+ return false;
+}
+
+bool AXP20X_Class::isDCDC2Enable()
+{
+ if (_chip_id == AXP173_CHIP_ID) {
+ uint8_t data;
+ _readByte(AXP173_EXTEN_DC2_CTL, 1, &data);
+ return IS_OPEN(data, AXP173_CTL_DC2_BIT);
+ }
+ //axp192 same axp202 dc2 bit
+ return IS_OPEN(_outputReg, AXP202_DCDC2);
+}
+
+bool AXP20X_Class::isDCDC3Enable()
+{
+ if (_chip_id == AXP173_CHIP_ID)
+ return false;
+ //axp192 same axp202 dc3 bit
+ return IS_OPEN(_outputReg, AXP202_DCDC3);
+}
+
+int AXP20X_Class::setPowerOutPut(uint8_t ch, bool en)
+{
+ uint8_t data;
+ uint8_t val = 0;
+ if (!_init)
+ return AXP_NOT_INIT;
+
+ //! Axp173 cannot use the REG12H register to control
+ //! DC2 and EXTEN. It is necessary to control REG10H separately.
+ if (_chip_id == AXP173_CHIP_ID) {
+ _readByte(AXP173_EXTEN_DC2_CTL, 1, &data);
+ if (ch & AXP173_DCDC2) {
+ data = en ? data | BIT_MASK(AXP173_CTL_DC2_BIT) : data & (~BIT_MASK(AXP173_CTL_DC2_BIT));
+ ch &= (~BIT_MASK(AXP173_DCDC2));
+ _writeByte(AXP173_EXTEN_DC2_CTL, 1, &data);
+ } else if (ch & AXP173_EXTEN) {
+ data = en ? data | BIT_MASK(AXP173_CTL_EXTEN_BIT) : data & (~BIT_MASK(AXP173_CTL_EXTEN_BIT));
+ ch &= (~BIT_MASK(AXP173_EXTEN));
+ _writeByte(AXP173_EXTEN_DC2_CTL, 1, &data);
+ }
+ }
+
+ _readByte(AXP202_LDO234_DC23_CTL, 1, &data);
+ if (en) {
+ data |= (1 << ch);
+ } else {
+ data &= (~(1 << ch));
+ }
+
+ if (_chip_id == AXP202_CHIP_ID) {
+ FORCED_OPEN_DCDC3(data); //! Must be forced open in T-Watch
+ }
+
+ _writeByte(AXP202_LDO234_DC23_CTL, 1, &data);
+ delay(1);
+ _readByte(AXP202_LDO234_DC23_CTL, 1, &val);
+ if (data == val) {
+ _outputReg = val;
+ return AXP_PASS;
+ }
+ return AXP_FAIL;
+}
+
+bool AXP20X_Class::isChargeing()
+{
+ uint8_t reg;
+ if (!_init)
+ return AXP_NOT_INIT;
+ _readByte(AXP202_MODE_CHGSTATUS, 1, ®);
+ return IS_OPEN(reg, 6);
+}
+
+bool AXP20X_Class::isBatteryConnect()
+{
+ uint8_t reg;
+ if (!_init)
+ return AXP_NOT_INIT;
+ _readByte(AXP202_MODE_CHGSTATUS, 1, ®);
+ return IS_OPEN(reg, 5);
+}
+
+float AXP20X_Class::getAcinVoltage()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ return _getRegistResult(AXP202_ACIN_VOL_H8, AXP202_ACIN_VOL_L4) * AXP202_ACIN_VOLTAGE_STEP;
+}
+
+float AXP20X_Class::getAcinCurrent()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ return _getRegistResult(AXP202_ACIN_CUR_H8, AXP202_ACIN_CUR_L4) * AXP202_ACIN_CUR_STEP;
+}
+
+float AXP20X_Class::getVbusVoltage()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ return _getRegistResult(AXP202_VBUS_VOL_H8, AXP202_VBUS_VOL_L4) * AXP202_VBUS_VOLTAGE_STEP;
+}
+
+float AXP20X_Class::getVbusCurrent()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ return _getRegistResult(AXP202_VBUS_CUR_H8, AXP202_VBUS_CUR_L4) * AXP202_VBUS_CUR_STEP;
+}
+
+float AXP20X_Class::getTemp()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ return _getRegistResult(AXP202_INTERNAL_TEMP_H8, AXP202_INTERNAL_TEMP_L4) * AXP202_INTERNAL_TEMP_STEP;
+}
+
+float AXP20X_Class::getTSTemp()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ return _getRegistResult(AXP202_TS_IN_H8, AXP202_TS_IN_L4) * AXP202_TS_PIN_OUT_STEP;
+}
+
+float AXP20X_Class::getGPIO0Voltage()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ return _getRegistResult(AXP202_GPIO0_VOL_ADC_H8, AXP202_GPIO0_VOL_ADC_L4) * AXP202_GPIO0_STEP;
+}
+
+float AXP20X_Class::getGPIO1Voltage()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ return _getRegistResult(AXP202_GPIO1_VOL_ADC_H8, AXP202_GPIO1_VOL_ADC_L4) * AXP202_GPIO1_STEP;
+}
+
+/*
+Note: the battery power formula:
+Pbat =2* register value * Voltage LSB * Current LSB / 1000.
+(Voltage LSB is 1.1mV; Current LSB is 0.5mA, and unit of calculation result is mW.)
+*/
+float AXP20X_Class::getBattInpower()
+{
+ float rslt;
+ uint8_t hv, mv, lv;
+ if (!_init)
+ return AXP_NOT_INIT;
+ _readByte(AXP202_BAT_POWERH8, 1, &hv);
+ _readByte(AXP202_BAT_POWERM8, 1, &mv);
+ _readByte(AXP202_BAT_POWERL8, 1, &lv);
+ rslt = (hv << 16) | (mv << 8) | lv;
+ rslt = 2 * rslt * 1.1 * 0.5 / 1000;
+ return rslt;
+}
+
+float AXP20X_Class::getBattVoltage()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ return _getRegistResult(AXP202_BAT_AVERVOL_H8, AXP202_BAT_AVERVOL_L4) * AXP202_BATT_VOLTAGE_STEP;
+}
+
+float AXP20X_Class::getBattChargeCurrent()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ switch (_chip_id) {
+ case AXP202_CHIP_ID:
+ return _getRegistResult(AXP202_BAT_AVERCHGCUR_H8, AXP202_BAT_AVERCHGCUR_L4) * AXP202_BATT_CHARGE_CUR_STEP;
+ case AXP192_CHIP_ID:
+ return _getRegistH8L5(AXP202_BAT_AVERCHGCUR_H8, AXP202_BAT_AVERCHGCUR_L5) * AXP202_BATT_CHARGE_CUR_STEP;
+ default:
+ return AXP_FAIL;
+ }
+}
+
+float AXP20X_Class::getBattDischargeCurrent()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ return _getRegistH8L5(AXP202_BAT_AVERDISCHGCUR_H8, AXP202_BAT_AVERDISCHGCUR_L5) * AXP202_BATT_DISCHARGE_CUR_STEP;
+}
+
+float AXP20X_Class::getSysIPSOUTVoltage()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ return _getRegistResult(AXP202_APS_AVERVOL_H8, AXP202_APS_AVERVOL_L4);
+}
+
+/*
+Coulomb calculation formula:
+C= 65536 * current LSB *(charge coulomb counter value - discharge coulomb counter value) /
+3600 / ADC sample rate. Refer to REG84H setting for ADC sample rate;the current LSB is
+0.5mA;unit of the calculation result is mAh. )
+*/
+uint32_t AXP20X_Class::getBattChargeCoulomb()
+{
+ uint8_t buffer[4];
+ if (!_init)
+ return AXP_NOT_INIT;
+ _readByte(0xB0, 4, buffer);
+ return (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3];
+}
+
+uint32_t AXP20X_Class::getBattDischargeCoulomb()
+{
+ uint8_t buffer[4];
+ if (!_init)
+ return AXP_NOT_INIT;
+ _readByte(0xB4, 4, buffer);
+ return (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3];
+}
+
+float AXP20X_Class::getCoulombData()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ uint32_t charge = getBattChargeCoulomb(), discharge = getBattDischargeCoulomb();
+ uint8_t rate = getAdcSamplingRate();
+ float result = 65536.0 * 0.5 * (charge - discharge) / 3600.0 / rate;
+ return result;
+}
+
+
+//-------------------------------------------------------
+// New Coulomb functions by MrFlexi
+//-------------------------------------------------------
+
+uint8_t AXP20X_Class::getCoulombRegister()
+{
+ uint8_t buffer;
+ if (!_init)
+ return AXP_NOT_INIT;
+ _readByte(AXP202_COULOMB_CTL, 1, &buffer);
+ return buffer;
+}
+
+
+int AXP20X_Class::setCoulombRegister(uint8_t val)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ _writeByte(AXP202_COULOMB_CTL, 1, &val);
+ return AXP_PASS;
+}
+
+
+int AXP20X_Class::EnableCoulombcounter(void)
+{
+
+ if (!_init)
+ return AXP_NOT_INIT;
+ uint8_t val = 0x80;
+ _writeByte(AXP202_COULOMB_CTL, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::DisableCoulombcounter(void)
+{
+
+ if (!_init)
+ return AXP_NOT_INIT;
+ uint8_t val = 0x00;
+ _writeByte(AXP202_COULOMB_CTL, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::StopCoulombcounter(void)
+{
+
+ if (!_init)
+ return AXP_NOT_INIT;
+ uint8_t val = 0xB8;
+ _writeByte(AXP202_COULOMB_CTL, 1, &val);
+ return AXP_PASS;
+}
+
+
+int AXP20X_Class::ClearCoulombcounter(void)
+{
+
+ if (!_init)
+ return AXP_NOT_INIT;
+ uint8_t val = 0xA0;
+ _writeByte(AXP202_COULOMB_CTL, 1, &val);
+ return AXP_PASS;
+}
+
+//-------------------------------------------------------
+// END
+//-------------------------------------------------------
+
+
+
+uint8_t AXP20X_Class::getAdcSamplingRate()
+{
+ //axp192 same axp202 aregister address 0x84
+ if (!_init)
+ return AXP_NOT_INIT;
+ uint8_t val;
+ _readByte(AXP202_ADC_SPEED, 1, &val);
+ return 25 * (int)pow(2, (val & 0xC0) >> 6);
+}
+
+int AXP20X_Class::setAdcSamplingRate(axp_adc_sampling_rate_t rate)
+{
+ //axp192 same axp202 aregister address 0x84
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (rate > AXP_ADC_SAMPLING_RATE_200HZ)
+ return AXP_FAIL;
+ uint8_t val;
+ _readByte(AXP202_ADC_SPEED, 1, &val);
+ uint8_t rw = rate;
+ val &= 0x3F;
+ val |= (rw << 6);
+ _writeByte(AXP202_ADC_SPEED, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::setTSfunction(axp_ts_pin_function_t func)
+{
+ //axp192 same axp202 aregister address 0x84
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (func > AXP_TS_PIN_FUNCTION_ADC)
+ return AXP_FAIL;
+ uint8_t val;
+ _readByte(AXP202_ADC_SPEED, 1, &val);
+ uint8_t rw = func;
+ val &= 0xFA;
+ val |= (rw << 2);
+ _writeByte(AXP202_ADC_SPEED, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::setTScurrent(axp_ts_pin_current_t current)
+{
+ //axp192 same axp202 aregister address 0x84
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (current > AXP_TS_PIN_CURRENT_80UA)
+ return AXP_FAIL;
+ uint8_t val;
+ _readByte(AXP202_ADC_SPEED, 1, &val);
+ uint8_t rw = current;
+ val &= 0xCF;
+ val |= (rw << 4);
+ _writeByte(AXP202_ADC_SPEED, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::setTSmode(axp_ts_pin_mode_t mode)
+{
+ //axp192 same axp202 aregister address 0x84
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (mode > AXP_TS_PIN_MODE_ENABLE)
+ return AXP_FAIL;
+ uint8_t val;
+ _readByte(AXP202_ADC_SPEED, 1, &val);
+ uint8_t rw = mode;
+ val &= 0xFC;
+ val |= rw;
+ _writeByte(AXP202_ADC_SPEED, 1, &val);
+
+ // TS pin ADC function enable/disable
+ if (mode == AXP_TS_PIN_MODE_DISABLE)
+ adc1Enable(AXP202_TS_PIN_ADC1, false);
+ else
+ adc1Enable(AXP202_TS_PIN_ADC1, true);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::adc1Enable(uint16_t params, bool en)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ uint8_t val;
+ _readByte(AXP202_ADC_EN1, 1, &val);
+ if (en)
+ val |= params;
+ else
+ val &= ~(params);
+ _writeByte(AXP202_ADC_EN1, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::adc2Enable(uint16_t params, bool en)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ uint8_t val;
+ _readByte(AXP202_ADC_EN2, 1, &val);
+ if (en)
+ val |= params;
+ else
+ val &= ~(params);
+ _writeByte(AXP202_ADC_EN2, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::enableIRQ(uint64_t params, bool en)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ uint8_t val, val1;
+ if (params & 0xFF) {
+ val1 = params & 0xFF;
+ _readByte(AXP202_INTEN1, 1, &val);
+ if (en)
+ val |= val1;
+ else
+ val &= ~(val1);
+ AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN1, val);
+ _writeByte(AXP202_INTEN1, 1, &val);
+ }
+ if (params & 0xFF00) {
+ val1 = params >> 8;
+ _readByte(AXP202_INTEN2, 1, &val);
+ if (en)
+ val |= val1;
+ else
+ val &= ~(val1);
+ AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN2, val);
+ _writeByte(AXP202_INTEN2, 1, &val);
+ }
+
+ if (params & 0xFF0000) {
+ val1 = params >> 16;
+ _readByte(AXP202_INTEN3, 1, &val);
+ if (en)
+ val |= val1;
+ else
+ val &= ~(val1);
+ AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN3, val);
+ _writeByte(AXP202_INTEN3, 1, &val);
+ }
+
+ if (params & 0xFF000000) {
+ val1 = params >> 24;
+ _readByte(AXP202_INTEN4, 1, &val);
+ if (en)
+ val |= val1;
+ else
+ val &= ~(val1);
+ AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN4, val);
+ _writeByte(AXP202_INTEN4, 1, &val);
+ }
+
+ if (params & 0xFF00000000) {
+ val1 = params >> 32;
+ _readByte(AXP202_INTEN5, 1, &val);
+ if (en)
+ val |= val1;
+ else
+ val &= ~(val1);
+ AXP_DEBUG("%s [0x%x]val:0x%x\n", en ? "enable" : "disable", AXP202_INTEN5, val);
+ _writeByte(AXP202_INTEN5, 1, &val);
+ }
+ return AXP_PASS;
+}
+
+int AXP20X_Class::readIRQ()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ switch (_chip_id) {
+ case AXP192_CHIP_ID:
+ for (int i = 0; i < 4; ++i) {
+ _readByte(AXP192_INTSTS1 + i, 1, &_irq[i]);
+ }
+ _readByte(AXP192_INTSTS5, 1, &_irq[4]);
+ return AXP_PASS;
+
+ case AXP202_CHIP_ID:
+ for (int i = 0; i < 5; ++i) {
+ _readByte(AXP202_INTSTS1 + i, 1, &_irq[i]);
+ }
+ return AXP_PASS;
+ default:
+ return AXP_FAIL;
+ }
+}
+
+void AXP20X_Class::clearIRQ()
+{
+ uint8_t val = 0xFF;
+ switch (_chip_id) {
+ case AXP192_CHIP_ID:
+ for (int i = 0; i < 3; i++) {
+ _writeByte(AXP192_INTSTS1 + i, 1, &val);
+ }
+ _writeByte(AXP192_INTSTS5, 1, &val);
+ break;
+ case AXP202_CHIP_ID:
+ for (int i = 0; i < 5; i++) {
+ _writeByte(AXP202_INTSTS1 + i, 1, &val);
+ }
+ break;
+ default:
+ break;
+ }
+ memset(_irq, 0, sizeof(_irq));
+}
+
+bool AXP20X_Class::isAcinOverVoltageIRQ()
+{
+ return (bool)(_irq[0] & BIT_MASK(7));
+}
+
+bool AXP20X_Class::isAcinPlugInIRQ()
+{
+ return (bool)(_irq[0] & BIT_MASK(6));
+}
+
+bool AXP20X_Class::isAcinRemoveIRQ()
+{
+ return (bool)(_irq[0] & BIT_MASK(5));
+}
+
+bool AXP20X_Class::isVbusOverVoltageIRQ()
+{
+ return (bool)(_irq[0] & BIT_MASK(4));
+}
+
+bool AXP20X_Class::isVbusPlugInIRQ()
+{
+ return (bool)(_irq[0] & BIT_MASK(3));
+}
+
+bool AXP20X_Class::isVbusRemoveIRQ()
+{
+ return (bool)(_irq[0] & BIT_MASK(2));
+}
+
+bool AXP20X_Class::isVbusLowVHOLDIRQ()
+{
+ return (bool)(_irq[0] & BIT_MASK(1));
+}
+
+bool AXP20X_Class::isBattPlugInIRQ()
+{
+ return (bool)(_irq[1] & BIT_MASK(7));
+}
+bool AXP20X_Class::isBattRemoveIRQ()
+{
+ return (bool)(_irq[1] & BIT_MASK(6));
+}
+bool AXP20X_Class::isBattEnterActivateIRQ()
+{
+ return (bool)(_irq[1] & BIT_MASK(5));
+}
+bool AXP20X_Class::isBattExitActivateIRQ()
+{
+ return (bool)(_irq[1] & BIT_MASK(4));
+}
+bool AXP20X_Class::isChargingIRQ()
+{
+ return (bool)(_irq[1] & BIT_MASK(3));
+}
+bool AXP20X_Class::isChargingDoneIRQ()
+{
+ return (bool)(_irq[1] & BIT_MASK(2));
+}
+bool AXP20X_Class::isBattTempLowIRQ()
+{
+ return (bool)(_irq[1] & BIT_MASK(1));
+}
+bool AXP20X_Class::isBattTempHighIRQ()
+{
+ return (bool)(_irq[1] & BIT_MASK(0));
+}
+
+bool AXP20X_Class::isPEKShortPressIRQ()
+{
+ return (bool)(_irq[2] & BIT_MASK(1));
+}
+
+bool AXP20X_Class::isPEKLongtPressIRQ()
+{
+ return (bool)(_irq[2] & BIT_MASK(0));
+}
+
+bool AXP20X_Class::isTimerTimeoutIRQ()
+{
+ return (bool)(_irq[4] & BIT_MASK(7));
+}
+
+bool AXP20X_Class::isVBUSPlug()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ uint8_t reg;
+ _readByte(AXP202_STATUS, 1, ®);
+ return IS_OPEN(reg, 5);
+}
+
+int AXP20X_Class::setDCDC2Voltage(uint16_t mv)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (mv < 700) {
+ AXP_DEBUG("DCDC2:Below settable voltage:700mV~2275mV");
+ mv = 700;
+ }
+ if (mv > 2275) {
+ AXP_DEBUG("DCDC2:Above settable voltage:700mV~2275mV");
+ mv = 2275;
+ }
+ uint8_t val = (mv - 700) / 25;
+ //! axp173/192/202 same register
+ _writeByte(AXP202_DC2OUT_VOL, 1, &val);
+ return AXP_PASS;
+}
+
+uint16_t AXP20X_Class::getDCDC2Voltage()
+{
+ uint8_t val = 0;
+ //! axp173/192/202 same register
+ _readByte(AXP202_DC2OUT_VOL, 1, &val);
+ return val * 25 + 700;
+}
+
+uint16_t AXP20X_Class::getDCDC3Voltage()
+{
+ if (!_init)
+ return 0;
+ if (_chip_id == AXP173_CHIP_ID)return AXP_NOT_SUPPORT;
+ uint8_t val = 0;
+ _readByte(AXP202_DC3OUT_VOL, 1, &val);
+ return val * 25 + 700;
+}
+
+int AXP20X_Class::setDCDC3Voltage(uint16_t mv)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (_chip_id == AXP173_CHIP_ID)return AXP_NOT_SUPPORT;
+ if (mv < 700) {
+ AXP_DEBUG("DCDC3:Below settable voltage:700mV~3500mV");
+ mv = 700;
+ }
+ if (mv > 3500) {
+ AXP_DEBUG("DCDC3:Above settable voltage:700mV~3500mV");
+ mv = 3500;
+ }
+ uint8_t val = (mv - 700) / 25;
+ _writeByte(AXP202_DC3OUT_VOL, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::setLDO2Voltage(uint16_t mv)
+{
+ uint8_t rVal, wVal;
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (mv < 1800) {
+ AXP_DEBUG("LDO2:Below settable voltage:1800mV~3300mV");
+ mv = 1800;
+ }
+ if (mv > 3300) {
+ AXP_DEBUG("LDO2:Above settable voltage:1800mV~3300mV");
+ mv = 3300;
+ }
+ wVal = (mv - 1800) / 100;
+ if (_chip_id == AXP202_CHIP_ID) {
+ _readByte(AXP202_LDO24OUT_VOL, 1, &rVal);
+ rVal &= 0x0F;
+ rVal |= (wVal << 4);
+ _writeByte(AXP202_LDO24OUT_VOL, 1, &rVal);
+ return AXP_PASS;
+ } else if (_chip_id == AXP192_CHIP_ID || _chip_id == AXP173_CHIP_ID) {
+ _readByte(AXP192_LDO23OUT_VOL, 1, &rVal);
+ rVal &= 0x0F;
+ rVal |= (wVal << 4);
+ _writeByte(AXP192_LDO23OUT_VOL, 1, &rVal);
+ return AXP_PASS;
+ }
+ return AXP_FAIL;
+}
+
+uint16_t AXP20X_Class::getLDO2Voltage()
+{
+ uint8_t rVal;
+ if (_chip_id == AXP202_CHIP_ID) {
+ _readByte(AXP202_LDO24OUT_VOL, 1, &rVal);
+ rVal &= 0xF0;
+ rVal >>= 4;
+ return rVal * 100 + 1800;
+ } else if (_chip_id == AXP192_CHIP_ID || _chip_id == AXP173_CHIP_ID ) {
+ _readByte(AXP192_LDO23OUT_VOL, 1, &rVal);
+ AXP_DEBUG("get result:%x\n", rVal);
+ rVal &= 0xF0;
+ rVal >>= 4;
+ return rVal * 100 + 1800;
+ }
+ return 0;
+}
+
+int AXP20X_Class::setLDO3Voltage(uint16_t mv)
+{
+ uint8_t rVal;
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (_chip_id == AXP202_CHIP_ID && mv < 700) {
+ AXP_DEBUG("LDO3:Below settable voltage:700mV~3500mV");
+ mv = 700;
+ } else if (_chip_id == AXP192_CHIP_ID && mv < 1800) {
+ AXP_DEBUG("LDO3:Below settable voltage:1800mV~3300mV");
+ mv = 1800;
+ }
+
+ if (_chip_id == AXP202_CHIP_ID && mv > 3500) {
+ AXP_DEBUG("LDO3:Above settable voltage:700mV~3500mV");
+ mv = 3500;
+ } else if (_chip_id == AXP192_CHIP_ID && mv > 3300) {
+ AXP_DEBUG("LDO3:Above settable voltage:1800mV~3300mV");
+ mv = 3300;
+ }
+
+ if (_chip_id == AXP202_CHIP_ID) {
+ _readByte(AXP202_LDO3OUT_VOL, 1, &rVal);
+ rVal &= 0x80;
+ rVal |= ((mv - 700) / 25);
+ _writeByte(AXP202_LDO3OUT_VOL, 1, &rVal);
+ return AXP_PASS;
+ } else if (_chip_id == AXP192_CHIP_ID || _chip_id == AXP173_CHIP_ID) {
+ _readByte(AXP192_LDO23OUT_VOL, 1, &rVal);
+ rVal &= 0xF0;
+ rVal |= ((mv - 1800) / 100);
+ _writeByte(AXP192_LDO23OUT_VOL, 1, &rVal);
+ return AXP_PASS;
+ }
+ return AXP_FAIL;
+}
+
+uint16_t AXP20X_Class::getLDO3Voltage()
+{
+ uint8_t rVal;
+ if (!_init)
+ return AXP_NOT_INIT;
+
+ if (_chip_id == AXP202_CHIP_ID) {
+ _readByte(AXP202_LDO3OUT_VOL, 1, &rVal);
+ if (rVal & 0x80) {
+ //! According to the hardware N_VBUSEN Pin selection
+ return getVbusVoltage() * 1000;
+ } else {
+ return (rVal & 0x7F) * 25 + 700;
+ }
+ } else if (_chip_id == AXP192_CHIP_ID || _chip_id == AXP173_CHIP_ID) {
+ _readByte(AXP192_LDO23OUT_VOL, 1, &rVal);
+ rVal &= 0x0F;
+ return rVal * 100 + 1800;
+ }
+ return 0;
+}
+
+//! Only axp173 support
+int AXP20X_Class::setLDO4Voltage(uint16_t mv)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (_chip_id != AXP173_CHIP_ID)
+ return AXP_FAIL;
+
+ if (mv < 700) {
+ AXP_DEBUG("LDO4:Below settable voltage:700mV~3500mV");
+ mv = 700;
+ }
+ if (mv > 3500) {
+ AXP_DEBUG("LDO4:Above settable voltage:700mV~3500mV");
+ mv = 3500;
+ }
+ uint8_t val = (mv - 700) / 25;
+ _writeByte(AXP173_LDO4_VLOTAGE, 1, &val);
+ return AXP_PASS;
+}
+
+uint16_t AXP20X_Class::getLDO4Voltage()
+{
+ const uint16_t ldo4_table[] = {1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500, 2700, 2800, 3000, 3100, 3200, 3300};
+ if (!_init)
+ return 0;
+ uint8_t val = 0;
+ switch (_chip_id) {
+ case AXP173_CHIP_ID:
+ _readByte(AXP173_LDO4_VLOTAGE, 1, &val);
+ return val * 25 + 700;
+ case AXP202_CHIP_ID:
+ _readByte(AXP202_LDO24OUT_VOL, 1, &val);
+ val &= 0xF;
+ return ldo4_table[val];
+ break;
+ case AXP192_CHIP_ID:
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+//! Only axp202 support
+int AXP20X_Class::setLDO4Voltage(axp_ldo4_table_t param)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (_chip_id == AXP202_CHIP_ID) {
+ if (param >= AXP202_LDO4_MAX)
+ return AXP_INVALID;
+ uint8_t val;
+ _readByte(AXP202_LDO24OUT_VOL, 1, &val);
+ val &= 0xF0;
+ val |= param;
+ _writeByte(AXP202_LDO24OUT_VOL, 1, &val);
+ return AXP_PASS;
+ }
+ return AXP_FAIL;
+}
+
+//! Only AXP202 support
+// 0 : LDO 1 : DCIN
+int AXP20X_Class::setLDO3Mode(uint8_t mode)
+{
+ uint8_t val;
+ if (_chip_id != AXP202_CHIP_ID)
+ return AXP_FAIL;
+ _readByte(AXP202_LDO3OUT_VOL, 1, &val);
+ if (mode) {
+ val |= BIT_MASK(7);
+ } else {
+ val &= (~BIT_MASK(7));
+ }
+ _writeByte(AXP202_LDO3OUT_VOL, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::setStartupTime(uint8_t param)
+{
+ uint8_t val;
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (param > sizeof(startupParams) / sizeof(startupParams[0]))
+ return AXP_INVALID;
+ _readByte(AXP202_POK_SET, 1, &val);
+ val &= (~0b11000000);
+ val |= startupParams[param];
+ _writeByte(AXP202_POK_SET, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::setlongPressTime(uint8_t param)
+{
+ uint8_t val;
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (param > sizeof(longPressParams) / sizeof(longPressParams[0]))
+ return AXP_INVALID;
+ _readByte(AXP202_POK_SET, 1, &val);
+ val &= (~0b00110000);
+ val |= longPressParams[param];
+ _writeByte(AXP202_POK_SET, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::setShutdownTime(uint8_t param)
+{
+ uint8_t val;
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (param > sizeof(shutdownParams) / sizeof(shutdownParams[0]))
+ return AXP_INVALID;
+ _readByte(AXP202_POK_SET, 1, &val);
+ val &= (~0b00000011);
+ val |= shutdownParams[param];
+ _writeByte(AXP202_POK_SET, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::setTimeOutShutdown(bool en)
+{
+ uint8_t val;
+ if (!_init)
+ return AXP_NOT_INIT;
+ _readByte(AXP202_POK_SET, 1, &val);
+ if (en)
+ val |= (1 << 3);
+ else
+ val &= (~(1 << 3));
+ _writeByte(AXP202_POK_SET, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::shutdown()
+{
+ uint8_t val;
+ if (!_init)
+ return AXP_NOT_INIT;
+ _readByte(AXP202_OFF_CTL, 1, &val);
+ val |= (1 << 7);
+ _writeByte(AXP202_OFF_CTL, 1, &val);
+ return AXP_PASS;
+}
+
+float AXP20X_Class::getSettingChargeCurrent()
+{
+ uint8_t val;
+ if (!_init)
+ return AXP_NOT_INIT;
+ _readByte(AXP202_CHARGE1, 1, &val);
+ val &= 0b00000111;
+ float cur = 300.0 + val * 100.0;
+ AXP_DEBUG("Setting Charge current : %.2f mA\n", cur);
+ return cur;
+}
+
+bool AXP20X_Class::isChargeingEnable()
+{
+ uint8_t val;
+ if (!_init)
+ return false;
+ _readByte(AXP202_CHARGE1, 1, &val);
+ if (val & (1 << 7)) {
+ AXP_DEBUG("Charging enable is enable\n");
+ val = true;
+ } else {
+ AXP_DEBUG("Charging enable is disable\n");
+ val = false;
+ }
+ return val;
+}
+
+int AXP20X_Class::enableChargeing(bool en)
+{
+ uint8_t val;
+ if (!_init)
+ return AXP_NOT_INIT;
+ _readByte(AXP202_CHARGE1, 1, &val);
+ val |= (1 << 7);
+ _writeByte(AXP202_CHARGE1, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::setChargingTargetVoltage(axp_chargeing_vol_t param)
+{
+ uint8_t val;
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (param > sizeof(targetVolParams) / sizeof(targetVolParams[0]))
+ return AXP_INVALID;
+ _readByte(AXP202_CHARGE1, 1, &val);
+ val &= ~(0b01100000);
+ val |= targetVolParams[param];
+ _writeByte(AXP202_CHARGE1, 1, &val);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::getBattPercentage()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (_chip_id != AXP202_CHIP_ID)
+ return AXP_NOT_SUPPORT;
+ uint8_t val;
+ if (!isBatteryConnect())
+ return 0;
+ _readByte(AXP202_BATT_PERCENTAGE, 1, &val);
+ if (!(val & BIT_MASK(7))) {
+ return val & (~BIT_MASK(7));
+ }
+ return 0;
+}
+
+int AXP20X_Class::setChgLEDMode(axp_chgled_mode_t mode)
+{
+ uint8_t val;
+ _readByte(AXP202_OFF_CTL, 1, &val);
+ val &= 0b11001111;
+ val |= BIT_MASK(3);
+ switch (mode) {
+ case AXP20X_LED_OFF:
+ _writeByte(AXP202_OFF_CTL, 1, &val);
+ break;
+ case AXP20X_LED_BLINK_1HZ:
+ val |= 0b00010000;
+ _writeByte(AXP202_OFF_CTL, 1, &val);
+ break;
+ case AXP20X_LED_BLINK_4HZ:
+ val |= 0b00100000;
+ _writeByte(AXP202_OFF_CTL, 1, &val);
+ break;
+ case AXP20X_LED_LOW_LEVEL:
+ val |= 0b00110000;
+ _writeByte(AXP202_OFF_CTL, 1, &val);
+ break;
+ default:
+ return AXP_FAIL;
+ }
+ return AXP_PASS;
+}
+
+int AXP20X_Class::debugCharging()
+{
+ uint8_t val;
+ _readByte(AXP202_CHARGE1, 1, &val);
+ AXP_DEBUG("SRC REG:0x%x\n", val);
+ if (val & (1 << 7)) {
+ AXP_DEBUG("Charging enable is enable\n");
+ } else {
+ AXP_DEBUG("Charging enable is disable\n");
+ }
+ AXP_DEBUG("Charging target-voltage : 0x%x\n", ((val & 0b01100000) >> 5) & 0b11);
+ if (val & (1 << 4)) {
+ AXP_DEBUG("end when the charge current is lower than 15%% of the set value\n");
+ } else {
+ AXP_DEBUG(" end when the charge current is lower than 10%% of the set value\n");
+ }
+ val &= 0b00000111;
+ AXP_DEBUG("Charge current : %.2f mA\n", 300.0 + val * 100.0);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::debugStatus()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ uint8_t val, val1, val2;
+ _readByte(AXP202_STATUS, 1, &val);
+ _readByte(AXP202_MODE_CHGSTATUS, 1, &val1);
+ _readByte(AXP202_IPS_SET, 1, &val2);
+ AXP_DEBUG("AXP202_STATUS: AXP202_MODE_CHGSTATUS AXP202_IPS_SET\n");
+ AXP_DEBUG("0x%x\t\t\t 0x%x\t\t\t 0x%x\n", val, val1, val2);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::limitingOff()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ uint8_t val;
+ _readByte(AXP202_IPS_SET, 1, &val);
+ if (_chip_id == AXP202_CHIP_ID) {
+ val |= 0x03;
+ } else {
+ val &= ~(1 << 1);
+ }
+ _writeByte(AXP202_IPS_SET, 1, &val);
+ return AXP_PASS;
+}
+
+// Only AXP129 chip and AXP173
+int AXP20X_Class::setDCDC1Voltage(uint16_t mv)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (_chip_id != AXP192_CHIP_ID && _chip_id != AXP173_CHIP_ID)
+ return AXP_FAIL;
+ if (mv < 700) {
+ AXP_DEBUG("DCDC1:Below settable voltage:700mV~3500mV");
+ mv = 700;
+ }
+ if (mv > 3500) {
+ AXP_DEBUG("DCDC1:Above settable voltage:700mV~3500mV");
+ mv = 3500;
+ }
+ uint8_t val = (mv - 700) / 25;
+ //! axp192 and axp173 dc1 control register same
+ _writeByte(AXP192_DC1_VLOTAGE, 1, &val);
+ return AXP_PASS;
+}
+
+// Only AXP129 chip and AXP173
+uint16_t AXP20X_Class::getDCDC1Voltage()
+{
+ if (_chip_id != AXP192_CHIP_ID && _chip_id != AXP173_CHIP_ID)
+ return AXP_FAIL;
+ uint8_t val = 0;
+ //! axp192 and axp173 dc1 control register same
+ _readByte(AXP192_DC1_VLOTAGE, 1, &val);
+ return val * 25 + 700;
+}
+
+
+/***********************************************
+ * !!! TIMER FUNCTION !!!
+ * *********************************************/
+
+int AXP20X_Class::setTimer(uint8_t minutes)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (_chip_id == AXP202_CHIP_ID) {
+ if (minutes > 63) {
+ return AXP_ARG_INVALID;
+ }
+ _writeByte(AXP202_TIMER_CTL, 1, &minutes);
+ return AXP_PASS;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+int AXP20X_Class::offTimer()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (_chip_id == AXP202_CHIP_ID) {
+ uint8_t minutes = 0x80;
+ _writeByte(AXP202_TIMER_CTL, 1, &minutes);
+ return AXP_PASS;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+int AXP20X_Class::clearTimerStatus()
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (_chip_id == AXP202_CHIP_ID) {
+ uint8_t val;
+ _readByte(AXP202_TIMER_CTL, 1, &val);
+ val |= 0x80;
+ _writeByte(AXP202_TIMER_CTL, 1, &val);
+ return AXP_PASS;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+/***********************************************
+ * !!! GPIO FUNCTION !!!
+ * *********************************************/
+
+int AXP20X_Class::_axp192_gpio_0_select( axp_gpio_mode_t mode)
+{
+ switch (mode) {
+ case AXP_IO_OUTPUT_LOW_MODE:
+ return 0b101;
+ case AXP_IO_INPUT_MODE:
+ return 0b001;
+ case AXP_IO_LDO_MODE:
+ return 0b010;
+ case AXP_IO_ADC_MODE:
+ return 0b100;
+ case AXP_IO_FLOATING_MODE:
+ return 0b111;
+ case AXP_IO_OPEN_DRAIN_OUTPUT_MODE:
+ return 0;
+ case AXP_IO_OUTPUT_HIGH_MODE:
+ case AXP_IO_PWM_OUTPUT_MODE:
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+int AXP20X_Class::_axp192_gpio_1_select( axp_gpio_mode_t mode)
+{
+ switch (mode) {
+ case AXP_IO_OUTPUT_LOW_MODE:
+ return 0b101;
+ case AXP_IO_INPUT_MODE:
+ return 0b001;
+ case AXP_IO_ADC_MODE:
+ return 0b100;
+ case AXP_IO_FLOATING_MODE:
+ return 0b111;
+ case AXP_IO_OPEN_DRAIN_OUTPUT_MODE:
+ return 0;
+ case AXP_IO_PWM_OUTPUT_MODE:
+ return 0b010;
+ case AXP_IO_OUTPUT_HIGH_MODE:
+ case AXP_IO_LDO_MODE:
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+
+int AXP20X_Class::_axp192_gpio_3_select( axp_gpio_mode_t mode)
+{
+ switch (mode) {
+ case AXP_IO_EXTERN_CHARGING_CTRL_MODE:
+ return 0;
+ case AXP_IO_OPEN_DRAIN_OUTPUT_MODE:
+ return 1;
+ case AXP_IO_INPUT_MODE:
+ return 2;
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+int AXP20X_Class::_axp192_gpio_4_select( axp_gpio_mode_t mode)
+{
+ switch (mode) {
+ case AXP_IO_EXTERN_CHARGING_CTRL_MODE:
+ return 0;
+ case AXP_IO_OPEN_DRAIN_OUTPUT_MODE:
+ return 1;
+ case AXP_IO_INPUT_MODE:
+ return 2;
+ case AXP_IO_ADC_MODE:
+ return 3;
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+
+int AXP20X_Class::_axp192_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode)
+{
+ int rslt;
+ uint8_t val;
+ switch (gpio) {
+ case AXP_GPIO_0: {
+ rslt = _axp192_gpio_0_select(mode);
+ if (rslt < 0)return rslt;
+ _readByte(AXP192_GPIO0_CTL, 1, &val);
+ val &= 0xF8;
+ val |= (uint8_t)rslt;
+ _writeByte(AXP192_GPIO0_CTL, 1, &val);
+ return AXP_PASS;
+ }
+ case AXP_GPIO_1: {
+ rslt = _axp192_gpio_1_select(mode);
+ if (rslt < 0)return rslt;
+ _readByte(AXP192_GPIO1_CTL, 1, &val);
+ val &= 0xF8;
+ val |= (uint8_t)rslt;
+ _writeByte(AXP192_GPIO1_CTL, 1, &val);
+ return AXP_PASS;
+ }
+ case AXP_GPIO_2: {
+ rslt = _axp192_gpio_1_select(mode);
+ if (rslt < 0)return rslt;
+ _readByte(AXP192_GPIO2_CTL, 1, &val);
+ val &= 0xF8;
+ val |= (uint8_t)rslt;
+ _writeByte(AXP192_GPIO2_CTL, 1, &val);
+ return AXP_PASS;
+ }
+ case AXP_GPIO_3: {
+ rslt = _axp192_gpio_3_select(mode);
+ if (rslt < 0)return rslt;
+ _readByte(AXP192_GPIO34_CTL, 1, &val);
+ val &= 0xFC;
+ val |= (uint8_t)rslt;
+ _writeByte(AXP192_GPIO34_CTL, 1, &val);
+ return AXP_PASS;
+ }
+ case AXP_GPIO_4: {
+ rslt = _axp192_gpio_4_select(mode);
+ if (rslt < 0)return rslt;
+ _readByte(AXP192_GPIO34_CTL, 1, &val);
+ val &= 0xF3;
+ val |= (uint8_t)rslt;
+ _writeByte(AXP192_GPIO34_CTL, 1, &val);
+ return AXP_PASS;
+ }
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+int AXP20X_Class::_axp202_gpio_0_select( axp_gpio_mode_t mode)
+{
+ switch (mode) {
+ case AXP_IO_OUTPUT_LOW_MODE:
+ return 0;
+ case AXP_IO_OUTPUT_HIGH_MODE:
+ return 1;
+ case AXP_IO_INPUT_MODE:
+ return 2;
+ case AXP_IO_LDO_MODE:
+ return 3;
+ case AXP_IO_ADC_MODE:
+ return 4;
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+int AXP20X_Class::_axp202_gpio_1_select( axp_gpio_mode_t mode)
+{
+ switch (mode) {
+ case AXP_IO_OUTPUT_LOW_MODE:
+ return 0;
+ case AXP_IO_OUTPUT_HIGH_MODE:
+ return 1;
+ case AXP_IO_INPUT_MODE:
+ return 2;
+ case AXP_IO_ADC_MODE:
+ return 4;
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+int AXP20X_Class::_axp202_gpio_2_select( axp_gpio_mode_t mode)
+{
+ switch (mode) {
+ case AXP_IO_OUTPUT_LOW_MODE:
+ return 0;
+ case AXP_IO_INPUT_MODE:
+ return 2;
+ case AXP_IO_FLOATING_MODE:
+ return 1;
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+
+int AXP20X_Class::_axp202_gpio_3_select(axp_gpio_mode_t mode)
+{
+ switch (mode) {
+ case AXP_IO_INPUT_MODE:
+ return 1;
+ case AXP_IO_OPEN_DRAIN_OUTPUT_MODE:
+ return 0;
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+int AXP20X_Class::_axp202_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode)
+{
+ uint8_t val;
+ int rslt;
+ switch (gpio) {
+ case AXP_GPIO_0: {
+ rslt = _axp202_gpio_0_select(mode);
+ if (rslt < 0)return rslt;
+ _readByte(AXP202_GPIO0_CTL, 1, &val);
+ val &= 0b11111000;
+ val |= (uint8_t)rslt;
+ _writeByte(AXP202_GPIO0_CTL, 1, &val);
+ return AXP_PASS;
+ }
+ case AXP_GPIO_1: {
+ rslt = _axp202_gpio_1_select(mode);
+ if (rslt < 0)return rslt;
+ _readByte(AXP202_GPIO1_CTL, 1, &val);
+ val &= 0b11111000;
+ val |= (uint8_t)rslt;
+ _writeByte(AXP202_GPIO1_CTL, 1, &val);
+ return AXP_PASS;
+ }
+ case AXP_GPIO_2: {
+ rslt = _axp202_gpio_2_select(mode);
+ if (rslt < 0)return rslt;
+ _readByte(AXP202_GPIO2_CTL, 1, &val);
+ val &= 0b11111000;
+ val |= (uint8_t)rslt;
+ _writeByte(AXP202_GPIO2_CTL, 1, &val);
+ return AXP_PASS;
+ }
+ case AXP_GPIO_3: {
+ rslt = _axp202_gpio_3_select(mode);
+ if (rslt < 0)return rslt;
+ _readByte(AXP202_GPIO3_CTL, 1, &val);
+ val = rslt ? (val | BIT_MASK(2)) : (val & (~BIT_MASK(2)));
+ _writeByte(AXP202_GPIO3_CTL, 1, &val);
+ return AXP_PASS;
+ }
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+
+int AXP20X_Class::setGPIOMode(axp_gpio_t gpio, axp_gpio_mode_t mode)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ switch (_chip_id) {
+ case AXP202_CHIP_ID:
+ return _axp202_gpio_set(gpio, mode);
+ break;
+ case AXP192_CHIP_ID:
+ return _axp192_gpio_set(gpio, mode);
+ break;
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+
+int AXP20X_Class::_axp_irq_mask(axp_gpio_irq_t irq)
+{
+ switch (irq) {
+ case AXP_IRQ_NONE:
+ return 0;
+ case AXP_IRQ_RISING:
+ return BIT_MASK(7);
+ case AXP_IRQ_FALLING:
+ return BIT_MASK(6);
+ case AXP_IRQ_DOUBLE_EDGE:
+ return 0b1100000;
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+int AXP20X_Class::_axp202_gpio_irq_set(axp_gpio_t gpio, axp_gpio_irq_t irq)
+{
+ uint8_t reg;
+ uint8_t val;
+ int mask;
+ mask = _axp_irq_mask(irq);
+
+ if (mask < 0)return mask;
+ switch (gpio) {
+ case AXP_GPIO_0:
+ reg = AXP202_GPIO0_CTL;
+ break;
+ case AXP_GPIO_1:
+ reg = AXP202_GPIO1_CTL;
+ break;
+ case AXP_GPIO_2:
+ reg = AXP202_GPIO2_CTL;
+ break;
+ case AXP_GPIO_3:
+ reg = AXP202_GPIO3_CTL;
+ break;
+ default:
+ return AXP_NOT_SUPPORT;
+ }
+ _readByte(reg, 1, &val);
+ val = mask == 0 ? (val & 0b00111111) : (val | mask);
+ _writeByte(reg, 1, &val);
+ return AXP_PASS;
+}
+
+
+int AXP20X_Class::setGPIOIrq(axp_gpio_t gpio, axp_gpio_irq_t irq)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ switch (_chip_id) {
+ case AXP202_CHIP_ID:
+ return _axp202_gpio_irq_set(gpio, irq);
+ case AXP192_CHIP_ID:
+ case AXP173_CHIP_ID:
+ return AXP_NOT_SUPPORT;
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+int AXP20X_Class::setLDO5Voltage(axp_ldo5_table_t vol)
+{
+ const uint8_t params[] = {
+ 0b11111000, //1.8V
+ 0b11111001, //2.5V
+ 0b11111010, //2.8V
+ 0b11111011, //3.0V
+ 0b11111100, //3.1V
+ 0b11111101, //3.3V
+ 0b11111110, //3.4V
+ 0b11111111, //3.5V
+ };
+ if (!_init)
+ return AXP_NOT_INIT;
+ if (_chip_id != AXP202_CHIP_ID)
+ return AXP_NOT_SUPPORT;
+ if (vol > sizeof(params) / sizeof(params[0]))
+ return AXP_ARG_INVALID;
+ uint8_t val = 0;
+ _readByte(AXP202_GPIO0_VOL, 1, &val);
+ val &= 0b11111000;
+ val |= params[vol];
+ _writeByte(AXP202_GPIO0_VOL, 1, &val);
+ return AXP_PASS;
+}
+
+
+int AXP20X_Class::_axp202_gpio_write(axp_gpio_t gpio, uint8_t val)
+{
+ uint8_t reg;
+ uint8_t wVal = 0;
+ switch (gpio) {
+ case AXP_GPIO_0:
+ reg = AXP202_GPIO0_CTL;
+ break;
+ case AXP_GPIO_1:
+ reg = AXP202_GPIO1_CTL;
+ break;
+ case AXP_GPIO_2:
+ reg = AXP202_GPIO2_CTL;
+ if (val) {
+ return AXP_NOT_SUPPORT;
+ }
+ break;
+ case AXP_GPIO_3:
+ if (val) {
+ return AXP_NOT_SUPPORT;
+ }
+ _readByte(AXP202_GPIO3_CTL, 1, &wVal);
+ wVal &= 0b11111101;
+ _writeByte(AXP202_GPIO3_CTL, 1, &wVal);
+ return AXP_PASS;
+ default:
+ return AXP_NOT_SUPPORT;
+ }
+ _readByte(reg, 1, &wVal);
+ wVal = val ? (wVal | 1) : (wVal & 0b11111000);
+ _writeByte(reg, 1, &wVal);
+ return AXP_PASS;
+}
+
+int AXP20X_Class::_axp202_gpio_read(axp_gpio_t gpio)
+{
+ uint8_t val;
+ uint8_t reg = AXP202_GPIO012_SIGNAL;
+ uint8_t offset;
+ switch (gpio) {
+ case AXP_GPIO_0:
+ offset = 4;
+ break;
+ case AXP_GPIO_1:
+ offset = 5;
+ break;
+ case AXP_GPIO_2:
+ offset = 6;
+ break;
+ case AXP_GPIO_3:
+ reg = AXP202_GPIO3_CTL;
+ offset = 0;
+ break;
+ default:
+ return AXP_NOT_SUPPORT;
+ }
+ _readByte(reg, 1, &val);
+ return val & BIT_MASK(offset) ? 1 : 0;
+}
+
+int AXP20X_Class::gpioWrite(axp_gpio_t gpio, uint8_t val)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ switch (_chip_id) {
+ case AXP202_CHIP_ID:
+ return _axp202_gpio_write(gpio, val);
+ case AXP192_CHIP_ID:
+ case AXP173_CHIP_ID:
+ return AXP_NOT_SUPPORT;
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+int AXP20X_Class::gpioRead(axp_gpio_t gpio)
+{
+ if (!_init)
+ return AXP_NOT_INIT;
+ switch (_chip_id) {
+ case AXP202_CHIP_ID:
+ return _axp202_gpio_read(gpio);
+ case AXP192_CHIP_ID:
+ case AXP173_CHIP_ID:
+ return AXP_NOT_SUPPORT;
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+
+
+int AXP20X_Class::getChargeControlCur()
+{
+ int cur;
+ uint8_t val;
+ if (!_init)
+ return AXP_NOT_INIT;
+ switch (_chip_id) {
+ case AXP202_CHIP_ID:
+ _readByte(AXP202_CHARGE1, 1, &val);
+ val &= 0x0F;
+ cur = val * 100 + 300;
+ if (cur > 1800 || cur < 300)return 0;
+ return cur;
+ case AXP192_CHIP_ID:
+ case AXP173_CHIP_ID:
+ _readByte(AXP202_CHARGE1, 1, &val);
+ return val & 0x0F;
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
+int AXP20X_Class::setChargeControlCur(uint16_t mA)
+{
+ uint8_t val;
+ if (!_init)
+ return AXP_NOT_INIT;
+ switch (_chip_id) {
+ case AXP202_CHIP_ID:
+ _readByte(AXP202_CHARGE1, 1, &val);
+ val &= 0b11110000;
+ mA -= 300;
+ val |= (mA / 100);
+ _writeByte(AXP202_CHARGE1, 1, &val);
+ return AXP_PASS;
+ case AXP192_CHIP_ID:
+ case AXP173_CHIP_ID:
+ _readByte(AXP202_CHARGE1, 1, &val);
+ val &= 0b11110000;
+ if(mA > AXP1XX_CHARGE_CUR_1320MA)
+ mA = AXP1XX_CHARGE_CUR_1320MA;
+ val |= mA;
+ _writeByte(AXP202_CHARGE1, 1, &val);
+ return AXP_PASS;
+ default:
+ break;
+ }
+ return AXP_NOT_SUPPORT;
+}
+
diff --git a/libesp32/TTGO_TWatch_Library/src/axp20x.h b/libesp32/TTGO_TWatch_Library/src/axp20x.h
new file mode 100755
index 000000000..f2ca85a77
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/src/axp20x.h
@@ -0,0 +1,827 @@
+/////////////////////////////////////////////////////////////////
+/*
+MIT License
+
+Copyright (c) 2019 lewis he
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+axp20x.h - Arduino library for X-Power AXP202 chip.
+Created by Lewis he on April 1, 2019.
+github:https://github.com/lewisxhe/AXP202X_Libraries
+*/
+/////////////////////////////////////////////////////////////////
+#pragma once
+
+#include
+#include
+
+// #define AXP_DEBUG_PORT Serial
+#ifdef AXP_DEBUG_PORT
+#define AXP_DEBUG(fmt, ...) AXP_DEBUG_PORT.printf_P((PGM_P)PSTR(fmt), ##__VA_ARGS__)
+#else
+#define AXP_DEBUG(...)
+#endif
+
+#ifndef RISING
+#define RISING 0x01
+#endif
+
+#ifndef FALLING
+#define FALLING 0x02
+#endif
+
+#ifdef _BV
+#undef _BV
+#endif
+#define _BV(b) (1ULL << (b))
+
+//! Error Code
+#define AXP_PASS (0)
+#define AXP_FAIL (-1)
+#define AXP_INVALID (-2)
+#define AXP_NOT_INIT (-3)
+#define AXP_NOT_SUPPORT (-4)
+#define AXP_ARG_INVALID (-5)
+
+//! Chip Address
+#define AXP202_SLAVE_ADDRESS (0x35)
+#define AXP192_SLAVE_ADDRESS (0x34)
+#define AXP173_SLAVE_ADDRESS (0x34)
+
+//! Chip ID
+#define AXP202_CHIP_ID 0x41
+#define AXP192_CHIP_ID 0x03
+#define AXP173_CHIP_ID 0xAD //!Axp173 does not have a chip ID, given a custom ID
+
+//! Logic states
+#define AXP202_ON 1
+#define AXP202_OFF 0
+
+//! REG MAP
+#define AXP202_STATUS (0x00)
+#define AXP202_MODE_CHGSTATUS (0x01)
+#define AXP202_OTG_STATUS (0x02)
+#define AXP202_IC_TYPE (0x03)
+#define AXP202_DATA_BUFFER1 (0x04)
+#define AXP202_DATA_BUFFER2 (0x05)
+#define AXP202_DATA_BUFFER3 (0x06)
+#define AXP202_DATA_BUFFER4 (0x07)
+#define AXP202_DATA_BUFFER5 (0x08)
+#define AXP202_DATA_BUFFER6 (0x09)
+#define AXP202_DATA_BUFFER7 (0x0A)
+#define AXP202_DATA_BUFFER8 (0x0B)
+#define AXP202_DATA_BUFFER9 (0x0C)
+#define AXP202_DATA_BUFFERA (0x0D)
+#define AXP202_DATA_BUFFERB (0x0E)
+#define AXP202_DATA_BUFFERC (0x0F)
+#define AXP202_LDO234_DC23_CTL (0x12)
+#define AXP202_DC2OUT_VOL (0x23)
+#define AXP202_LDO3_DC2_DVM (0x25)
+#define AXP202_DC3OUT_VOL (0x27)
+#define AXP202_LDO24OUT_VOL (0x28)
+#define AXP202_LDO3OUT_VOL (0x29)
+#define AXP202_IPS_SET (0x30)
+#define AXP202_VOFF_SET (0x31)
+#define AXP202_OFF_CTL (0x32)
+#define AXP202_CHARGE1 (0x33)
+#define AXP202_CHARGE2 (0x34)
+#define AXP202_BACKUP_CHG (0x35)
+#define AXP202_POK_SET (0x36)
+#define AXP202_DCDC_FREQSET (0x37)
+#define AXP202_VLTF_CHGSET (0x38)
+#define AXP202_VHTF_CHGSET (0x39)
+#define AXP202_APS_WARNING1 (0x3A)
+#define AXP202_APS_WARNING2 (0x3B)
+#define AXP202_TLTF_DISCHGSET (0x3C)
+#define AXP202_THTF_DISCHGSET (0x3D)
+#define AXP202_DCDC_MODESET (0x80)
+#define AXP202_ADC_EN1 (0x82)
+#define AXP202_ADC_EN2 (0x83)
+#define AXP202_ADC_SPEED (0x84)
+#define AXP202_ADC_INPUTRANGE (0x85)
+#define AXP202_ADC_IRQ_RETFSET (0x86)
+#define AXP202_ADC_IRQ_FETFSET (0x87)
+#define AXP202_TIMER_CTL (0x8A)
+#define AXP202_VBUS_DET_SRP (0x8B)
+#define AXP202_HOTOVER_CTL (0x8F)
+#define AXP202_GPIO0_CTL (0x90)
+#define AXP202_GPIO0_VOL (0x91)
+#define AXP202_GPIO1_CTL (0x92)
+#define AXP202_GPIO2_CTL (0x93)
+#define AXP202_GPIO012_SIGNAL (0x94)
+#define AXP202_GPIO3_CTL (0x95)
+#define AXP202_INTEN1 (0x40)
+#define AXP202_INTEN2 (0x41)
+#define AXP202_INTEN3 (0x42)
+#define AXP202_INTEN4 (0x43)
+#define AXP202_INTEN5 (0x44)
+#define AXP202_INTSTS1 (0x48)
+#define AXP202_INTSTS2 (0x49)
+#define AXP202_INTSTS3 (0x4A)
+#define AXP202_INTSTS4 (0x4B)
+#define AXP202_INTSTS5 (0x4C)
+
+//Irq control register
+#define AXP192_INTEN1 (0x40)
+#define AXP192_INTEN2 (0x41)
+#define AXP192_INTEN3 (0x42)
+#define AXP192_INTEN4 (0x43)
+#define AXP192_INTEN5 (0x4A)
+//Irq status register
+#define AXP192_INTSTS1 (0x44)
+#define AXP192_INTSTS2 (0x45)
+#define AXP192_INTSTS3 (0x46)
+#define AXP192_INTSTS4 (0x47)
+#define AXP192_INTSTS5 (0x4D)
+
+#define AXP192_DC1_VLOTAGE (0x26)
+#define AXP192_LDO23OUT_VOL (0x28)
+#define AXP192_GPIO0_CTL (0x90)
+#define AXP192_GPIO0_VOL (0x91)
+#define AXP192_GPIO1_CTL (0X92)
+#define AXP192_GPIO2_CTL (0x93)
+#define AXP192_GPIO012_SIGNAL (0x94)
+#define AXP192_GPIO34_CTL (0x95)
+
+
+
+/* axp 192/202 adc data register */
+#define AXP202_BAT_AVERVOL_H8 (0x78)
+#define AXP202_BAT_AVERVOL_L4 (0x79)
+#define AXP202_BAT_AVERCHGCUR_H8 (0x7A)
+#define AXP202_BAT_AVERCHGCUR_L4 (0x7B)
+#define AXP202_BAT_AVERCHGCUR_L5 (0x7B)
+#define AXP202_ACIN_VOL_H8 (0x56)
+#define AXP202_ACIN_VOL_L4 (0x57)
+#define AXP202_ACIN_CUR_H8 (0x58)
+#define AXP202_ACIN_CUR_L4 (0x59)
+#define AXP202_VBUS_VOL_H8 (0x5A)
+#define AXP202_VBUS_VOL_L4 (0x5B)
+#define AXP202_VBUS_CUR_H8 (0x5C)
+#define AXP202_VBUS_CUR_L4 (0x5D)
+#define AXP202_INTERNAL_TEMP_H8 (0x5E)
+#define AXP202_INTERNAL_TEMP_L4 (0x5F)
+#define AXP202_TS_IN_H8 (0x62)
+#define AXP202_TS_IN_L4 (0x63)
+#define AXP202_GPIO0_VOL_ADC_H8 (0x64)
+#define AXP202_GPIO0_VOL_ADC_L4 (0x65)
+#define AXP202_GPIO1_VOL_ADC_H8 (0x66)
+#define AXP202_GPIO1_VOL_ADC_L4 (0x67)
+
+#define AXP202_BAT_AVERDISCHGCUR_H8 (0x7C)
+#define AXP202_BAT_AVERDISCHGCUR_L5 (0x7D)
+#define AXP202_APS_AVERVOL_H8 (0x7E)
+#define AXP202_APS_AVERVOL_L4 (0x7F)
+#define AXP202_INT_BAT_CHGCUR_H8 (0xA0)
+#define AXP202_INT_BAT_CHGCUR_L4 (0xA1)
+#define AXP202_EXT_BAT_CHGCUR_H8 (0xA2)
+#define AXP202_EXT_BAT_CHGCUR_L4 (0xA3)
+#define AXP202_INT_BAT_DISCHGCUR_H8 (0xA4)
+#define AXP202_INT_BAT_DISCHGCUR_L4 (0xA5)
+#define AXP202_EXT_BAT_DISCHGCUR_H8 (0xA6)
+#define AXP202_EXT_BAT_DISCHGCUR_L4 (0xA7)
+#define AXP202_BAT_CHGCOULOMB3 (0xB0)
+#define AXP202_BAT_CHGCOULOMB2 (0xB1)
+#define AXP202_BAT_CHGCOULOMB1 (0xB2)
+#define AXP202_BAT_CHGCOULOMB0 (0xB3)
+#define AXP202_BAT_DISCHGCOULOMB3 (0xB4)
+#define AXP202_BAT_DISCHGCOULOMB2 (0xB5)
+#define AXP202_BAT_DISCHGCOULOMB1 (0xB6)
+#define AXP202_BAT_DISCHGCOULOMB0 (0xB7)
+#define AXP202_COULOMB_CTL (0xB8)
+#define AXP202_BAT_POWERH8 (0x70)
+#define AXP202_BAT_POWERM8 (0x71)
+#define AXP202_BAT_POWERL8 (0x72)
+
+#define AXP202_VREF_TEM_CTRL (0xF3)
+#define AXP202_BATT_PERCENTAGE (0xB9)
+
+/* bit definitions for AXP events, irq event */
+/* AXP202 */
+#define AXP202_IRQ_USBLO (1)
+#define AXP202_IRQ_USBRE (2)
+#define AXP202_IRQ_USBIN (3)
+#define AXP202_IRQ_USBOV (4)
+#define AXP202_IRQ_ACRE (5)
+#define AXP202_IRQ_ACIN (6)
+#define AXP202_IRQ_ACOV (7)
+
+#define AXP202_IRQ_TEMLO (8)
+#define AXP202_IRQ_TEMOV (9)
+#define AXP202_IRQ_CHAOV (10)
+#define AXP202_IRQ_CHAST (11)
+#define AXP202_IRQ_BATATOU (12)
+#define AXP202_IRQ_BATATIN (13)
+#define AXP202_IRQ_BATRE (14)
+#define AXP202_IRQ_BATIN (15)
+
+#define AXP202_IRQ_POKLO (16)
+#define AXP202_IRQ_POKSH (17)
+#define AXP202_IRQ_LDO3LO (18)
+#define AXP202_IRQ_DCDC3LO (19)
+#define AXP202_IRQ_DCDC2LO (20)
+#define AXP202_IRQ_CHACURLO (22)
+#define AXP202_IRQ_ICTEMOV (23)
+
+#define AXP202_IRQ_EXTLOWARN2 (24)
+#define AXP202_IRQ_EXTLOWARN1 (25)
+#define AXP202_IRQ_SESSION_END (26)
+#define AXP202_IRQ_SESS_AB_VALID (27)
+#define AXP202_IRQ_VBUS_UN_VALID (28)
+#define AXP202_IRQ_VBUS_VALID (29)
+#define AXP202_IRQ_PDOWN_BY_NOE (30)
+#define AXP202_IRQ_PUP_BY_NOE (31)
+
+#define AXP202_IRQ_GPIO0TG (32)
+#define AXP202_IRQ_GPIO1TG (33)
+#define AXP202_IRQ_GPIO2TG (34)
+#define AXP202_IRQ_GPIO3TG (35)
+#define AXP202_IRQ_PEKFE (37)
+#define AXP202_IRQ_PEKRE (38)
+#define AXP202_IRQ_TIMER (39)
+
+//Signal Capture
+#define AXP202_BATT_VOLTAGE_STEP (1.1F)
+#define AXP202_BATT_DISCHARGE_CUR_STEP (0.5F)
+#define AXP202_BATT_CHARGE_CUR_STEP (0.5F)
+#define AXP202_ACIN_VOLTAGE_STEP (1.7F)
+#define AXP202_ACIN_CUR_STEP (0.625F)
+#define AXP202_VBUS_VOLTAGE_STEP (1.7F)
+#define AXP202_VBUS_CUR_STEP (0.375F)
+#define AXP202_INTERNAL_TEMP_STEP (0.1F)
+#define AXP202_APS_VOLTAGE_STEP (1.4F)
+#define AXP202_TS_PIN_OUT_STEP (0.8F)
+#define AXP202_GPIO0_STEP (0.5F)
+#define AXP202_GPIO1_STEP (0.5F)
+// AXP192 only
+#define AXP202_GPIO2_STEP (0.5F)
+#define AXP202_GPIO3_STEP (0.5F)
+
+// AXP173
+#define AXP173_EXTEN_DC2_CTL (0x10)
+#define AXP173_CTL_DC2_BIT (0)
+#define AXP173_CTL_EXTEN_BIT (2)
+#define AXP173_DC1_VLOTAGE (0x26)
+#define AXP173_LDO4_VLOTAGE (0x27)
+
+#define FORCED_OPEN_DCDC3(x) (x |= (AXP202_ON << AXP202_DCDC3))
+#define BIT_MASK(x) (1 << x)
+#define IS_OPEN(reg, channel) (bool)(reg & BIT_MASK(channel))
+
+enum {
+ AXP202_EXTEN = 0,
+ AXP202_DCDC3 = 1,
+ AXP202_LDO2 = 2,
+ AXP202_LDO4 = 3,
+ AXP202_DCDC2 = 4,
+ AXP202_LDO3 = 6,
+ AXP202_OUTPUT_MAX,
+};
+
+enum {
+ AXP192_DCDC1 = 0,
+ AXP192_DCDC3 = 1,
+ AXP192_LDO2 = 2,
+ AXP192_LDO3 = 3,
+ AXP192_DCDC2 = 4,
+ AXP192_EXTEN = 6,
+ AXP192_OUTPUT_MAX,
+};
+
+enum {
+ AXP173_DCDC1 = 0,
+ AXP173_LDO4 = 1,
+ AXP173_LDO2 = 2,
+ AXP173_LDO3 = 3,
+ AXP173_DCDC2 = 4,
+ AXP173_EXTEN = 6,
+ AXP173_OUTPUT_MAX,
+};
+
+typedef enum {
+ AXP202_STARTUP_TIME_128MS,
+ AXP202_STARTUP_TIME_3S,
+ AXP202_STARTUP_TIME_1S,
+ AXP202_STARTUP_TIME_2S,
+} axp202_startup_time_t;
+
+typedef enum {
+ AXP192_STARTUP_TIME_128MS,
+ AXP192_STARTUP_TIME_512MS,
+ AXP192_STARTUP_TIME_1S,
+ AXP192_STARTUP_TIME_2S,
+} axp192_startup_time_t;
+
+typedef enum {
+ AXP_LONGPRESS_TIME_1S,
+ AXP_LONGPRESS_TIME_1S5,
+ AXP_LONGPRESS_TIME_2S,
+ AXP_LONGPRESS_TIME_2S5,
+} axp_loonPress_time_t;
+
+typedef enum {
+ AXP_POWER_OFF_TIME_4S,
+ AXP_POWER_OFF_TIME_65,
+ AXP_POWER_OFF_TIME_8S,
+ AXP_POWER_OFF_TIME_16S,
+} axp_poweroff_time_t;
+
+//REG 33H: Charging control 1 Charging target-voltage setting
+typedef enum {
+ AXP202_TARGET_VOL_4_1V,
+ AXP202_TARGET_VOL_4_15V,
+ AXP202_TARGET_VOL_4_2V,
+ AXP202_TARGET_VOL_4_36V
+} axp_chargeing_vol_t;
+
+//REG 82H: ADC Enable 1 register Parameter
+typedef enum {
+ AXP202_BATT_VOL_ADC1 = 1 << 7,
+ AXP202_BATT_CUR_ADC1 = 1 << 6,
+ AXP202_ACIN_VOL_ADC1 = 1 << 5,
+ AXP202_ACIN_CUR_ADC1 = 1 << 4,
+ AXP202_VBUS_VOL_ADC1 = 1 << 3,
+ AXP202_VBUS_CUR_ADC1 = 1 << 2,
+ AXP202_APS_VOL_ADC1 = 1 << 1,
+ AXP202_TS_PIN_ADC1 = 1 << 0
+} axp_adc1_func_t;
+
+// REG 83H: ADC Enable 2 register Parameter
+typedef enum {
+ AXP202_TEMP_MONITORING_ADC2 = 1 << 7,
+ AXP202_GPIO1_FUNC_ADC2 = 1 << 3,
+ AXP202_GPIO0_FUNC_ADC2 = 1 << 2
+} axp_adc2_func_t;
+
+typedef enum {
+ AXP202_LDO3_MODE_LDO,
+ AXP202_LDO3_MODE_DCIN
+} axp202_ldo3_mode_t;
+
+
+
+typedef enum {
+ //! IRQ1 REG 40H
+ AXP202_VBUS_VHOLD_LOW_IRQ = _BV(1), //VBUS is available, but lower than V HOLD, IRQ enable
+ AXP202_VBUS_REMOVED_IRQ = _BV(2), //VBUS removed, IRQ enable
+ AXP202_VBUS_CONNECT_IRQ = _BV(3), //VBUS connected, IRQ enable
+ AXP202_VBUS_OVER_VOL_IRQ = _BV(4), //VBUS over-voltage, IRQ enable
+ AXP202_ACIN_REMOVED_IRQ = _BV(5), //ACIN removed, IRQ enable
+ AXP202_ACIN_CONNECT_IRQ = _BV(6), //ACIN connected, IRQ enable
+ AXP202_ACIN_OVER_VOL_IRQ = _BV(7), //ACIN over-voltage, IRQ enable
+
+ //! IRQ2 REG 41H
+ AXP202_BATT_LOW_TEMP_IRQ = _BV(8), //Battery low-temperature, IRQ enable
+ AXP202_BATT_OVER_TEMP_IRQ = _BV(9), //Battery over-temperature, IRQ enable
+ AXP202_CHARGING_FINISHED_IRQ = _BV(10), //Charge finished, IRQ enable
+ AXP202_CHARGING_IRQ = _BV(11), //Be charging, IRQ enable
+ AXP202_BATT_EXIT_ACTIVATE_IRQ = _BV(12), //Exit battery activate mode, IRQ enable
+ AXP202_BATT_ACTIVATE_IRQ = _BV(13), //Battery activate mode, IRQ enable
+ AXP202_BATT_REMOVED_IRQ = _BV(14), //Battery removed, IRQ enable
+ AXP202_BATT_CONNECT_IRQ = _BV(15), //Battery connected, IRQ enable
+
+ //! IRQ3 REG 42H
+ AXP202_PEK_LONGPRESS_IRQ = _BV(16), //PEK long press, IRQ enable
+ AXP202_PEK_SHORTPRESS_IRQ = _BV(17), //PEK short press, IRQ enable
+ AXP202_LDO3_LOW_VOL_IRQ = _BV(18), //LDO3output voltage is lower than the set value, IRQ enable
+ AXP202_DC3_LOW_VOL_IRQ = _BV(19), //DC-DC3output voltage is lower than the set value, IRQ enable
+ AXP202_DC2_LOW_VOL_IRQ = _BV(20), //DC-DC2 output voltage is lower than the set value, IRQ enable
+ //**Reserved and unchangeable BIT 5
+ AXP202_CHARGE_LOW_CUR_IRQ = _BV(22), //Charge current is lower than the set current, IRQ enable
+ AXP202_CHIP_TEMP_HIGH_IRQ = _BV(23), //AXP202 internal over-temperature, IRQ enable
+
+ //! IRQ4 REG 43H
+ AXP202_APS_LOW_VOL_LEVEL2_IRQ = _BV(24), //APS low-voltage, IRQ enable(LEVEL2)
+ APX202_APS_LOW_VOL_LEVEL1_IRQ = _BV(25), //APS low-voltage, IRQ enable(LEVEL1)
+ AXP202_VBUS_SESSION_END_IRQ = _BV(26), //VBUS Session End IRQ enable
+ AXP202_VBUS_SESSION_AB_IRQ = _BV(27), //VBUS Session A/B IRQ enable
+ AXP202_VBUS_INVALID_IRQ = _BV(28), //VBUS invalid, IRQ enable
+ AXP202_VBUS_VAILD_IRQ = _BV(29), //VBUS valid, IRQ enable
+ AXP202_NOE_OFF_IRQ = _BV(30), //N_OE shutdown, IRQ enable
+ AXP202_NOE_ON_IRQ = _BV(31), //N_OE startup, IRQ enable
+
+ //! IRQ5 REG 44H
+ AXP202_GPIO0_EDGE_TRIGGER_IRQ = _BV(32), //GPIO0 input edge trigger, IRQ enable
+ AXP202_GPIO1_EDGE_TRIGGER_IRQ = _BV(33), //GPIO1input edge trigger or ADC input, IRQ enable
+ AXP202_GPIO2_EDGE_TRIGGER_IRQ = _BV(34), //GPIO2input edge trigger, IRQ enable
+ AXP202_GPIO3_EDGE_TRIGGER_IRQ = _BV(35), //GPIO3 input edge trigger, IRQ enable
+ //**Reserved and unchangeable BIT 4
+ AXP202_PEK_FALLING_EDGE_IRQ = _BV(37), //PEK press falling edge, IRQ enable
+ AXP202_PEK_RISING_EDGE_IRQ = _BV(38), //PEK press rising edge, IRQ enable
+ AXP202_TIMER_TIMEOUT_IRQ = _BV(39), //Timer timeout, IRQ enable
+
+ AXP202_ALL_IRQ = (0xFFFFFFFFFFULL)
+} axp_irq_t;
+
+typedef enum {
+ AXP202_LDO4_1250MV,
+ AXP202_LDO4_1300MV,
+ AXP202_LDO4_1400MV,
+ AXP202_LDO4_1500MV,
+ AXP202_LDO4_1600MV,
+ AXP202_LDO4_1700MV,
+ AXP202_LDO4_1800MV,
+ AXP202_LDO4_1900MV,
+ AXP202_LDO4_2000MV,
+ AXP202_LDO4_2500MV,
+ AXP202_LDO4_2700MV,
+ AXP202_LDO4_2800MV,
+ AXP202_LDO4_3000MV,
+ AXP202_LDO4_3100MV,
+ AXP202_LDO4_3200MV,
+ AXP202_LDO4_3300MV,
+ AXP202_LDO4_MAX,
+} axp_ldo4_table_t;
+
+typedef enum {
+ AXP202_LDO5_1800MV,
+ AXP202_LDO5_2500MV,
+ AXP202_LDO5_2800MV,
+ AXP202_LDO5_3000MV,
+ AXP202_LDO5_3100MV,
+ AXP202_LDO5_3300MV,
+ AXP202_LDO5_3400MV,
+ AXP202_LDO5_3500MV,
+} axp_ldo5_table_t;
+
+typedef enum {
+ AXP20X_LED_OFF,
+ AXP20X_LED_BLINK_1HZ,
+ AXP20X_LED_BLINK_4HZ,
+ AXP20X_LED_LOW_LEVEL,
+} axp_chgled_mode_t;
+
+typedef enum {
+ AXP_ADC_SAMPLING_RATE_25HZ = 0,
+ AXP_ADC_SAMPLING_RATE_50HZ = 1,
+ AXP_ADC_SAMPLING_RATE_100HZ = 2,
+ AXP_ADC_SAMPLING_RATE_200HZ = 3,
+} axp_adc_sampling_rate_t;
+
+typedef enum {
+ AXP_TS_PIN_CURRENT_20UA = 0,
+ AXP_TS_PIN_CURRENT_40UA = 1,
+ AXP_TS_PIN_CURRENT_60UA = 2,
+ AXP_TS_PIN_CURRENT_80UA = 3,
+} axp_ts_pin_current_t;
+
+typedef enum {
+ AXP_TS_PIN_FUNCTION_BATT = 0,
+ AXP_TS_PIN_FUNCTION_ADC = 1,
+} axp_ts_pin_function_t;
+
+typedef enum {
+ AXP_TS_PIN_MODE_DISABLE = 0,
+ AXP_TS_PIN_MODE_CHARGING = 1,
+ AXP_TS_PIN_MODE_SAMPLING = 2,
+ AXP_TS_PIN_MODE_ENABLE = 3,
+} axp_ts_pin_mode_t;
+
+//! Only AXP192 and AXP202 have gpio function
+typedef enum {
+ AXP_GPIO_0,
+ AXP_GPIO_1,
+ AXP_GPIO_2,
+ AXP_GPIO_3,
+ AXP_GPIO_4,
+} axp_gpio_t;
+
+typedef enum {
+ AXP_IO_OUTPUT_LOW_MODE,
+ AXP_IO_OUTPUT_HIGH_MODE,
+ AXP_IO_INPUT_MODE,
+ AXP_IO_LDO_MODE,
+ AXP_IO_ADC_MODE,
+ AXP_IO_FLOATING_MODE,
+ AXP_IO_OPEN_DRAIN_OUTPUT_MODE,
+ AXP_IO_PWM_OUTPUT_MODE,
+ AXP_IO_EXTERN_CHARGING_CTRL_MODE,
+} axp_gpio_mode_t;
+
+typedef enum {
+ AXP_IRQ_NONE,
+ AXP_IRQ_RISING,
+ AXP_IRQ_FALLING,
+ AXP_IRQ_DOUBLE_EDGE,
+} axp_gpio_irq_t;
+
+
+typedef enum {
+ AXP192_GPIO_1V8,
+ AXP192_GPIO_1V9,
+ AXP192_GPIO_2V0,
+ AXP192_GPIO_2V1,
+ AXP192_GPIO_2V2,
+ AXP192_GPIO_2V3,
+ AXP192_GPIO_2V4,
+ AXP192_GPIO_2V5,
+ AXP192_GPIO_2V6,
+ AXP192_GPIO_2V7,
+ AXP192_GPIO_2V8,
+ AXP192_GPIO_2V9,
+ AXP192_GPIO_3V0,
+ AXP192_GPIO_3V1,
+ AXP192_GPIO_3V2,
+ AXP192_GPIO_3V3,
+} axp192_gpio_voltage_t;
+
+typedef enum {
+ AXP1XX_CHARGE_CUR_100MA,
+ AXP1XX_CHARGE_CUR_190MA,
+ AXP1XX_CHARGE_CUR_280MA,
+ AXP1XX_CHARGE_CUR_360MA,
+ AXP1XX_CHARGE_CUR_450MA,
+ AXP1XX_CHARGE_CUR_550MA,
+ AXP1XX_CHARGE_CUR_630MA,
+ AXP1XX_CHARGE_CUR_700MA,
+ AXP1XX_CHARGE_CUR_780MA,
+ AXP1XX_CHARGE_CUR_880MA,
+ AXP1XX_CHARGE_CUR_960MA,
+ AXP1XX_CHARGE_CUR_1000MA,
+ AXP1XX_CHARGE_CUR_1080MA,
+ AXP1XX_CHARGE_CUR_1160MA,
+ AXP1XX_CHARGE_CUR_1240MA,
+ AXP1XX_CHARGE_CUR_1320MA,
+} axp1xx_charge_current_t;
+
+typedef uint8_t (*axp_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len);
+
+
+class AXP20X_Class
+{
+public:
+ int begin(TwoWire &port = Wire, uint8_t addr = AXP202_SLAVE_ADDRESS, bool isAxp173 = false);
+ int begin(axp_com_fptr_t read_cb, axp_com_fptr_t write_cb, uint8_t addr = AXP202_SLAVE_ADDRESS, bool isAxp173 = false);
+
+ // Power Output Control
+ int setPowerOutPut(uint8_t ch, bool en);
+
+ bool isBatteryConnect();
+ bool isChargeing();
+ bool isLDO2Enable();
+ bool isLDO3Enable();
+ bool isLDO4Enable();
+ bool isDCDC3Enable();
+ bool isDCDC2Enable();
+ bool isChargeingEnable();
+ bool isVBUSPlug();
+ bool isExtenEnable();
+
+ //Only axp192 chip
+ bool isDCDC1Enable();
+
+
+ //IRQ Status
+ bool isAcinOverVoltageIRQ();
+ bool isAcinPlugInIRQ();
+ bool isAcinRemoveIRQ();
+ bool isVbusOverVoltageIRQ();
+ bool isVbusPlugInIRQ();
+ bool isVbusRemoveIRQ();
+ bool isVbusLowVHOLDIRQ();
+
+ bool isBattPlugInIRQ();
+ bool isBattRemoveIRQ();
+ bool isBattEnterActivateIRQ();
+ bool isBattExitActivateIRQ();
+ bool isChargingIRQ();
+ bool isChargingDoneIRQ();
+ bool isBattTempLowIRQ();
+ bool isBattTempHighIRQ();
+
+ bool isPEKShortPressIRQ();
+ bool isPEKLongtPressIRQ();
+ bool isTimerTimeoutIRQ();
+
+ //! Group4 ADC data
+ float getAcinVoltage();
+ float getAcinCurrent();
+ float getVbusVoltage();
+ float getVbusCurrent();
+ float getTemp();
+ float getTSTemp();
+ float getGPIO0Voltage();
+ float getGPIO1Voltage();
+ float getBattInpower();
+ float getBattVoltage();
+ float getBattChargeCurrent();
+ float getBattDischargeCurrent();
+ float getSysIPSOUTVoltage();
+ uint32_t getBattChargeCoulomb();
+ uint32_t getBattDischargeCoulomb();
+ float getSettingChargeCurrent();
+
+ int setChargingTargetVoltage(axp_chargeing_vol_t param);
+ int enableChargeing(bool en);
+
+ int adc1Enable(uint16_t params, bool en);
+ int adc2Enable(uint16_t params, bool en);
+
+ int setTScurrent(axp_ts_pin_current_t current);
+ int setTSfunction(axp_ts_pin_function_t func);
+ int setTSmode(axp_ts_pin_mode_t mode);
+
+
+ int setTimer(uint8_t minutes);
+ int offTimer();
+ int clearTimerStatus();
+ /**
+ * param: axp202_startup_time_t or axp192_startup_time_t
+ */
+ int setStartupTime(uint8_t param);
+
+ /**
+ * param: axp_loonPress_time_t
+ */
+ int setlongPressTime(uint8_t param);
+
+ /**
+ * @param param: axp_poweroff_time_t
+ */
+ int setShutdownTime(uint8_t param);
+
+ int setTimeOutShutdown(bool en);
+
+ int shutdown();
+
+ /**
+ * params: axp_irq_t
+ */
+ int enableIRQ(uint64_t params, bool en);
+ int readIRQ();
+ void clearIRQ();
+
+ int setDCDC1Voltage(uint16_t mv); //! Only AXP192 support and AXP173
+ // return mv
+ uint16_t getDCDC1Voltage(); //! Only AXP192 support and AXP173
+
+ // -----------------
+
+ /*
+ !! Chip resource table
+ | CHIP | AXP173 | AXP192 | AXP202 |
+ | -------- | ---------------- | ---------------- | ---------------- |
+ | DC1 | 0v7~3v5 /1200mA | 0v7~3v5 /1200mA | X |
+ | DC2 | 0v7~2v275/1600mA | 0v7~2v275/1600mA | 0v7~2v275/1600mA |
+ | DC3 | X | 0v7~3v5 /700mA | 0v7~3v5 /1200mA |
+ | LDO1 | 3v3 /30mA | 3v3 /30mA | 3v3 /30mA |
+ | LDO2 | 1v8~3v3 /200mA | 1v8~3v3 /200mA | 1v8~3v3 /200mA |
+ | LDO3 | 1v8~3v3 /200mA | 1v8~3v3 /200mA | 0v7~3v3 /200mA |
+ | LDO4 | 0v7~3v5 /500mA | X | 1v8~3v3 /200mA |
+ | LDO5/IO0 | X | 1v8~3v3 /50mA | 1v8~3v3 /50mA |
+ */
+ int setDCDC2Voltage(uint16_t mv);
+ uint16_t getDCDC2Voltage();
+
+ int setDCDC3Voltage(uint16_t mv);
+ uint16_t getDCDC3Voltage();
+
+ int setLDO2Voltage(uint16_t mv);
+ uint16_t getLDO2Voltage();
+
+ int setLDO3Voltage(uint16_t mv);
+ uint16_t getLDO3Voltage();
+
+
+ int setLDO4Voltage(axp_ldo4_table_t param); //! Only axp202 support
+ int setLDO4Voltage(uint16_t mv); //! Only axp173 support
+
+ // return mv
+ uint16_t getLDO4Voltage(); //! Only axp173/axp202 support
+
+
+ /**
+ * @param mode: axp_chgled_mode_t
+ */
+ int setChgLEDMode(axp_chgled_mode_t mode);
+
+ /**
+ * @param mode: axp202_ldo3_mode_t
+ */
+ int setLDO3Mode(uint8_t mode); //! Only AXP202 support
+
+ int getBattPercentage();
+
+ int debugCharging();
+ int debugStatus();
+ int limitingOff();
+
+ int setAdcSamplingRate(axp_adc_sampling_rate_t rate);
+ uint8_t getAdcSamplingRate();
+ float getCoulombData();
+ uint8_t getCoulombRegister();
+ int setCoulombRegister(uint8_t val);
+ int EnableCoulombcounter(void);
+ int DisableCoulombcounter(void);
+ int StopCoulombcounter(void);
+ int ClearCoulombcounter(void);
+
+
+ int setGPIOMode(axp_gpio_t gpio, axp_gpio_mode_t mode);
+ int setGPIOIrq(axp_gpio_t gpio, axp_gpio_irq_t irq);
+ int setLDO5Voltage(axp_ldo5_table_t vol);
+
+ int gpioWrite(axp_gpio_t gpio, uint8_t vol);
+ int gpioRead(axp_gpio_t gpio);
+
+ // When the chip is axp192 / 173, the allowed values are 0 ~ 15, corresponding to the axp1xx_charge_current_t enumeration
+ // When the chip is axp202 allows maximum charging current of 1800mA, minimum 300mA
+ int getChargeControlCur();
+ int setChargeControlCur(uint16_t mA);
+
+private:
+ uint16_t _getRegistH8L5(uint8_t regh8, uint8_t regl5)
+ {
+ uint8_t hv, lv;
+ _readByte(regh8, 1, &hv);
+ _readByte(regl5, 1, &lv);
+ return (hv << 5) | (lv & 0x1F);
+ }
+
+ uint16_t _getRegistResult(uint8_t regh8, uint8_t regl4)
+ {
+ uint8_t hv, lv;
+ _readByte(regh8, 1, &hv);
+ _readByte(regl4, 1, &lv);
+ return (hv << 4) | (lv & 0x0F);
+ }
+
+ int _readByte(uint8_t reg, uint8_t nbytes, uint8_t *data)
+ {
+ if (_read_cb != nullptr) {
+ return _read_cb(_address, reg, data, nbytes);
+ }
+ if (nbytes == 0 || !data)
+ return -1;
+ _i2cPort->beginTransmission(_address);
+ _i2cPort->write(reg);
+ _i2cPort->endTransmission();
+ _i2cPort->requestFrom(_address, nbytes);
+ uint8_t index = 0;
+ while (_i2cPort->available())
+ data[index++] = _i2cPort->read();
+ return 0;
+ }
+
+ int _writeByte(uint8_t reg, uint8_t nbytes, uint8_t *data)
+ {
+ if (_write_cb != nullptr) {
+ return _write_cb(_address, reg, data, nbytes);
+ }
+ if (nbytes == 0 || !data)
+ return -1;
+ _i2cPort->beginTransmission(_address);
+ _i2cPort->write(reg);
+ for (uint8_t i = 0; i < nbytes; i++) {
+ _i2cPort->write(data[i]);
+ }
+ _i2cPort->endTransmission();
+ return 0;
+ }
+
+ int _setGpioInterrupt(uint8_t *val, int mode, bool en);
+ int _axp_probe();
+ int _axp_irq_mask(axp_gpio_irq_t irq);
+
+ int _axp192_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode);
+ int _axp192_gpio_0_select( axp_gpio_mode_t mode);
+ int _axp192_gpio_1_select( axp_gpio_mode_t mode);
+ int _axp192_gpio_3_select( axp_gpio_mode_t mode);
+ int _axp192_gpio_4_select( axp_gpio_mode_t mode);
+
+ int _axp202_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode);
+ int _axp202_gpio_0_select( axp_gpio_mode_t mode);
+ int _axp202_gpio_1_select( axp_gpio_mode_t mode);
+ int _axp202_gpio_2_select( axp_gpio_mode_t mode);
+ int _axp202_gpio_3_select( axp_gpio_mode_t mode);
+ int _axp202_gpio_irq_set(axp_gpio_t gpio, axp_gpio_irq_t irq);
+ int _axp202_gpio_write(axp_gpio_t gpio, uint8_t val);
+ int _axp202_gpio_read(axp_gpio_t gpio);
+
+
+ static const uint8_t startupParams[], longPressParams[], shutdownParams[], targetVolParams[];
+ static uint8_t _outputReg;
+ uint8_t _address, _irq[5], _chip_id, _gpio[4];
+ bool _init = false;
+ axp_com_fptr_t _read_cb = nullptr;
+ axp_com_fptr_t _write_cb = nullptr;
+ TwoWire *_i2cPort;
+ bool _isAxp173;
+};
diff --git a/libesp32/TTGO_TWatch_Library/src/bma.cpp b/libesp32/TTGO_TWatch_Library/src/bma.cpp
new file mode 100755
index 000000000..63502fa42
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/src/bma.cpp
@@ -0,0 +1,279 @@
+#include "bma.h"
+#include
+
+I2CBus *BMA::_bus = nullptr;
+
+BMA::BMA(I2CBus &bus)
+{
+ _bus = &bus;
+}
+
+BMA::~BMA()
+{
+
+}
+
+uint16_t BMA::read(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len)
+{
+ return _bus->readBytes(addr, reg, data, len);
+}
+
+uint16_t BMA::write(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len)
+{
+ return _bus->writeBytes(addr, reg, data, len);
+}
+
+bool BMA::begin()
+{
+ _dev.dev_addr = BMA4_I2C_ADDR_SECONDARY;
+ _dev.interface = BMA4_I2C_INTERFACE;
+ _dev.bus_read = read;
+ _dev.bus_write = write;
+ _dev.delay = delay;
+ _dev.read_write_len = 8;
+ _dev.resolution = 12;
+ _dev.feature_len = BMA423_FEATURE_SIZE;
+
+ reset();
+
+ delay(20);
+
+ if (bma423_init(&_dev) != BMA4_OK) {
+ //Serial.println("bma4 init fail");
+ return false;
+ }
+
+ config();
+
+ return true;
+}
+
+void BMA::reset()
+{
+ uint8_t reg = 0xB6;
+ _bus->writeBytes(BMA4_I2C_ADDR_SECONDARY, 0x7E, ®, 1);
+}
+
+uint16_t BMA::config()
+{
+ return bma423_write_config_file(&_dev);
+}
+
+bool BMA::getAccel(Accel &acc)
+{
+ memset(&acc, 0, sizeof(acc));
+ if (bma4_read_accel_xyz(&acc, &_dev) != BMA4_OK) {
+ return false;
+ }
+ return true;
+}
+
+uint8_t BMA::direction()
+{
+ Accel acc;
+ if (bma4_read_accel_xyz(&acc, &_dev) != BMA4_OK) {
+ return 0;
+ }
+ uint16_t absX = abs(acc.x);
+ uint16_t absY = abs(acc.y);
+ uint16_t absZ = abs(acc.z);
+
+ if ((absZ > absX) && (absZ > absY)) {
+ if (acc.z > 0) {
+ return DIRECTION_DISP_DOWN;
+ } else {
+ return DIRECTION_DISP_UP;
+ }
+ } else if ((absY > absX) && (absY > absZ)) {
+ if (acc.y > 0) {
+ return DIRECTION_BOTTOM_EDGE;
+ } else {
+ return DIRECTION_TOP_EDGE;
+ }
+ } else {
+ if (acc.x < 0) {
+ return DIRECTION_RIGHT_EDGE;
+ } else {
+ return DIRECTION_LEFT_EDGE;
+ }
+ }
+}
+
+float BMA::temperature()
+{
+ int32_t data = 0;
+ bma4_get_temperature(&data, BMA4_DEG, &_dev);
+ float res = (float)data / (float)BMA4_SCALE_TEMP;
+ /* 0x80 - temp read from the register and 23 is the ambient temp added.
+ * If the temp read from register is 0x80, it means no valid
+ * information is available */
+ if (((data - 23) / BMA4_SCALE_TEMP) == 0x80) {
+ res = 0;
+ }
+ return res;
+}
+
+
+void BMA::enableAccel()
+{
+ if (bma4_set_accel_enable(BMA4_ENABLE, &_dev)) {
+ return;
+ }
+ Acfg cfg;
+ cfg.odr = BMA4_OUTPUT_DATA_RATE_100HZ;
+ cfg.range = BMA4_ACCEL_RANGE_2G;
+ cfg.bandwidth = BMA4_ACCEL_NORMAL_AVG4;
+ cfg.perf_mode = BMA4_CONTINUOUS_MODE;
+
+ if (bma4_set_accel_config(&cfg, &_dev)) {
+ Serial.println("[bma4] set accel config fail");
+ return;
+ }
+}
+
+void BMA::disalbeIrq()
+{
+ bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT /* |BMA423_WAKEUP_INT*/, BMA4_DISABLE, &_dev);
+}
+
+void BMA::enableIrq()
+{
+ bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT /* |BMA423_WAKEUP_INT*/, BMA4_ENABLE, &_dev);
+}
+
+//attachInterrupt bma423 int1
+void BMA::attachInterrupt()
+{
+ uint16_t rslt = BMA4_OK;
+ enableAccel();
+ // rslt |= bma423_reset_step_counter(&_dev);
+ rslt |= bma423_step_detector_enable(BMA4_ENABLE, &_dev);
+ rslt |= bma423_feature_enable(BMA423_STEP_CNTR, BMA4_ENABLE, &_dev);
+ rslt |= bma423_feature_enable(BMA423_WAKEUP, BMA4_ENABLE, &_dev);
+ rslt |= bma423_feature_enable(BMA423_TILT, BMA4_ENABLE, &_dev);
+ rslt |= bma423_step_counter_set_watermark(100, &_dev);
+
+ // rslt |= bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT | BMA423_WAKEUP_INT, BMA4_ENABLE, &_dev);
+
+ rslt |= bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT, BMA4_ENABLE, &_dev);
+ rslt |= bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_TILT_INT, BMA4_ENABLE, &_dev);
+
+ bma423_anymotion_enable_axis(BMA423_ALL_AXIS_DIS, &_dev);
+
+ struct bma4_int_pin_config config ;
+
+ config.edge_ctrl = BMA4_LEVEL_TRIGGER;
+ config.lvl = BMA4_ACTIVE_HIGH;
+ config.od = BMA4_PUSH_PULL;
+ config.output_en = BMA4_OUTPUT_ENABLE;
+ config.input_en = BMA4_INPUT_DISABLE;
+ rslt |= bma4_set_int_pin_config(&config, BMA4_INTR1_MAP, &_dev);
+
+ // Serial.printf("[bma4] attachInterrupt %s\n", rslt != 0 ? "fail" : "pass");
+
+
+ struct bma423_axes_remap remap_data;
+
+ remap_data.x_axis = 0;
+ remap_data.x_axis_sign = 1;
+ remap_data.y_axis = 1;
+ remap_data.y_axis_sign = 1;
+ remap_data.z_axis = 2;
+ remap_data.z_axis_sign = 0;
+
+ bma423_set_remap_axes(&remap_data, &_dev);
+
+}
+
+bool BMA::set_remap_axes(struct bma423_axes_remap *remap_data)
+{
+ bma423_set_remap_axes(remap_data, &_dev);
+}
+
+bool BMA::readInterrupt()
+{
+ return bma423_read_int_status(&_irqStatus, &_dev) == BMA4_OK;
+}
+
+uint8_t BMA::getIrqStatus()
+{
+ return _irqStatus;
+}
+
+uint32_t BMA::getCounter()
+{
+ uint32_t stepCount;
+ if (bma423_step_counter_output(&stepCount, &_dev) == BMA4_OK) {
+ return stepCount;
+ }
+ return 0;
+}
+
+bool BMA::isStepCounter()
+{
+ return (bool)(BMA423_STEP_CNTR_INT & _irqStatus);
+}
+
+bool BMA::isDoubleClick()
+{
+ return (bool)(BMA423_WAKEUP_INT & _irqStatus);
+}
+
+
+bool BMA::isTilt()
+{
+ return (bool)(BMA423_TILT_INT & _irqStatus);
+}
+
+
+bool BMA::isActivity()
+{
+ return (bool)(BMA423_ACTIVITY_INT & _irqStatus);
+}
+
+bool BMA::isAnyNoMotion()
+{
+ return (bool)(BMA423_ANY_NO_MOTION_INT & _irqStatus);
+}
+
+
+const char *BMA::getActivity()
+{
+ uint8_t activity;
+ bma423_activity_output(&activity, &_dev);
+ if (activity & BMA423_USER_STATIONARY) {
+ return "BMA423_USER_STATIONARY";
+ } else if (activity & BMA423_USER_WALKING) {
+ return "BMA423_USER_WALKING";
+ } else if (activity & BMA423_USER_RUNNING) {
+ return "BMA423_USER_RUNNING";
+ } else if (activity & BMA423_STATE_INVALID) {
+ return "BMA423_STATE_INVALID";
+ }
+ return "None";
+}
+
+bool BMA::enableStepCountInterrupt(bool en)
+{
+ return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_STEP_CNTR_INT, en, &_dev));
+}
+
+bool BMA::enableTiltInterrupt(bool en)
+{
+ return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_TILT_INT, en, &_dev));
+}
+
+bool BMA::enableWakeupInterrupt(bool en)
+{
+ return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_WAKEUP_INT, en, &_dev));
+}
+
+bool BMA::enableAnyNoMotionInterrupt(bool en)
+{
+ return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_ANY_NO_MOTION_INT, en, &_dev));
+}
+
+bool BMA::enableActivityInterrupt(bool en)
+{
+ return (BMA4_OK == bma423_map_interrupt(BMA4_INTR1_MAP, BMA423_ACTIVITY_INT, en, &_dev));
+}
diff --git a/libesp32/TTGO_TWatch_Library/src/bma.h b/libesp32/TTGO_TWatch_Library/src/bma.h
new file mode 100755
index 000000000..31a13ec6c
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/src/bma.h
@@ -0,0 +1,64 @@
+
+#pragma once
+
+#include "bma423.h"
+#include "i2c_bus.h"
+
+
+enum {
+ DIRECTION_TOP_EDGE = 0,
+ DIRECTION_BOTTOM_EDGE = 1,
+ DIRECTION_LEFT_EDGE = 2,
+ DIRECTION_RIGHT_EDGE = 3,
+ DIRECTION_DISP_UP = 4,
+ DIRECTION_DISP_DOWN = 5
+} ;
+typedef struct bma4_dev Bma;
+typedef struct bma4_accel Accel;
+typedef struct bma4_accel_config Acfg;
+
+class BMA
+{
+public:
+ BMA(I2CBus &bus);
+ ~BMA();
+ bool begin();
+ void reset();
+ uint8_t direction();
+ float temperature();
+ void enableAccel();
+
+ void disalbeIrq();
+ void enableIrq();
+ void attachInterrupt();
+ uint32_t getCounter();
+ bool isStepCounter();
+ bool isDoubleClick();
+ bool readInterrupt();
+ bool isTilt();
+ bool isActivity();
+ bool isAnyNoMotion();
+ bool getAccel(Accel &acc);
+ uint8_t getIrqStatus();
+ const char * getActivity();
+
+ bool set_remap_axes(struct bma423_axes_remap *remap_data);
+ bool enableStepCountInterrupt(bool en = true);
+ bool enableTiltInterrupt(bool en = true);
+ bool enableWakeupInterrupt(bool en = true);
+ bool enableAnyNoMotionInterrupt(bool en = true);
+ bool enableActivityInterrupt(bool en = true);
+
+private:
+ static uint16_t read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_data, uint16_t len);
+ static uint16_t write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_data, uint16_t len);
+
+ uint16_t config();
+ Bma _dev;
+ static bma4_com_fptr_t _read;
+ static bma4_com_fptr_t _write;
+ static I2CBus *_bus;
+ bool _irqRead = false;
+ uint16_t _irqStatus;
+
+};
diff --git a/libesp32/TTGO_TWatch_Library/src/bma4.c b/libesp32/TTGO_TWatch_Library/src/bma4.c
new file mode 100755
index 000000000..01a59a2fd
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/src/bma4.c
@@ -0,0 +1,4204 @@
+/*
+****************************************************************************
+* Copyright (C) 2015 - 2016 Bosch Sensortec GmbH
+*
+* File :bma4.c
+*
+* Date: 12 Oct 2017
+*
+* Revision: 2.1.9 $
+*
+* Usage: Sensor Driver for BMA4 family of sensors
+*
+****************************************************************************
+* Disclaimer
+*
+* Common:
+* Bosch Sensortec products are developed for the consumer goods industry.
+* They may only be used within the parameters of the respective valid
+* product data sheet. Bosch Sensortec products are provided with the
+* express understanding that there is no warranty of fitness for a
+* particular purpose.They are not fit for use in life-sustaining,
+* safety or security sensitive systems or any system or device
+* that may lead to bodily harm or property damage if the system
+* or device malfunctions. In addition,Bosch Sensortec products are
+* not fit for use in products which interact with motor vehicle systems.
+* The resale and or use of products are at the purchasers own risk and
+* his own responsibility. The examination of fitness for the intended use
+* is the sole responsibility of the Purchaser.
+*
+* The purchaser shall indemnify Bosch Sensortec from all third party
+* claims, including any claims for incidental, or consequential damages,
+* arising from any product use not covered by the parameters of
+* the respective valid product data sheet or not approved by
+* Bosch Sensortec and reimburse Bosch Sensortec for all costs in
+* connection with such claims.
+*
+* The purchaser must monitor the market for the purchased products,
+* particularly with regard to product safety and inform Bosch Sensortec
+* without delay of all security relevant incidents.
+*
+* Engineering Samples are marked with an asterisk (*) or (e).
+* Samples may vary from the valid technical specifications of the product
+* series. They are therefore not intended or fit for resale to third
+* parties or for use in end products. Their sole purpose is internal
+* client testing. The testing of an engineering sample may in no way
+* replace the testing of a product series. Bosch Sensortec assumes
+* no liability for the use of engineering samples.
+* By accepting the engineering samples, the Purchaser agrees to indemnify
+* Bosch Sensortec from all claims arising from the use of engineering
+* samples.
+*
+* Special:
+* This software module (hereinafter called "Software") and any information
+* on application-sheets (hereinafter called "Information") is provided
+* free of charge for the sole purpose to support your application work.
+* The Software and Information is subject to the following
+* terms and conditions:
+*
+* The Software is specifically designed for the exclusive use for
+* Bosch Sensortec products by personnel who have special experience
+* and training. Do not use this Software if you do not have the
+* proper experience or training.
+*
+* This Software package is provided `` as is `` and without any expressed
+* or implied warranties,including without limitation, the implied warranties
+* of merchantability and fitness for a particular purpose.
+*
+* Bosch Sensortec and their representatives and agents deny any liability
+* for the functional impairment
+* of this Software in terms of fitness, performance and safety.
+* Bosch Sensortec and their representatives and agents shall not be liable
+* for any direct or indirect damages or injury, except as
+* otherwise stipulated in mandatory applicable law.
+*
+* The Information provided is believed to be accurate and reliable.
+* Bosch Sensortec assumes no responsibility for the consequences of use
+* of such Information nor for any infringement of patents or
+* other rights of third parties which may result from its use.
+* No license is granted by implication or otherwise under any patent or
+* patent rights of Bosch. Specifications mentioned in the Information are
+* subject to change without notice.
+**************************************************************************/
+/*! \file bma4.c
+ \brief Sensor Driver for BMA4 family of sensors */
+/***************************************************************************/
+/**\name Header files
+****************************************************************************/
+#include "bma4.h"
+
+/***************************************************************************/
+/**\name Static Data Buffer
+****************************************************************************/
+/* Local array to store the values read from the register
+ * using read_regs API */
+static uint8_t temp_buff[BMA4_MAX_BUFFER_SIZE] = {0};
+
+/***************************************************************************/
+/**\name Local structures
+****************************************************************************/
+/*!
+ * @brief Accel difference value of axis.
+ */
+struct data_with_sign {
+ /*! Difference value */
+ int16_t val;
+ /*! Indicates negative value if set */
+ uint8_t is_negative;
+};
+
+/*!
+ * @brief Accel data deviation from ideal value
+ */
+struct offset_delta {
+ /*! Accel x axis */
+ struct data_with_sign x;
+ /*! Accel y axis */
+ struct data_with_sign y;
+ /*! Accel z axis */
+ struct data_with_sign z;
+};
+
+/*!
+ * @brief Accel offset xyz structure
+ */
+struct accel_offset {
+ /*! Accel offset X data */
+ uint8_t x;
+ /*! Accel offset Y data */
+ uint8_t y;
+ /*! Accel offset Z data */
+ uint8_t z;
+};
+
+/*!
+ * @brief Accel self test diff xyz data structure
+ */
+struct selftest_delta_limit {
+ /*! Accel X data */
+ int32_t x;
+ /*! Accel Y data */
+ int32_t y;
+ /*! Accel Z data */
+ int32_t z;
+};
+
+/*!
+ * @brief Structure to store temp data values
+ */
+struct accel_temp {
+ /*! Accel X temp data */
+ int32_t x;
+ /*! Accel Y temp data */
+ int32_t y;
+ /*! Accel Z temp data */
+ int32_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 uint16_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 uint16_t validate_odr(uint8_t odr);
+
+/*!
+ * @brief This API is used to reset the FIFO related configurations
+ * in the fifo_frame structure.
+ *
+ * @param dev[in,out] : Structure instance of bma4_dev
+ *
+ */
+static void reset_fifo_data_structure(const struct bma4_dev *dev);
+
+/*!
+ * @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] dev : Structure instance of bma4_dev.
+ *
+ */
+static void get_accel_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *acc_count,
+ const struct bma4_dev *dev);
+
+/*!
+ * @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] dev : Structure instance of bma4_dev.
+ */
+static void check_empty_fifo(uint16_t *data_index, const struct bma4_dev *dev);
+
+/*!
+ * @brief This API is used to parse the accelerometer data from the
+ * FIFO data in header mode.
+ *
+ * @param[in,out] accel_data : Structure instance of 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.
+ *
+ */
+static void extract_accel_header_mode(struct bma4_accel *accel_data, uint16_t *accel_length,
+ 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] 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_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] dev : Structure instance of bma4_dev.
+ *
+ */
+static void unpack_accel_data(struct bma4_accel *accel_data, uint16_t data_start_index, 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] dev : Structure instance of bma4_dev.
+ *
+ */
+static void get_mag_len_to_parse(uint16_t *start_idx, uint16_t *len, const uint16_t *mag_count,
+ const struct bma4_dev *dev);
+/*!
+ * @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] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+static uint16_t extract_mag_header_mode(struct bma4_mag *data, uint16_t *len, 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 dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+static uint16_t unpack_mag_frm(struct bma4_mag *data, uint16_t *idx, uint16_t *mag_idx, uint8_t frm,
+ 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 dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+static uint16_t unpack_mag_data(struct bma4_mag *mag_data, uint16_t start_idx, 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] dev : Structure instance of bma4_dev.
+ *
+ */
+static void unpack_sensortime_frame(uint16_t *data_index, const struct bma4_dev *dev);
+
+/*!
+ * @brief This API is used to parse and store the skipped_frame_count from
+ * the FIFO data in the structure instance dev.
+ *
+ * @param[in,out] data_index : Index of the FIFO data which
+ * has the skipped frame count.
+ * @param[in,out] dev : Structure instance of bma4_dev.
+ *
+ */
+static void unpack_skipped_frame(uint16_t *data_index, const struct bma4_dev *dev);
+
+/*!
+ * @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] dev : Structure instance of bma4_dev.
+ *
+ */
+static void unpack_dropped_frame(uint16_t *data_index, const struct bma4_dev *dev);
+
+/*!
+ * @brief This API is used to move the data index ahead of the
+ * current_frame_length parameter when unnecessary FIFO data appears while
+ * extracting the user specified data.
+ *
+ * @param[in,out] data_index : Index of the FIFO data which
+ * is to be moved ahead of the
+ * current_frame_length
+ * @param[in] current_frame_length : Number of bytes in a particular frame
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ */
+static void move_next_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bma4_dev *dev);
+
+/*!
+* @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 Any non zero value -> Fail
+*/
+static uint16_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_selftest_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 Any non zero value -> Fail
+ *
+ */
+static uint16_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 Any non zero value -> Fail
+ *
+ */
+static uint16_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 Any non zero value -> Fail
+ *
+ */
+static uint16_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 Any non zero value -> Fail
+ *
+ */
+static uint16_t set_accel_selftest_config(struct bma4_dev *dev);
+
+/*!
+ * @brief This API validates the Accel g value provided as input by the
+ * user for Accel offset compensation.
+ *
+ * @param[in] gvalue : Pointer variable used to specify the g value
+ * set by the user for Accel offset compensation.
+ *
+ * @note The g-values to be passed to the parameter should be
+ * multiples of 1000000.
+ *
+ * @return results of the status of user input validation
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+static uint16_t validate_user_input(const int32_t *gvalue);
+/*!
+ * @brief This API converts the range value into corresponding integer
+ * value.
+ *
+ * @param[in] range_in : input range value.
+ * @param[out] range_out : pointer to store the integer value of range.
+ *
+ * @return results of the status of user input validation
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+static void map_range(uint8_t range_in, uint8_t *range_out);
+
+/*!
+ * @brief This API normalise the data with offset.
+ *
+ * @param[out] compensated_data : pointer to store the compensated data.
+ * @param[in] offset_data : pointer of offset.
+ *
+ * @return results of the status of user input validation
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+static void normalise_offset(const struct offset_delta *compensated_data, struct accel_offset *offset_data);
+
+/*!
+ * @brief This API normalise the data with offset.
+ *
+ * @param[in] res : resolution of the sensor.
+ * @param[in] range : G-range of the accel.
+ * @param[in] delta : pointer of offset_delta.
+ * @param[out] data : pointer to store accel_offset data.
+ *
+ * @return results of the status of user input validation
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+static void scale_offset(uint8_t res, uint8_t range, const struct offset_delta *delta, struct accel_offset *data);
+
+/*!
+ * @brief This API compensate the accel data against gravity.
+ *
+ * @param[in] lsb_per_g : lsb value pre 1g.
+ * @param[in] g_val : G reference value of all axis.
+ * @param[in] data : pointer of accel_offset data.
+ * @param[out] comp_data : pointer to store compensated data.
+ *
+ * @note The g-values to be passed to the parameter should be
+ * multiples of 1000000.
+ *
+ * @return results of the status of user input validation
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+static void comp_for_grvty(uint16_t lsb_per_g, const int32_t g_val[3], const struct bma4_accel *data,
+ struct offset_delta *comp_data);
+/*!
+ * @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 uint16_t validate_selftest(const struct selftest_delta_limit *accel_data_diff,
+ const struct bma4_dev *dev);
+
+/*!
+ * @brief This function configure the Accel for FOC.
+ *
+ * @param[in] acc_conf : accel config structure instance
+ * @param[in] acc_en : enables the accel
+ * @param[in] pwr_mode : set the power mode
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return results of self test operation
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+static uint16_t foc_config(struct bma4_accel_config *acc_conf, uint8_t *acc_en, uint8_t *pwr_mode,
+ 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
+ *
+ * @return None *
+ */
+static void convert_lsb_g(const struct selftest_delta_limit *accel_data_diff,
+ struct 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 Any non zero value -> Fail
+ */
+static uint16_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 Any non zero value -> Fail
+ */
+static uint16_t increment_feature_config_addr(const struct bma4_dev *dev);
+
+/*!
+ * @brief This API reads the 8-bit data from the given register
+ * in the sensor.
+ */
+static uint16_t read_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev);
+
+/*!
+ * @brief This API writes the 8-bit data to the given register
+ * in the sensor.
+ */
+static uint16_t write_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev);
+
+/*!
+ * @brief This API sets the feature config. data start address in the sensor.
+ */
+static uint16_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 performs roundoff on given value
+ *
+ * @param[in] value : Value which is need to be rounded off
+ *
+ * @return : None
+ */
+static int8_t roundoff(int32_t value);
+
+/*!
+ * @brief This API finds the bit position of 3.9mg according to given range
+ * and resolution.
+ *
+ * @param[in] range : range of the accel.
+ * @param[in] res : resolution of the accel.
+ *
+ * @return : bit position of 3.9mg
+ */
+static int8_t get_bit_pos_3_9mg(uint8_t range, uint8_t res);
+
+/*!
+ * @brief This API finds the the null error of the device pointer structure
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Null error
+ */
+static uint16_t bma4_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
+ *
+ * @retval 0 if success, else fail
+ */
+static uint16_t bma4_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
+ *
+ * @retval 0 if success, else fail
+ */
+static uint16_t bma4_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
+ *
+ * @retval 0 if success, else fail
+ */
+static uint16_t bma4_map_read_len(uint8_t *len, const 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.
+ */
+uint16_t bma4_init(struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+ /* Check the bma4 structure as NULL */
+ if ((dev == NULL) || (dev->bus_read == NULL) || (dev->bus_write == NULL)) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ if (dev->interface == BMA4_SPI_INTERFACE)
+ dev->dummy_byte = 1;
+ else
+ dev->dummy_byte = 0;
+
+ 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
+ */
+uint16_t bma4_write_config_file(struct bma4_dev *dev)
+{
+ uint16_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(1);
+
+ if (rslt == BMA4_OK) {
+ /* Disable config loading*/
+ rslt |= bma4_write_regs(BMA4_INIT_CTRL_ADDR, &config_load, 1, dev);
+ /* Write the config stream */
+ for (index = 0; index < BMA4_CONFIG_STREAM_SIZE; index += dev->read_write_len)
+ rslt |= stream_transfer_write((dev->config_file_ptr + index), index, dev);
+
+ /* Enable config loading and FIFO mode */
+ config_load = 0x01;
+ rslt |= bma4_write_regs(BMA4_INIT_CTRL_ADDR, &config_load, 1, dev);
+ /* Wait till ASIC is initialized. Refer the data-sheet for
+ more information*/
+ dev->delay(150);
+ /* Read the status of config stream operation */
+ rslt |= bma4_read_regs(BMA4_INTERNAL_STAT, &config_stream_status, 1, dev);
+
+ 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);
+ 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.
+ */
+uint16_t bma4_write_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev)
+{
+ uint8_t i;
+ uint8_t loop_count;
+ uint8_t overflow;
+ uint8_t index;
+ uint16_t rslt = BMA4_OK;
+ uint8_t adv_pwr_save = 0;
+
+ /* Check the dev structure as NULL*/
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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_set_advance_power_save(BMA4_DISABLE, dev);
+ /* Wait for sensor time synchronization. Refer the data-sheet for
+ more information*/
+ dev->delay(1);
+ }
+
+ 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 (i = 0; i < loop_count; i++) {
+ rslt |= write_regs(BMA4_FEATURE_CONFIG_ADDR, data + index,
+ dev->read_write_len, dev);
+ rslt |= increment_feature_config_addr(dev);
+ index = index + dev->read_write_len;
+ }
+ if (overflow)
+ rslt |= write_regs(BMA4_FEATURE_CONFIG_ADDR, data + index,
+ overflow, dev);
+ 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 once write feature config register is done */
+ rslt = bma4_get_advance_power_save(&adv_pwr_save, dev);
+ if (adv_pwr_save == BMA4_DISABLE) {
+ rslt |= bma4_set_advance_power_save(BMA4_ENABLE, dev);
+ /* Wait for sensor time synchronization. Refer the data-sheet for
+ more information*/
+ dev->delay(1);
+ }
+ }
+
+ } else {
+ rslt = write_regs(addr, data, len, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API writes the 8-bit data to the given register
+ * in the sensor.
+ */
+static uint16_t write_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ if (dev->interface == BMA4_SPI_INTERFACE)
+ addr = addr & BMA4_SPI_WR_MASK;
+ /* write data in the register*/
+ rslt |= dev->bus_write(dev->dev_addr, addr, data, len);
+ }
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the feature config. data start address in the sensor.
+ */
+static uint16_t get_feature_config_start_addr(struct bma4_dev *dev)
+{
+ uint16_t rslt;
+ uint8_t asic_lsb;
+ uint8_t asic_msb;
+
+ rslt = read_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev);
+ rslt |= read_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev);
+
+ /* 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 uint16_t set_feature_config_start_addr(struct bma4_dev *dev)
+{
+ uint16_t rslt;
+
+ rslt = write_regs(BMA4_RESERVED_REG_5B_ADDR, &dev->asic_data.asic_lsb, 1, dev);
+ 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 uint16_t increment_feature_config_addr(const struct bma4_dev *dev)
+{
+ uint16_t rslt;
+ uint16_t asic_addr;
+ uint8_t asic_lsb;
+ uint8_t asic_msb;
+
+ /* Read the asic address from the sensor */
+ rslt = read_regs(BMA4_RESERVED_REG_5B_ADDR, &asic_lsb, 1, dev);
+ rslt |= read_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev);
+ /* 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);
+ rslt |= write_regs(BMA4_RESERVED_REG_5C_ADDR, &asic_msb, 1, dev);
+
+ return rslt;
+}
+
+/*!
+ * @brief This API checks whether the read operation requested is for feature
+ * or register read and accordingly reads the data from the sensor.
+ */
+uint16_t bma4_read_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev)
+{
+ uint8_t i;
+ uint8_t loop_count;
+ uint8_t overflow;
+ uint8_t index;
+ uint16_t rslt = BMA4_OK;
+ uint8_t adv_pwr_save = 0;
+
+ /* Check the dev structure as NULL*/
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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(1);
+ }
+
+ 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 (i = 0; i < loop_count; i++) {
+ rslt |= read_regs(BMA4_FEATURE_CONFIG_ADDR, data + index,
+ dev->read_write_len, dev);
+ rslt |= increment_feature_config_addr(dev);
+ index = index + dev->read_write_len;
+ }
+ if (overflow)
+ rslt |= read_regs(BMA4_FEATURE_CONFIG_ADDR, data + index,
+ overflow, dev);
+ 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 once read feature config register is done */
+ rslt = bma4_get_advance_power_save(&adv_pwr_save, dev);
+ if (adv_pwr_save == BMA4_DISABLE) {
+ rslt |= bma4_set_advance_power_save(BMA4_ENABLE, dev);
+ /* Wait for sensor time synchronization. Refer the data-sheet for
+ more information*/
+ dev->delay(1);
+ }
+ }
+ } else {
+ rslt = read_regs(addr, data, len, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the 8-bit data from the given register
+ * in the sensor.
+ */
+static uint16_t read_regs(uint8_t addr, uint8_t *data, uint8_t len, const struct bma4_dev *dev)
+{
+ /* variable used to return the status of communication result*/
+ uint16_t rslt = 0;
+ uint16_t temp_len = len + dev->dummy_byte;
+ uint16_t i;
+
+ if (dev->interface == BMA4_SPI_INTERFACE) {
+ /* SPI mask added */
+ addr = addr | BMA4_SPI_RD_MASK;
+ }
+
+ if (temp_len > BMA4_MAX_BUFFER_SIZE) {
+ /* Buffer size is not sufficient */
+ rslt |= BMA4_E_OUT_OF_RANGE;
+ }
+
+ if (rslt == BMA4_OK) {
+ /* Read the data from the register */
+ rslt |= dev->bus_read(dev->dev_addr, addr, temp_buff, temp_len);
+
+ for (i = 0; i < len; i++) {
+ /* Parsing and storing the valid data */
+ data[i] = temp_buff[i + dev->dummy_byte];
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the error status from the sensor.
+ */
+uint16_t bma4_get_error_status(struct bma4_err_reg *err_reg, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the sensor status from the sensor.
+ */
+uint16_t bma4_get_status(uint8_t *status, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* Read the error codes*/
+ rslt |= bma4_read_regs(BMA4_STATUS_ADDR, &data, 1, dev);
+
+ if (rslt == BMA4_OK)
+ *status = data;
+ }
+
+ 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.
+ */
+uint16_t bma4_read_accel_xyz(struct bma4_accel *accel, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint16_t lsb = 0;
+ uint16_t msb = 0;
+ uint8_t data[BMA4_ACCEL_DATA_LENGTH] = {0};
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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);
+ }
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the sensor time of Sensor time gets updated
+ * with every update of data register or FIFO.
+ */
+uint16_t bma4_get_sensor_time(uint32_t *sensor_time, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data[BMA4_SENSOR_TIME_LENGTH] = {0};
+ uint8_t msb = 0;
+ uint8_t xlsb = 0;
+ uint8_t lsb = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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);
+ }
+ }
+
+ 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
+ */
+uint16_t bma4_get_temperature(int32_t *temp, uint8_t temp_unit, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data[BMA4_TEMP_DATA_SIZE] = {0};
+ int32_t temp_raw_scaled = 0;
+
+ /* Check for Null pointer error */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the Output data rate, Bandwidth, perf_mode
+ * and Range of accel.
+ */
+uint16_t bma4_get_accel_config(struct bma4_accel_config *accel, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data[2] = {0};
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the output_data_rate, bandwidth, perf_mode
+ * and range of Accel.
+ */
+uint16_t bma4_set_accel_config(const struct bma4_accel_config *accel, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t accel_config_data[2] = {0, 0};
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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;
+
+ /* Burst write is not possible in
+ suspend mode hence individual write is
+ used with delay of 1 ms */
+ rslt |= bma4_write_regs(BMA4_ACCEL_CONFIG_ADDR, &accel_config_data[0], 1, dev);
+ dev->delay(BMA4_GEN_READ_WRITE_DELAY);
+ rslt |= bma4_write_regs((BMA4_ACCEL_CONFIG_ADDR + 1), &accel_config_data[1],
+ 1, dev);
+ }
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API validates the bandwidth and perf_mode
+ * value set by the user.
+ */
+static uint16_t validate_bandwidth_perfmode(uint8_t bandwidth, uint8_t perf_mode)
+{
+ uint16_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 uint16_t validate_odr(uint8_t odr)
+{
+ uint16_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;
+}
+
+/*!
+ * @brief This API sets the advance power save mode in the sensor.
+ */
+uint16_t bma4_set_advance_power_save(uint8_t adv_pwr_save, struct bma4_dev *dev)
+{
+ uint16_t rslt = BMA4_OK;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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.
+ */
+uint16_t bma4_get_advance_power_save(uint8_t *adv_pwr_save, struct bma4_dev *dev)
+{
+ uint16_t rslt = BMA4_OK;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the FIFO self wake up functionality in the sensor.
+ */
+uint16_t bma4_set_fifo_self_wakeup(uint8_t fifo_self_wakeup, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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.
+ */
+uint16_t bma4_get_fifo_self_wakeup(uint8_t *fifo_self_wake_up, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API enables or disables the Accel in the sensor.
+ */
+uint16_t bma4_set_accel_enable(uint8_t accel_en, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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.
+ */
+uint16_t bma4_get_accel_enable(uint8_t *accel_en, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ rslt |= bma4_read_regs(BMA4_POWER_CTRL_ADDR, &data, 1, dev);
+
+ if (rslt == BMA4_OK)
+ *accel_en = BMA4_GET_BITSLICE(data, BMA4_ACCEL_ENABLE);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API is used to enable or disable auxiliary Mag
+ * in the sensor.
+ */
+uint16_t bma4_set_mag_enable(uint8_t mag_en, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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.
+ */
+uint16_t bma4_get_mag_enable(uint8_t *mag_en, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the SPI interface mode which is set for primary
+ * interface.
+ */
+uint16_t bma4_get_spi_interface(uint8_t *spi, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API configures the SPI interface Mode for primary interface
+ */
+uint16_t bma4_set_spi_interface(uint8_t spi, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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.
+*/
+uint16_t bma4_set_command_register(uint8_t command_reg, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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
+ */
+uint16_t bma4_set_i2c_device_addr(struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0, dev_id = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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.
+ */
+uint16_t bma4_set_mag_manual_enable(uint8_t mag_manual, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* Write the Mag manual*/
+ rslt |= bma4_read_regs(BMA4_AUX_IF_CONF_ADDR, &data, 1, dev);
+ dev->delay(BMA4_GEN_READ_WRITE_DELAY);
+
+ 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.
+ */
+uint16_t bma4_get_mag_manual_enable(uint8_t *mag_manual, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the I2C interface configuration(if) mode
+ * for auxiliary Mag.
+ */
+uint16_t bma4_set_aux_if_mode(uint8_t if_mode, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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.
+ */
+uint16_t bma4_get_mag_read_addr(uint8_t *mag_read_addr, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the address of the register of Aux Mag sensor
+ * where the data to be read.
+ */
+uint16_t bma4_set_mag_read_addr(uint8_t mag_read_addr, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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.
+ */
+uint16_t bma4_get_mag_write_addr(uint8_t *mag_write_addr, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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);
+ }
+
+ 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.
+ */
+uint16_t bma4_set_mag_write_addr(uint8_t mag_write_addr, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL)
+ rslt |= BMA4_E_NULL_PTR;
+ else
+ 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.
+ */
+uint16_t bma4_get_mag_write_data(uint8_t *mag_write_data, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the data in the sensor which in turn will
+ * be written to Mag.
+ */
+uint16_t bma4_set_mag_write_data(uint8_t mag_write_data, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL)
+ rslt |= BMA4_E_NULL_PTR;
+ else
+ 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.
+ */
+uint16_t bma4_read_mag_xyzr(struct bma4_mag_xyzr *mag, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint16_t msb = 0;
+ uint16_t lsb = 0;
+ uint8_t data[BMA4_MAG_XYZR_DATA_LENGTH] = {0};
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the burst data length (1,2,6,8 byte) of auxiliary
+ * Mag sensor.
+ */
+uint16_t bma4_set_mag_burst(uint8_t mag_burst, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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.
+ */
+uint16_t bma4_get_mag_burst(uint8_t *mag_burst, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the FIFO data of Accel and/or Mag sensor
+ */
+uint16_t bma4_read_fifo_data(struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+ uint8_t addr = BMA4_FIFO_DATA_ADDR;
+ /* check the bma4 structure as NULL*/
+ if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ reset_fifo_data_structure(dev);
+ /* read FIFO data*/
+ if (dev->interface == BMA4_SPI_INTERFACE)
+ addr = addr | BMA4_SPI_RD_MASK;
+
+ rslt |= dev->bus_read(dev->dev_addr, addr, dev->fifo->data, dev->fifo->length);
+ /* read fifo frame content configuration*/
+ rslt |= bma4_read_regs(BMA4_FIFO_CONFIG_1_ADDR, &data, 1, dev);
+ /* filter fifo header enabled status */
+ dev->fifo->fifo_header_enable = data & BMA4_FIFO_HEADER;
+ /* filter accel/mag data enabled status */
+ dev->fifo->fifo_data_enable = data & BMA4_FIFO_M_A_ENABLE;
+ }
+
+ 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.
+ */
+uint16_t bma4_extract_accel(struct bma4_accel *accel_data, uint16_t *accel_length, const struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint16_t data_index = 0;
+ uint16_t accel_index = 0;
+ uint16_t data_read_length = 0;
+
+ if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* Parsing the FIFO data in header-less mode */
+ if (dev->fifo->fifo_header_enable == 0) {
+ get_accel_len_to_parse(&data_index, &data_read_length, accel_length, dev);
+
+ for (; data_index < data_read_length;) {
+ unpack_acc_frm(accel_data, &data_index, &accel_index, dev->fifo->fifo_data_enable, dev);
+ /*Check for the availability of next
+ two bytes of FIFO data */
+ check_empty_fifo(&data_index, dev);
+ }
+ /* update number of accel data read*/
+ *accel_length = accel_index;
+ /*update the accel byte index*/
+ dev->fifo->accel_byte_start_idx = data_index;
+ } else {
+ /* Parsing the FIFO data in header mode */
+ extract_accel_header_mode(accel_data, accel_length, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API parses and extracts the 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
+ */
+uint16_t bma4_extract_mag(struct bma4_mag *mag_data, uint16_t *mag_length, const struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint16_t data_index = 0;
+ uint16_t mag_index = 0;
+ uint16_t data_read_length = 0;
+
+ if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* Parsing the FIFO data in header-less mode */
+ if (dev->fifo->fifo_header_enable == 0) {
+ get_mag_len_to_parse(&data_index, &data_read_length, mag_length, dev);
+ for (; data_index < data_read_length;) {
+ rslt |= unpack_mag_frm(mag_data, &data_index, &mag_index,
+ dev->fifo->fifo_data_enable, dev);
+ /*Check for the availability of next
+ two bytes of FIFO data */
+ check_empty_fifo(&data_index, dev);
+ }
+ /* update number of Aux. sensor data read*/
+ *mag_length = mag_index;
+ /*update the Aux. sensor frame index*/
+ dev->fifo->mag_byte_start_idx = data_index;
+ } else {
+ /* Parsing the FIFO data in header mode */
+ rslt |= extract_mag_header_mode(mag_data, mag_length, dev);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the FIFO water mark level which is set
+ * in the sensor.
+ */
+uint16_t bma4_get_fifo_wm(uint16_t *fifo_wm, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data[2] = {0, 0};
+
+ /* Check the bma4 structure as NULL*/
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* Read the FIFO water mark level*/
+ rslt |= bma4_read_regs(BMA4_FIFO_WTM_0_ADDR, data, BMA4_FIFO_WM_LENGTH, dev);
+
+ if (BMA4_OK == rslt)
+ *fifo_wm = (data[1] << 8) | (data[0]);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the FIFO watermark level in the sensor.
+ */
+uint16_t bma4_set_fifo_wm(uint16_t fifo_wm, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data[2] = {0, 0};
+
+ /* Check the bma4 structure as NULL*/
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+
+ 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);
+ dev->delay(BMA4_GEN_READ_WRITE_DELAY);
+ 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.
+ */
+uint16_t bma4_get_accel_fifo_filter_data(uint8_t *accel_fifo_filter, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the condition of Accel FIFO data either to
+ * filtered or unfiltered mode.
+ */
+uint16_t bma4_set_accel_fifo_filter_data(uint8_t accel_fifo_filter, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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.
+ */
+uint16_t bma4_get_fifo_down_accel(uint8_t *fifo_down, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the down-sampling rates for Accel FIFO.
+ */
+uint16_t bma4_set_fifo_down_accel(uint8_t fifo_down, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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.
+ */
+uint16_t bma4_get_fifo_length(uint16_t *fifo_length, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t index = 0;
+ uint8_t data[BMA4_FIFO_DATA_LENGTH] = {0, 0};
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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]);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API aligns and compensates the Mag data of BMM150/AKM9916
+ * sensor.
+ */
+uint16_t bma4_second_if_mag_compensate_xyz(struct bma4_mag_fifo_data mag_fifo_data,
+ uint8_t mag_second_if, struct bma4_mag *compensated_mag_data)
+{
+ uint16_t rslt = 0;
+#ifdef BMM150
+ int16_t mag_x = 0;
+ int16_t mag_y = 0;
+ int16_t mag_z = 0;
+ uint16_t mag_r = 0;
+#endif
+
+ 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
+ default:
+ rslt |= BMA4_E_OUT_OF_RANGE;
+ break;
+ }
+ return rslt;
+}
+
+/*!
+ * @brief This API reads Mag. x,y and z axis data from either BMM150 or
+ * AKM9916 sensor
+ */
+uint16_t bma4_read_mag_xyz(struct bma4_mag *mag, uint8_t sensor_select, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+
+#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};
+#endif
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ switch (sensor_select) {
+
+#if defined(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
+
+#if defined(AKM9916)
+ case BMA4_SEC_IF_AKM09916:
+
+ if (AKM9916_SENSOR == dev->aux_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
+
+ default:
+ rslt |= BMA4_E_OUT_OF_RANGE;
+ break;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the auxiliary I2C interface configuration which
+ * is set in the sensor.
+ */
+uint16_t bma4_get_if_mode(uint8_t *if_mode, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API sets the auxiliary interface configuration in the
+ * sensor.
+ */
+uint16_t bma4_set_if_mode(uint8_t if_mode, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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.
+ */
+uint16_t bma4_get_accel_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /*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);
+ }
+
+ 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.
+ */
+uint16_t bma4_get_mag_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /*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);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the ASIC status from the sensor.
+ * The status information is mentioned in the below table.
+ */
+uint16_t bma4_get_asic_status(struct bma4_asic_status *asic_status, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API enables the offset compensation for filtered and
+ * unfiltered Accel data.
+ */
+uint16_t bma4_set_offset_comp(uint8_t offset_en, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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
+ */
+uint16_t bma4_get_offset_comp(uint8_t *offset_en, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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);
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API performs Fast Offset Compensation for Accel.
+ *
+ * @note The g-values to be passed to the parameter should be
+ * multiples of 1000000.
+ */
+uint16_t bma4_perform_accel_foc(const int32_t accel_g_value[3], struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ struct bma4_accel accel_value[10] = { {0} };
+ struct accel_offset offset = {0};
+ struct offset_delta delta = { {0} };
+ struct bma4_accel_config acc_conf = {0};
+ uint8_t accel_en = 0;
+ uint8_t adv_pwr_save = 0;
+ uint8_t range = 0;
+ uint16_t lsb_per_g = 0;
+ struct accel_temp temp = {0};
+ struct bma4_accel avg = {0};
+ struct bma4_accel accel_data = {0};
+ uint8_t i = 0;
+
+ /* used to validate user input */
+ rslt |= validate_user_input(accel_g_value);
+
+ if (BMA4_OK == rslt) {
+ /* Configure accel config, accel enable and
+ advance power save for FOC */
+ rslt |= foc_config(&acc_conf, &accel_en, &adv_pwr_save, dev);
+
+ /*TO DO: Check for data ready status before
+ reading accel values*/
+
+ if (BMA4_OK == rslt) {
+ /* Giving a delay of 20ms before reading accel data
+ since odr is configured as 50Hz */
+ for (i = 0; i < 10; i++) {
+ dev->delay(20);
+ rslt |= bma4_read_accel_xyz(&accel_value[i], dev);
+ temp.x = temp.x + (int32_t)accel_value[i].x;
+ temp.y = temp.y + (int32_t)accel_value[i].y;
+ temp.z = temp.z + (int32_t)accel_value[i].z;
+ }
+
+ /* Take average of x, y and z data for lesser noise */
+ avg.x = (int16_t)(temp.x / 10);
+ avg.y = (int16_t)(temp.y / 10);
+ avg.z = (int16_t)(temp.z / 10);
+
+ /* Copy average value in another structure */
+ accel_data = avg;
+
+ if (BMA4_OK == rslt) {
+ /* Get the exact range value */
+ map_range(acc_conf.range, &range);
+ /* Get LSB per bit given the range and resolution */
+ lsb_per_g = (uint16_t)(power(2, dev->resolution) / (2 * range));
+ /* Compensate accel data against gravity */
+ comp_for_grvty(lsb_per_g, accel_g_value, &accel_data, &delta);
+ /* scale according to offset register resolution*/
+ scale_offset(dev->resolution, range, &delta, &offset);
+ /* normalise the data with offset*/
+ normalise_offset(&delta, &offset);
+
+ /* offset values are written in the offset register */
+ rslt |= bma4_write_regs(BMA4_OFFSET_0_ADDR, (uint8_t *)&offset.x, 1, dev);
+ rslt |= bma4_write_regs(BMA4_OFFSET_1_ADDR, (uint8_t *)&offset.y, 1, dev);
+ rslt |= bma4_write_regs(BMA4_OFFSET_2_ADDR, (uint8_t *)&offset.z, 1, dev);
+
+ /* Enable offset compensation */
+ rslt |= bma4_set_offset_comp(BMA4_ENABLE, dev);
+
+ /* Set accel config, accel enable and advance power save */
+ rslt |= bma4_set_accel_config(&acc_conf, dev);
+ rslt |= bma4_set_accel_enable(accel_en, dev);
+ rslt |= bma4_set_advance_power_save(adv_pwr_save, dev);
+ } else {
+ rslt |= BMA4_E_FOC_FAIL;
+ }
+ }
+ }
+ 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
+ */
+uint16_t bma4_perform_accel_selftest(uint8_t *result, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ struct bma4_accel positive = {0};
+ struct bma4_accel negative = {0};
+ /*! Structure for difference of accel values in g*/
+ struct selftest_delta_limit accel_data_diff = {0};
+ /*! Structure for difference of accel values in mg*/
+ struct selftest_delta_limit accel_data_diff_mg = {0};
+
+ *result = BMA4_SELFTEST_FAIL;
+
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+
+ rslt = set_accel_selftest_config(dev);
+ dev->delay(20);
+ rslt |= bma4_selftest_config(BMA4_ENABLE, dev);
+
+ if (rslt == BMA4_OK) {
+ dev->delay(100);
+ rslt = bma4_read_accel_xyz(&positive, dev);
+ rslt |= bma4_selftest_config(BMA4_DISABLE, dev);
+
+ if (rslt == BMA4_OK) {
+ dev->delay(100);
+ rslt = bma4_read_accel_xyz(&negative, dev);
+
+ accel_data_diff.x = ABS(positive.x) + ABS(negative.x);
+ accel_data_diff.y = ABS(positive.y) + ABS(negative.y);
+ accel_data_diff.z = ABS(positive.z) + ABS(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);
+
+ if (rslt == BMA4_OK)
+ *result = BMA4_SELFTEST_PASS;
+
+ /* Triggers a soft reset */
+ rslt |= bma4_set_command_register(0xB6, dev);
+ dev->delay(200);
+ }
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API performs the steps needed for Self test operation
+ * before reading the Accel Self test data.
+ */
+uint16_t bma4_selftest_config(uint8_t sign, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+
+ rslt |= set_accel_selftest_enable(BMA4_ENABLE, dev);
+ rslt |= set_accel_selftest_sign(sign, dev);
+
+ /* Set self test amplitude based on variant */
+ switch (dev->variant) {
+ case BMA42X_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.
+ */
+uint16_t bma4_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data[3] = {0, 0, 0};
+ uint8_t index[2] = {BMA4_INT_MAP_1_ADDR, BMA4_INT_MAP_2_ADDR};
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+
+ rslt |= bma4_read_regs(BMA4_INT_MAP_1_ADDR, data, 3, dev);
+
+ if (enable == TRUE) {
+ /* Feature interrupt mapping */
+ data[int_line] |= (uint8_t)(int_map & (0x00FF));
+ /* Hardware interrupt mapping */
+ if (int_line == BMA4_INTR2_MAP)
+ data[2] |= (uint8_t)((int_map & (0xFF00)) >> 4);
+ else
+ data[2] |= (uint8_t)((int_map & (0xFF00)) >> 8);
+
+ rslt |= bma4_write_regs(index[int_line], &data[int_line], 1, dev);
+ rslt |= bma4_write_regs(BMA4_INT_MAP_DATA_ADDR, &data[2], 1, dev);
+
+ } else {
+ /* Feature interrupt un-mapping */
+ data[int_line] &= (~(uint8_t)(int_map & (0x00FF)));
+ /* Hardware interrupt un-mapping */
+ if (int_line == BMA4_INTR2_MAP)
+ data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 4));
+ else
+ data[2] &= (~(uint8_t)((int_map & (0xFF00)) >> 8));
+
+ rslt |= bma4_write_regs(index[int_line], &data[int_line], 1, dev);
+ 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.
+ */
+uint16_t bma4_set_interrupt_mode(uint8_t mode, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+
+ 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.
+ */
+uint16_t bma4_get_interrupt_mode(uint8_t *mode, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ rslt |= bma4_read_regs(BMA4_INTR_LATCH_ADDR, &data, 1, dev);
+ *mode = data;
+ }
+
+ return rslt;
+
+}
+
+/*!
+ * @brief This API sets the auxiliary Mag(BMM150 or AKM9916) output data
+ * rate and offset.
+ */
+uint16_t bma4_set_aux_mag_config(const struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the auxiliary Mag(BMM150 or AKM9916) output data
+ * rate and offset.
+ */
+uint16_t bma4_get_aux_mag_config(struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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;
+ }
+ }
+
+ return rslt;
+}
+
+/*! @brief This API sets the FIFO configuration in the sensor.
+ */
+uint16_t bma4_set_fifo_config(uint8_t config, uint8_t enable, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data[2] = {0, 0};
+ uint8_t fifo_config_0 = config & BMA4_FIFO_CONFIG_0_MASK;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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);
+ dev->delay(BMA4_GEN_READ_WRITE_DELAY);
+ 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.
+ */
+uint16_t bma4_get_fifo_config(uint8_t *fifo_config, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data[2] = {0, 0};
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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])));
+
+ }
+
+ return rslt;
+}
+
+/*! @brief This function sets the electrical behaviour of interrupt pin1 or
+ * pin2 in the sensor.
+ */
+uint16_t bma4_set_int_pin_config(const struct bma4_int_pin_config *int_pin_config, uint8_t int_line,
+ struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t interrupt_address_array[2] = {BMA4_INT1_IO_CTRL_ADDR, BMA4_INT2_IO_CTRL_ADDR};
+ uint8_t data = 0;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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;
+ }
+ }
+
+ return rslt;
+}
+
+/*! @brief This API reads the electrical behavior of interrupt pin1 or pin2
+ * from the sensor.
+ */
+uint16_t bma4_get_int_pin_config(struct bma4_int_pin_config *int_pin_config, uint8_t int_line, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t interrupt_address_array[2] = {BMA4_INT1_IO_CTRL_ADDR, BMA4_INT2_IO_CTRL_ADDR};
+ uint8_t data = 0;
+
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the Feature and Hardware interrupt status from the sensor.
+ */
+uint16_t bma4_read_int_status(uint16_t *int_status, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data[2] = {0};
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ 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];
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the Feature interrupt status from the sensor.
+ */
+uint16_t bma4_read_int_status_0(uint8_t *int_status_0, struct bma4_dev *dev)
+{
+ uint16_t rslt = BMA4_OK;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ /* Null pointer check */
+ rslt = BMA4_E_NULL_PTR;
+ } else {
+ rslt = bma4_read_regs(BMA4_INT_STAT_0_ADDR, int_status_0, 1, dev);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API reads the Hardware interrupt status from the sensor.
+ */
+uint16_t bma4_read_int_status_1(uint8_t *int_status_1, struct bma4_dev *dev)
+{
+ uint16_t rslt = BMA4_OK;
+
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ /* Null pointer check */
+ rslt = BMA4_E_NULL_PTR;
+ } else {
+ rslt = bma4_read_regs(BMA4_INT_STAT_1_ADDR, int_status_1, 1, dev);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API initializes the auxiliary interface to access
+ * auxiliary sensor
+ */
+uint16_t bma4_aux_interface_init(struct bma4_dev *dev)
+{
+ /* Variable to return error codes */
+ uint16_t rslt = BMA4_OK;
+
+ /* Check for Null pointer error */
+ rslt |= bma4_null_pointer_check(dev);
+ if (rslt == BMA4_OK) {
+ /* Set the auxiliary sensor configuration */
+ rslt = bma4_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
+*/
+uint16_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 */
+ uint16_t rslt = BMA4_OK;
+
+ /* Check for Null pointer error */
+ rslt |= bma4_null_pointer_check(dev);
+ if (rslt == BMA4_OK) {
+ /* Read the data from the data register in terms of
+ user defined length */
+ rslt = bma4_extract_aux_data(aux_reg_addr, aux_data, len, dev);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API writes the data into the auxiliary sensor
+*/
+uint16_t bma4_aux_write(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev)
+{
+
+ uint16_t rslt = BMA4_OK;
+
+ /* Check for Null pointer error */
+ rslt |= bma4_null_pointer_check(dev);
+ if (rslt == BMA4_OK) {
+ /* 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(BMA4_AUX_COM_DELAY);
+ if (rslt == BMA4_OK) {
+ /* Then set address to write */
+ rslt = bma4_write_regs(BMA4_AUX_WR_ADDR, &aux_reg_addr, 1, dev);
+ dev->delay(BMA4_AUX_COM_DELAY);
+
+ /* 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_FAIL;
+ }
+ }
+ } else {
+ rslt = BMA4_E_RD_WR_LENGTH_INVALID;
+ }
+ }
+
+ return rslt;
+}
+
+/*****************************************************************************/
+/* Static function definition */
+/*!
+ * @brief This API converts lsb value of axes to mg for self-test *
+ */
+static void convert_lsb_g(const struct selftest_delta_limit *accel_data_diff,
+ struct 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 uint16_t stream_transfer_write(const uint8_t *stream_data, uint16_t index, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t asic_msb = (uint8_t)((index / 2) >> 4);
+ uint8_t asic_lsb = ((index / 2) & 0x0F);
+
+ 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);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API enables or disables the Accel Self test feature in the
+ * sensor.
+ */
+static uint16_t set_accel_selftest_enable(uint8_t accel_selftest_enable, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+ /* 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 uint16_t set_accel_selftest_sign(uint8_t accel_selftest_sign, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+
+ 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 uint16_t set_accel_selftest_amp(uint8_t accel_selftest_amp, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t data = 0;
+ /* Check the bma4 structure as NULL */
+ if (dev == NULL) {
+ rslt |= BMA4_E_NULL_PTR;
+ } else {
+
+ 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 uint16_t set_accel_selftest_config(struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ struct bma4_accel_config accel = {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(1);
+ rslt |= bma4_set_accel_config(&accel, dev);
+
+ return rslt;
+}
+
+/*!
+ * @brief This API validates the Accel g value provided as input by the
+ * user for Accel offset compensation.
+ *
+ * @note The g-values to be passed to the parameter should be
+ * multiples of 1000000.
+ */
+static uint16_t validate_user_input(const int32_t *gvalue)
+
+{
+ uint8_t index = 0;
+ int32_t min_gval = (int32_t)(-1.0 * BMA4XY_MULTIPLIER);
+ int32_t max_gval = (int32_t)(1.0 * BMA4XY_MULTIPLIER);
+
+ while (index < 3) {
+ if (gvalue[index] >= min_gval && gvalue[index] <= max_gval)
+ index++;
+ else
+ return BMA4_E_OUT_OF_RANGE;
+ }
+
+ return BMA4_OK;
+}
+
+/*!
+ * @brief This API normalise the data with offset
+ */
+static void normalise_offset(const struct offset_delta *compensated_data, struct accel_offset *offset_data)
+{
+ /* for handling negative offset */
+ /* employing twos's Complement method*/
+ if (compensated_data->x.is_negative == TRUE) {
+ offset_data->x = ~offset_data->x;
+ offset_data->x += 1;
+ }
+
+ if (compensated_data->y.is_negative == TRUE) {
+ offset_data->y = ~offset_data->y;
+ offset_data->y += 1;
+ }
+
+ if (compensated_data->z.is_negative == TRUE) {
+ offset_data->z = ~offset_data->z;
+ offset_data->z += 1;
+ }
+
+ 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 API normalize the data with offset.
+ */
+static void scale_offset(uint8_t res, uint8_t range, const struct offset_delta *delta, struct accel_offset *data)
+{
+ int8_t bit_pos_3_9mg, bit_pos_3_9mg_nextbit;
+ uint8_t round_off = 0;
+
+ /* Find the bit position of 3.9mg */
+ bit_pos_3_9mg = get_bit_pos_3_9mg(range, res);
+
+ /* Data register resolution less than or equal to 3.9 mg */
+ if (bit_pos_3_9mg > 0) {
+ /* Round off, consider if the next bit is high */
+ bit_pos_3_9mg_nextbit = bit_pos_3_9mg - 1;
+ round_off = (uint8_t)(1 * power(2, ((uint8_t) bit_pos_3_9mg_nextbit)));
+ /* scale according to offset register resolution*/
+ data->x = (uint8_t)((delta->x.val + round_off) / power(2, ((uint8_t)bit_pos_3_9mg)));
+ data->y = (uint8_t)((delta->y.val + round_off) / power(2, ((uint8_t)bit_pos_3_9mg)));
+ data->z = (uint8_t)((delta->z.val + round_off) / power(2, ((uint8_t)bit_pos_3_9mg)));
+ } else if (bit_pos_3_9mg < 0) {
+ bit_pos_3_9mg = (int8_t)(bit_pos_3_9mg * -1);
+ data->x = (uint8_t)(delta->x.val * power(2, ((uint8_t)bit_pos_3_9mg)));
+ data->y = (uint8_t)(delta->y.val * power(2, ((uint8_t)bit_pos_3_9mg)));
+ data->z = (uint8_t)(delta->z.val * power(2, ((uint8_t)bit_pos_3_9mg)));
+ } else {
+ /* Scale according to offset register resolution */
+ data->x = (uint8_t)(delta->x.val);
+ data->y = (uint8_t)(delta->y.val);
+ data->z = (uint8_t)(delta->z.val);
+ }
+}
+
+/*!
+ * @brief This API compensate the accel data against gravity.
+ *
+ * @note The g-values to be passed to the parameter should be
+ * multiples of 1000000.
+ */
+static void comp_for_grvty(uint16_t lsb_per_g, const int32_t g_val[3], const struct bma4_accel *data,
+ struct offset_delta *comp_data)
+{
+ int64_t accel_value_lsb[3] = {0};
+ uint8_t index;
+
+ for (index = 0; index < 3; index++) {
+ /* convert g to lsb */
+ accel_value_lsb[index] = ((int64_t)(lsb_per_g) * (int64_t)(g_val[index]));
+ }
+
+ /* Dividing the accel value in LSB by 1000000 to get
+ compensated data back in g-value */
+ comp_data->x.val = (int16_t)(data->x - (int16_t)((accel_value_lsb[BMA4_X_AXIS] / (int64_t)BMA4XY_MULTIPLIER)));
+ comp_data->y.val = (int16_t)(data->y - (int16_t)((accel_value_lsb[BMA4_Y_AXIS] / (int64_t)BMA4XY_MULTIPLIER)));
+ comp_data->z.val = (int16_t)(data->z - (int16_t)((accel_value_lsb[BMA4_Z_AXIS] / (int64_t)BMA4XY_MULTIPLIER)));
+
+ if (comp_data->x.val < 0) {
+ comp_data->x.val = ABS(comp_data->x.val);
+ comp_data->x.is_negative = 1;
+ }
+
+ if (comp_data->y.val < 0) {
+ comp_data->y.val = ABS(comp_data->y.val);
+ comp_data->y.is_negative = 1;
+ }
+
+ if (comp_data->z.val < 0) {
+ comp_data->z.val = ABS(comp_data->z.val);
+ comp_data->z.is_negative = 1;
+ }
+}
+
+/*!
+ * @brief This API converts the range value into corresponding
+ * integer value.
+ */
+static void map_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:
+ break;
+ }
+}
+
+/*!
+ * @brief This API is used to reset the FIFO related configurations
+ * in the fifo_frame structure.
+ *
+ */
+static void reset_fifo_data_structure(const struct bma4_dev *dev)
+{
+ /*Prepare for next FIFO read by resetting FIFO's
+ internal data structures*/
+ dev->fifo->accel_byte_start_idx = 0;
+ dev->fifo->mag_byte_start_idx = 0;
+ dev->fifo->sc_frame_byte_start_idx = 0;
+ dev->fifo->sensor_time = 0;
+ dev->fifo->skipped_frame_count = 0;
+ dev->fifo->accel_dropped_frame_count = 0;
+ dev->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_dev *dev)
+{
+ uint8_t dummy_byte_spi = 0;
+
+ /*Check if this is the first iteration of data unpacking
+ if yes, then consider dummy byte on SPI*/
+ if (dev->fifo->accel_byte_start_idx == 0)
+ dummy_byte_spi = dev->dummy_byte;
+
+ /*Data start index*/
+ *start_idx = dev->fifo->accel_byte_start_idx + dummy_byte_spi;
+
+ if (dev->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) + dummy_byte_spi);
+ } else if (dev->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) + dummy_byte_spi);
+ } 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 = dev->fifo->length;
+ }
+ if ((*len) > dev->fifo->length) {
+ /*Handling the case where more data is requested
+ than available*/
+ *len = dev->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_dev *dev)
+{
+ if ((*data_index + 2) < dev->fifo->length) {
+ /* Check if FIFO is empty */
+ if ((dev->fifo->data[*data_index] == FIFO_MSB_CONFIG_CHECK)
+ && (dev->fifo->data[*data_index + 1] == FIFO_LSB_CONFIG_CHECK)) {
+ /*Update the data index as complete*/
+ *data_index = dev->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, 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 (dev->fifo->accel_byte_start_idx == 0)
+ dev->fifo->accel_byte_start_idx = dev->dummy_byte;
+
+ for (data_index = dev->fifo->accel_byte_start_idx; data_index < dev->fifo->length;) {
+ /*Header byte is stored in the variable frame_header*/
+ frame_header = dev->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 FIFO_HEAD_A:
+ case FIFO_HEAD_M_A:
+ unpack_acc_frm(accel_data, &data_index, &accel_index, frame_header, dev);
+ break;
+ /* Aux. sensor frame */
+ case FIFO_HEAD_M:
+ move_next_frame(&data_index, BMA4_FIFO_M_LENGTH, dev);
+ break;
+ /* Sensor time frame */
+ case FIFO_HEAD_SENSOR_TIME:
+ unpack_sensortime_frame(&data_index, dev);
+ break;
+ /* Skip frame */
+ case FIFO_HEAD_SKIP_FRAME:
+ unpack_skipped_frame(&data_index, dev);
+ break;
+ /* Input config frame */
+ case FIFO_HEAD_INPUT_CONFIG:
+ move_next_frame(&data_index, 1, dev);
+ break;
+ /* Sample drop frame */
+ case FIFO_HEAD_SAMPLE_DROP:
+ unpack_dropped_frame(&data_index, dev);
+ break;
+ /* Over read FIFO data */
+ case FIFO_HEAD_OVER_READ_MSB:
+ /* Update the data index as complete*/
+ data_index = dev->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*/
+ dev->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_dev *dev)
+{
+ switch (frm) {
+ case FIFO_HEAD_A:
+ case BMA4_FIFO_A_ENABLE:
+ /*Partial read, then skip the data*/
+ if ((*idx + BMA4_FIFO_A_LENGTH) > dev->fifo->length) {
+ /*Update the data index as complete*/
+ *idx = dev->fifo->length;
+ break;
+ }
+ /*Unpack the data array into the structure instance "acc" */
+ unpack_accel_data(&acc[*acc_idx], *idx, dev);
+ /*Move the data index*/
+ *idx = *idx + BMA4_FIFO_A_LENGTH;
+ (*acc_idx)++;
+ break;
+ case FIFO_HEAD_M_A:
+ case BMA4_FIFO_M_A_ENABLE:
+ /*Partial read, then skip the data*/
+ if ((*idx + BMA4_FIFO_MA_LENGTH) > dev->fifo->length) {
+ /*Update the data index as complete*/
+ *idx = dev->fifo->length;
+ break;
+ }
+ /*Unpack the data array into structure instance "acc"*/
+ unpack_accel_data(&acc[*acc_idx], *idx + BMA4_MA_FIFO_A_X_LSB, dev);
+ /*Move the data index*/
+ *idx = *idx + BMA4_FIFO_MA_LENGTH;
+ (*acc_idx)++;
+ break;
+ /* Aux. sensor frame */
+ case 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_dev *dev)
+{
+ uint16_t data_lsb;
+ uint16_t data_msb;
+
+ /* Accel raw x data */
+ data_lsb = dev->fifo->data[data_start_index++];
+ data_msb = dev->fifo->data[data_start_index++];
+ accel_data->x = (int16_t)((data_msb << 8) | data_lsb);
+
+ /* Accel raw y data */
+ data_lsb = dev->fifo->data[data_start_index++];
+ data_msb = dev->fifo->data[data_start_index++];
+ accel_data->y = (int16_t)((data_msb << 8) | data_lsb);
+
+ /* Accel raw z data */
+ data_lsb = dev->fifo->data[data_start_index++];
+ data_msb = dev->fifo->data[data_start_index++];
+ accel_data->z = (int16_t)((data_msb << 8) | data_lsb);
+
+ 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_dev *dev)
+{
+ uint8_t dummy_byte_spi = 0;
+
+ /*Check if this is the first iteration of data unpacking
+ if yes, then consider dummy byte on SPI*/
+ if (dev->fifo->mag_byte_start_idx == 0)
+ dummy_byte_spi = dev->dummy_byte;
+
+ /*Data start index*/
+ *start_idx = dev->fifo->mag_byte_start_idx + dummy_byte_spi;
+
+ if (dev->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) + dummy_byte_spi);
+ } else if (dev->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) + dummy_byte_spi);
+ } 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 = dev->fifo->length;
+ }
+
+ /*Handling the case where more data is requested than available*/
+ if ((*len) > dev->fifo->length) {
+ /*Len is equal to the FIFO length*/
+ *len = dev->fifo->length;
+ }
+}
+
+/*!
+ * @brief This API is used to parse the magnetometer data from the
+ * FIFO data in header mode.
+ *
+ */
+static uint16_t extract_mag_header_mode(struct bma4_mag *data, uint16_t *len, const struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ 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 (dev->fifo->mag_byte_start_idx == 0)
+ dev->fifo->mag_byte_start_idx = dev->dummy_byte;
+
+ for (data_index = dev->fifo->mag_byte_start_idx; data_index < dev->fifo->length;) {
+ /*Header byte is stored in the variable frame_header*/
+ frame_header = dev->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 FIFO_HEAD_M:
+ case FIFO_HEAD_M_A:
+ rslt |= unpack_mag_frm(data, &data_index, &mag_index, frame_header, dev);
+ break;
+ /* Aux. sensor frame */
+ case FIFO_HEAD_A:
+ move_next_frame(&data_index, BMA4_FIFO_A_LENGTH, dev);
+ break;
+ /* Sensor time frame */
+ case FIFO_HEAD_SENSOR_TIME:
+ unpack_sensortime_frame(&data_index, dev);
+ break;
+ /* Skip frame */
+ case FIFO_HEAD_SKIP_FRAME:
+ unpack_skipped_frame(&data_index, dev);
+ break;
+ /* Input config frame */
+ case FIFO_HEAD_INPUT_CONFIG:
+ move_next_frame(&data_index, 1, dev);
+ break;
+ /* Sample drop frame */
+ case FIFO_HEAD_SAMPLE_DROP:
+ unpack_dropped_frame(&data_index, dev);
+ break;
+ case FIFO_HEAD_OVER_READ_MSB:
+ /*Update the data index as complete*/
+ data_index = dev->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*/
+ dev->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 uint16_t unpack_mag_frm(struct bma4_mag *data, uint16_t *idx, uint16_t *mag_idx, uint8_t frm,
+ const struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+
+ switch (frm) {
+ case FIFO_HEAD_M:
+ case BMA4_FIFO_M_ENABLE:
+ /*partial read, then skip the data*/
+ if ((*idx + BMA4_FIFO_M_LENGTH) > dev->fifo->length) {
+ /*update the data index as complete*/
+ *idx = dev->fifo->length;
+ break;
+ }
+
+ /*unpack the data array into Aux. sensor data structure*/
+ rslt |= unpack_mag_data(&data[*mag_idx], *idx, dev);
+ /*move the data index*/
+ *idx = *idx + BMA4_FIFO_M_LENGTH;
+ (*mag_idx)++;
+ break;
+ case FIFO_HEAD_M_A:
+ case BMA4_FIFO_M_A_ENABLE:
+ /*partial read, then skip the data*/
+ if ((*idx + BMA4_FIFO_MA_LENGTH) > dev->fifo->length) {
+ /*update the data index as complete*/
+ *idx = dev->fifo->length;
+ break;
+ }
+
+ /*unpack the data array into Aux. sensor data structure*/
+ rslt |= unpack_mag_data(&data[*mag_idx], *idx, dev);
+ /*move the data index to next frame*/
+ *idx = *idx + BMA4_FIFO_MA_LENGTH;
+ (*mag_idx)++;
+ break;
+ /* aux. sensor frame */
+ case 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 uint16_t unpack_mag_data(struct bma4_mag *mag_data, uint16_t start_idx, const struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ struct bma4_mag_fifo_data mag_fifo_data;
+
+ /* Aux. mag sensor raw x data */
+ mag_fifo_data.mag_x_lsb = dev->fifo->data[start_idx++];
+ mag_fifo_data.mag_x_msb = dev->fifo->data[start_idx++];
+
+ /* Aux. mag sensor raw y data */
+ mag_fifo_data.mag_y_lsb = dev->fifo->data[start_idx++];
+ mag_fifo_data.mag_y_msb = dev->fifo->data[start_idx++];
+
+ /* Aux. mag sensor raw z data */
+ mag_fifo_data.mag_z_lsb = dev->fifo->data[start_idx++];
+ mag_fifo_data.mag_z_msb = dev->fifo->data[start_idx++];
+
+ /* Aux. mag sensor raw r data */
+ mag_fifo_data.mag_r_y2_lsb = dev->fifo->data[start_idx++];
+ mag_fifo_data.mag_r_y2_msb = dev->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, const struct bma4_dev *dev)
+{
+ uint32_t sensor_time_byte3 = 0;
+ uint16_t sensor_time_byte2 = 0;
+ uint8_t sensor_time_byte1 = 0;
+
+ /*Partial read, then move the data index to last data*/
+ if ((*data_index + BMA4_SENSOR_TIME_LENGTH) > dev->fifo->length) {
+ /*Update the data index as complete*/
+ *data_index = dev->fifo->length;
+ } else {
+ sensor_time_byte3 = dev->fifo->data[(*data_index) + BMA4_SENSOR_TIME_MSB_BYTE] << 16;
+ sensor_time_byte2 = dev->fifo->data[(*data_index) + BMA4_SENSOR_TIME_XLSB_BYTE] << 8;
+ sensor_time_byte1 = dev->fifo->data[(*data_index)];
+ /* Sensor time */
+ dev->fifo->sensor_time = (uint32_t)(sensor_time_byte3 | sensor_time_byte2 | sensor_time_byte1);
+ *data_index = (*data_index) + 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, const struct bma4_dev *dev)
+{
+ /*Partial read, then move the data index to last data*/
+ if (*data_index >= dev->fifo->length) {
+ /*Update the data index as complete*/
+ *data_index = dev->fifo->length;
+ } else {
+ dev->fifo->skipped_frame_count = dev->fifo->data[*data_index];
+ /*Move the data index*/
+ *data_index = (*data_index) + 1;
+ }
+}
+
+/*!
+ * @brief This API is used to 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, const struct bma4_dev *dev)
+{
+ uint8_t dropped_frame = 0;
+ /*Partial read, then move the data index to last data*/
+ if (*data_index >= dev->fifo->length) {
+ /*Update the data index as complete*/
+ *data_index = dev->fifo->length;
+ } else {
+ /*Extract accel and mag dropped frame count*/
+ dropped_frame = dev->fifo->data[*data_index] & ACCEL_AUX_FIFO_DROP;
+ /*Move the data index and update the dropped frame count*/
+ switch (dropped_frame) {
+ case ACCEL_FIFO_DROP:
+ *data_index = (*data_index) + BMA4_FIFO_A_LENGTH;
+ dev->fifo->accel_dropped_frame_count = dev->fifo->accel_dropped_frame_count + 1;
+ break;
+ case AUX_FIFO_DROP:
+ *data_index = (*data_index) + BMA4_FIFO_M_LENGTH;
+ dev->fifo->mag_dropped_frame_count = dev->fifo->mag_dropped_frame_count + 1;
+ break;
+ case ACCEL_AUX_FIFO_DROP:
+ *data_index = (*data_index) + BMA4_FIFO_MA_LENGTH;
+ dev->fifo->accel_dropped_frame_count = dev->fifo->accel_dropped_frame_count + 1;
+ dev->fifo->mag_dropped_frame_count = dev->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_dev *dev)
+{
+ /*Partial read, then move the data index to last data*/
+ if ((*data_index + current_frame_length) > dev->fifo->length) {
+ /*Update the data index as complete*/
+ *data_index = dev->fifo->length;
+ } else {
+ /*Move the data index to next frame*/
+ *data_index = *data_index + current_frame_length;
+ }
+}
+
+/*!
+ * @brief This function validates the Accel Self test data and decides the
+ * result of Self test operation.
+ */
+static uint16_t validate_selftest(const struct selftest_delta_limit *accel_data_diff,
+ const struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+
+ /* Set self test amplitude based on variant */
+ switch (dev->variant) {
+ case BMA42X_VARIANT:
+ /* Validating accel data by comparing with minimum value of the axes in mg */
+ /* For BMA42x - > x axis limit 400mg, y axis limit 800mg and z axis limit 400mg */
+ if ((accel_data_diff->x > BMA42X_ST_ACC_X_AXIS_SIGNAL_DIFF) &&
+ (accel_data_diff->y > BMA42X_ST_ACC_Y_AXIS_SIGNAL_DIFF) &&
+ (accel_data_diff->z > BMA42X_ST_ACC_Z_AXIS_SIGNAL_DIFF)) {
+ rslt = BMA4_OK;
+ } else {
+ rslt = BMA4_E_SELF_TEST_FAIL;
+ }
+ break;
+
+ case BMA45X_VARIANT:
+ /* Validating accel data by comparing with minimum value of the axes in mg */
+ /* For BMA45x - > x axis limit 1800mg, y axis limit 1800mg and z axis limit 1800mg */
+ if ((accel_data_diff->x > BMA45X_ST_ACC_X_AXIS_SIGNAL_DIFF) &&
+ (accel_data_diff->y > BMA45X_ST_ACC_Y_AXIS_SIGNAL_DIFF) &&
+ (accel_data_diff->z > BMA45X_ST_ACC_Z_AXIS_SIGNAL_DIFF)) {
+ rslt = BMA4_OK;
+ } else {
+ rslt = BMA4_E_SELF_TEST_FAIL;
+ }
+ break;
+
+ default:
+ rslt = BMA4_E_INVALID_SENSOR;
+ break;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This function configure the Accel for FOC.
+ */
+static uint16_t foc_config(struct bma4_accel_config *acc_conf, uint8_t *acc_en, uint8_t *pwr_mode, struct bma4_dev *dev)
+{
+ uint16_t rslt = 0;
+ uint8_t accel_cnf = BMA4_ACCEL_CONFIG_FOC;
+
+ /* for saving Accel configuration,
+ Accel enable status, advance power save*/
+ rslt |= bma4_get_accel_config(acc_conf, dev);
+ rslt |= bma4_get_accel_enable(acc_en, dev);
+ rslt |= bma4_get_advance_power_save(pwr_mode, dev);
+
+ /* Disabling offset compensation that is in place*/
+ rslt |= bma4_set_offset_comp(BMA4_DISABLE, dev);
+
+ if (rslt == BMA4_OK) {
+ /* Set Accel config to 50Hz, continuous filter mode,
+ no under sampling */
+ rslt |= bma4_write_regs(BMA4_ACCEL_CONFIG_ADDR, &accel_cnf, 1, dev);
+
+ if (rslt == BMA4_OK) {
+ /* Switch Accel to normal mode and
+ advance power save to zero*/
+ rslt |= bma4_set_accel_enable(BMA4_ENABLE, dev);
+ rslt |= bma4_set_advance_power_save(BMA4_DISABLE, dev);
+ }
+ }
+
+ 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 API performs the roundoff on given value
+ */
+static int8_t roundoff(int32_t value)
+{
+ /* Variable to return the round off value */
+ int8_t ret = 0;
+
+ /* Since the value passed is scaled in multiples of 100,
+ the return value is divided by 100 to get the round off value */
+ if (value < 0)
+ ret = (int8_t)(((value) - 50) / 100);
+ else
+ ret = (int8_t)(((value) + 50) / 100);
+
+
+ return ret;
+}
+
+/*!
+ * @brief This 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, uint8_t res)
+{
+ /* Variable to store the bit position of 3.9mg */
+ int8_t bit_pos_3_9mg = 0;
+ /* Variable to store the value to be rounded off */
+ int32_t value = 0;
+ /* Variable to store the LSB per bit in micros */
+ int32_t ug_per_bit;
+ /* Variable to store the rounded off value */
+ int8_t round_off_int;
+ /* Variable to store the bit count */
+ uint8_t bit_count = 0;
+ /* Variable to store the signed range value */
+ int32_t range_value;
+
+ /* Scaling range with a multiplier to get integer value of ug_per_bit */
+ range_value = (int32_t)(2 * range * BMA4XY_MULTIPLIER);
+
+ /* Get the G-per bit resolution*/
+ ug_per_bit = (int32_t)(range_value / power(2, res));
+
+ /* Compare for -ve & +ve bit position w.r.t 3900micro-g or as reference
+ * Note: Value scaled in 100s to get accurate integer value */
+ if (ug_per_bit > 3900)
+ value = (int32_t)(ug_per_bit * 100 / 3900);
+ else
+ value = (int32_t)(3900 * 100 / ug_per_bit);
+
+ /* Round off the value */
+ round_off_int = (int8_t)(roundoff(value));
+
+ /* Find the bit position of 3.9mg*/
+ while (round_off_int != 1) {
+ round_off_int = (round_off_int / 0x02);
+ bit_count++;
+ }
+
+ /* Check for +ve and -ve bit position of 3.9 mg */
+ if (ug_per_bit > 3900)
+ bit_pos_3_9mg = (int8_t)(bit_count * (-1));
+ else
+ bit_pos_3_9mg = (int8_t)bit_count;
+
+ return bit_pos_3_9mg;
+}
+/*!
+ * @brief This internal API brings up the secondary interface to access
+ * auxiliary sensor *
+ */
+static uint16_t bma4_set_aux_interface_config(struct bma4_dev *dev)
+{
+ /* Variable to return error codes */
+ uint16_t rslt = BMA4_OK;
+
+ /* Check for null pointer error */
+ rslt |= bma4_null_pointer_check(dev);
+
+ if (rslt == BMA4_OK) {
+ /* Enable the auxiliary sensor */
+ rslt |= bma4_set_mag_enable(0x01, dev);
+ dev->delay(BMA4_AUX_COM_DELAY);
+
+ /* Disable advance power save */
+ rslt |= bma4_set_advance_power_save(0x00, dev);
+ dev->delay(BMA4_AUX_COM_DELAY);
+
+ /* Set the I2C device address of auxiliary device */
+ rslt |= bma4_set_i2c_device_addr(dev);
+ dev->delay(BMA4_AUX_COM_DELAY);
+
+ /* Set auxiliary interface to manual mode */
+ rslt |= bma4_set_mag_manual_enable(dev->aux_config.manual_enable, dev);
+ dev->delay(BMA4_AUX_COM_DELAY);
+
+ /* Set the number of bytes for burst read */
+ rslt |= bma4_set_mag_burst(dev->aux_config.burst_read_length, dev);
+ dev->delay(BMA4_AUX_COM_DELAY);
+
+ /* Switch on the the auxiliary interface mode */
+ rslt |= bma4_set_if_mode(dev->aux_config.if_mode, dev);
+ dev->delay(BMA4_AUX_COM_DELAY);
+
+ }
+
+ return rslt;
+}
+
+/*!
+* @brief This internal API reads the data from the auxiliary sensor
+* depending on burst length configured
+*/
+static uint16_t bma4_extract_aux_data(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev)
+{
+ /* Variable to return error codes */
+ uint16_t rslt = BMA4_OK;
+ /* 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 |= bma4_map_read_len(&burst_len, dev);
+
+ 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(BMA4_AUX_COM_DELAY);
+
+ 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(BMA4_AUX_COM_DELAY);
+
+ 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_FAIL;
+ }
+ } else {
+ rslt = BMA4_E_FAIL;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This internal API maps the actual burst read length with user
+ length set.
+ */
+static uint16_t bma4_map_read_len(uint8_t *len, const struct bma4_dev *dev)
+{
+ /* Variable to return error codes */
+ uint16_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 uint16_t bma4_null_pointer_check(const struct bma4_dev *dev)
+{
+ uint16_t rslt = BMA4_OK;
+
+ if ((dev == NULL) || (dev->bus_read == NULL) || (dev->bus_write == NULL))
+ rslt |= BMA4_E_NULL_PTR;
+ else
+ rslt = BMA4_OK;
+
+ return rslt;
+}
diff --git a/libesp32/TTGO_TWatch_Library/src/bma4.h b/libesp32/TTGO_TWatch_Library/src/bma4.h
new file mode 100755
index 000000000..eba44b26c
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/src/bma4.h
@@ -0,0 +1,1574 @@
+/*
+*
+****************************************************************************
+* Copyright (C) 2015 - 2016 Bosch Sensortec GmbH
+*
+* File : bma4.h
+*
+* Date: 12 Oct 2017
+*
+* Revision: 2.1.9 $
+*
+* Usage: Sensor Driver for BMA4 family of sensors
+*
+****************************************************************************
+*
+* Disclaimer
+*
+* Common:
+* Bosch Sensortec products are developed for the consumer goods industry.
+* They may only be used within the parameters of the respective valid
+* product data sheet. Bosch Sensortec products are provided with the
+* express understanding that there is no warranty of fitness for a
+* particular purpose.They are not fit for use in life-sustaining,
+* safety or security sensitive systems or any system or device
+* that may lead to bodily harm or property damage if the system
+* or device malfunctions. In addition,Bosch Sensortec products are
+* not fit for use in products which interact with motor vehicle systems.
+* The resale and or use of products are at the purchasers own risk and
+* his own responsibility. The examination of fitness for the intended use
+* is the sole responsibility of the Purchaser.
+*
+* The purchaser shall indemnify Bosch Sensortec from all third party
+* claims, including any claims for incidental, or consequential damages,
+* arising from any product use not covered by the parameters of
+* the respective valid product data sheet or not approved by
+* Bosch Sensortec and reimburse Bosch Sensortec for all costs in
+* connection with such claims.
+*
+* The purchaser must monitor the market for the purchased products,
+* particularly with regard to product safety and inform Bosch Sensortec
+* without delay of all security relevant incidents.
+*
+* Engineering Samples are marked with an asterisk (*) or (e).
+* Samples may vary from the valid technical specifications of the product
+* series. They are therefore not intended or fit for resale to third
+* parties or for use in end products. Their sole purpose is internal
+* client testing. The testing of an engineering sample may in no way
+* replace the testing of a product series. Bosch Sensortec assumes
+* no liability for the use of engineering samples.
+* By accepting the engineering samples, the Purchaser agrees to indemnify
+* Bosch Sensortec from all claims arising from the use of engineering
+* samples.
+*
+* Special:
+* This software module (hereinafter called "Software") and any information
+* on application-sheets (hereinafter called "Information") is provided
+* free of charge for the sole purpose to support your application work.
+* The Software and Information is subject to the following
+* terms and conditions:
+*
+* The Software is specifically designed for the exclusive use for
+* Bosch Sensortec products by personnel who have special experience
+* and training. Do not use this Software if you do not have the
+* proper experience or training.
+*
+* This Software package is provided `` as is `` and without any expressed
+* or implied warranties,including without limitation, the implied warranties
+* of merchantability and fitness for a particular purpose.
+*
+* Bosch Sensortec and their representatives and agents deny any liability
+* for the functional impairment
+* of this Software in terms of fitness, performance and safety.
+* Bosch Sensortec and their representatives and agents shall not be liable
+* for any direct or indirect damages or injury, except as
+* otherwise stipulated in mandatory applicable law.
+*
+* The Information provided is believed to be accurate and reliable.
+* Bosch Sensortec assumes no responsibility for the consequences of use
+* of such Information nor for any infringement of patents or
+* other rights of third parties which may result from its use.
+* No license is granted by implication or otherwise under any patent or
+* patent rights of Bosch. Specifications mentioned in the Information are
+* subject to change without notice.
+**************************************************************************/
+/*! \file bma4.h
+ \brief Sensor Driver for BMA4 family of sensors */
+#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 */
+/*!
+ * @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.
+ *
+ * @param[in,out] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> 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)
+ */
+uint16_t bma4_init(struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_write_config_file(struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ */
+uint16_t bma4_write_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev);
+
+/*!
+ * @brief 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
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ */
+uint16_t bma4_read_regs(uint8_t addr, uint8_t *data, uint8_t len, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ */
+uint16_t bma4_get_error_status(struct bma4_err_reg *err_reg, struct bma4_dev *dev);
+
+/*!
+ * @brief This API reads the sensor status from the dev sensor.
+ *
+ * Below table lists the sensor status flags
+ * 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.
+ *
+ * @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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_status(uint8_t *status, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_read_accel_xyz(struct bma4_accel *accel, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_sensor_time(uint32_t *sensor_time, struct bma4_dev *dev);
+
+/*!
+ * @brief 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
+ * temp_unit | description
+ * ------------|-------------------
+ * BMA4_DEG | degrees Celsius
+ * BMA4_FAHREN | degrees fahrenheit
+ * BMA4_KELVIN | degrees kelvin
+ *
+ * @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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_temperature(int32_t *temp, uint8_t temp_unit, struct bma4_dev *dev);
+
+/*!
+ * @brief 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.
+ *
+ * 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
+ *
+ * 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
+ *
+ * Value | g_range
+ * --------|---------------------
+ * 0x00 | BMA4_ACCEL_RANGE_2G
+ * 0x01 | BMA4_ACCEL_RANGE_4G
+ * 0x02 | BMA4_ACCEL_RANGE_8G
+ * 0x03 | BMA4_ACCEL_RANGE_16G
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_accel_config(struct bma4_accel_config *accel, struct bma4_dev *dev);
+
+/*!
+ * @brief 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.
+ * 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
+ *
+ * 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
+ *
+ * Value | g_range
+ * --------|---------------------
+ * 0x00 | BMA4_ACCEL_RANGE_2G
+ * 0x01 | BMA4_ACCEL_RANGE_4G
+ * 0x02 | BMA4_ACCEL_RANGE_8G
+ * 0x03 | BMA4_ACCEL_RANGE_16G
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_accel_config(const struct bma4_accel_config *accel, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_advance_power_save(uint8_t adv_pwr_save,
+ struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_advance_power_save(uint8_t *adv_pwr_save, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_fifo_self_wakeup(uint8_t fifo_self_wakeup, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_fifo_self_wakeup(uint8_t *fifo_self_wake_up, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_accel_enable(uint8_t accel_en, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_accel_enable(uint8_t *accel_en, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_mag_enable(uint8_t mag_en, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_mag_enable(uint8_t *mag_en, struct bma4_dev *dev);
+
+/*!
+ * @brief This API reads the SPI interface mode which is set for primary
+ * interface.
+ *
+ * @param[out] spi : Pointer variable which stores the SPI mode selection
+ * Value | Description
+ * --------|------------------
+ * 0 | SPI 4-wire mode
+ * 1 | SPI 3-wire mode
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_spi_interface(uint8_t *spi, struct bma4_dev *dev);
+
+/*!
+ * @brief This API configures the SPI interface Mode for primary interface
+ *
+ * @param[in] spi : The value of SPI mode selection
+ * Value | Description
+ * --------|------------------
+ * 0 | SPI 4-wire mode
+ * 1 | SPI 3-wire mode
+ *
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_spi_interface(uint8_t spi, struct bma4_dev *dev);
+
+ /*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_command_register(uint8_t command_reg, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_i2c_device_addr(struct bma4_dev *dev);
+
+/*!
+ * @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.
+ *
+ * @param[in] mag_manual : Variable used to specify the Mag manual
+ * enable status.
+ * value | mag manual
+ * ---------|--------------------
+ * 0x01 | BMA4_ENABLE
+ * 0x00 | BMA4_DISABLE
+ *
+ * @param[out] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_mag_manual_enable(uint8_t mag_manual, struct bma4_dev *dev);
+
+/*!
+ * @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.
+ *
+ * @param[out] mag_manual : Mag manual enable value
+ * value | mag_manual
+ * --------|-------------------
+ * 0x01 | BMA4_ENABLE
+ * 0x00 | BMA4_DISABLE
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_mag_manual_enable(uint8_t *mag_manual, struct bma4_dev *dev);
+
+/*!
+ * @brief This API sets the I2C interface configuration(if) mode
+ * for auxiliary Mag.
+ *
+ * @param[in] if_mode : The value of interface configuration mode
+ * Value | Description
+ * ------------|-------------------------------------------
+ * 0 | p_auto_s_off Auxiliary interface:off
+ * 1 | p_auto_s_mag Auxiliary interface:on
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_aux_if_mode(uint8_t if_mode, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_mag_read_addr(uint8_t *mag_read_addr, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_mag_read_addr(uint8_t mag_read_addr, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_mag_write_addr(uint8_t *mag_write_addr, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_mag_write_addr(uint8_t mag_write_addr, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_mag_write_data(uint8_t *mag_write_data, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_mag_write_data(uint8_t mag_write_data, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_read_mag_xyzr(struct bma4_mag_xyzr *mag, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_mag_burst(uint8_t mag_burst, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_mag_burst(uint8_t *mag_burst, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_read_fifo_data(struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_fifo_wm(uint16_t *fifo_wm, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_fifo_wm(uint16_t fifo_wm, struct bma4_dev *dev);
+
+/*!
+ * @brief 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.
+ * Value | accel_fifo_filter
+ * ---------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ * @param[in] dev : structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_accel_fifo_filter_data(uint8_t *accel_fifo_filter, struct bma4_dev *dev);
+
+/*!
+ * @brief 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.
+ * value | accel_fifo_filter_data
+ * -----------|-------------------------
+ * 0x00 | Unfiltered data
+ * 0x01 | Filtered data
+ * @param[out] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_accel_fifo_filter_data(uint8_t accel_fifo_filter, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_fifo_down_accel(uint8_t *fifo_down, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_fifo_down_accel(uint8_t fifo_down, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_fifo_length(uint16_t *fifo_length, struct bma4_dev *dev);
+
+/*!
+ * @brief 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.
+ * Value | mag_second_if
+ * --------|----------------------
+ * 1 | BMA4_SEC_IF_BMM150
+ * 2 | BMA4_SEC_IF_AKM09916
+ *
+ * @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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_second_if_mag_compensate_xyz(struct bma4_mag_fifo_data mag_fifo_data,
+ uint8_t mag_second_if,
+ struct bma4_mag *compensated_mag_data);
+
+/*!
+ * @brief 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
+ * Value | Sensor
+ * ---------|----------------------
+ * 0 | BMA4_SEC_IF_NULL
+ * 1 | BMA4_SEC_IF_BMM150
+ * 2 | BMA4_SEC_IF_AKM09916
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_read_mag_xyz(struct bma4_mag *mag, uint8_t sensor_select, struct bma4_dev *dev);
+
+/*!
+ * @brief 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.
+ * Value | Description
+ * ----- |----------------------------------
+ * 0x00 | auxiliary interface:off
+ * 0x01 | auxiliary interface:on
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_if_mode(uint8_t *if_mode, struct bma4_dev *dev);
+
+/*!
+ * @brief This API sets the auxiliary interface configuration in the sensor.
+ *
+ * @param[in] if_mode : Variable used to select the auxiliary interface
+ * configuration.
+ * Value | Description
+ * ----- |--------------------------
+ * 0x00 | auxiliary interface:off
+ * 0x01 | auxiliary interface:on
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_if_mode(uint8_t if_mode, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_accel_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_mag_data_rdy(uint8_t *data_rdy, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_asic_status(struct bma4_asic_status *asic_status, struct bma4_dev *dev);
+
+/*!
+ * @brief This API enables the offset compensation for filtered and
+ * unfiltered Accel data.
+ *
+ * @param[in] offset_en : Variable used to enable or disable offset
+ * compensation
+ * offset_en | Description
+ * ------------|----------------------
+ * 0 | BMA4_DISABLE
+ * 1 | BMA4_ENABLE
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_offset_comp(uint8_t offset_en, struct bma4_dev *dev);
+
+/*!
+ * @brief 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.
+ * offset_en | Description
+ * ----------|--------------
+ * 0 | BMA4_DISABLE
+ * 1 | BMA4_ENABLE
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_offset_comp(uint8_t *offset_en, struct bma4_dev *dev);
+
+/*!
+ * @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.
+ *
+ * @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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_extract_accel(struct bma4_accel *accel_data, uint16_t *accel_length, const struct bma4_dev *dev);
+
+/*!
+ * @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
+ *
+ * @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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_extract_mag(struct bma4_mag *mag_data, uint16_t *mag_length, const struct bma4_dev *dev);
+
+/*!
+ * @brief 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.
+ * 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
+ *
+ * @param[in] dev : structure instance of dev
+ *
+ * @note The g-values to be passed to the parameter should be
+ * multiples of 1000000.
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_perform_accel_foc(const int32_t accel_g_value[3], struct bma4_dev *dev);
+/*!
+ * @brief 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
+ * result | Description
+ * ---------|--------------------
+ * 0x00 | BMA4_SELFTEST_PASS
+ * 0x01 | BMA4_SELFTEST_FAIL
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return results of self test
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_perform_accel_selftest(uint8_t *result, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 results of self test
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_selftest_config(uint8_t sign, struct bma4_dev *dev);
+
+/*!
+ * @brief 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
+ * int_line | interrupt selection
+ * ---------|-------------------
+ * 0 | BMA4_INTR1_MAP
+ * 1 | BMA4_INTR2_MAP
+ *
+ * @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
+ * Value | Behaviour
+ * ---------|-------------------
+ * 0x01 | BMA4_ENABLE
+ * 0x00 | BMA4_DISABLE
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev);
+
+/*!
+ * @brief 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.
+ * Mode | Value
+ * ----------------------- |---------
+ * BMA4_NON_LATCH_MODE | 0
+ * BMA4_LATCH_MODE | 1
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return status of bus communication function
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_interrupt_mode(uint8_t mode, struct bma4_dev *dev);
+
+/*!
+ * @brief 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.
+ * Mode | Value
+ * ---------------------|---------------
+ * BMA4_NON_LATCH_MODE | 0
+ * BMA4_LATCH_MODE | 1
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return status of bus communication function
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_interrupt_mode(uint8_t *mode, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 status of bus communication function
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_aux_mag_config(const struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 status of bus communication function
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_aux_mag_config(struct bma4_aux_mag_config *aux_mag, struct bma4_dev *dev);
+
+/*! @brief 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.
+ * 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
+ *
+ * @param[in] enable : Parameter used to enable or disable the above
+ * FIFO configuration
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return status of bus communication result
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_set_fifo_config(uint8_t config, uint8_t enable, struct bma4_dev *dev);
+
+/*! @brief 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.
+ * 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
+ *
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return status of bus communication function
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_fifo_config(uint8_t *fifo_config, struct bma4_dev *dev);
+
+/*! @brief 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.
+ * int_line | Value
+ * ----------------|----------------------
+ * BMA4_INTR1_MAP | 0
+ * BMA4_INTR2_MAP | 1
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return status of bus communication function
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ */
+uint16_t bma4_set_int_pin_config(const struct bma4_int_pin_config *int_pin_config, uint8_t int_line,
+ struct bma4_dev *dev);
+
+/*! @brief 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.
+ * int_line | Value
+ * -------------------|---------------
+ * BMA4_INTR1_MAP | 0
+ * BMA4_INTR2_MAP | 1
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return status of bus communication function
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_get_int_pin_config(struct bma4_int_pin_config *int_pin_config, uint8_t int_line, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_read_int_status(uint16_t *int_status, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_read_int_status_0(uint8_t *int_status_0, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_read_int_status_1(uint8_t *int_status_1, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_aux_interface_init(struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_aux_read(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ *
+ */
+uint16_t bma4_aux_write(uint8_t aux_reg_addr, uint8_t *aux_data, uint16_t len, struct bma4_dev *dev);
+
+
+#endif
+/* End of __BMA4_H__ */
diff --git a/libesp32/TTGO_TWatch_Library/src/bma423.c b/libesp32/TTGO_TWatch_Library/src/bma423.c
new file mode 100755
index 000000000..3d5d9c63c
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/src/bma423.c
@@ -0,0 +1,1695 @@
+/**\mainpage
+*
+****************************************************************************
+* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH
+*
+* File : bma423.c
+*
+* Date: 12 Oct 2017
+*
+* Revision : 1.1.4 $
+*
+* Usage: Sensor Driver for BMA423 sensor
+*
+****************************************************************************
+*
+* \section Disclaimer
+*
+* Common:
+* Bosch Sensortec products are developed for the consumer goods industry.
+* They may only be used within the parameters of the respective valid
+* product data sheet. Bosch Sensortec products are provided with the
+* express understanding that there is no warranty of fitness for a
+* particular purpose.They are not fit for use in life-sustaining,
+* safety or security sensitive systems or any system or device
+* that may lead to bodily harm or property damage if the system
+* or device malfunctions. In addition,Bosch Sensortec products are
+* not fit for use in products which interact with motor vehicle systems.
+* The resale and or use of products are at the purchasers own risk and
+* his own responsibility. The examination of fitness for the intended use
+* is the sole responsibility of the Purchaser.
+*
+* The purchaser shall indemnify Bosch Sensortec from all third party
+* claims, including any claims for incidental, or consequential damages,
+* arising from any product use not covered by the parameters of
+* the respective valid product data sheet or not approved by
+* Bosch Sensortec and reimburse Bosch Sensortec for all costs in
+* connection with such claims.
+*
+* The purchaser must monitor the market for the purchased products,
+* particularly with regard to product safety and inform Bosch Sensortec
+* without delay of all security relevant incidents.
+*
+* Engineering Samples are marked with an asterisk (*) or (e).
+* Samples may vary from the valid technical specifications of the product
+* series. They are therefore not intended or fit for resale to third
+* parties or for use in end products. Their sole purpose is internal
+* client testing. The testing of an engineering sample may in no way
+* replace the testing of a product series. Bosch Sensortec assumes
+* no liability for the use of engineering samples.
+* By accepting the engineering samples, the Purchaser agrees to indemnify
+* Bosch Sensortec from all claims arising from the use of engineering
+* samples.
+*
+* Special:
+* This software module (hereinafter called "Software") and any information
+* on application-sheets (hereinafter called "Information") is provided
+* free of charge for the sole purpose to support your application work.
+* The Software and Information is subject to the following
+* terms and conditions:
+*
+* The Software is specifically designed for the exclusive use for
+* Bosch Sensortec products by personnel who have special experience
+* and training. Do not use this Software if you do not have the
+* proper experience or training.
+*
+* This Software package is provided `` as is `` and without any expressed
+* or implied warranties,including without limitation, the implied warranties
+* of merchantability and fitness for a particular purpose.
+*
+* Bosch Sensortec and their representatives and agents deny any liability
+* for the functional impairment
+* of this Software in terms of fitness, performance and safety.
+* Bosch Sensortec and their representatives and agents shall not be liable
+* for any direct or indirect damages or injury, except as
+* otherwise stipulated in mandatory applicable law.
+*
+* The Information provided is believed to be accurate and reliable.
+* Bosch Sensortec assumes no responsibility for the consequences of use
+* of such Information nor for any infringement of patents or
+* other rights of third parties which may result from its use.
+* No license is granted by implication or otherwise under any patent or
+* patent rights of Bosch. Specifications mentioned in the Information are
+* subject to change without notice.
+**************************************************************************/
+/*! \file bma423.c
+ \brief Sensor Driver for BMA423 sensor */
+
+#include "bma423.h"
+
+/**\name Feature configuration file */
+const uint8_t bma423_config_file[] = {
+ 0x80, 0x2e, 0xfc, 0x00, 0x80, 0x2e, 0xfe, 0x00, 0xc8, 0x2e, 0x00, 0x2e,
+ 0x80, 0x2e, 0xfa, 0x00, 0x80, 0x2e, 0x23, 0xb1, 0x80, 0x2e, 0xfd, 0x00,
+ 0x80, 0x2e, 0xfb, 0x00, 0x80, 0x2e, 0x5a, 0xb1, 0x50, 0x39, 0x21, 0x2e,
+ 0xb0, 0xf0, 0x10, 0x30, 0x21, 0x2e, 0x16, 0xf0, 0x80, 0x2e, 0xfc, 0x01,
+ 0x5d, 0x50, 0x45, 0x52, 0x01, 0x42, 0x3b, 0x80, 0x41, 0x30, 0x01, 0x42,
+ 0x3c, 0x80, 0x00, 0x2e, 0x01, 0x40, 0x01, 0x42, 0x21, 0x2e, 0xff, 0xaf,
+ 0xb8, 0x2e, 0xb6, 0xd6, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0xfd, 0x2d, 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, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x24, 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, 0x98, 0x2e,
+ 0x99, 0x01, 0x20, 0x26, 0x98, 0x2e, 0xf6, 0x00, 0x98, 0x2e, 0xe9, 0x01,
+ 0x10, 0x30, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0x00, 0x2e,
+ 0x00, 0x2e, 0xd0, 0x2e, 0x98, 0x2e, 0xdd, 0x00, 0x01, 0x2e, 0x56, 0x00,
+ 0x00, 0xb2, 0x11, 0x2f, 0x00, 0x30, 0x21, 0x2e, 0x56, 0x00, 0x41, 0x50,
+ 0x98, 0x2e, 0xcc, 0xb0, 0x41, 0x50, 0x98, 0x2e, 0x8f, 0xb4, 0x01, 0x2e,
+ 0x03, 0xf0, 0x0d, 0xbc, 0x0f, 0xb8, 0x00, 0x90, 0x02, 0x2f, 0x45, 0x50,
+ 0x21, 0x2e, 0xbc, 0xf0, 0x01, 0x2e, 0x55, 0x00, 0x00, 0xb2, 0x1a, 0x2f,
+ 0x00, 0x30, 0x21, 0x2e, 0x55, 0x00, 0x43, 0x50, 0x98, 0x2e, 0xcc, 0xb0,
+ 0x43, 0x50, 0x98, 0x2e, 0xdc, 0xb1, 0x43, 0x50, 0x98, 0x2e, 0x92, 0xb5,
+ 0x43, 0x50, 0x98, 0x2e, 0x00, 0xb0, 0x01, 0x2e, 0x1c, 0x01, 0x0f, 0xbc,
+ 0x0f, 0xb8, 0x00, 0x90, 0x45, 0x50, 0x02, 0x2f, 0x21, 0x2e, 0xbc, 0xf0,
+ 0x02, 0x2d, 0x21, 0x2e, 0xba, 0xf0, 0x98, 0x2e, 0xd8, 0x00, 0xc3, 0x2d,
+ 0x01, 0x2e, 0x55, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0x55, 0xf0, 0x03, 0x2e,
+ 0x00, 0xf0, 0x45, 0x54, 0x01, 0x2e, 0x59, 0xf0, 0x4a, 0x0e, 0x02, 0x2f,
+ 0xf1, 0x33, 0x0d, 0x2c, 0x01, 0x08, 0xf2, 0x30, 0x4a, 0x08, 0x79, 0x84,
+ 0x82, 0xa2, 0x04, 0x2f, 0x02, 0x34, 0x82, 0x0a, 0x47, 0xa2, 0x03, 0x2c,
+ 0x10, 0x22, 0x45, 0x52, 0x01, 0x0a, 0xc0, 0x2e, 0x21, 0x2e, 0x59, 0xf0,
+ 0x00, 0x31, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0xc8, 0x2e, 0xc8, 0x2e,
+ 0xc8, 0x2e, 0xc8, 0x2e, 0xc8, 0x2e, 0x44, 0x47, 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, 0x06, 0x00, 0x00, 0x00, 0x43, 0x28, 0x88, 0x00,
+ 0x52, 0x00, 0x4f, 0x00, 0x80, 0x00, 0x5b, 0x00, 0x00, 0x40, 0xaf, 0x00,
+ 0xff, 0x00, 0xff, 0xb7, 0x00, 0x02, 0x00, 0xb0, 0x05, 0x80, 0xb1, 0xf0,
+ 0xc0, 0x00, 0x00, 0x01, 0x5e, 0xf0, 0x39, 0xf0, 0x89, 0xf0, 0x00, 0x20,
+ 0xff, 0x7f, 0x7d, 0x00, 0x5e, 0x00, 0x62, 0x00, 0x7c, 0x00, 0xff, 0xfb,
+ 0x52, 0xf0, 0x56, 0xf0, 0x33, 0x09, 0x33, 0x07, 0x00, 0x08, 0x90, 0x01,
+ 0x00, 0xf8, 0x67, 0x00, 0x4c, 0x04, 0xa0, 0x00, 0xe8, 0x03, 0x81, 0x00,
+ 0x82, 0x00, 0x6a, 0x00, 0x6d, 0x00, 0x6c, 0x00, 0xeb, 0x07, 0xae, 0x07,
+ 0x72, 0x00, 0x6f, 0x00, 0xa1, 0x01, 0x1e, 0x05, 0x47, 0xfd, 0x73, 0x00,
+ 0x77, 0x00, 0x79, 0x00, 0x76, 0x00, 0xcc, 0x00, 0x30, 0x50, 0x50, 0x40,
+ 0x00, 0x18, 0x50, 0x40, 0x56, 0x25, 0x47, 0x25, 0x00, 0x18, 0x2e, 0x00,
+ 0x41, 0x40, 0xa7, 0x02, 0x09, 0x18, 0xc6, 0x00, 0xfb, 0x7f, 0x00, 0x30,
+ 0x49, 0x52, 0x05, 0x30, 0x05, 0x2c, 0x17, 0x03, 0x1e, 0xbd, 0xd2, 0xba,
+ 0x92, 0xb8, 0x6a, 0x0b, 0x61, 0x0e, 0xf9, 0x2f, 0x61, 0x1a, 0x01, 0x2f,
+ 0x5d, 0x0e, 0xf5, 0x2f, 0xd4, 0x7f, 0x02, 0x30, 0x1f, 0x2c, 0xe3, 0x7f,
+ 0x85, 0x01, 0xd1, 0x03, 0x7c, 0x0e, 0x03, 0x2f, 0x7c, 0x1a, 0x0f, 0x2f,
+ 0x73, 0x0f, 0x0d, 0x2f, 0xe3, 0x6f, 0xde, 0x04, 0x5f, 0xba, 0x11, 0xbf,
+ 0xb4, 0x0b, 0xd4, 0x6f, 0x27, 0x07, 0xb3, 0x25, 0xd1, 0xbf, 0xeb, 0x7f,
+ 0x07, 0x00, 0xb4, 0x25, 0x96, 0x02, 0xdb, 0x7f, 0x2f, 0xbf, 0x9e, 0xbf,
+ 0x01, 0xb8, 0xd2, 0xba, 0x21, 0xb9, 0x92, 0xb8, 0x06, 0x0a, 0x6f, 0x0b,
+ 0x40, 0x90, 0xdf, 0x2f, 0x40, 0x91, 0xdd, 0x2f, 0xfb, 0x6f, 0xd0, 0x5f,
+ 0xb8, 0x2e, 0x57, 0x50, 0x41, 0x30, 0x02, 0x40, 0x51, 0x0a, 0x01, 0x42,
+ 0x18, 0x82, 0x4b, 0x50, 0x60, 0x42, 0x70, 0x3c, 0x4d, 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, 0x13, 0x90, 0x20, 0x2f, 0x03, 0x30,
+ 0x51, 0x50, 0x4f, 0x54, 0xf4, 0x34, 0x06, 0x30, 0x55, 0x52, 0x55, 0x32,
+ 0x1d, 0x1a, 0xe3, 0x22, 0x18, 0x1a, 0x53, 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, 0xf4, 0x34,
+ 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, 0xd8, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e,
+ 0xfb, 0x6f, 0xf0, 0x5f, 0xb8, 0x2e, 0x01, 0x2e, 0xb1, 0xf0, 0x59, 0x52,
+ 0x01, 0x0a, 0x21, 0x2e, 0xb1, 0xf0, 0x01, 0x2e, 0x1c, 0x01, 0x0f, 0xbc,
+ 0x0f, 0xb8, 0x00, 0x90, 0x45, 0x50, 0x02, 0x2f, 0xc0, 0x2e, 0x21, 0x2e,
+ 0xbc, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0x1a, 0x24, 0x26, 0x00,
+ 0x80, 0x2e, 0x8f, 0x00, 0x03, 0x2e, 0x01, 0x01, 0x05, 0x2e, 0x01, 0x01,
+ 0x92, 0xbd, 0x20, 0x50, 0x03, 0x2e, 0x01, 0x01, 0xbf, 0xba, 0x21, 0xbd,
+ 0x2f, 0xbb, 0x1f, 0xba, 0x40, 0x91, 0xf0, 0x7f, 0x04, 0x2f, 0x80, 0x91,
+ 0x02, 0x2f, 0x00, 0xb3, 0x90, 0x2e, 0xc7, 0xb0, 0x03, 0x2e, 0x7b, 0x00,
+ 0x01, 0x80, 0x40, 0x90, 0x14, 0x2f, 0x41, 0x84, 0xf1, 0x6f, 0x25, 0x2e,
+ 0x7b, 0x00, 0x41, 0x40, 0x23, 0x2e, 0x5a, 0x00, 0x47, 0x52, 0x12, 0x40,
+ 0x52, 0x42, 0x02, 0x30, 0x00, 0x40, 0x40, 0x42, 0xe0, 0x5f, 0x25, 0x2e,
+ 0x57, 0x00, 0x25, 0x2e, 0x58, 0x00, 0x25, 0x2e, 0x5d, 0x00, 0xb8, 0x2e,
+ 0x07, 0x2e, 0x00, 0x01, 0x03, 0x2e, 0x01, 0x01, 0x05, 0x2e, 0x00, 0x01,
+ 0x24, 0xbd, 0x0f, 0x2e, 0x59, 0x00, 0xb5, 0xbd, 0x93, 0xbc, 0x2f, 0xb9,
+ 0xb5, 0xb9, 0x93, 0xb8, 0x3a, 0x1a, 0x06, 0x2f, 0x07, 0x30, 0x25, 0x2e,
+ 0x59, 0x00, 0x2f, 0x2e, 0x57, 0x00, 0x2f, 0x2e, 0x58, 0x00, 0x40, 0xb3,
+ 0x05, 0x30, 0x07, 0x30, 0x0a, 0x2f, 0xf7, 0x6f, 0xe6, 0x7f, 0x00, 0x2e,
+ 0xc6, 0x41, 0x0f, 0x2e, 0x5a, 0x00, 0xb7, 0x05, 0x80, 0xa9, 0xee, 0x05,
+ 0xf7, 0x23, 0xe6, 0x6f, 0x80, 0xb3, 0x06, 0x30, 0x09, 0x2f, 0xe7, 0x7f,
+ 0x00, 0x2e, 0x06, 0x40, 0x0f, 0x2e, 0x5b, 0x00, 0xb7, 0x05, 0x80, 0xa9,
+ 0xee, 0x05, 0xb7, 0x23, 0xe7, 0x6f, 0x00, 0xb3, 0x04, 0x30, 0x0b, 0x2f,
+ 0xf4, 0x6f, 0x02, 0x89, 0xe7, 0x7f, 0x00, 0x2e, 0x04, 0x41, 0x0f, 0x2e,
+ 0x5c, 0x00, 0x27, 0x05, 0x00, 0xa9, 0xec, 0x05, 0x27, 0x23, 0xe7, 0x6f,
+ 0x7b, 0x0f, 0x17, 0x30, 0x0b, 0x2f, 0x73, 0x0f, 0x05, 0x30, 0x17, 0x30,
+ 0x07, 0x2f, 0x63, 0x0f, 0x15, 0x30, 0x17, 0x30, 0x00, 0x2f, 0x07, 0x30,
+ 0xe3, 0x0e, 0x00, 0x2f, 0x05, 0x30, 0x80, 0x90, 0x05, 0x2e, 0x57, 0x00,
+ 0x13, 0x30, 0x13, 0x29, 0xf2, 0x6f, 0x47, 0x5c, 0x17, 0x2f, 0xc0, 0x91,
+ 0x05, 0x30, 0x0b, 0x2f, 0x07, 0x2e, 0x58, 0x00, 0xc1, 0x86, 0x2b, 0x2e,
+ 0x57, 0x00, 0x59, 0x0e, 0x27, 0x2e, 0x58, 0x00, 0x24, 0x2f, 0x2b, 0x2e,
+ 0x5d, 0x00, 0x22, 0x2d, 0x61, 0x0e, 0x29, 0x2e, 0x57, 0x00, 0x2b, 0x2e,
+ 0x58, 0x00, 0x1b, 0x2f, 0x27, 0x2e, 0x5d, 0x00, 0x19, 0x2d, 0x40, 0x91,
+ 0x05, 0x2f, 0x01, 0x30, 0x23, 0x2e, 0x57, 0x00, 0x23, 0x2e, 0x5d, 0x00,
+ 0x06, 0x2d, 0x29, 0x2e, 0x57, 0x00, 0x61, 0x0e, 0x01, 0x2f, 0x27, 0x2e,
+ 0x5d, 0x00, 0x81, 0x40, 0x23, 0x2e, 0x5a, 0x00, 0x30, 0x25, 0x47, 0x52,
+ 0xd4, 0x40, 0x54, 0x42, 0x00, 0x2e, 0xc3, 0x40, 0x43, 0x42, 0x00, 0x2e,
+ 0x03, 0x2e, 0x5d, 0x00, 0x40, 0xb2, 0x0d, 0x2f, 0x81, 0x40, 0x23, 0x2e,
+ 0x5a, 0x00, 0x11, 0x40, 0x91, 0x43, 0x01, 0x34, 0x00, 0x40, 0x80, 0x43,
+ 0x23, 0x2e, 0x5e, 0xf0, 0x03, 0x2d, 0x00, 0x30, 0x21, 0x2e, 0x7b, 0x00,
+ 0xe0, 0x5f, 0xb8, 0x2e, 0x50, 0x50, 0xf0, 0x7f, 0x1a, 0x25, 0x13, 0x40,
+ 0x7b, 0x84, 0xe0, 0x7f, 0x83, 0x42, 0x35, 0x30, 0x11, 0x40, 0x04, 0x40,
+ 0xc1, 0x7f, 0xd4, 0x7f, 0x86, 0x31, 0x07, 0x2e, 0x59, 0xf0, 0x03, 0x2e,
+ 0x1f, 0x01, 0x0d, 0x09, 0x02, 0xab, 0x05, 0x30, 0x8e, 0x09, 0x2c, 0x23,
+ 0xe3, 0xba, 0x42, 0xab, 0x16, 0x30, 0x75, 0x23, 0x59, 0x5c, 0x8e, 0x09,
+ 0x66, 0xbb, 0x82, 0xab, 0x27, 0x30, 0xbe, 0x23, 0x3e, 0x80, 0x25, 0x1a,
+ 0x06, 0x2f, 0x2e, 0x1a, 0x04, 0x2f, 0x26, 0x1a, 0x02, 0x2f, 0xf7, 0x3d,
+ 0x03, 0x2c, 0xdf, 0x08, 0x07, 0x32, 0xdf, 0x0a, 0x14, 0x01, 0x55, 0x01,
+ 0x04, 0x41, 0x14, 0x42, 0x16, 0x01, 0x42, 0x41, 0x45, 0x30, 0x4d, 0x09,
+ 0x04, 0x41, 0x12, 0x42, 0x04, 0x42, 0x40, 0xb3, 0x04, 0x2f, 0xf0, 0x6f,
+ 0x02, 0x30, 0x04, 0x40, 0x94, 0x04, 0x02, 0x42, 0x00, 0x32, 0x08, 0x08,
+ 0x00, 0xb2, 0x00, 0x30, 0x05, 0x2f, 0xe2, 0x6f, 0x00, 0x2e, 0x84, 0x40,
+ 0x04, 0x05, 0x84, 0x42, 0x00, 0x2e, 0x5b, 0x54, 0x4a, 0x08, 0x40, 0xb2,
+ 0xf1, 0x6f, 0x04, 0x2f, 0x42, 0x82, 0x00, 0x2e, 0x42, 0x40, 0x02, 0x04,
+ 0x40, 0x42, 0xb0, 0x5f, 0x27, 0x2e, 0x59, 0xf0, 0xb8, 0x2e, 0x50, 0x50,
+ 0xf7, 0x7f, 0x00, 0x2e, 0x0f, 0x2e, 0xb8, 0xf0, 0xf8, 0xbf, 0xff, 0xbb,
+ 0xc0, 0xb3, 0x2a, 0x2f, 0x0f, 0x2e, 0x01, 0xf0, 0xfe, 0xbf, 0xe6, 0x7f,
+ 0x7e, 0xbb, 0xd5, 0x7f, 0x37, 0x30, 0x5f, 0x5a, 0xbe, 0x05, 0x67, 0x41,
+ 0xc4, 0x7f, 0x78, 0xbe, 0x47, 0x41, 0x27, 0x0b, 0xb3, 0x7f, 0xe6, 0x11,
+ 0x41, 0x56, 0x43, 0x89, 0xd7, 0x42, 0x00, 0x2e, 0x27, 0x41, 0x05, 0x41,
+ 0xf8, 0xbf, 0x7d, 0x0b, 0x6e, 0x11, 0x03, 0x8f, 0xd5, 0x42, 0x14, 0x30,
+ 0xe5, 0x41, 0xc7, 0x41, 0xd8, 0xbe, 0x6f, 0x0b, 0x6e, 0x11, 0xc5, 0x42,
+ 0x29, 0x2e, 0x56, 0x00, 0x45, 0x56, 0x27, 0x2e, 0xb8, 0xf0, 0xe6, 0x6f,
+ 0xd5, 0x6f, 0xc4, 0x6f, 0xb3, 0x6f, 0xf7, 0x6f, 0xb0, 0x5f, 0xc8, 0x2e,
+ 0x50, 0x50, 0xe5, 0x7f, 0xd7, 0x7f, 0xf6, 0x7f, 0x36, 0x30, 0x0b, 0x2e,
+ 0x01, 0xf0, 0xde, 0xbe, 0xde, 0xbb, 0x61, 0x5a, 0xb7, 0x05, 0x67, 0x41,
+ 0xc4, 0x7f, 0x78, 0xbe, 0x47, 0x41, 0x27, 0x0b, 0xb3, 0x7f, 0xe6, 0x11,
+ 0x43, 0x56, 0x43, 0x89, 0xd7, 0x42, 0x00, 0x2e, 0x27, 0x41, 0x05, 0x41,
+ 0xf8, 0xbf, 0x7d, 0x0b, 0x6e, 0x11, 0x03, 0x8f, 0xd5, 0x42, 0x14, 0x30,
+ 0xe5, 0x41, 0xc7, 0x41, 0xd8, 0xbe, 0x6f, 0x0b, 0x6e, 0x11, 0xc5, 0x42,
+ 0x29, 0x2e, 0x55, 0x00, 0x03, 0x31, 0x27, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f,
+ 0xe5, 0x6f, 0xd7, 0x6f, 0xc4, 0x6f, 0xb3, 0x6f, 0xb0, 0x5f, 0xc8, 0x2e,
+ 0x40, 0x50, 0xf6, 0x7f, 0x1a, 0x18, 0x63, 0x56, 0x33, 0x00, 0x06, 0x30,
+ 0xfe, 0x03, 0x0e, 0xb8, 0xf2, 0xbf, 0x07, 0x0a, 0x2a, 0x18, 0x63, 0x5a,
+ 0xb5, 0x01, 0x03, 0x30, 0xfb, 0x03, 0x6e, 0xbb, 0xf2, 0xbf, 0xe1, 0x7f,
+ 0xf7, 0x0b, 0x56, 0x40, 0x36, 0x25, 0x46, 0x40, 0x06, 0x28, 0xc7, 0x7f,
+ 0x22, 0x18, 0xd1, 0x7f, 0xb5, 0x00, 0x01, 0x30, 0x39, 0x03, 0x2e, 0xb9,
+ 0x42, 0xbe, 0x14, 0x0b, 0xf2, 0x6f, 0x10, 0x18, 0xb5, 0x00, 0xb9, 0x03,
+ 0x2e, 0xb9, 0x62, 0xbf, 0x96, 0x0a, 0xb6, 0x6f, 0x30, 0x18, 0x75, 0x01,
+ 0xb9, 0x03, 0x5c, 0x28, 0xe2, 0xbf, 0xde, 0xb9, 0xd6, 0x6f, 0xdf, 0x0a,
+ 0x8a, 0x28, 0xc4, 0x6f, 0x82, 0x43, 0x23, 0x29, 0xe5, 0x6f, 0xc0, 0x2e,
+ 0x44, 0x43, 0xc0, 0x5f, 0x40, 0x50, 0xd0, 0x7f, 0x4a, 0x17, 0x00, 0x40,
+ 0x01, 0x18, 0x46, 0x25, 0x07, 0x25, 0x65, 0x56, 0xd9, 0x04, 0x53, 0x18,
+ 0xeb, 0x18, 0x05, 0x30, 0x49, 0x16, 0x69, 0x06, 0xca, 0x18, 0xa6, 0x00,
+ 0xc7, 0x02, 0x65, 0x58, 0xcb, 0x7f, 0x98, 0x2e, 0x7f, 0xb6, 0xcb, 0x6f,
+ 0xd2, 0x6f, 0xc0, 0x2e, 0x80, 0x42, 0xc0, 0x5f, 0x09, 0x2e, 0x1b, 0x01,
+ 0x05, 0x2e, 0x1b, 0x01, 0xa3, 0xbc, 0x44, 0xbe, 0x90, 0x50, 0x4f, 0xb9,
+ 0x07, 0x2e, 0x1b, 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, 0x87, 0xb2, 0x20, 0x25, 0x01, 0x2e, 0x64, 0x00,
+ 0x01, 0x90, 0x0e, 0x2f, 0x67, 0x52, 0x01, 0x2e, 0x61, 0x00, 0xb4, 0x7f,
+ 0xa2, 0x7f, 0x98, 0x2e, 0x8d, 0xb2, 0x00, 0x30, 0x21, 0x2e, 0x64, 0x00,
+ 0xc1, 0x6f, 0xd3, 0x6f, 0xa2, 0x6f, 0xb4, 0x6f, 0x0b, 0x30, 0x01, 0x2e,
+ 0x1b, 0x01, 0x06, 0xbc, 0x06, 0xbb, 0x57, 0x25, 0x01, 0x2e, 0x1b, 0x01,
+ 0x94, 0xb1, 0x05, 0xbc, 0xb6, 0x7f, 0x0f, 0xbb, 0x6b, 0x50, 0x80, 0xb3,
+ 0x0f, 0x2f, 0x0d, 0x2e, 0x1b, 0x01, 0x6f, 0x5e, 0xb7, 0x09, 0x2d, 0x2e,
+ 0x1b, 0x01, 0x71, 0x5c, 0x69, 0x5e, 0x9b, 0x43, 0x9b, 0x43, 0xdb, 0x43,
+ 0x9b, 0x43, 0x1b, 0x42, 0xcb, 0x43, 0x0b, 0x42, 0x8b, 0x43, 0x40, 0xb2,
+ 0x05, 0x2f, 0x69, 0x50, 0x00, 0x2e, 0x16, 0x40, 0x0b, 0x40, 0x76, 0x7f,
+ 0x8b, 0x7f, 0xcb, 0x0a, 0x01, 0x2e, 0x61, 0x00, 0x67, 0x52, 0x6d, 0x5c,
+ 0x98, 0x2e, 0xd3, 0xb2, 0x90, 0x6f, 0x00, 0xb2, 0x0b, 0x2f, 0xf0, 0x6f,
+ 0x00, 0xb2, 0x08, 0x2f, 0x69, 0x58, 0x6b, 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, 0x71, 0x54, 0x88, 0xbd,
+ 0xc8, 0xb8, 0x4b, 0x0a, 0x94, 0x42, 0x91, 0x42, 0x90, 0x42, 0x88, 0xba,
+ 0x69, 0x52, 0xf3, 0x6f, 0x54, 0x42, 0x85, 0x42, 0xc0, 0x90, 0x40, 0x42,
+ 0x15, 0x2f, 0x6b, 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, 0x6b, 0x54,
+ 0x21, 0x30, 0x94, 0x42, 0x80, 0x42, 0x23, 0x2e, 0x5e, 0xf0, 0xd0, 0x6f,
+ 0x00, 0xb2, 0x13, 0x2f, 0x01, 0x2e, 0x60, 0x00, 0x09, 0x2e, 0x7c, 0x00,
+ 0x04, 0x1a, 0x0d, 0x2f, 0x73, 0x50, 0x29, 0x2e, 0x60, 0x00, 0x24, 0x42,
+ 0x44, 0x30, 0x02, 0x40, 0x02, 0x42, 0x09, 0x80, 0x00, 0x2e, 0x04, 0x42,
+ 0x03, 0x2d, 0x10, 0x30, 0x21, 0x2e, 0x64, 0x00, 0xeb, 0x6f, 0x70, 0x5f,
+ 0xb8, 0x2e, 0x09, 0x86, 0x49, 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, 0x95, 0x00,
+ 0xb3, 0xb5, 0x23, 0xb5, 0x53, 0x42, 0x52, 0x42, 0x53, 0x42, 0x42, 0x42,
+ 0x71, 0x82, 0x75, 0x54, 0x52, 0x42, 0x10, 0x50, 0x77, 0x54, 0x52, 0x42,
+ 0xfb, 0x7f, 0x22, 0x30, 0x79, 0x56, 0x43, 0x42, 0x44, 0x82, 0x0b, 0x30,
+ 0x52, 0x42, 0x5b, 0x42, 0x7c, 0x84, 0x4b, 0x42, 0x35, 0x82, 0x8c, 0x80,
+ 0x8b, 0x42, 0x0b, 0x42, 0x39, 0x80, 0x04, 0x30, 0x0b, 0x42, 0x37, 0x80,
+ 0x15, 0x30, 0x60, 0x25, 0x98, 0x2e, 0xc6, 0xb2, 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, 0x7b, 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, 0x54, 0x01, 0xc0, 0x7e, 0x00, 0xac, 0x01, 0x2f, 0x65, 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, 0x8a, 0xb1, 0x23, 0x6f, 0xd1, 0x6f, 0xc2, 0x40,
+ 0xf9, 0x86, 0x23, 0x7f, 0x80, 0xb2, 0xe0, 0x7e, 0x0f, 0x2f, 0x32, 0x6f,
+ 0x64, 0x6f, 0x82, 0x40, 0xf2, 0x7f, 0x4e, 0x82, 0x42, 0x6f, 0x50, 0x6f,
+ 0x73, 0x6f, 0x85, 0x40, 0xc3, 0x40, 0x04, 0x41, 0x06, 0x40, 0xe2, 0x6e,
+ 0x98, 0x2e, 0x8a, 0xb1, 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, 0xc2, 0xb1, 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, 0x7d, 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, 0xc2, 0xb1, 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, 0xc2, 0xb1,
+ 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, 0xc2, 0xb1, 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, 0x77, 0xb4, 0x04, 0x40, 0x25, 0x29, 0x04, 0x42, 0x83, 0x42,
+ 0x45, 0x82, 0x94, 0x6f, 0x04, 0x85, 0xc0, 0xb2, 0x90, 0x2e, 0x63, 0xb4,
+ 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, 0xc6, 0xb2, 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, 0xc2, 0xb1,
+ 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, 0x4d, 0x54, 0x03, 0x30, 0x11, 0x2c, 0x10, 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, 0xc6, 0xb2, 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, 0x03, 0x2e,
+ 0x1c, 0x01, 0x9c, 0xbc, 0x1d, 0xb9, 0x02, 0x82, 0x25, 0x2e, 0x8e, 0x00,
+ 0x83, 0x56, 0x13, 0x18, 0x01, 0x2e, 0x66, 0x00, 0x43, 0x40, 0xd8, 0x04,
+ 0x05, 0x2e, 0x65, 0x00, 0x40, 0x50, 0x27, 0x2e, 0x65, 0x00, 0xfb, 0x7f,
+ 0xda, 0x05, 0x8b, 0x50, 0x4b, 0x40, 0x02, 0x40, 0x81, 0x82, 0x01, 0x42,
+ 0x03, 0x80, 0x81, 0x52, 0xb1, 0x00, 0x03, 0x40, 0x3b, 0x82, 0x85, 0x58,
+ 0x14, 0x01, 0xc0, 0xb2, 0x37, 0x2e, 0x66, 0x00, 0xd1, 0x7f, 0xe2, 0x7f,
+ 0x04, 0x2f, 0x05, 0x2e, 0x6b, 0x00, 0x81, 0x84, 0x25, 0x2e, 0x6b, 0x00,
+ 0x62, 0x40, 0x3a, 0x0f, 0x45, 0x40, 0xc1, 0x7f, 0x21, 0x30, 0x12, 0x30,
+ 0x42, 0x2f, 0x0d, 0x2e, 0x69, 0x00, 0x3e, 0x0e, 0x33, 0x2f, 0x05, 0x2e,
+ 0x6a, 0x00, 0x01, 0x35, 0x91, 0x0e, 0x01, 0x30, 0x03, 0x2f, 0x09, 0x2e,
+ 0x6e, 0x00, 0x00, 0xb3, 0x24, 0x2f, 0xc0, 0x35, 0x90, 0x0e, 0x39, 0x2f,
+ 0x8f, 0x50, 0x02, 0x30, 0x01, 0x40, 0x7f, 0x82, 0x43, 0xa2, 0x02, 0x2f,
+ 0x00, 0x2e, 0x0c, 0x2c, 0x01, 0x30, 0xc0, 0xb2, 0x11, 0x30, 0x02, 0x2f,
+ 0x25, 0x2e, 0x6d, 0x00, 0x03, 0x2d, 0x23, 0x2e, 0x6d, 0x00, 0x21, 0x30,
+ 0x25, 0x2e, 0x6b, 0x00, 0x42, 0xb2, 0x04, 0x2f, 0x41, 0xb2, 0x02, 0x2f,
+ 0x25, 0x2e, 0x6d, 0x00, 0x31, 0x30, 0x3e, 0x80, 0x04, 0x86, 0x25, 0x2e,
+ 0x6c, 0x00, 0x02, 0x42, 0xc2, 0x42, 0x18, 0x2d, 0x02, 0x35, 0x01, 0x42,
+ 0x25, 0x2e, 0x6a, 0x00, 0x13, 0x2d, 0x2c, 0x04, 0x38, 0x1e, 0x21, 0x2e,
+ 0x69, 0x00, 0x7f, 0x50, 0x11, 0x30, 0x22, 0x30, 0x98, 0x2e, 0x66, 0xb5,
+ 0x09, 0x2c, 0x01, 0x30, 0x2c, 0x00, 0x38, 0x1c, 0x21, 0x2e, 0x68, 0x00,
+ 0x7f, 0x50, 0x98, 0x2e, 0x66, 0xb5, 0x01, 0x30, 0xc0, 0x6f, 0xd4, 0xb1,
+ 0xf5, 0xbd, 0x6b, 0xba, 0x91, 0x5a, 0x02, 0x40, 0x15, 0x18, 0xf5, 0xbe,
+ 0xeb, 0xbb, 0xe3, 0x0a, 0x3d, 0x0b, 0xd2, 0x6f, 0xe3, 0x00, 0x84, 0x40,
+ 0x63, 0x05, 0x93, 0x58, 0x2c, 0x18, 0xf5, 0xbe, 0x03, 0x42, 0xeb, 0xbb,
+ 0xfd, 0x0b, 0xe0, 0x6f, 0x58, 0x01, 0xdf, 0x01, 0x7d, 0x1f, 0x95, 0x42,
+ 0x18, 0x04, 0x85, 0x40, 0x5d, 0x05, 0x2c, 0x18, 0x75, 0xbe, 0xeb, 0xba,
+ 0x2c, 0x0b, 0xdc, 0x04, 0x18, 0x1c, 0x80, 0x42, 0x84, 0x80, 0x02, 0x30,
+ 0x00, 0x40, 0x00, 0xb2, 0x0c, 0x2f, 0x01, 0x2e, 0x6b, 0x00, 0x03, 0x35,
+ 0x83, 0x0e, 0x07, 0x2f, 0x8d, 0x50, 0x3e, 0x80, 0x25, 0x2e, 0x6d, 0x00,
+ 0x02, 0x42, 0x03, 0x80, 0x00, 0x2e, 0x02, 0x42, 0x40, 0xb2, 0x04, 0x2f,
+ 0x8b, 0x50, 0x04, 0x80, 0x25, 0x2e, 0x6a, 0x00, 0x02, 0x42, 0x42, 0xb2,
+ 0x89, 0x56, 0x9a, 0x22, 0x41, 0xb2, 0x01, 0x2e, 0x1c, 0x01, 0x87, 0x52,
+ 0x0b, 0xbc, 0x8a, 0x22, 0x0f, 0xb8, 0x00, 0x90, 0x01, 0x32, 0x06, 0x2f,
+ 0x10, 0x30, 0x90, 0x08, 0x80, 0xb2, 0x08, 0x2f, 0x23, 0x2e, 0x5e, 0xf0,
+ 0x06, 0x2d, 0x20, 0x30, 0x90, 0x08, 0x80, 0xb2, 0x01, 0x2f, 0x23, 0x2e,
+ 0x5e, 0xf0, 0xfb, 0x6f, 0xc0, 0x5f, 0xb8, 0x2e, 0x07, 0x86, 0xfc, 0x88,
+ 0xc6, 0x40, 0x05, 0x41, 0x31, 0x1a, 0x12, 0x2f, 0x80, 0x91, 0x22, 0x2f,
+ 0x01, 0x35, 0x29, 0x0f, 0x0a, 0x2f, 0x06, 0x80, 0x00, 0x2e, 0x00, 0x40,
+ 0x00, 0xb2, 0x01, 0x2f, 0x44, 0xa9, 0x03, 0x2f, 0x00, 0x30, 0xc0, 0x42,
+ 0x00, 0x43, 0xb8, 0x2e, 0xc2, 0x42, 0x01, 0x43, 0xb8, 0x2e, 0x01, 0x35,
+ 0xa9, 0x0e, 0x0e, 0x2f, 0x03, 0x3b, 0xeb, 0x00, 0xcc, 0xa8, 0x0a, 0x2f,
+ 0x05, 0x86, 0xc2, 0x80, 0xc3, 0x40, 0x02, 0x42, 0x3c, 0x84, 0xc1, 0x80,
+ 0x81, 0x42, 0x82, 0x84, 0xc0, 0x2e, 0x80, 0x42, 0x00, 0x2e, 0xb8, 0x2e,
+ 0x03, 0x2e, 0x1d, 0x01, 0x9f, 0xbc, 0x9f, 0xb8, 0x90, 0x50, 0x40, 0xb2,
+ 0x90, 0x2e, 0x71, 0xb6, 0x12, 0x40, 0x03, 0x30, 0x11, 0x40, 0x80, 0xa8,
+ 0x5a, 0x05, 0x9f, 0x58, 0x55, 0x23, 0x00, 0x40, 0x75, 0x7f, 0x40, 0xa8,
+ 0x16, 0x41, 0xd9, 0x05, 0xcf, 0x23, 0x56, 0x05, 0x40, 0xa9, 0x9d, 0x05,
+ 0x87, 0x7f, 0x6e, 0x23, 0x17, 0x41, 0xa5, 0x7f, 0x3e, 0x8b, 0x04, 0x41,
+ 0x52, 0x43, 0x00, 0xa8, 0x98, 0x05, 0xf2, 0x7f, 0x86, 0x22, 0xcf, 0x05,
+ 0xc0, 0xa9, 0x9f, 0x05, 0xbe, 0x23, 0x04, 0x05, 0x92, 0x7f, 0x00, 0xa9,
+ 0xdc, 0x05, 0x51, 0x43, 0xb6, 0x7f, 0x27, 0x23, 0xa7, 0x54, 0xe1, 0x7f,
+ 0x02, 0x18, 0x7d, 0x83, 0x40, 0x43, 0xeb, 0xba, 0x75, 0xbd, 0xaa, 0x0a,
+ 0x0b, 0x2e, 0x71, 0x00, 0x77, 0x5c, 0x2e, 0x18, 0xf5, 0xbe, 0x6b, 0xbb,
+ 0x75, 0x0b, 0xaa, 0x00, 0xc4, 0x7f, 0x25, 0x2e, 0x71, 0x00, 0xb2, 0x6f,
+ 0xa5, 0x6f, 0xaa, 0x00, 0x54, 0x01, 0x84, 0x6f, 0x72, 0x6f, 0x94, 0x05,
+ 0x80, 0xa9, 0xde, 0x05, 0xb7, 0x23, 0x99, 0x5e, 0x77, 0x0e, 0x41, 0x40,
+ 0x97, 0x5c, 0xb1, 0x01, 0xd5, 0x7f, 0x00, 0x2e, 0x85, 0x41, 0x0e, 0x2f,
+ 0x00, 0xa0, 0x0c, 0x2f, 0x14, 0x0f, 0x04, 0x2f, 0xe0, 0x6f, 0x00, 0xac,
+ 0x10, 0x30, 0x08, 0x2c, 0x18, 0x22, 0xf0, 0x6f, 0x00, 0xac, 0x30, 0x30,
+ 0x24, 0x30, 0x02, 0x2c, 0x20, 0x22, 0x40, 0x30, 0x0d, 0x2e, 0x71, 0x00,
+ 0x80, 0xa1, 0x1e, 0x23, 0x79, 0x5e, 0x37, 0x0f, 0xbc, 0x23, 0x00, 0x90,
+ 0x14, 0x30, 0x10, 0x30, 0x18, 0x2f, 0x9d, 0x50, 0x30, 0x00, 0x9b, 0x56,
+ 0x43, 0x0e, 0x02, 0x2f, 0x10, 0x30, 0x0a, 0x2c, 0x03, 0x30, 0x99, 0x50,
+ 0x10, 0x0e, 0x13, 0x30, 0x00, 0x2f, 0x03, 0x30, 0x90, 0x0f, 0x10, 0x30,
+ 0x00, 0x2f, 0x00, 0x30, 0x00, 0x90, 0x10, 0x30, 0x00, 0x2f, 0x00, 0x30,
+ 0xc0, 0x90, 0x13, 0x30, 0x00, 0x2f, 0x03, 0x30, 0x40, 0xb2, 0x87, 0x5c,
+ 0x22, 0x2f, 0x41, 0x90, 0x4a, 0x2f, 0xa5, 0x50, 0x00, 0x2e, 0x01, 0x40,
+ 0x41, 0x82, 0x01, 0x42, 0x02, 0x80, 0x4a, 0xa8, 0x01, 0x40, 0x06, 0x2f,
+ 0xd0, 0x6f, 0x85, 0x0e, 0x3e, 0x2f, 0x41, 0x80, 0x21, 0x2e, 0x78, 0x00,
+ 0x3b, 0x2d, 0x95, 0x50, 0xfb, 0x7f, 0x4a, 0xa8, 0x06, 0x2f, 0x98, 0x2e,
+ 0x73, 0xb6, 0xc0, 0x90, 0xfb, 0x6f, 0x32, 0x2f, 0x00, 0x2e, 0x30, 0x2d,
+ 0x98, 0x2e, 0x73, 0xb6, 0x29, 0x2e, 0x7a, 0x00, 0x2b, 0x2c, 0xfb, 0x6f,
+ 0xa1, 0x52, 0xd2, 0x6f, 0x95, 0x0e, 0x41, 0x40, 0x05, 0x2f, 0x00, 0x90,
+ 0x17, 0x2f, 0x05, 0x2e, 0x7a, 0x00, 0x80, 0x90, 0x13, 0x2f, 0x7f, 0x82,
+ 0x40, 0xac, 0x23, 0x2e, 0x77, 0x00, 0x01, 0x30, 0x18, 0x2f, 0xa1, 0x54,
+ 0x82, 0x84, 0x23, 0x2e, 0x77, 0x00, 0x82, 0x40, 0x80, 0xb2, 0x11, 0x2f,
+ 0x00, 0x90, 0x23, 0x2e, 0x79, 0x00, 0x0d, 0x2f, 0x29, 0x2e, 0x72, 0x00,
+ 0x0b, 0x2d, 0x41, 0x80, 0x21, 0x2e, 0x77, 0x00, 0x0f, 0xa4, 0x05, 0x2f,
+ 0xa3, 0x50, 0x3e, 0x80, 0xf1, 0x30, 0x29, 0x2e, 0x79, 0x00, 0x01, 0x42,
+ 0x06, 0x30, 0x34, 0x08, 0x00, 0xb2, 0x02, 0x2f, 0x80, 0x30, 0x21, 0x2e,
+ 0x5e, 0xf0, 0x70, 0x5f, 0xb8, 0x2e, 0x04, 0x84, 0x01, 0x30, 0x81, 0x42,
+ 0x82, 0x84, 0x01, 0x42, 0xa1, 0x42, 0x81, 0x42, 0x82, 0x84, 0x00, 0x2e,
+ 0x91, 0x42, 0x81, 0x42, 0xb8, 0x2e, 0x30, 0x50, 0xf3, 0x7f, 0xc0, 0xac,
+ 0xe4, 0x7f, 0xd5, 0x7f, 0x03, 0x2f, 0x00, 0x30, 0x82, 0x04, 0xf3, 0x6f,
+ 0xc3, 0x06, 0x40, 0xad, 0x05, 0x2f, 0xe0, 0x6f, 0x05, 0x30, 0x28, 0x04,
+ 0xd1, 0x6f, 0x69, 0x07, 0xe0, 0x7f, 0x40, 0xa1, 0x01, 0x30, 0x20, 0x2f,
+ 0x13, 0x25, 0x02, 0x25, 0x04, 0x32, 0x06, 0x30, 0x02, 0x30, 0x03, 0x30,
+ 0xaf, 0xbb, 0xb1, 0xbd, 0xdf, 0x0a, 0x9f, 0xbb, 0x21, 0xbd, 0x97, 0x0a,
+ 0x8f, 0xbb, 0x91, 0xbc, 0x01, 0xbc, 0x4f, 0x0a, 0x6b, 0x0e, 0x04, 0x2f,
+ 0x6b, 0x1a, 0x07, 0x2f, 0xe7, 0x6f, 0x7a, 0x0f, 0x04, 0x2f, 0xe7, 0x6f,
+ 0x97, 0x04, 0x17, 0x30, 0x07, 0x0a, 0xdd, 0x06, 0x81, 0x8d, 0x34, 0x0e,
+ 0xe6, 0x2f, 0x00, 0x2e, 0x0d, 0x2d, 0x6b, 0x0e, 0x00, 0x30, 0x05, 0x2f,
+ 0x6b, 0x1a, 0x07, 0x2f, 0xe0, 0x6f, 0x42, 0x0f, 0x00, 0x30, 0x03, 0x2f,
+ 0xe0, 0x6f, 0x90, 0x04, 0xdd, 0x06, 0x10, 0x30, 0xf5, 0x6f, 0xc3, 0x7f,
+ 0xb2, 0x7f, 0x40, 0xad, 0x06, 0x2f, 0x03, 0x30, 0xb2, 0x6f, 0x9a, 0x04,
+ 0xc4, 0x6f, 0xdc, 0x06, 0xb2, 0x7f, 0xc3, 0x7f, 0x00, 0x2e, 0xd2, 0x6f,
+ 0xaa, 0x0c, 0x80, 0xac, 0x02, 0x30, 0x01, 0x2f, 0x10, 0x04, 0x51, 0x06,
+ 0xd0, 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
+};
+
+/***************************************************************************/
+/*! Static Function Declarations
+****************************************************************************/
+/*!
+ * @brief This API update the length for read and write.
+ *
+ * @param[in] len : Length for read and write
+ * @param[in] feature : Variable to specify the features
+ * which are to be set in the sensor.
+ * @param[in] enable : Variable which specifies whether to enable or
+ * disable the features in the bma455 sensor.
+ * enable | Macros
+ * ----------------|-------------------
+ * 0x01 | BMA4_EN
+ * 0x00 | BMA4_DIS
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @return none
+ */
+static void update_len(uint8_t *len, uint8_t feature, uint8_t enable);
+
+/*!
+ * @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 to 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 Any positive value mentioned in ERROR CODES -> Fail
+ */
+static uint16_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 to 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 Any positive value mentioned in ERROR CODES -> Fail
+ */
+static uint16_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.
+ */
+#include
+uint16_t bma423_init(struct bma4_dev *dev)
+{
+ uint16_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->variant = BMA42X_VARIANT;
+ } else {
+ rslt |= BMA4_E_INVALID_SENSOR;
+ }
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API is used to upload the config file to enable
+ * the features of the sensor.
+ */
+uint16_t bma423_write_config_file(struct bma4_dev *dev)
+{
+ uint16_t rslt = BMA4_OK;
+
+ if (dev != NULL) {
+ if (dev->chip_id == BMA423_CHIP_ID) {
+ /* Config. 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.
+ */
+uint16_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;
+ uint16_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/unsets the user provided interrupt to either
+ * interrupt pin1 or pin2 in the sensor.
+ */
+uint16_t bma423_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev)
+{
+ uint16_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.
+ */
+uint16_t bma423_read_int_status(uint16_t *int_status, struct bma4_dev *dev)
+{
+ uint16_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.
+ */
+uint16_t bma423_feature_enable(uint8_t feature, uint8_t enable, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = {0};
+ uint16_t rslt = BMA4_OK;
+ uint8_t len;
+
+ if (dev != NULL) {
+ if (dev->chip_id == BMA423_CHIP_ID) {
+ /* Update the length for read and write */
+ update_len(&len, feature, enable);
+ 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.
+ */
+uint16_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;
+ uint16_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.
+ */
+uint16_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;
+ uint16_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 enables the any motion feature according to the axis
+ * set by the user in the sensor.
+ */
+uint16_t bma423_anymotion_enable_axis(uint8_t axis, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_ANYMOTION_EN_LEN + 2] = {0};
+ /* Anymotion axis enable bit pos. is 3 byte ahead of the
+ anymotion base address(0x00) */
+ uint8_t index = 3;
+ uint16_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_ANYMOTION_EN_LEN + 2, dev);
+ if (rslt == BMA4_OK) {
+ feature_config[index] = BMA4_SET_BITSLICE(feature_config[index],
+ BMA423_ANY_NO_MOTION_AXIS_EN, axis);
+ rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config,
+ BMA423_ANYMOTION_EN_LEN + 2, dev);
+ }
+ } 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.
+ */
+uint16_t bma423_set_any_motion_config(const struct bma423_anymotion_config *any_motion, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_ANYMOTION_EN_LEN + 2] = {0};
+ uint8_t index = BMA423_ANY_NO_MOTION_OFFSET;
+ uint16_t duration_lsb = 0;
+ uint16_t duration_msb = 0;
+ uint16_t duration = 0;
+ uint16_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_ANYMOTION_EN_LEN + 2, dev);
+ if (rslt == BMA4_OK) {
+ /* Assign threshold value in feature config array */
+ feature_config[index++] = BMA4_GET_LSB(any_motion->threshold);
+ feature_config[index] = BMA4_GET_MSB(any_motion->threshold);
+ /* Assign no motion selection value in feature config array*/
+ feature_config[index++] |= (uint8_t)
+ (any_motion->nomotion_sel << BMA423_ANY_NO_MOTION_SEL_POS);
+
+ /* Extract duration */
+ duration_lsb = feature_config[index];
+ duration_msb = feature_config[index + 1] << 8;
+ duration = duration_lsb | duration_msb;
+ duration = BMA4_SET_BITS_POS_0(duration,
+ BMA423_ANY_NO_MOTION_DUR, any_motion->duration);
+ /* Assign duration value in feature config array*/
+ feature_config[index++] = BMA4_GET_LSB(duration);
+ feature_config[index] = BMA4_GET_MSB(duration);
+
+ /* Write any motion settings to the sensor*/
+ rslt |= bma4_write_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config,
+ BMA423_ANYMOTION_EN_LEN + 2, dev);
+ }
+ } else {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ } else {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*! @brief This API gets the configuration of any motion feature from
+ * the sensor.
+ */
+uint16_t bma423_get_any_motion_config(struct bma423_anymotion_config *any_motion, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_ANYMOTION_EN_LEN + 2] = {0};
+ uint8_t anymotion = 0;
+ uint16_t rslt = BMA4_OK;
+ uint16_t *data_p = (uint16_t *)feature_config;
+
+ if (dev != NULL) {
+ if (dev->chip_id == BMA423_CHIP_ID) {
+ rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config,
+ BMA423_ANYMOTION_EN_LEN + 2, dev);
+ if (rslt == BMA4_OK) {
+ /* Extract threshold value */
+ any_motion->threshold = (*data_p) & BMA423_ANY_NO_MOTION_THRES_MSK;
+ /* Extract threshold & nomotion selection
+ * data */
+ anymotion = ((uint8_t)(*(data_p++) >> 8)) & BMA423_ANY_NO_MOTION_SEL_MSK;
+ /* Extract no motion field */
+ any_motion->nomotion_sel = anymotion >>
+ BMA423_ANY_NO_MOTION_SEL_POS;
+ /* Extract duration value */
+ any_motion->duration = (*(data_p)) & BMA423_ANY_NO_MOTION_DUR_MSK;
+ }
+ } else {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ } else {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API enables or disables the step detector feature in the
+ * sensor.
+ */
+uint16_t bma423_step_detector_enable(uint8_t enable, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = {0};
+ uint16_t rslt = BMA4_OK;
+ /* Step detector enable bit pos. 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.
+ */
+uint16_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;
+ uint16_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
+ */
+uint16_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;
+ uint16_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.
+ */
+uint16_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;
+ uint16_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.
+ */
+uint16_t bma423_step_counter_output(uint32_t *step_count, struct bma4_dev *dev)
+{
+ uint8_t data[BMA423_STEP_CNTR_DATA_SIZE] = {0};
+ uint16_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.
+ */
+uint16_t bma423_activity_output(uint8_t *activity, struct bma4_dev *dev)
+{
+ uint8_t data = 0;
+ uint16_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 select the platform configuration wrist(Default) or phone.
+ */
+uint16_t bma423_select_platform(uint8_t platform, struct bma4_dev *dev)
+{
+ uint16_t rslt = BMA4_OK;
+ struct bma423_stepcounter_settings sc_settings = {0};
+
+ if (dev != NULL) {
+ if (dev->chip_id == BMA423_CHIP_ID) {
+ switch (platform) {
+ case BMA423_PHONE_CONFIG:
+ sc_settings.param1 = BMA423_PHONE_SC_PARAM_1;
+ sc_settings.param2 = BMA423_PHONE_SC_PARAM_2;
+ sc_settings.param3 = BMA423_PHONE_SC_PARAM_3;
+ sc_settings.param4 = BMA423_PHONE_SC_PARAM_4;
+ sc_settings.param5 = BMA423_PHONE_SC_PARAM_5;
+ sc_settings.param6 = BMA423_PHONE_SC_PARAM_6;
+ sc_settings.param7 = BMA423_PHONE_SC_PARAM_7;
+ sc_settings.param8 = BMA423_PHONE_SC_PARAM_8;
+ sc_settings.param9 = BMA423_PHONE_SC_PARAM_9;
+ sc_settings.param10 = BMA423_PHONE_SC_PARAM_10;
+ sc_settings.param11 = BMA423_PHONE_SC_PARAM_11;
+ sc_settings.param12 = BMA423_PHONE_SC_PARAM_12;
+ sc_settings.param13 = BMA423_PHONE_SC_PARAM_13;
+ sc_settings.param14 = BMA423_PHONE_SC_PARAM_14;
+ sc_settings.param15 = BMA423_PHONE_SC_PARAM_15;
+ sc_settings.param16 = BMA423_PHONE_SC_PARAM_16;
+ sc_settings.param17 = BMA423_PHONE_SC_PARAM_17;
+ sc_settings.param18 = BMA423_PHONE_SC_PARAM_18;
+ sc_settings.param19 = BMA423_PHONE_SC_PARAM_19;
+ sc_settings.param20 = BMA423_PHONE_SC_PARAM_20;
+ sc_settings.param21 = BMA423_PHONE_SC_PARAM_21;
+ sc_settings.param22 = BMA423_PHONE_SC_PARAM_22;
+ sc_settings.param23 = BMA423_PHONE_SC_PARAM_23;
+ sc_settings.param24 = BMA423_PHONE_SC_PARAM_24;
+ sc_settings.param25 = BMA423_PHONE_SC_PARAM_25;
+ break;
+
+ case BMA423_WRIST_CONFIG:
+ sc_settings.param1 = BMA423_WRIST_SC_PARAM_1;
+ sc_settings.param2 = BMA423_WRIST_SC_PARAM_2;
+ sc_settings.param3 = BMA423_WRIST_SC_PARAM_3;
+ sc_settings.param4 = BMA423_WRIST_SC_PARAM_4;
+ sc_settings.param5 = BMA423_WRIST_SC_PARAM_5;
+ sc_settings.param6 = BMA423_WRIST_SC_PARAM_6;
+ sc_settings.param7 = BMA423_WRIST_SC_PARAM_7;
+ sc_settings.param8 = BMA423_WRIST_SC_PARAM_8;
+ sc_settings.param9 = BMA423_WRIST_SC_PARAM_9;
+ sc_settings.param10 = BMA423_WRIST_SC_PARAM_10;
+ sc_settings.param11 = BMA423_WRIST_SC_PARAM_11;
+ sc_settings.param12 = BMA423_WRIST_SC_PARAM_12;
+ sc_settings.param13 = BMA423_WRIST_SC_PARAM_13;
+ sc_settings.param14 = BMA423_WRIST_SC_PARAM_14;
+ sc_settings.param15 = BMA423_WRIST_SC_PARAM_15;
+ sc_settings.param16 = BMA423_WRIST_SC_PARAM_16;
+ sc_settings.param17 = BMA423_WRIST_SC_PARAM_17;
+ sc_settings.param18 = BMA423_WRIST_SC_PARAM_18;
+ sc_settings.param19 = BMA423_WRIST_SC_PARAM_19;
+ sc_settings.param20 = BMA423_WRIST_SC_PARAM_20;
+ sc_settings.param21 = BMA423_WRIST_SC_PARAM_21;
+ sc_settings.param22 = BMA423_WRIST_SC_PARAM_22;
+ sc_settings.param23 = BMA423_WRIST_SC_PARAM_23;
+ sc_settings.param24 = BMA423_WRIST_SC_PARAM_24;
+ sc_settings.param25 = BMA423_WRIST_SC_PARAM_25;
+ break;
+
+ default:
+ rslt = BMA4_E_OUT_OF_RANGE;
+ break;
+ }
+ } else {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ } else {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ if (rslt == BMA4_OK) {
+ /* Set the step counter parameter */
+ rslt = bma423_stepcounter_set_parameter(&sc_settings, dev);
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API gets the parameter1 to parameter7 settings of the
+ * step counter feature.
+ */
+uint16_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 *)feature_config;
+ uint16_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.
+ */
+uint16_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;
+ uint16_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 stepcounter 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 wake up feature in the sensor
+ */
+uint16_t bma423_wakeup_set_sensitivity(uint8_t sensitivity, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = {0};
+ uint8_t index = BMA423_WAKEUP_OFFSET;
+ uint16_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_WAKEUP_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 wake up feature in the sensor
+ */
+uint16_t bma423_wakeup_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *dev)
+{
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = {0};
+ uint8_t index = BMA423_WAKEUP_OFFSET;
+ uint16_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_WAKEUP_SENS);
+ }
+ } else {
+ rslt = BMA4_E_INVALID_SENSOR;
+ }
+ } else {
+ rslt = BMA4_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+/*!
+ * @brief This API is used to select single/double tap
+ * feature in the sensor
+ */
+uint16_t bma423_tap_selection(const uint8_t tap_select, struct bma4_dev *dev)
+{
+ uint16_t rslt = BMA4_OK;
+ uint8_t feature_config[BMA423_FEATURE_SIZE] = {0,};
+ uint8_t index = BMA423_WAKEUP_OFFSET;
+
+ 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_SEL, tap_select);
+ 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 update the length for read and write.
+ */
+static void update_len(uint8_t *len, uint8_t feature, uint8_t enable)
+{
+ uint8_t length = BMA423_FEATURE_SIZE;
+
+ if ((feature == BMA423_ANY_MOTION) || (feature == BMA423_NO_MOTION)) {
+ /* Change the feature length to 2 for reading and writing of 2 bytes for
+ any/no-motion enable */
+ length = BMA423_ANYMOTION_EN_LEN;
+
+ /* Read and write 4 byte to disable the any/no motion completely along with
+ all axis */
+ if (enable == BMA4_DISABLE) {
+ /*Change the feature length to 4 for reading and writing
+ of 4 bytes for any/no-motion enable */
+ length = length + 2;
+ }
+ }
+
+ *len = length;
+}
+
+/*!
+ * @brief This API enables the features of the sensor.
+ */
+static uint16_t feature_enable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev)
+{
+ uint8_t index = 0;
+ uint16_t rslt;
+
+ /* Enable step counter */
+ if ((feature & BMA423_STEP_CNTR) > 0) {
+ /* Step counter enable bit pos. is 1 byte ahead of the
+ base address */
+ index = BMA423_STEP_CNTR_OFFSET + 1;
+ feature_config[index] = feature_config[index] | BMA423_STEP_CNTR_EN_MSK;
+ }
+
+ /* Enable activity */
+ if ((feature & BMA423_ACTIVITY) > 0) {
+ /* Activity enable bit pos. is 1 byte ahead of the
+ base address */
+ index = BMA423_STEP_CNTR_OFFSET + 1;
+ feature_config[index] = feature_config[index] | BMA423_ACTIVITY_EN_MSK;
+ }
+ /* Enable tilt */
+ if ((feature & BMA423_TILT) > 0) {
+ /* Tilt enable bit pos. is the base address(0x3A) of tilt */
+ index = BMA423_TILT_OFFSET;
+ feature_config[index] = feature_config[index] | BMA423_TILT_EN_MSK;
+ }
+
+ /* Enable wakeup */
+ if ((feature & BMA423_WAKEUP) > 0) {
+ /* Wakeup enable bit pos. is the base address(0x38) of wakeup */
+ index = BMA423_WAKEUP_OFFSET;
+ feature_config[index] = feature_config[index] | BMA423_WAKEUP_EN_MSK;
+ }
+
+ /* Enable anymotion/nomotion */
+ if ((feature & BMA423_ANY_MOTION) > 0 || (feature & BMA423_NO_MOTION) > 0) {
+ /* Any/Nomotion enable bit pos. is 1 bytes ahead of the
+ any/nomotion base address(0x00) */
+ index = 1;
+
+ if ((feature & BMA423_ANY_MOTION) > 0) {
+ /* Enable anymotion */
+ feature_config[index] = feature_config[index] & (~BMA423_ANY_NO_MOTION_SEL_MSK);
+ } else {
+ /* Enable nomotion */
+ feature_config[index] = feature_config[index] | BMA423_ANY_NO_MOTION_SEL_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 uint16_t feature_disable(uint8_t feature, uint8_t len, uint8_t *feature_config, struct bma4_dev *dev)
+{
+ uint8_t index = 0;
+ uint16_t rslt;
+
+ /* Disable step counter */
+ if ((feature & BMA423_STEP_CNTR) > 0) {
+ /* Step counter enable bit pos. is 1 byte ahead of the
+ base address */
+ index = BMA423_STEP_CNTR_OFFSET + 1;
+ feature_config[index] = feature_config[index] & (~BMA423_STEP_CNTR_EN_MSK);
+ }
+
+ /* Disable activity */
+ if ((feature & BMA423_ACTIVITY) > 0) {
+ /* Activity enable bit pos. is 1 byte ahead of the
+ base address */
+ index = BMA423_STEP_CNTR_OFFSET + 1;
+ feature_config[index] = feature_config[index] & (~BMA423_ACTIVITY_EN_MSK);
+ }
+ /* Disable tilt */
+ if ((feature & BMA423_TILT) > 0) {
+ /* Tilt enable bit pos. is the base address(0x3A) of tilt */
+ index = BMA423_TILT_OFFSET;
+ feature_config[index] = feature_config[index] & (~BMA423_TILT_EN_MSK);
+ }
+
+ /* Disable wakeup */
+ if ((feature & BMA423_WAKEUP) > 0) {
+ /* Tilt enable bit pos. is the base address(0x38) of wakeup */
+ index = BMA423_WAKEUP_OFFSET;
+ feature_config[index] = feature_config[index] & (~BMA423_WAKEUP_EN_MSK);
+ }
+
+ /* Disable anymotion/nomotion */
+ if ((feature & BMA423_ANY_MOTION) > 0 || (feature & BMA423_NO_MOTION) > 0) {
+ /* Any/Nomotion enable bit pos. is 1 bytes ahead of the
+ any/nomotion base address(0x00) */
+ index = 1;
+
+ if ((feature & BMA423_ANY_MOTION) > 0) {
+ /* Disable anymotion */
+ feature_config[index] = feature_config[index] | BMA423_ANY_NO_MOTION_SEL_MSK;
+ } else {
+ /* Disable nomotion */
+ feature_config[index] = feature_config[index] & (~BMA423_ANY_NO_MOTION_SEL_MSK);
+ }
+ /* Any/Nomotion axis enable bit pos. is 3 byte ahead of the
+ any/nomotion base address(0x00) */
+ index = 3;
+ feature_config[index] = feature_config[index] & (~BMA423_ANY_NO_MOTION_AXIS_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;
+}
diff --git a/libesp32/TTGO_TWatch_Library/src/bma423.h b/libesp32/TTGO_TWatch_Library/src/bma423.h
new file mode 100755
index 000000000..2137f36c2
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/src/bma423.h
@@ -0,0 +1,804 @@
+/*
+*
+****************************************************************************
+* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH
+*
+* File : bma423.h
+*
+* Date: 12 Oct 2017
+*
+* Revision : 1.1.4 $
+*
+* Usage: Sensor Driver for BMA423 sensor
+*
+****************************************************************************
+*
+* Disclaimer
+*
+* Common:
+* Bosch Sensortec products are developed for the consumer goods industry.
+* They may only be used within the parameters of the respective valid
+* product data sheet. Bosch Sensortec products are provided with the
+* express understanding that there is no warranty of fitness for a
+* particular purpose.They are not fit for use in life-sustaining,
+* safety or security sensitive systems or any system or device
+* that may lead to bodily harm or property damage if the system
+* or device malfunctions. In addition,Bosch Sensortec products are
+* not fit for use in products which interact with motor vehicle systems.
+* The resale and or use of products are at the purchasers own risk and
+* his own responsibility. The examination of fitness for the intended use
+* is the sole responsibility of the Purchaser.
+*
+* The purchaser shall indemnify Bosch Sensortec from all third party
+* claims, including any claims for incidental, or consequential damages,
+* arising from any product use not covered by the parameters of
+* the respective valid product data sheet or not approved by
+* Bosch Sensortec and reimburse Bosch Sensortec for all costs in
+* connection with such claims.
+*
+* The purchaser must monitor the market for the purchased products,
+* particularly with regard to product safety and inform Bosch Sensortec
+* without delay of all security relevant incidents.
+*
+* Engineering Samples are marked with an asterisk (*) or (e).
+* Samples may vary from the valid technical specifications of the product
+* series. They are therefore not intended or fit for resale to third
+* parties or for use in end products. Their sole purpose is internal
+* client testing. The testing of an engineering sample may in no way
+* replace the testing of a product series. Bosch Sensortec assumes
+* no liability for the use of engineering samples.
+* By accepting the engineering samples, the Purchaser agrees to indemnify
+* Bosch Sensortec from all claims arising from the use of engineering
+* samples.
+*
+* Special:
+* This software module (hereinafter called "Software") and any information
+* on application-sheets (hereinafter called "Information") is provided
+* free of charge for the sole purpose to support your application work.
+* The Software and Information is subject to the following
+* terms and conditions:
+*
+* The Software is specifically designed for the exclusive use for
+* Bosch Sensortec products by personnel who have special experience
+* and training. Do not use this Software if you do not have the
+* proper experience or training.
+*
+* This Software package is provided `` as is `` and without any expressed
+* or implied warranties,including without limitation, the implied warranties
+* of merchantability and fitness for a particular purpose.
+*
+* Bosch Sensortec and their representatives and agents deny any liability
+* for the functional impairment
+* of this Software in terms of fitness, performance and safety.
+* Bosch Sensortec and their representatives and agents shall not be liable
+* for any direct or indirect damages or injury, except as
+* otherwise stipulated in mandatory applicable law.
+*
+* The Information provided is believed to be accurate and reliable.
+* Bosch Sensortec assumes no responsibility for the consequences of use
+* of such Information nor for any infringement of patents or
+* other rights of third parties which may result from its use.
+* No license is granted by implication or otherwise under any patent or
+* patent rights of Bosch. Specifications mentioned in the Information are
+* subject to change without notice.
+**************************************************************************/
+/*! \file bma423.h
+ \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(0x13)
+
+/**\name Sensor feature size */
+#define BMA423_FEATURE_SIZE UINT8_C(64)
+#define BMA423_ANYMOTION_EN_LEN UINT8_C(2)
+#define BMA423_RD_WR_MIN_LEN UINT8_C(2)
+
+/**\name Feature offset address */
+#define BMA423_ANY_NO_MOTION_OFFSET UINT8_C(0x00)
+#define BMA423_STEP_CNTR_OFFSET UINT8_C(0x36)
+#define BMA423_STEP_CNTR_PARAM_OFFSET UINT8_C(0x04)
+#define BMA423_WAKEUP_OFFSET UINT8_C(0x38)
+#define BMA423_TILT_OFFSET UINT8_C(0x3A)
+#define BMA423_CONFIG_ID_OFFSET UINT8_C(0x3C)
+#define BMA423_AXES_REMAP_OFFSET UINT8_C(0x3E)
+
+
+/**************************************************************/
+/**\name Remap 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 */
+/**************************************************************/
+/**\name Step counter enable macros */
+#define BMA423_STEP_CNTR_EN_POS UINT8_C(4)
+#define BMA423_STEP_CNTR_EN_MSK UINT8_C(0x10)
+#define BMA423_ACTIVITY_EN_MSK UINT8_C(0x20)
+
+/**\name Step counter watermark 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 Tilt enable macros */
+#define BMA423_TILT_EN_MSK UINT8_C(0x01)
+
+/**\name Step count output length*/
+#define BMA423_STEP_CNTR_DATA_SIZE UINT16_C(4)
+
+/**\name Wakeup enable macros */
+#define BMA423_WAKEUP_EN_MSK UINT8_C(0x01)
+
+/**\name Wake up sensitivity macros */
+#define BMA423_WAKEUP_SENS_POS UINT8_C(1)
+#define BMA423_WAKEUP_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 Motion */
+/**************************************************************/
+/**\name Any motion threshold macros */
+#define BMA423_ANY_NO_MOTION_THRES_POS UINT8_C(0)
+#define BMA423_ANY_NO_MOTION_THRES_MSK UINT16_C(0x07FF)
+
+/**\name Any motion selection macros */
+#define BMA423_ANY_NO_MOTION_SEL_POS UINT8_C(3)
+#define BMA423_ANY_NO_MOTION_SEL_MSK UINT8_C(0x08)
+
+/**\name Any motion enable macros */
+#define BMA423_ANY_NO_MOTION_AXIS_EN_POS UINT8_C(5)
+#define BMA423_ANY_NO_MOTION_AXIS_EN_MSK UINT8_C(0xE0)
+
+/**\name Any motion duration macros */
+#define BMA423_ANY_NO_MOTION_DUR_MSK UINT16_C(0x1FFF)
+
+/**************************************************************/
+/**\name User macros */
+/**************************************************************/
+
+/**\name Anymotion/Nomotion 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_ALL_AXIS_EN UINT8_C(0x07)
+#define BMA423_ALL_AXIS_DIS UINT8_C(0x00)
+
+/**\name Feature enable macros for the sensor */
+#define BMA423_STEP_CNTR UINT8_C(0x01)
+/**\name Below macros are mutually exclusive */
+#define BMA423_ANY_MOTION UINT8_C(0x02)
+#define BMA423_NO_MOTION UINT8_C(0x04)
+#define BMA423_ACTIVITY UINT8_C(0x08)
+#define BMA423_TILT UINT8_C(0x10)
+#define BMA423_WAKEUP UINT8_C(0x20)
+
+/**\name Interrupt status macros */
+#define BMA423_STEP_CNTR_INT UINT8_C(0x02)
+#define BMA423_ACTIVITY_INT UINT8_C(0x04)
+#define BMA423_TILT_INT UINT8_C(0x08)
+#define BMA423_WAKEUP_INT UINT8_C(0x20)
+#define BMA423_ANY_NO_MOTION_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 Configuration selection macros */
+#define BMA423_PHONE_CONFIG UINT8_C(0x00)
+#define BMA423_WRIST_CONFIG UINT8_C(0x01)
+
+/**\name Step counter parameter setting(1-25) for phone */
+#define BMA423_PHONE_SC_PARAM_1 UINT16_C(0x132)
+#define BMA423_PHONE_SC_PARAM_2 UINT16_C(0x78E6)
+#define BMA423_PHONE_SC_PARAM_3 UINT16_C(0x84)
+#define BMA423_PHONE_SC_PARAM_4 UINT16_C(0x6C9C)
+#define BMA423_PHONE_SC_PARAM_5 UINT8_C(0x07)
+#define BMA423_PHONE_SC_PARAM_6 UINT16_C(0x7564)
+#define BMA423_PHONE_SC_PARAM_7 UINT16_C(0x7EAA)
+#define BMA423_PHONE_SC_PARAM_8 UINT16_C(0x55F)
+#define BMA423_PHONE_SC_PARAM_9 UINT16_C(0xABE)
+#define BMA423_PHONE_SC_PARAM_10 UINT16_C(0x55F)
+#define BMA423_PHONE_SC_PARAM_11 UINT16_C(0xE896)
+#define BMA423_PHONE_SC_PARAM_12 UINT16_C(0x41EF)
+#define BMA423_PHONE_SC_PARAM_13 UINT8_C(0x01)
+#define BMA423_PHONE_SC_PARAM_14 UINT8_C(0x0C)
+#define BMA423_PHONE_SC_PARAM_15 UINT8_C(0x0C)
+#define BMA423_PHONE_SC_PARAM_16 UINT8_C(0x4A)
+#define BMA423_PHONE_SC_PARAM_17 UINT8_C(0xA0)
+#define BMA423_PHONE_SC_PARAM_18 UINT8_C(0x00)
+#define BMA423_PHONE_SC_PARAM_19 UINT8_C(0x0C)
+#define BMA423_PHONE_SC_PARAM_20 UINT16_C(0x3CF0)
+#define BMA423_PHONE_SC_PARAM_21 UINT16_C(0x100)
+#define BMA423_PHONE_SC_PARAM_22 UINT8_C(0x00)
+#define BMA423_PHONE_SC_PARAM_23 UINT8_C(0x00)
+#define BMA423_PHONE_SC_PARAM_24 UINT8_C(0x00)
+#define BMA423_PHONE_SC_PARAM_25 UINT8_C(0x00)
+
+/**\name Step counter parameter setting(1-25) for wrist (Default) */
+#define BMA423_WRIST_SC_PARAM_1 UINT16_C(0x12D)
+#define BMA423_WRIST_SC_PARAM_2 UINT16_C(0x7BD4)
+#define BMA423_WRIST_SC_PARAM_3 UINT16_C(0x13B)
+#define BMA423_WRIST_SC_PARAM_4 UINT16_C(0x7ADB)
+#define BMA423_WRIST_SC_PARAM_5 UINT8_C(0x04)
+#define BMA423_WRIST_SC_PARAM_6 UINT16_C(0x7B3F)
+#define BMA423_WRIST_SC_PARAM_7 UINT16_C(0x6CCD)
+#define BMA423_WRIST_SC_PARAM_8 UINT16_C(0x4C3)
+#define BMA423_WRIST_SC_PARAM_9 UINT16_C(0x985)
+#define BMA423_WRIST_SC_PARAM_10 UINT16_C(0x4C3)
+#define BMA423_WRIST_SC_PARAM_11 UINT16_C(0xE6EC)
+#define BMA423_WRIST_SC_PARAM_12 UINT16_C(0x460C)
+#define BMA423_WRIST_SC_PARAM_13 UINT8_C(0x01)
+#define BMA423_WRIST_SC_PARAM_14 UINT8_C(0x27)
+#define BMA423_WRIST_SC_PARAM_15 UINT8_C(0x19)
+#define BMA423_WRIST_SC_PARAM_16 UINT8_C(0x96)
+#define BMA423_WRIST_SC_PARAM_17 UINT8_C(0xA0)
+#define BMA423_WRIST_SC_PARAM_18 UINT8_C(0x01)
+#define BMA423_WRIST_SC_PARAM_19 UINT8_C(0x0C)
+#define BMA423_WRIST_SC_PARAM_20 UINT16_C(0x3CF0)
+#define BMA423_WRIST_SC_PARAM_21 UINT16_C(0x100)
+#define BMA423_WRIST_SC_PARAM_22 UINT8_C(0x01)
+#define BMA423_WRIST_SC_PARAM_23 UINT8_C(0x03)
+#define BMA423_WRIST_SC_PARAM_24 UINT8_C(0x01)
+#define BMA423_WRIST_SC_PARAM_25 UINT8_C(0x0E)
+
+/*!
+ * @brief Any motion configuration
+ */
+struct bma423_anymotion_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;
+ /*! Indicates if No-motion or Any-motion is selected */
+ uint8_t nomotion_sel;
+};
+
+/*!
+ * @brief Axes remapping configuration
+ */
+struct bma423_axes_remap {
+ uint8_t x_axis;
+ uint8_t x_axis_sign;
+ uint8_t y_axis;
+ uint8_t y_axis_sign;
+ uint8_t z_axis;
+ 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;
+};
+
+/*!
+ * @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.
+ *
+ * @param[in,out] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ */
+uint16_t bma423_init(struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ */
+uint16_t bma423_write_config_file(struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ */
+uint16_t bma423_get_config_id(uint16_t *config_id, struct bma4_dev *dev);
+
+
+/*!
+ * @brief 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.
+ * int_line | Macros
+ * ------------|-------------------
+ * 0 | BMA4_INTR1_MAP
+ * 1 | BMA4_INTR2_MAP
+ * @param[in] int_map : Variable to specify the interrupts.
+ * @param[in] enable : Variable to specify mapping or unmapping of
+ * interrupts.
+ * enable | Macros
+ * --------------------|-------------------
+ * 0x00 | BMA4_DISABLE
+ * 0x01 | BMA4_ENABLE
+ * @param[in] dev : Structure instance of bma4_dev.
+ *
+ * @note Below macros specify the interrupts.
+ * Feature Interrupts
+ * - BMA423_STEP_CNTR_INT
+ * - BMA423_ACTIVITY_INT
+ * - BMA423_TILT_INT
+ * - BMA423_WAKEUP_INT
+ * - BMA423_ANY_NO_MOTION_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 Any non zero value -> Fail
+ */
+uint16_t bma423_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable, struct bma4_dev *dev);
+
+/*!
+ * @brief 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_TILT_INT
+ * - BMA423_WAKEUP_INT
+ * - BMA423_ANY_NO_MOTION_INT
+ * - BMA423_ERROR_INT
+ *
+ *
+ * Hardware Interrupts
+ * - BMA4_FIFO_FULL_INT
+ * - BMA4_FIFO_WM_INT
+ * - BMA4_MAG_DATA_RDY_INT
+ * - BMA4_ACCEL_DATA_RDY_INT
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ */
+uint16_t bma423_read_int_status(uint16_t *int_status, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 bma423 sensor
+ * enable | Macros
+ * --------------------|-------------------
+ * 0x00 | BMA4_DISABLE
+ * 0x01 | BMA4_ENABLE
+ * @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_ANY_MOTION (or) BMA423_NO_MOTION
+ * - BMA423_ACTIVITY
+ * - BMA423_WAKEUP
+ * - BMA423_TILT
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ */
+uint16_t bma423_feature_enable(uint8_t feature, uint8_t enable, struct bma4_dev *dev);
+
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ */
+uint16_t bma423_set_remap_axes(const struct bma423_axes_remap *remap_data, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ */
+uint16_t bma423_get_remap_axes(struct bma423_axes_remap *remap_data, struct bma4_dev *dev);
+
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ */
+uint16_t bma423_step_counter_set_watermark(uint16_t step_counter_wm, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ */
+uint16_t bma423_step_counter_get_watermark(uint16_t *step_counter_wm, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ */
+uint16_t bma423_reset_step_counter(struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ */
+uint16_t bma423_step_counter_output(uint32_t *step_count, struct bma4_dev *dev);
+
+/*!
+ * @brief This API gets the output for activity feature.
+ *
+ * @param[out] activity : Pointer variable which stores activity output
+ * read from the sensor.
+ * activity | State
+ * --------------|------------------------
+ * 0x00 | BMA423_USER_STATIONARY
+ * 0x01 | BMA423_USER_WALKING
+ * 0x02 | BMA423_USER_RUNNING
+ * 0x03 | BMA423_STATE_INVALID
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ */
+uint16_t bma423_activity_output(uint8_t *activity, struct bma4_dev *dev);
+
+/*!
+ * @brief This API select the platform configuration wrist(default) or phone.
+ *
+ * @param[in] platform : Variable to select wrist/phone
+ *
+ * platform | Macros
+ * -------------|------------------------
+ * 0x00 | BMA423_PHONE_CONFIG
+ * 0x01 | BMA423_WRIST_CONFIG
+ *
+ * @param[in] dev : Structure instance of bma4_dev
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ */
+uint16_t bma423_select_platform(uint8_t platform, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ */
+uint16_t bma423_stepcounter_get_parameter(struct bma423_stepcounter_settings *setting, struct bma4_dev *dev);
+
+/*!
+ * @brief 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 Any non zero value -> Fail
+ */
+uint16_t bma423_stepcounter_set_parameter(const struct bma423_stepcounter_settings *setting, struct bma4_dev *dev);
+
+/*!
+ * @brief This API enables or disables the step detector feature in the
+ * sensor.
+ *
+ * @param[in] enable : Variable used to enable or disable step detector
+ * enable | Macros
+ * --------------------|-------------------
+ * 0x00 | BMA4_DISABLE
+ * 0x01 | BMA4_ENABLE
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ */
+uint16_t bma423_step_detector_enable(uint8_t enable, struct bma4_dev *dev);
+
+/*!
+ * @brief This API enables the any motion feature according to the axis
+ * set by the user in the sensor.
+ *
+ * @param[in] axis : Variable to specify the axis of the any motion feature
+ * to be enabled in the sensor.
+ * Value | Axis
+ * ---------|-------------------------
+ * 0x00 | BMA423_ALL_AXIS_DIS
+ * 0x01 | BMA423_X_AXIS_EN
+ * 0x02 | BMA423_Y_AXIS_EN
+ * 0x04 | BMA423_Z_AXIS_EN
+ * 0x07 | BMA423_ALL_AXIS_EN
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ */
+uint16_t bma423_anymotion_enable_axis(uint8_t axis, struct bma4_dev *dev);
+
+/*! @brief This API sets the configuration of Any motion feature in
+ * the sensor.
+ *
+ * @param[in] any_motion : Pointer to structure variable to specify
+ * the any motion feature settings.
+ * Structure members are provided in the table below
+ *@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 / No-motion detection
+ * threshold | in 5.11g format.
+ * | Range is 0 to 1g.
+ * | Default value is 0xAA = 83mg.
+ * --------------------------------|----------------------------------------
+ * | Indicates if No motion (1) or
+ * nomotion_sel | Any-motion (0) is selected;
+ * | default value is 0 Any-motion.
+ * -------------------------------------------------------------------------
+ *@endverbatim
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ */
+uint16_t bma423_set_any_motion_config(const struct bma423_anymotion_config *any_motion, struct bma4_dev *dev);
+
+/*! @brief This API gets the configuration of any motion feature from
+ * the sensor.
+ *
+ * @param[out] any_motion : Pointer to structure variable used to store
+ * the any motion feature settings read from the sensor.
+ * Structure members are provided in the table below
+ *@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 / No-motion detection
+ * threshold | in 5.11g format.
+ * | Range is 0 to 1g.
+ * | Default value is 0xAA = 83mg.
+ * --------------------------------|----------------------------------------
+ * | Indicates if No motion (1) or
+ * nomotion_sel | Any-motion (0) is selected;
+ * | default value is 0 Any-motion.
+ * -------------------------------------------------------------------------
+ *@endverbatim
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ */
+uint16_t bma423_get_any_motion_config(struct bma423_anymotion_config *any_motion, struct bma4_dev *dev);
+
+/*!
+ * @brief This API sets the sensitivity of wake up feature in the sensor
+ *
+ * @param[in] sensitivity : Variable used to specify the sensitivity of the
+ * Wake up feature.
+ * Value | Sensitivity
+ * --------|-------------------------
+ * 0x00 | MOST SENSITIVE
+ * 0x07 | LEAST SENSITIVE
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ */
+uint16_t bma423_wakeup_set_sensitivity(uint8_t sensitivity, struct bma4_dev *dev);
+
+/*!
+ * @brief This API gets the sensitivity of wake up feature in the sensor
+ *
+ * @param[out] sensitivity : Pointer variable which stores the sensitivity
+ * value read from the sensor.
+ * Value | Sensitivity
+ * --------|-------------------------
+ * 0x00 | MOST SENSITIVE
+ * 0x07 | LEAST SENSITIVE
+ * @param[in] dev : Structure instance of bma4_dev
+ *
+ * @return Result of API execution status
+ * @retval 0 -> Success
+ * @retval Any non zero value -> Fail
+ */
+uint16_t bma423_wakeup_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *dev);
+
+/*!
+ * @brief This API is used to select single/double tap
+ * feature in the sensor
+ *
+ * @param tap_select : Variable used to specify the single or
+ * double tap selection in the sensor
+ * tap_select | description
+ * ------------|------------------------
+ * 0x00 | Double tap selected
+ * 0x01 | single tap selected
+ *
+ * @param dev : Structure instance of bma4_dev
+ *
+ * @return results of stream_transfer operation
+ * @retval 0 -> Success
+ * @retval Any positive value mentioned in ERROR CODES -> Fail
+ *
+ */
+uint16_t bma423_tap_selection(const uint8_t tap_select, struct bma4_dev *dev);
+
+#ifdef __cplusplus
+}
+#endif /*End of CPP guard */
+
+#endif /*End of header guard macro */
diff --git a/libesp32/TTGO_TWatch_Library/src/bma4_defs.h b/libesp32/TTGO_TWatch_Library/src/bma4_defs.h
new file mode 100755
index 000000000..9ff81d659
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/src/bma4_defs.h
@@ -0,0 +1,960 @@
+/*
+*
+****************************************************************************
+* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH
+*
+* File : bma4_defs.h
+*
+* Date: 12 Oct 2017
+*
+* Revision: 2.1.9 $
+*
+* Usage: Sensor Driver for BMA4 family of sensors
+*
+****************************************************************************
+*
+* Disclaimer
+*
+* Common:
+* Bosch Sensortec products are developed for the consumer goods industry.
+* They may only be used within the parameters of the respective valid
+* product data sheet. Bosch Sensortec products are provided with the
+* express understanding that there is no warranty of fitness for a
+* particular purpose.They are not fit for use in life-sustaining,
+* safety or security sensitive systems or any system or device
+* that may lead to bodily harm or property damage if the system
+* or device malfunctions. In addition,Bosch Sensortec products are
+* not fit for use in products which interact with motor vehicle systems.
+* The resale and or use of products are at the purchasers own risk and
+* his own responsibility. The examination of fitness for the intended use
+* is the sole responsibility of the Purchaser.
+*
+* The purchaser shall indemnify Bosch Sensortec from all third party
+* claims, including any claims for incidental, or consequential damages,
+* arising from any product use not covered by the parameters of
+* the respective valid product data sheet or not approved by
+* Bosch Sensortec and reimburse Bosch Sensortec for all costs in
+* connection with such claims.
+*
+* The purchaser must monitor the market for the purchased products,
+* particularly with regard to product safety and inform Bosch Sensortec
+* without delay of all security relevant incidents.
+*
+* Engineering Samples are marked with an asterisk (*) or (e).
+* Samples may vary from the valid technical specifications of the product
+* series. They are therefore not intended or fit for resale to third
+* parties or for use in end products. Their sole purpose is internal
+* client testing. The testing of an engineering sample may in no way
+* replace the testing of a product series. Bosch Sensortec assumes
+* no liability for the use of engineering samples.
+* By accepting the engineering samples, the Purchaser agrees to indemnify
+* Bosch Sensortec from all claims arising from the use of engineering
+* samples.
+*
+* Special:
+* This software module (hereinafter called "Software") and any information
+* on application-sheets (hereinafter called "Information") is provided
+* free of charge for the sole purpose to support your application work.
+* The Software and Information is subject to the following
+* terms and conditions:
+*
+* The Software is specifically designed for the exclusive use for
+* Bosch Sensortec products by personnel who have special experience
+* and training. Do not use this Software if you do not have the
+* proper experience or training.
+*
+* This Software package is provided `` as is `` and without any expressed
+* or implied warranties,including without limitation, the implied warranties
+* of merchantability and fitness for a particular purpose.
+*
+* Bosch Sensortec and their representatives and agents deny any liability
+* for the functional impairment
+* of this Software in terms of fitness, performance and safety.
+* Bosch Sensortec and their representatives and agents shall not be liable
+* for any direct or indirect damages or injury, except as
+* otherwise stipulated in mandatory applicable law.
+*
+* The Information provided is believed to be accurate and reliable.
+* Bosch Sensortec assumes no responsibility for the consequences of use
+* of such Information nor for any infringement of patents or
+* other rights of third parties which may result from its use.
+* No license is granted by implication or otherwise under any patent or
+* patent rights of Bosch. Specifications mentioned in the Information are
+* subject to change without notice.
+**************************************************************************/
+/*! \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
+#else
+#include
+#include
+#include
+#endif
+
+/*********************************************************************/
+/* macro definitions */
+
+/*
+#if (LONG_MAX) > 0x7fffffff
+#define __have_long64 1
+#elif (LONG_MAX) == 0x7fffffff
+#define __have_long32 1
+#endif
+*/
+
+#if !defined(UINT8_C)
+#define INT8_C(x) x
+#if (INT_MAX) > 0x7f
+#define UINT8_C(x) x
+#else
+#define UINT8_C(x) x##U
+#endif
+#endif
+
+#if !defined(UINT16_C)
+#define INT16_C(x) x
+#if (INT_MAX) > 0x7fff
+#define UINT16_C(x) x
+#else
+#define UINT16_C(x) x##U
+#endif
+#endif
+
+#if !defined(INT32_C) && !defined(UINT32_C)
+#if __have_long32
+#define INT32_C(x) x##L
+#define UINT32_C(x) x##UL
+#else
+#define INT32_C(x) x
+#define UINT32_C(x) x##U
+#endif
+#endif
+
+#if !defined(INT64_C) && !defined(UINT64_C)
+#if __have_long64
+#define INT64_C(x) x##L
+#define UINT64_C(x) x##UL
+#else
+#define INT64_C(x) x##LL
+#define UINT64_C(x) x##ULL
+#endif
+#endif
+
+/**\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 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_INTERFACE UINT8_C(1)
+#define BMA4_I2C_INTERFACE UINT8_C(2)
+
+/**\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_CONFIG_STREAM_SIZE UINT16_C(6144)
+#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 UINT8_C(1)
+#define BMA4_AUX_COM_DELAY UINT8_C(10)
+
+/**\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 ERROR CODES */
+#define BMA4_OK UINT16_C(0)
+#define BMA4_E_NULL_PTR UINT16_C(1)
+#define BMA4_E_OUT_OF_RANGE UINT16_C(1 << 1)
+#define BMA4_E_INVALID_SENSOR UINT16_C(1 << 2)
+#define BMA4_E_CONFIG_STREAM_ERROR UINT16_C(1 << 3)
+#define BMA4_E_SELF_TEST_FAIL UINT16_C(1 << 4)
+#define BMA4_E_FOC_FAIL UINT16_C(1 << 5)
+#define BMA4_E_FAIL UINT16_C(1 << 6)
+#define BMA4_E_INT_LINE_INVALID UINT16_C(1 << 7)
+#define BMA4_E_RD_WR_LENGTH_INVALID UINT16_C(1 << 8)
+#define BMA4_E_AUX_CONFIG_FAIL UINT16_C(1 << 9)
+#define BMA4_E_SC_FIFO_HEADER_ERR UINT16_C(1 << 10)
+#define BMA4_E_SC_FIFO_CONFIG_ERR UINT16_C(1 << 11)
+
+/**\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)
+
+/**\name FOC RELATED MACROS */
+#define BMA4_ACCEL_CONFIG_FOC UINT8_C(0xB7)
+
+/* Macros used for Self test */
+/* 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)
+
+/* 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 Maximum number of bytes to be read from the sensor */
+#define BMA4_MAX_BUFFER_SIZE UINT8_C(81)
+
+/**\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 FIFO_HEAD_A UINT8_C(0x84)
+#define FIFO_HEAD_M UINT8_C(0x90)
+#define FIFO_HEAD_M_A UINT8_C(0x94)
+#define FIFO_HEAD_SENSOR_TIME UINT8_C(0x44)
+#define FIFO_HEAD_INPUT_CONFIG UINT8_C(0x48)
+#define FIFO_HEAD_SKIP_FRAME UINT8_C(0x40)
+#define FIFO_HEAD_OVER_READ_MSB UINT8_C(0x80)
+#define 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 FIFO_LSB_CONFIG_CHECK UINT8_C(0x00)
+#define FIFO_MSB_CONFIG_CHECK UINT8_C(0x80)
+#define BMA4_FIFO_TAG_INTR_MASK UINT8_C(0xFC)
+
+/**\name FIFO DROPPED FRAME DEFINITION */
+#define AUX_FIFO_DROP UINT8_C(0x04)
+#define ACCEL_AUX_FIFO_DROP UINT8_C(0x05)
+#define 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 UINT8_C(0)
+#define BMA4_SELFTEST_FAIL UINT8_C(1)
+
+/**\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 AKM_POWER_DOWN_MODE UINT8_C(0)
+#define 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 FORCE_MODE UINT8_C(0)
+#define SUSPEND_MODE UINT8_C(1)
+
+/**\name ACCEL POWER MODE */
+#define ACCEL_MODE_NORMAL UINT8_C(0x11)
+
+/**\name MAG POWER MODE */
+#define 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 MULTIPLIER */
+/*! for handling micro-g values */
+#define BMA4XY_MULTIPLIER UINT32_C(1000000)
+/*! 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 0
+#define BMA4_AUX_READ_LEN_1 1
+#define BMA4_AUX_READ_LEN_2 2
+#define BMA4_AUX_READ_LEN_3 3
+
+#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<> 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))
+
+/**\name TYPEDEF DEFINITIONS */
+/*!
+ * @brief Bus communication function pointer which should be mapped to
+ * the platform specific read and write functions of the user
+ */
+typedef uint16_t (*bma4_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_data, uint16_t len);
+
+/*! delay function pointer */
+typedef void (*bma4_delay_fptr_t)(uint32_t);
+
+/******************************************************************************/
+/*! @name Enum Declarations */
+/******************************************************************************/
+
+/*! @name Enum to define BMA4 variants */
+enum bma4_variant {
+ BMA42X_VARIANT = 1,
+ BMA45X_VARIANT
+};
+
+/**\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;
+ /*! Device address of BMA4 */
+ uint8_t dev_addr;
+ /*! Interface detail */
+ uint8_t interface;
+ /*! 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;*/
+ /*! FIFO related configurations */
+ struct bma4_fifo_frame *fifo;
+ /*! Config stream data buffer address will be assigned*/
+ const uint8_t *config_file_ptr;
+ /*! Max read/write length (maximum supported length is 32).
+ To be set by the user */
+ uint8_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_com_fptr_t bus_read;
+ /*! Bus write function pointer */
+ bma4_com_fptr_t bus_write;
+ /*! delay(in ms) function pointer */
+ bma4_delay_fptr_t delay;
+};
+
+/*!
+ * @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;
+};
+
+#endif
+/* End of __BMA4_H__ */
diff --git a/libesp32/TTGO_TWatch_Library/src/i2c_bus.cpp b/libesp32/TTGO_TWatch_Library/src/i2c_bus.cpp
new file mode 100755
index 000000000..d643098b0
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/src/i2c_bus.cpp
@@ -0,0 +1,94 @@
+#include "i2c_bus.h"
+#include "Wire.h"
+#include
+
+void I2CBus::scan(void)
+{
+ uint8_t err, addr;
+ int nDevices = 0;
+ for (addr = 1; addr < 127; addr++) {
+ _port->beginTransmission(addr);
+ err = _port->endTransmission();
+ if (err == 0) {
+ Serial.print("I2C device found at address 0x");
+ if (addr < 16)
+ Serial.print("0");
+ Serial.print(addr, HEX);
+ Serial.println(" !");
+ nDevices++;
+ } else if (err == 4) {
+ Serial.print("Unknow error at address 0x");
+ if (addr < 16)
+ Serial.print("0");
+ Serial.println(addr, HEX);
+ }
+ }
+ if (nDevices == 0)
+ Serial.println("No I2C devices found\n");
+ else
+ Serial.println("done\n");
+}
+
+
+uint16_t I2CBus::readBytes(uint8_t addr, uint8_t *data, uint16_t len, uint16_t delay_ms)
+{
+ uint16_t ret = 0;
+ xSemaphoreTakeRecursive(_i2c_mux, portMAX_DELAY);
+ uint8_t cnt = _port->requestFrom(addr, (uint8_t)len, (uint8_t)1);
+ if (!cnt) {
+ ret = 1 << 13;
+ }
+ uint16_t index = 0;
+ while (_port->available()) {
+ if (index > len)return 1 << 14;
+ if (delay_ms)delay(delay_ms);
+ data[index++] = _port->read();
+ }
+ xSemaphoreGiveRecursive(_i2c_mux);
+ return ret;
+}
+
+
+uint16_t I2CBus::readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len)
+{
+ uint16_t ret = 0;
+ xSemaphoreTakeRecursive(_i2c_mux, portMAX_DELAY);
+ _port->beginTransmission(addr);
+ _port->write(reg);
+ _port->endTransmission(false);
+ uint8_t cnt = _port->requestFrom(addr, (uint8_t)len, (uint8_t)1);
+ if (!cnt) {
+ ret = 1 << 13;
+ }
+ uint16_t index = 0;
+ while (_port->available()) {
+ if (index > len)return 1 << 14;
+ data[index++] = _port->read();
+ }
+ xSemaphoreGiveRecursive(_i2c_mux);
+ return ret;
+}
+
+uint16_t I2CBus::writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len)
+{
+ uint16_t ret = 0;
+ xSemaphoreTakeRecursive(_i2c_mux, portMAX_DELAY);
+ _port->beginTransmission(addr);
+ _port->write(reg);
+ for (uint16_t i = 0; i < len; i++) {
+ _port->write(data[i]);
+ }
+ ret = _port->endTransmission();
+ xSemaphoreGiveRecursive(_i2c_mux);
+ return ret ? 1 << 12 : ret;
+}
+
+bool I2CBus::deviceProbe(uint8_t addr)
+{
+ uint16_t ret = 0;
+ xSemaphoreTakeRecursive(_i2c_mux, portMAX_DELAY);
+ _port->beginTransmission(addr);
+ ret = _port->endTransmission();
+ xSemaphoreGiveRecursive(_i2c_mux);
+ return (ret == 0);
+}
\ No newline at end of file
diff --git a/libesp32/TTGO_TWatch_Library/src/i2c_bus.h b/libesp32/TTGO_TWatch_Library/src/i2c_bus.h
new file mode 100755
index 000000000..b8d261758
--- /dev/null
+++ b/libesp32/TTGO_TWatch_Library/src/i2c_bus.h
@@ -0,0 +1,26 @@
+#ifndef TTGO_I2CBUF_H
+#define TTGO_I2CBUF_H
+
+#include
+#include "freertos/FreeRTOS.h"
+#include "freertos/semphr.h"
+class I2CBus
+{
+public:
+ I2CBus(TwoWire &port = Wire, int sda = 21, int scl = 22)
+ {
+ _port = &port;
+ _port->begin(sda, scl);
+ _i2c_mux = xSemaphoreCreateRecursiveMutex();
+ };
+ void scan();
+ uint16_t readBytes(uint8_t addr, uint8_t *data, uint16_t len, uint16_t delay_ms = 0);
+ uint16_t readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len);
+ uint16_t writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len);
+ bool deviceProbe(uint8_t addr);
+private:
+ TwoWire *_port;
+ SemaphoreHandle_t _i2c_mux = NULL;
+};
+
+#endif
\ No newline at end of file
diff --git a/tasmota/xdrv_42_i2s_audio.ino b/tasmota/xdrv_42_i2s_audio.ino
index 00f20c19b..77492992b 100644
--- a/tasmota/xdrv_42_i2s_audio.ino
+++ b/tasmota/xdrv_42_i2s_audio.ino
@@ -53,10 +53,11 @@ AudioOutputI2S *out;
AudioFileSourceID3 *id3;
AudioGeneratorMP3 *decoder = NULL;
+
#ifdef USE_WEBRADIO
AudioFileSourceICYStream *ifile = NULL;
AudioFileSourceBuffer *buff = NULL;
-//char title[64];
+char wr_title[64];
//char status[64];
#ifdef ESP8266
@@ -211,8 +212,13 @@ void I2S_Init(void) {
out->stop();
#ifdef USE_WEBRADIO
- preallocateBuffer = malloc(preallocateBufferSize);
- preallocateCodec = malloc(preallocateCodecSize);
+ if (psramFound()) {
+ preallocateBuffer = heap_caps_malloc(preallocateBufferSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
+ preallocateCodec = heap_caps_malloc(preallocateCodecSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
+ } else {
+ preallocateBuffer = malloc(preallocateBufferSize);
+ preallocateCodec = malloc(preallocateCodecSize);
+ }
if (!preallocateBuffer || !preallocateCodec) {
//Serial.printf_P(PSTR("FATAL ERROR: Unable to preallocate %d bytes for app\n"), preallocateBufferSize+preallocateCodecSize);
}
@@ -246,8 +252,9 @@ void MDCallback(void *cbData, const char *type, bool isUnicode, const char *str)
(void) isUnicode; // Punt this ball for now
(void) ptr;
if (strstr_P(type, PSTR("Title"))) {
- //strncpy(title, str, sizeof(title));
- //title[sizeof(title)-1] = 0;
+ strncpy(wr_title, str, sizeof(wr_title));
+ wr_title[sizeof(wr_title)-1] = 0;
+ //AddLog_P2(LOG_LEVEL_INFO,PSTR("WR-Title: %s"),wr_title);
} else {
// Who knows what to do? Not me!
}
@@ -331,6 +338,15 @@ void Cmd_WebRadio(void) {
}
+const char HTTP_WEBRADIO[] PROGMEM =
+ "{s}" "I2S_WR-Title" "{m}%s{e}";
+
+void I2S_WR_Show(void) {
+ if (decoder) {
+ WSContentSend_PD(HTTP_WEBRADIO,wr_title);
+ }
+}
+
#endif
#ifdef ESP32
@@ -338,14 +354,33 @@ void Play_mp3(const char *path) {
#if defined(USE_SCRIPT) && defined(USE_SCRIPT_FATFS)
if (decoder || mp3) return;
+ bool I2S_Task;
+
TTGO_PWR_ON
+ if (*path=='+') {
+ I2S_Task = true;
+ path++;
+ } else {
+ I2S_Task = false;
+ }
file = new AudioFileSourceFS(*fsp,path);
id3 = new AudioFileSourceID3(file);
mp3 = new AudioGeneratorMP3();
mp3->begin(id3, out);
- xTaskCreatePinnedToCore(mp3_task, "MP3", 8192, NULL, 3, &mp3_task_h, 1);
+ if (I2S_Task) {
+ xTaskCreatePinnedToCore(mp3_task, "MP3", 8192, NULL, 3, &mp3_task_h, 1);
+ } else {
+ while (mp3->isRunning()) {
+ if (!mp3->loop()) {
+ mp3->stop();
+ mp3_delete();
+ break;
+ }
+ OsWatchLoop();
+ }
+ }
#endif // USE_SCRIPT
}
@@ -440,7 +475,13 @@ bool Xdrv42(uint8_t function) {
case FUNC_INIT:
I2S_Init();
break;
-
+#ifdef USE_WEBSERVER
+#ifdef USE_WEBRADIO
+ case FUNC_WEB_SENSOR:
+ I2S_WR_Show();
+ break;
+#endif
+#endif
}
return result;
}
diff --git a/tasmota/xdrv_83_esp32watch.ino b/tasmota/xdrv_83_esp32watch.ino
new file mode 100644
index 000000000..2f759aa9a
--- /dev/null
+++ b/tasmota/xdrv_83_esp32watch.ino
@@ -0,0 +1,453 @@
+/*
+ xdrv_83_esp32watch.ino - ESP32 TTGO watch support for Tasmota
+
+ Copyright (C) 2020 Gerhard Mutz and Theo Arends
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifdef ESP32
+#ifdef USE_TTGO_WATCH
+
+#include
+#include
+#include
+#include
+
+#define XDRV_83 83
+
+#define AXP202_INT 35
+
+struct TTGO_ADC {
+ float vbus_v;
+ float vbus_c;
+ float batt_v;
+ float batt_c;
+ float temp;
+ uint16_t per;
+} ttgo_adc;
+
+enum {
+ Q_EVENT_WIFI_SCAN_DONE,
+ Q_EVENT_WIFI_CONNECT,
+ Q_EVENT_BMA_INT,
+ Q_EVENT_AXP_INT,
+} ;
+
+#define BMA423_INT1 39
+#define BMA423_INT2 0
+
+#define WATCH_FLAG_SLEEP_MODE _BV(1)
+#define WATCH_FLAG_SLEEP_EXIT _BV(2)
+#define WATCH_FLAG_BMA_IRQ _BV(3)
+#define WATCH_FLAG_AXP_IRQ _BV(4)
+
+struct TTGO_globs {
+ AXP20X_Class *ttgo_power = nullptr;
+ I2CBus *i2c = nullptr;
+ BMA *bma = nullptr;
+ QueueHandle_t g_event_queue_handle = NULL;
+ //EventGroupHandle_t g_event_group = NULL;
+ EventGroupHandle_t isr_group = NULL;
+ bool lenergy = false;
+ bool bma_double_click = false;
+ bool bma_click = false;
+ bool bma_button = false;
+} ttgo_globs;
+
+
+void TTGO_Init(void) {
+ ttgo_globs.ttgo_power = new AXP20X_Class();
+ ttgo_globs.i2c = new I2CBus();
+ initPower();
+
+#ifdef USE_BMA423
+ ttgo_globs.bma = new BMA(*ttgo_globs.i2c);
+ if (ttgo_globs.bma->begin()) {
+ I2cSetActiveFound(BMA4_I2C_ADDR_SECONDARY, "BMA423");
+ } else {
+ return;
+ }
+
+ ttgo_globs.bma->attachInterrupt();
+ pinMode(BMA423_INT1, INPUT);
+ attachInterrupt(BMA423_INT1, [] {
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ EventBits_t bits = xEventGroupGetBitsFromISR(ttgo_globs.isr_group);
+ if (bits & WATCH_FLAG_SLEEP_MODE)
+ {
+ // Use an XEvent when waking from low energy sleep mode.
+ xEventGroupSetBitsFromISR(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_EXIT | WATCH_FLAG_BMA_IRQ, &xHigherPriorityTaskWoken);
+ } else
+ {
+ // Use the XQueue mechanism when we are already awake.
+ uint8_t data = Q_EVENT_BMA_INT;
+ xQueueSendFromISR(ttgo_globs.g_event_queue_handle, &data, &xHigherPriorityTaskWoken);
+ }
+
+ if (xHigherPriorityTaskWoken)
+ {
+ portYIELD_FROM_ISR ();
+ }
+ }, RISING);
+ struct bma423_axes_remap remap_data;
+
+ remap_data.x_axis = 0;
+ remap_data.x_axis_sign = 1;
+ remap_data.y_axis = 1;
+ remap_data.y_axis_sign = 0;
+ remap_data.z_axis = 2;
+ remap_data.z_axis_sign = 1;
+
+ ttgo_globs.bma->set_remap_axes(&remap_data);
+ // Enable the double tap wakeup.
+ ttgo_globs.bma->enableWakeupInterrupt(true);
+ ttgo_globs.bma->enableAnyNoMotionInterrupt(true);
+ ttgo_globs.bma->enableAccel();
+#endif
+}
+
+void initPower(void) {
+ int ret = ttgo_globs.ttgo_power->begin(axpReadBytes, axpWriteBytes);
+ if (ret == AXP_FAIL) {
+ //DBGX("AXP Power begin failed");
+ } else {
+ I2cSetActiveFound(AXP202_SLAVE_ADDRESS, "AXP202");
+ //Change the button boot time to 4 seconds
+ ttgo_globs.ttgo_power->setShutdownTime(AXP_POWER_OFF_TIME_4S);
+ // Turn off the charging instructions, there should be no
+ ttgo_globs.ttgo_power->setChgLEDMode(AXP20X_LED_OFF);
+ // Turn off external enable
+ ttgo_globs.ttgo_power->setPowerOutPut(AXP202_EXTEN, false);
+ //axp202 allows maximum charging current of 1800mA, minimum 300mA
+ ttgo_globs.ttgo_power->setChargeControlCur(300);
+
+ ttgo_globs.ttgo_power->adc1Enable(AXP202_VBUS_VOL_ADC1 | AXP202_VBUS_CUR_ADC1 | AXP202_BATT_CUR_ADC1 | AXP202_BATT_VOL_ADC1, true);
+
+ ttgo_globs.ttgo_power->adc2Enable(AXP202_TEMP_MONITORING_ADC2, true);
+
+ ttgo_globs.ttgo_power->enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_CHARGING_FINISHED_IRQ, AXP202_ON);
+ ttgo_globs.ttgo_power->clearIRQ();
+
+ ttgo_globs.ttgo_power->setPowerOutPut(AXP202_LDO2, AXP202_ON);
+
+ ttgo_globs.isr_group = xEventGroupCreate();
+ ttgo_globs.g_event_queue_handle = xQueueCreate(20, sizeof(uint8_t));
+
+ // Connection interrupted to the specified pin
+ pinMode(AXP202_INT, INPUT);
+ attachInterrupt(AXP202_INT, [] {
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ EventBits_t bits = xEventGroupGetBitsFromISR(ttgo_globs.isr_group);
+ if (bits & WATCH_FLAG_SLEEP_MODE) {
+ // Use an XEvent when waking from low energy sleep mode.
+ xEventGroupSetBitsFromISR(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_EXIT | WATCH_FLAG_AXP_IRQ, &xHigherPriorityTaskWoken);
+ } else {
+ // Use the XQueue mechanism when we are already awake.
+ uint8_t data = Q_EVENT_AXP_INT;
+ xQueueSendFromISR(ttgo_globs.g_event_queue_handle, &data, &xHigherPriorityTaskWoken);
+ }
+ if (xHigherPriorityTaskWoken) {
+ portYIELD_FROM_ISR ();
+ }
+ }, FALLING);
+ }
+
+}
+
+static uint8_t axpWriteBytes(uint8_t devAddress, uint8_t regAddress, uint8_t *data, uint8_t len) {
+ ttgo_globs.i2c->writeBytes(devAddress, regAddress, data, len);
+ return 0;
+}
+
+static uint8_t axpReadBytes(uint8_t devAddress, uint8_t regAddress, uint8_t *data, uint8_t len) {
+ ttgo_globs.i2c->readBytes(devAddress, regAddress, data, len);
+ return 0;
+}
+
+
+void TTGO_GetADC(void) {
+ ttgo_adc.vbus_v = ttgo_globs.ttgo_power->getVbusVoltage();
+ ttgo_adc.vbus_c = ttgo_globs.ttgo_power->getVbusCurrent();
+ ttgo_adc.batt_v = ttgo_globs.ttgo_power->getBattVoltage();
+ ttgo_adc.per = ttgo_globs.ttgo_power->getBattPercentage();
+ ttgo_adc.batt_c = ttgo_globs.ttgo_power->getBattDischargeCurrent();
+ ttgo_adc.temp = ttgo_globs.ttgo_power->getTemp();
+}
+
+#ifdef USE_WEBSERVER
+const char HTTP_TTGO[] PROGMEM =
+ "{s}TTGO " "VBUS Voltage" "{m}%s mV" "{e}"
+ "{s}TTGO " "VBUS Current" "{m}%s mA" "{e}"
+ "{s}TTGO " "BATT Voltage" "{m}%s mV" "{e}"
+ "{s}TTGO " "BATT Current" "{m}%s mA" "{e}"
+ "{s}TTGO " "BATT Percentage" "{m}%d %%" "{e}"
+ "{s}TTGO " "Temperature" "{m}%s C" "{e}";
+#ifdef USE_BMA423
+const char HTTP_TTGO_BMA[] PROGMEM =
+ "{s}TTGO " "BMA x" "{m}%d mg" "{e}"
+ "{s}TTGO " "BMA y" "{m}%d mg" "{e}"
+ "{s}TTGO " "BMA z" "{m}%d mg" "{e}";
+#endif // USE_BMA423
+#endif // USE_WEBSERVER
+
+
+void TTGO_WebShow(uint32_t json) {
+
+ TTGO_GetADC();
+
+ char vstring[32];
+ char cstring[32];
+ char bvstring[32];
+ char bcstring[32];
+ char tstring[32];
+ dtostrfd(ttgo_adc.vbus_v,2,vstring);
+ dtostrfd(ttgo_adc.vbus_c,2,cstring);
+ dtostrfd(ttgo_adc.batt_v,2,bvstring);
+ dtostrfd(ttgo_adc.batt_c,2,bcstring);
+ dtostrfd(ttgo_adc.temp,2,tstring);
+
+#ifdef USE_BMA423
+ Accel acc;
+ bool res = ttgo_globs.bma->getAccel(acc);
+#endif // USE_BMA423
+
+ if (json) {
+ ResponseAppend_P(PSTR(",\"TTGO_WATCH\":{\"VBV\":%s,\"VBC\":%s,\"BV\":%s,\"BC\":%s,\"BP\":%d,\"CT\":%s"),
+ vstring, cstring, bvstring, bcstring, ttgo_adc.per, tstring);
+#ifdef USE_BMA423
+ ResponseAppend_P(PSTR(",\"BMAX\":%d,\"BMAY\":%d,\"BMAZ\":%d"),acc.x,acc.y,acc.z);
+#endif
+ ResponseJsonEnd();
+ } else {
+ WSContentSend_PD(HTTP_TTGO,vstring,cstring,bvstring,bcstring,ttgo_adc.per,tstring);
+#ifdef USE_BMA423
+ WSContentSend_PD(HTTP_TTGO_BMA,acc.x,acc.y,acc.z);
+#endif // USE_BMA423
+ }
+}
+
+
+void enableLDO3(bool en = true) {
+ if (!ttgo_globs.ttgo_power) return;
+ ttgo_globs.ttgo_power->setLDO3Mode(1);
+ ttgo_globs.ttgo_power->setPowerOutPut(AXP202_LDO3, en);
+}
+
+void TTGO_audio_power(bool power) {
+ enableLDO3(power);
+}
+
+const char TTGO_Commands[] PROGMEM = "TTGO|"
+ "LSLP";
+
+void (* const TTTGO_Command[])(void) PROGMEM = {
+ &TTGO_LightSleep};
+
+void TTGO_LightSleep(void) {
+int32_t ttgo_sleeptime;
+
+ // switch device off
+ if ((abs(XdrvMailbox.payload) >= 10) && (abs(XdrvMailbox.payload) <= 3600*24)) {
+ ttgo_sleeptime = XdrvMailbox.payload;
+ } else {
+ ttgo_sleeptime = 0;
+ }
+
+ ResponseCmndNumber(ttgo_sleeptime);
+
+ TTGO_Sleep(ttgo_sleeptime);
+
+}
+
+void TTGO_Sleep(int32_t stime) {
+int32_t ttgo_sleeptime;
+
+ ttgo_sleeptime = stime;
+
+ DisplayOnOff(0);
+
+ if (ttgo_sleeptime>=0) {
+ // ligh sleep mode
+ WifiShutdown();
+ SettingsSaveAll();
+ RtcSettingsSave();
+ ttgo_globs.lenergy = true;
+ rtc_clk_cpu_freq_set(RTC_CPU_FREQ_2M);
+ xEventGroupSetBits(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_MODE);
+ gpio_wakeup_enable ((gpio_num_t)AXP202_INT, GPIO_INTR_LOW_LEVEL);
+ gpio_wakeup_enable ((gpio_num_t)BMA423_INT1, GPIO_INTR_HIGH_LEVEL);
+ esp_sleep_enable_gpio_wakeup();
+ if (ttgo_sleeptime) {
+ esp_sleep_enable_timer_wakeup(ttgo_sleeptime * 1000000);
+ }
+ esp_light_sleep_start();
+ } else {
+ ttgo_globs.ttgo_power->setPowerOutPut(0xFF, false);
+ Settings.deepsleep = -ttgo_sleeptime;
+#ifdef USE_DEEPSLEEP
+ RtcSettings.nextwakeup = 0;
+ deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : DEEPSLEEP_START_COUNTDOWN;
+ if (deepsleep_flag) {
+ if (!Settings.tele_period) {
+ Settings.tele_period = TELE_PERIOD; // Need teleperiod to go back to sleep
+ }
+ }
+#endif
+ return;
+ }
+
+ if (ttgo_sleeptime) {
+ ttgo_globs.lenergy = false;
+ rtc_clk_cpu_freq_set(RTC_CPU_FREQ_240M);
+ DisplayOnOff(1);
+ } else {
+ while (ttgo_globs.lenergy == true) {
+ TTGO_loop(0);
+ OsWatchLoop();
+ }
+ }
+}
+
+
+void TTGO_loop(uint32_t flg) {
+bool rlst;
+uint8_t data;
+
+ if (!flg) {
+// An XEvent signifies that there has been a wakeup interrupt, bring the CPU out of low energy mode
+ EventBits_t bits = xEventGroupGetBits(ttgo_globs.isr_group);
+ if (bits & WATCH_FLAG_SLEEP_EXIT) {
+ if (ttgo_globs.lenergy) {
+ ttgo_globs.lenergy = false;
+ rtc_clk_cpu_freq_set(RTC_CPU_FREQ_240M);
+ DisplayOnOff(1);
+ }
+
+#ifdef USE_BMA423
+ if (bits & WATCH_FLAG_BMA_IRQ) {
+ do {
+ rlst = ttgo_globs.bma->readInterrupt();
+ } while (!rlst);
+ xEventGroupClearBits(ttgo_globs.isr_group, WATCH_FLAG_BMA_IRQ);
+ }
+#endif
+
+ if (bits & WATCH_FLAG_AXP_IRQ) {
+ ttgo_globs.ttgo_power->readIRQ();
+ ttgo_globs.ttgo_power->clearIRQ();
+ xEventGroupClearBits(ttgo_globs.isr_group, WATCH_FLAG_AXP_IRQ);
+ }
+ xEventGroupClearBits(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_EXIT);
+ xEventGroupClearBits(ttgo_globs.isr_group, WATCH_FLAG_SLEEP_MODE);
+ }
+ } else {
+ //! Normal polling
+ if (xQueueReceive(ttgo_globs.g_event_queue_handle, &data, 5 / portTICK_RATE_MS) == pdPASS) {
+ switch (data) {
+#ifdef USE_BMA423
+ case Q_EVENT_BMA_INT:
+ // DSERIAL(println, "Q_EVENT_BMA_IRQ");
+ do {
+ rlst = ttgo_globs.bma->readInterrupt();
+ } while (!rlst);
+
+ if (ttgo_globs.bma->isDoubleClick()) {
+ ttgo_globs.bma_double_click = true;
+ //AddLog_P2(LOG_LEVEL_INFO, PSTR("double click"));
+ }
+ if (ttgo_globs.bma->isAnyNoMotion()) {
+ ttgo_globs.bma_click = true;
+ //AddLog_P2(LOG_LEVEL_INFO, PSTR("click"));
+ }
+
+ //! setp counter
+ if (ttgo_globs.bma->isStepCounter()) {
+ //updateStepCounter(ttgo_globs.bma->getCounter());
+ }
+ break;
+#endif
+ case Q_EVENT_AXP_INT:
+ // DSERIAL(println, "Q_EVENT_AXP_INT");
+ ttgo_globs.ttgo_power->readIRQ();
+ if (ttgo_globs.ttgo_power->isVbusPlugInIRQ()) {
+ //batState = LV_ICON_CHARGE;
+ //updateBatteryIcon(LV_ICON_CHARGE);
+ }
+ if (ttgo_globs.ttgo_power->isVbusRemoveIRQ()) {
+ //batState = LV_ICON_CALCULATION;
+ //updateBatteryIcon(LV_ICON_CALCULATION);
+ }
+ if (ttgo_globs.ttgo_power->isChargingDoneIRQ()) {
+ //batState = LV_ICON_CALCULATION;
+ //updateBatteryIcon(LV_ICON_CALCULATION);
+ }
+ if (ttgo_globs.ttgo_power->isPEKShortPressIRQ()) {
+ ttgo_globs.bma_button = true;
+ //AddLog_P2(LOG_LEVEL_INFO, PSTR("button press"));
+ }
+ ttgo_globs.ttgo_power->clearIRQ();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+bool TTGO_doubleclick(void) {
+ bool retval = ttgo_globs.bma_double_click;
+ ttgo_globs.bma_double_click = false;
+ return retval;
+}
+
+bool TTGO_button(void) {
+ bool retval = ttgo_globs.bma_button;
+ ttgo_globs.bma_button = false;
+ return retval;
+}
+
+/*********************************************************************************************\
+ * Interface
+\*********************************************************************************************/
+
+bool Xdrv83(uint8_t function) {
+ bool result = false;
+
+ switch (function) {
+
+ case FUNC_WEB_SENSOR:
+#ifdef USE_WEBSERVER
+ TTGO_WebShow(0);
+#endif
+ break;
+ case FUNC_JSON_APPEND:
+ TTGO_WebShow(1);
+ break;
+ case FUNC_COMMAND:
+ result = DecodeCommand(TTGO_Commands, TTTGO_Command);
+ break;
+ case FUNC_INIT:
+ TTGO_Init();
+ break;
+ case FUNC_LOOP:
+ TTGO_loop(1);
+ break;
+
+ }
+ return result;
+}
+
+#endif // USE_TTGO_WATCH
+#endif // ESP32