增加n9编译选项,添加GPS,血压服务,优化原像心率计算 1829/1
authorpenglei <1624952103@qq.com>
Fri, 13 Jun 2025 08:59:12 +0000 (16:59 +0800)
committerpenglei <1624952103@qq.com>
Fri, 13 Jun 2025 08:59:12 +0000 (16:59 +0800)
103 files changed:
autobuild.sh
code/sdk/application/brandy/brandy_standard/input_app.c
code/sdk/application/brandy/brandy_standard/thread_pri_init.c
code/sdk/application/wearable/fd230app/nativelauncher/include/UiConfig.h
code/sdk/application/wearable/fd230app/nativeui/alarmclocktimerconfig/src/AlarmClockTimerConfig.cpp
code/sdk/application/wearable/fd230app/nativeui/clock/src/MainClockView.cpp
code/sdk/application/wearable/fd230app/nativeui/main/src/MainModel.cpp
code/sdk/application/wearable/fd230app/nativeui/producttest/include/testPresenter.h
code/sdk/application/wearable/fd230app/nativeui/producttest/include/testView.h
code/sdk/application/wearable/fd230app/nativeui/producttest/include/testgyro.h [new file with mode: 0644]
code/sdk/application/wearable/fd230app/nativeui/producttest/src/testView.cpp
code/sdk/application/wearable/fd230app/nativeui/producttest/src/testgyro.cpp [new file with mode: 0644]
code/sdk/application/wearable/fd230app/nativeui/set_dial/src/SetDialModel.cpp
code/sdk/application/wearable/fd230app/nativeui/system/src/SystemAboutTheWatchView.cpp
code/sdk/application/wearable/fd230app/nativeui/system/src/SystemSuperviseView.cpp
code/sdk/application/wearable/service/ble_service/bleservice/bleService.c
code/sdk/application/wearable/service/ble_service/bleservice/bleService.h
code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.c
code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.h
code/sdk/application/wearable/service/msg_center/brandy-native-js-n9/libmsg_center.a [new file with mode: 0644]
code/sdk/application/wstp/at_service/app/app_at_process.c
code/sdk/build/config/target_config/brandy/config.py
code/sdk/build/config/target_config/brandy/mk_fs_image/n9/file.bin
code/sdk/build/config/target_config/brandy/mk_fs_image/n9/file_tmp.bin
code/sdk/build/config/target_config/brandy/mk_fs_image/w9/file.bin
code/sdk/build/config/target_config/brandy/mk_fs_image/w9/file_tmp.bin
code/sdk/drivers/boards/brandy_evb/board_config/board_w9.h
code/sdk/drivers/chips/brandy/clocks/drivers/acore/clocks_config_priv.c
code/sdk/drivers/chips/brandy/porting/pinctrl/pinctrl_porting_brandy.c
code/sdk/drivers/peripheral/CMakeLists.txt
code/sdk/drivers/peripheral/bp/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/bp/bn02/bn02.c [new file with mode: 0644]
code/sdk/drivers/peripheral/bp/bn02/bn02.h [new file with mode: 0644]
code/sdk/drivers/peripheral/bp/lib/lib_hr.h [new file with mode: 0644]
code/sdk/drivers/peripheral/bp/lib/lib_hr_yll_v0.5.3.060325.a [new file with mode: 0644]
code/sdk/drivers/peripheral/bp/lib/yyl_pfev01.h [new file with mode: 0644]
code/sdk/drivers/peripheral/bp/service/bp_at_cmd.c [new file with mode: 0644]
code/sdk/drivers/peripheral/bp/service/bp_at_cmd.h [new file with mode: 0644]
code/sdk/drivers/peripheral/bp/service/bp_ble_service.c [new file with mode: 0644]
code/sdk/drivers/peripheral/bp/service/bp_ble_service.h [new file with mode: 0644]
code/sdk/drivers/peripheral/bp/service/bp_service.c [new file with mode: 0644]
code/sdk/drivers/peripheral/bp/service/bp_service.h [new file with mode: 0644]
code/sdk/drivers/peripheral/bp/service/bp_tcp_server.c [new file with mode: 0644]
code/sdk/drivers/peripheral/bp/service/bp_tcp_server.h [new file with mode: 0644]
code/sdk/drivers/peripheral/cywee/service/cywee_ble_Service.c
code/sdk/drivers/peripheral/cywee/src/main_dml.c
code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_pin_port.h
code/sdk/drivers/peripheral/gnss/sample/gnss_sample/gnss_sample.c
code/sdk/drivers/peripheral/gnss/src/gnss_ctl.c
code/sdk/drivers/peripheral/gnss/src/uart_gnss.c
code/sdk/drivers/peripheral/gyro/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/gyro/service/gyro_at_cmd.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gyro/service/gyro_at_cmd.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gyro/service/gyro_hal.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gyro/service/gyro_hal.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gyro/service/gyro_service.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gyro/service/gyro_service.h [new file with mode: 0644]
code/sdk/drivers/peripheral/gyro/sh5001/sh5001.c [new file with mode: 0644]
code/sdk/drivers/peripheral/gyro/sh5001/sh5001.h [new file with mode: 0644]
code/sdk/drivers/peripheral/lcd/lcd_config.c
code/sdk/drivers/peripheral/lcd/lcd_private.c
code/sdk/drivers/peripheral/ppg/CMakeLists.txt
code/sdk/drivers/peripheral/ppg/gh3x2x/CMakeLists.txt [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_adt.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_agc.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_demo.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_drv.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_ecg.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_user.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_version.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_hal.h [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_adt.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_agc.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_demo.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_drv.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_lead_off.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_user.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_hal.c [new file with mode: 0644]
code/sdk/drivers/peripheral/ppg/hal/ppg_hal.c
code/sdk/drivers/peripheral/ppg/hal/ppg_hal.h
code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_bsp.c
code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_main.c
code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_8009_reg_arr_default_20220623.h
code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x_config.h
code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.c
code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.h
code/sdk/drivers/peripheral/slip/cat1Service/cat1_ctl.cpp
code/sdk/drivers/peripheral/utils/custom_utils.c
code/sdk/middleware/chips/brandy/pm/include/pm_definition.h
code/sdk/middleware/chips/brandy/pm/pm.c
code/sdk/middleware/services/gpu/api/rm/brandy-native-js-n9-r/libgfx_rm.a [new file with mode: 0644]
code/sdk/middleware/services/gpu/api/rm/brandy-native-js-n9/libgfx_rm.a [new file with mode: 0644]
code/sdk/middleware/services/gui/hal/display/brandy-native-js-n9/libdisplay_gfx.a [new file with mode: 0644]
code/sdk/middleware/services/gui/uikit/brandy-native-js-n9/libuikit_ext.a [new file with mode: 0644]
code/sdk/middleware/services/gui/uikit/proprietary/src/service/src/graphic_service_wrapper.cpp
code/sdk/middleware/utils/fs/vfs/brandy-native-js-n9-r/libx_vfs_private.a [new file with mode: 0644]
code/sdk/middleware/utils/fs/vfs/brandy-native-js-n9/libx_vfs_private.a [new file with mode: 0644]
code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-n9-r/libfs_yaffs2.a [new file with mode: 0644]
code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-n9/libfs_yaffs2.a [new file with mode: 0644]
code/sdk/open_source/openharmony/foundation/aafwk/aafwk_lite/brandy-native-js-n9/libams.a [new file with mode: 0644]
code/sdk/open_source/openharmony/foundation/ace/ace_engine_lite/brandy-native-js-n9/libace.a [new file with mode: 0644]
code/sdk/open_source/openharmony/foundation/appexecfwk/appexecfwk_lite/brandy-native-js-n9/libbms.a [new file with mode: 0644]
code/sdk/open_source/openharmony/third_party/jerryscript/brandy-native-js-n9/libjerryscript.a [new file with mode: 0644]

index 5a928a9..97f90dd 100755 (executable)
@@ -132,6 +132,15 @@ DEFAULT_SSB_NAME=brandy-native-js-fd230-ssb
 BUILD_NAME=_FD230
 fi
 
+if [ "$1" == "n9" ]
+then
+TARGET_PACK_NAME=pack_brandy_native_js_n9
+APPLICATION_NAME=brandy-native-js-n9
+RECOVERY_NAME=brandy-native-js-n9-r
+DEFAULT_SSB_NAME=brandy-native-js-n9-ssb
+BUILD_NAME=_N9
+fi
+
 if [ "$1" == "leakcheck" ]
 then
 TARGET_PACK_NAME=pack_brandy_native_js_leakcheck
index 2763d4f..a93ff54 100755 (executable)
@@ -122,7 +122,11 @@ uint32_t g_button_press_time = BUTTON_PRESS_TIME_1S;
 
 button_map_t g_brandy_button_pin_map[BUTTON_PIN_MAP_MAX] = {
     { PIN_NONE, BUTTON_PWR },
+#ifdef BOARD_N9
+    { S_AGPIO_R3, BUTTON_1 },
+#else
     { S_AGPIO_R10, BUTTON_1 },
+#endif
     { PIN_NONE, BUTTON_2 },
     { PIN_NONE, BUTTON_3 },
     { PIN_NONE, BUTTON_4 },
index 6700e7a..dbded9e 100755 (executable)
 #include "mixo_service.h"\r
 #endif\r
 \r
+#ifdef ENABLE_BN02\r
+#include "bp_service.h"\r
+#include "bp_tcp_server.h"\r
+#endif\r
+\r
+#ifdef ENABLE_GYRO\r
+#include "gyro_service.h"\r
+#endif\r
+\r
 #define EMMC_BASE_ADDR              0x52062000\r
 #define TASK_PRIORITY_APP           (osPriority_t)(17)\r
 #define TICK_TEN_MS                 (10U)\r
@@ -504,7 +513,17 @@ uapi_pm_remove_sleep_veto(PM_ID_DEBUG);
     \r
 #ifdef ENABLE_CUSTOM_I2C\r
 \r
-    custom_iic_init();\r
+    custom_i2c_init(I2C_BUS_2);\r
+\r
+#ifdef ENABLE_BN02\r
+    // custom_i2c_init(I2C_BUS_0);\r
+    // uapi_bp_service_init();\r
+    // uapi_bp_tcp_server_init();\r
+#endif\r
+\r
+    #ifdef ROTARYENCODER_MIXO\r
+        uapi_mixo_service_init();\r
+    #endif\r
 \r
     #ifdef MAG_MMC5603\r
         uapi_mag_service_init();\r
@@ -518,9 +537,10 @@ uapi_pm_remove_sleep_veto(PM_ID_DEBUG);
         uapi_cywee_service_init();\r
     #endif \r
 \r
-    #ifdef ROTARYENCODER_MIXO\r
-        uapi_mixo_service_init();\r
-    #endif\r
+#endif\r
+\r
+#ifdef ENABLE_GYRO\r
+    uapi_gyro_service_init();\r
 #endif\r
 \r
     /*启动蓝牙ble服务,cywee有重置 mac地址的操作,会需要把 蓝牙服务开启放在cywee服务之后*/\r
@@ -540,7 +560,7 @@ uapi_pm_remove_sleep_veto(PM_ID_DEBUG);
     uapi_pin_set_ie(S_MGPIO34, HAL_PIO_IE_ENBALE);\r
 #endif\r
 \r
-#ifdef SUPPORT_GNSS_SERVICE\r
+#ifdef SUPPORT_GNSS_SERVER\r
     gnss_uart_init();\r
 #endif\r
 \r
index df62ff5..bbde3ce 100644 (file)
@@ -101,7 +101,7 @@ namespace OHOS
 #ifdef CUSTOM_Z1
     static constexpr const char *DEFAULT_DIALBACK_PATH = APP_RES_PATH "/dial_soures/z1background.bin";
     static constexpr const char *DEFAULT_DIALPER_PATH = APP_RES_PATH "/dial_soures/Z1VIEW.bin";
-#elif BOARD_W9
+#elif defined(BOARD_W9) || defined(BOARD_N9)
     static constexpr const char *DEFAULT_DIALBACK_PATH = APP_RES_PATH "/dial_soures/main_bg.bin";
     static constexpr const char *DEFAULT_DIALPER_PATH = APP_RES_PATH "/dial_soures/thumbnail.bin";
 #else
index 2a2c6e1..9e5e3b9 100644 (file)
@@ -435,7 +435,9 @@ extern "C"
         }\r
 \r
         HandleDrinkReminder(&curTime);  \r
+#ifdef BOARD_FD230\r
         HandleHeartRateDetection(&curTime);  \r
+#endif\r
     }\r
     \r
     //判断是否绑定\r
index 623cce3..fd4c7f4 100644 (file)
@@ -346,7 +346,7 @@ namespace OHOS
     */
     bool MainClockView::InitBatteryView(BatteryDisplayType type)
     {
-        #if !defined(BOARD_W9)  // N9需要显示电池
+        #if !(defined(BOARD_W9) || defined(BOARD_N9))// N9和W9需要显示电池
         // 不显示电池 icon
         if (type == BATTERY_DISPLAY_NONE)
         {
@@ -568,7 +568,7 @@ namespace OHOS
             datelabel->SetText(dateStr.c_str());  
 
         // Update battery status  
-        #if !defined(BOARD_W9)  // N9需要显示电池
+        #if !(defined(BOARD_W9) || defined(BOARD_N9))// N9和W9需要显示电池
         if (batterySetting == BATTERY_DISPLAY_NONE)  
             return;  
         #endif
index bd8a797..35f7edd 100644 (file)
@@ -53,7 +53,7 @@ namespace OHOS
     const DialInfo dialInfoMap[] = {\r
 #ifdef CUSTOM_Z1\r
         {DIAL_CLOCK, "Z1", DEFAULT_DIALPER_PATH, DEFAULT_TASK_PERIOD},\r
-#elif BOARD_W9\r
+#elif defined(BOARD_W9) || defined(BOARD_N9)\r
         {DIAL_CLOCK, "N9", DEFAULT_DIALPER_PATH, DEFAULT_TASK_PERIOD}, \r
 #else\r
         {DIAL_CLOCK, "KUMI", DEFAULT_DIALPER_PATH, DEFAULT_TASK_PERIOD},\r
@@ -438,7 +438,7 @@ namespace OHOS
         if (len < 0)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Failed to retrieve dial settings. Initializing to default settings.\r\n");\r
-        #ifdef BOARD_W9\r
+        #if defined(BOARD_W9) || defined(BOARD_N9)\r
             InitDialSettingDefault(DIAL_CLOCK);//N9使用默认静态表盘\r
         #else\r
             //判断黑耀表盘是否存在\r
@@ -468,7 +468,7 @@ namespace OHOS
         else\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: First value is empty. Initializing to default settings.\r\n");\r
-        #ifdef BOARD_W9\r
+        #if defined(BOARD_W9) || defined(BOARD_N9)\r
             InitDialSettingDefault(DIAL_CLOCK);//N9使用默认静态表盘\r
         #else\r
             //判断黑耀表盘是否存在\r
@@ -494,7 +494,7 @@ namespace OHOS
         else\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Second value is empty. Initializing to default settings.\r\n");\r
-        #ifdef BOARD_W9\r
+        #if defined(BOARD_W9) || defined(BOARD_N9)\r
             InitDialSettingDefault(DIAL_CLOCK);//N9使用默认静态表盘\r
         #else\r
             //判断黑耀表盘是否存在\r
index 6f05b73..796f00a 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: penglei 1624952103@qq.com\r
  * @Date: 2024-08-23 10:50:37\r
  * @LastEditors: penglei 1624952103@qq.com\r
- * @LastEditTime: 2025-06-06 15:56:14\r
+ * @LastEditTime: 2025-06-11 17:46:10\r
  * @FilePath: /FD230/code/sdk/application/wearable/fd230/nativeapp/nativeui/producttest/include/testPresenter.h\r
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE\r
  */\r
@@ -44,18 +44,19 @@ namespace OHOS
         MICROPHONE,\r
         HRSENSON,\r
         GSENSON,\r
-        BTTEST,\r
-        SEChipTest,\r
-        PingTest,\r
 #ifdef SUPPORT_GNSS\r
         GPSTEST,\r
 #endif\r
+        BTTEST,\r
+        SEChipTest,\r
+        PingTest,\r
+\r
 #ifdef ENABLE_LQBP002TA\r
         PRESSURETEST,\r
 #endif\r
-#ifdef ENABLE_GYRO\r
-        GYROTEST,\r
-#endif\r
+// #ifdef ENABLE_GYRO\r
+//         GYROTEST,\r
+// #endif\r
         OLDTEST,\r
         DEEPSLEEP,\r
         \r
index 99c8777..2999a25 100644 (file)
 #include "producttest/include/testbt.h"\r
 #include "producttest/include/testSEChipTest.h"\r
 #include "producttest/include/testPing.h"\r
+#ifdef SUPPORT_GNSS\r
 #include "producttest/include/testGPS.h"\r
+#endif\r
+#ifdef ENABLE_GYRO\r
+#include "producttest/include/testgyro.h"\r
+#endif\r
 #ifdef SUPPORT_A5133_SERVICE\r
 #include "producttest/include/testA5133.h"\r
 #endif\r
@@ -98,7 +103,12 @@ namespace OHOS
         bool ChangeBTTESTView(int16_t thisView);\r
         bool ChangeSEChipTESTView(int16_t thisView);\r
         bool ChangePingTESTView(int16_t thisView);\r
+#ifdef SUPPORT_GNSS\r
         bool ChangeGPSTESTView(int16_t thisView);\r
+#endif\r
+#ifdef ENABLE_GYRO\r
+        bool ChangegyroTestTESTView(int16_t thisView);\r
+#endif\r
     #ifdef SUPPORT_A5133_SERVICE\r
         bool ChangeA5133TESTView(int16_t thisView);\r
     #endif\r
@@ -138,8 +148,12 @@ namespace OHOS
 \r
         testSEChipView *test_SEChip_view{nullptr};\r
         testPingView *test_Ping_view{nullptr};\r
+#ifdef SUPPORT_GNSS\r
         testGPSView *test_GPS_view{nullptr};\r
-        \r
+#endif\r
+#ifdef ENABLE_GYRO\r
+        testgyroView *test_gyro_view{nullptr};\r
+#endif\r
     #ifdef SUPPORT_A5133_SERVICE\r
         testA5133View  *test_A5133_view{nullptr};\r
     #endif\r
diff --git a/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testgyro.h b/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testgyro.h
new file mode 100644 (file)
index 0000000..b904f15
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2025-05-12 15:44:33
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-06-09 15:04:11
+ * @FilePath: /sdk615/code/sdk/zhihui/UI/producttest/include/testgyro.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+#ifndef TEST_GYRO_VIEW_H
+#define TEST_GYRO_VIEW_H
+
+#include "BaseView.h"
+#include "View.h"
+#include "components/ui_scroll_view.h"
+#include "components/ui_label.h"
+#include "components/ui_label_ext.h"
+#include "components/ui_button.h"
+#include "components/ui_image_view.h"
+#include "components/ui_label_button_ext.h"
+
+//#include "cmsis_os.h"
+#include <iostream>
+namespace OHOS
+{
+
+    class testgyroView
+    {
+
+    public:
+       struct ButtonConfig_ext_t
+        {
+            int x;
+            int y;
+            int w;
+            int h;
+            const char *str;
+            const char *ViewId;
+            const char *ImageSrc;
+
+            //label
+            int label_x;
+            int label_y;
+            uint8_t ALIGN;
+            int  Fontsize;
+        
+        };
+
+
+        
+        struct LabelConfig
+        {
+            int16_t left;
+            int16_t top;
+            int16_t width;
+            int16_t height;
+            int16_t fontSize;      // 字体大小
+            int16_t lineHeigh;     // 行高
+            char *text;      // 文本
+            uint8_t lineBreakMode; // 断行模式。
+        };
+
+
+       
+        
+        testgyroView();
+        virtual ~testgyroView();
+        static testgyroView *GetInstance(void);
+   
+        UIScrollView *testgyroInitIView(uint8_t);
+        void  gyrodataTimerCallBack(void);
+
+        void ClearAll(void);
+    private:
+        UILabelButtonExt *SetTheButton_ext(ButtonConfig_ext_t &buttonconfig);//, UIView::OnTouchListener *clickListener);
+        UILabel *InitLabel(LabelConfig &labelConfig);
+        bool testgyroScrollViewcrollViewinit(uint8_t);
+        UIScrollView *testgyroScrollView{nullptr};
+        UILabel *label_1_MSG=NULL;
+        UILabel *label_2_MSG{nullptr};
+        UILabel *label_3_MSG{nullptr};
+
+        UILabelButtonExt* labelButton_next = nullptr;
+        bool initViewStatus{false};
+        UILabel *Title{nullptr};           // 标题
+
+    };
+}
+#endif
\ No newline at end of file
index 2a886e7..23b1757 100644 (file)
@@ -40,22 +40,19 @@ namespace OHOS
         {MICROPHONE,"microphonebutton","microphone", "microphonebutton_next",&testView::ChangeMPTESTView,true},\r
         {HRSENSON,"hrsensonbutton","hrsensor", "hrsensonbutton_next",&testView::ChangeHRTESTView,true},\r
         {GSENSON,"gsensonbutton","gsensor","gsensonbutton_next" ,&testView::ChangeGTESTView,true},\r
-        {BTTEST,"BTbutton","BT" ,"BTbutton_next",&testView::ChangeBTTESTView,true},\r
-        {SEChipTest,"SEChipTestbutton","SEChipTest","SEChipTestbutton_next" ,&testView::ChangeSEChipTESTView,true},\r
-        {PingTest,"PingTestbutton","PingTest","PingTestbutton_next" ,&testView::ChangePingTESTView,true},\r
-\r
 #if defined(SUPPORT_GNSS)\r
         {GPSTEST,"GPSTestbutton","GPSTest","GPSTestbutton_next" ,&testView::ChangeGPSTESTView,true},\r
 #endif\r
+        {BTTEST,"BTbutton","BT" ,"BTbutton_next",&testView::ChangeBTTESTView,true},\r
+        {SEChipTest,"SEChipTestbutton","SEChipTest","SEChipTestbutton_next" ,&testView::ChangeSEChipTESTView,true},\r
+        {PingTest,"PingTestbutton","PingTest","PingTestbutton_next" ,&testView::ChangePingTESTView,true},\r
 #if defined(ENABLE_LQBP002TA)\r
         {PRESSURETEST,"pressureTestbutton","pressureTest","pressureTestbutton_next" ,&testView::ChangepressureTestTESTView,true},\r
 #endif\r
-#if defined(ENABLE_GYRO)\r
-        {GYROTEST,"gyroTestbutton","gyroTest","gyroTestbutton_next" ,&testView::ChangegyroTestTESTView,true},\r
-#endif\r
-#ifdef AGINGTEST\r
+// #if defined(ENABLE_GYRO)\r
+//         {GYROTEST,"gyroTestbutton","gyroTest","gyroTestbutton_next" ,&testView::ChangegyroTestTESTView,true},\r
+// #endif\r
         {OLDTEST,"oldtestbutton","aging" ,"oldtestexit",&testView::ChangeoldTESTView,true},\r
-#endif\r
         {DEEPSLEEP,"deepsleep","DeepSleepCurrent","xxxxxxxxx" ,&testView::ChangeoldTESTView,true},\r
         {shutdown,"shutdown","shutdown", "xxxxxxxxx",&testView::ChangeoldTESTView,true},\r
         {RESET,"reset","reset", "xxxxxxxxx",&testView::ChangeoldTESTView,true},\r
@@ -562,7 +559,6 @@ namespace OHOS
 \r
      bool testView::ChangeoldTESTView(int16_t thisView)\r
     {\r
-          #ifdef AGINGTEST\r
         if (SystemScrollView[thisView] == nullptr)\r
         {\r
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::ChangeoldTESTView");\r
@@ -575,7 +571,6 @@ namespace OHOS
             SystemScrollView[thisView] = test_old_view->testoldInitIView(thisView);\r
             RootView::GetInstance()->Add(SystemScrollView[thisView]);\r
         }\r
-          #endif\r
         return true;\r
        \r
     }\r
@@ -890,14 +885,14 @@ namespace OHOS
                 SystemScrollView[hideView]=nullptr;\r
                 break;\r
 #endif\r
-#if defined(ENABLE_GYRO)\r
-             case GYROTEST:\r
-                RootView::GetInstance()->Remove(SystemScrollView[hideView]);\r
-                delete test_gyro_view;  \r
-                test_gyro_view = nullptr;\r
-                SystemScrollView[hideView]=nullptr;\r
-                break;\r
-#endif\r
+// #if defined(ENABLE_GYRO)\r
+//              case GYROTEST:\r
+//                 RootView::GetInstance()->Remove(SystemScrollView[hideView]);\r
+//                 delete test_gyro_view;  \r
+//                 test_gyro_view = nullptr;\r
+//                 SystemScrollView[hideView]=nullptr;\r
+//                 break;\r
+// #endif\r
 \r
            default:\r
             break;\r
diff --git a/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testgyro.cpp b/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testgyro.cpp
new file mode 100644 (file)
index 0000000..acc799f
--- /dev/null
@@ -0,0 +1,301 @@
+#include "wearable_log.h"
+#include "custom_utils.h"
+#include "producttest/include/testPresenter.h"
+
+#include "cmsis_os2.h"
+#include "producttest/include/testView.h"
+#include "producttest/include/testgyro.h"
+// #include "gnss_sample.h"
+#include "graphic_service.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C"
+{
+#endif
+#endif
+#ifdef ENABLE_GYRO
+#include "gyro_service.h"
+#include "gyro_hal.h"
+#endif
+
+#ifdef ROTARYENCODER_MIXO
+#include "mixo_service.h"
+#endif
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+
+
+
+namespace OHOS
+{
+
+    static testgyroView *g_pSystemAboutTheWatchView{nullptr};
+
+    testgyroView::testgyroView()
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemAboutTheWatchView::SystemAboutTheWatchView");
+        g_pSystemAboutTheWatchView = this;
+    }
+
+    testgyroView::~testgyroView()
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "testgyroView::~testgyroView");
+        ClearAll();
+        //g_pSystemAboutTheWatchView = nullptr;
+    }
+
+    testgyroView *testgyroView::GetInstance()
+    {
+
+        return g_pSystemAboutTheWatchView;
+    }
+    static osTimerId_t  P_TEST_timer=NULL;
+
+    void testgyroView::ClearAll()
+    {
+#ifdef ENABLE_GYRO
+        gyro_stop();
+#ifdef ROTARYENCODER_MIXO
+        do_mixo_service_check_msg(MIXO_SERVICE_CMD_START_CHECK);
+#endif
+#endif
+        if(testgyroScrollView)
+        {
+            testgyroScrollView->RemoveAll();
+
+            if (P_TEST_timer != NULL) {
+                osTimerStop(P_TEST_timer);
+                osTimerDelete(P_TEST_timer);
+                P_TEST_timer = NULL;
+            }
+            if(labelButton_next)
+            {
+                delete labelButton_next;
+                labelButton_next=nullptr;
+            }
+            if(label_1_MSG)
+            {
+                delete label_1_MSG;
+                label_1_MSG=nullptr;
+            }
+
+            if(label_2_MSG)
+            {
+                delete label_2_MSG;
+                label_2_MSG=nullptr;
+            }
+
+            if(label_3_MSG)
+            {
+                delete label_3_MSG;
+                label_3_MSG=nullptr;
+            }
+
+            if(Title)
+            {
+                delete Title;
+                Title=nullptr;
+            }
+        
+            delete testgyroScrollView;
+            testgyroScrollView=nullptr;
+       }
+    }
+   
+    UILabelButtonExt *testgyroView::SetTheButton_ext(ButtonConfig_ext_t &buttonconfig)
+    {
+        UILabelButtonExt *button = new UILabelButtonExt();
+        if (button == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, " SystemView::SetTheButton: button new  fail!");
+            return nullptr;
+        }
+        button->SetPosition(buttonconfig.x, buttonconfig.y, buttonconfig.w, buttonconfig.h);
+        button->SetViewId(buttonconfig.ViewId);
+        button->SetStyle(STYLE_BACKGROUND_COLOR, Color::Blue().full);
+        //button->SetStyle(STYLE_BORDER_RADIUS,0);
+        button->SetStyleForState(STYLE_BACKGROUND_COLOR, Color::Black().full, UIButton::PRESSED);
+        //button->SetStyleForState(STYLE_BORDER_RADIUS,0, UIButton::PRESSED);
+        button->SetTouchable(true);
+        button->SetStyle(STYLE_BACKGROUND_OPA, 0x80);
+        button->SetText(buttonconfig.str);
+        button->SetAlign(TEXT_ALIGNMENT_LEFT);
+        button->SetLabelPosition(buttonconfig.label_x,buttonconfig.label_y );
+        button->SetFont(DEFAULT_VECTOR_FONT_FILENAME_EN, buttonconfig.Fontsize);
+        UIView:: OnClickListener *touchListener = static_cast<UIView::OnClickListener *>(testPresenter::GetInstance());
+        button->SetOnClickListener(touchListener);
+
+        return button;
+    }
+   
+     UILabel *testgyroView::InitLabel(LabelConfig &labelConfig)
+    {
+        UILabel *label = new UILabel();
+        if (label == nullptr)
+        {
+            return nullptr;
+        }
+        label->SetPosition(labelConfig.left, labelConfig.top, labelConfig.width, labelConfig.height); // 位置大小
+        label->SetStyle(STYLE_TEXT_FONT, labelConfig.fontSize);                                       // 字体大小
+        label->SetStyle(STYLE_LINE_HEIGHT, labelConfig.lineHeigh);                                    // 字体行高
+        label->SetText(labelConfig.text);                                                             // 内容
+        label->SetLineBreakMode(labelConfig.lineBreakMode);                                           // 断行模式。
+        label->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_TOP);
+        label->SetFont(DEFAULT_VECTOR_FONT_FILENAME_EN, labelConfig.fontSize);
+        label->SetAlign(TEXT_ALIGNMENT_LEFT);
+        return label;
+    }
+    
+
+    void testgyroView:: gyrodataTimerCallBack(void)
+    {
+        //此处实现数据刷新
+        char buf1[32]={0};
+        char buf2[32]={0};
+        char buf3[32]={0};
+#ifdef ENABLE_GYRO
+        gyro_data_t data = gyro_get_data();
+
+        // printf("gyro.x:%.2f gyro.y:%.2f gyro.z:%.2f \n",data.x,data.y,data.z);
+
+        sprintf(buf1,"gyro.x:%.2f",data.x);
+        sprintf(buf2,"gyro.y:%.2f",data.y);
+        sprintf(buf3,"gyro.z:%.2f",data.z);
+#endif
+        label_1_MSG->SetText(buf1);
+        label_2_MSG->SetText(buf2);
+        label_3_MSG->SetText(buf3);
+        RootView::GetInstance()->Invalidate();
+    }
+
+    void gyrodataTimerCallBackproc()
+    {
+         GraphicService::GetInstance()->PostGraphicEvent(std::bind(&testgyroView::gyrodataTimerCallBack,testgyroView::GetInstance()));
+    }
+
+    
+    bool testgyroView::testgyroScrollViewcrollViewinit(uint8_t id)
+    {
+
+        testgyroScrollView = new UIScrollView();
+        if (testgyroScrollView == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemAboutTheWatchView::testgyroScrollView new fail!");
+            return false;
+        }
+        testgyroScrollView->SetPosition(0, 0, Screen::GetInstance().GetWidth(), Screen::GetInstance().GetHeight());
+        testgyroScrollView->SetStyle(STYLE_BACKGROUND_OPA, 0xff);
+        testgyroScrollView->SetStyle(STYLE_BORDER_RADIUS, 0);
+        testgyroScrollView->SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full);
+        testgyroScrollView->SetStyle(STYLE_BORDER_COLOR, Color::Yellow().blue);
+
+
+        UIView::OnDragListener *draglistener = static_cast<UIView::OnDragListener *>(testPresenter::GetInstance());
+        if (draglistener == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::draglistener can not be nullptr!");
+            return false;
+        }
+       testgyroScrollView->SetOnDragListener(draglistener);
+
+        LabelConfig Config = {
+            .left = 100,
+            .top = 100,
+            .width = 300,
+            .height = 35,
+            .fontSize = 40,
+            .lineHeigh = 35,
+            .text = "",
+            .lineBreakMode = UILabel::LINE_BREAK_WRAP,
+        };
+        label_1_MSG= InitLabel(Config);
+        if (label_1_MSG == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::SystemAboutTheWatchTitle new fail!");
+            return false;
+        }
+        testgyroScrollView->Add(label_1_MSG);
+
+        Config = {
+            .left = 100,
+            .top = 180,
+            .width = 300,
+            .height = 35,
+            .fontSize = 40,
+            .lineHeigh = 35,
+            .text = "",
+            .lineBreakMode = UILabel::LINE_BREAK_WRAP,
+        };
+        label_2_MSG= InitLabel(Config);
+        if (label_2_MSG == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::SystemAboutTheWatchTitle new fail!");
+            return false;
+        }
+        testgyroScrollView->Add(label_2_MSG);
+
+        Config = {
+            .left = 100,
+            .top = 260,
+            .width = 300,
+            .height = 35,
+            .fontSize = 40,
+            .lineHeigh = 35,
+            .text = "",
+            .lineBreakMode = UILabel::LINE_BREAK_WRAP,
+        };
+        label_3_MSG= InitLabel(Config);
+        if (label_3_MSG == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::SystemAboutTheWatchTitle new fail!");
+            return false;
+        }
+        testgyroScrollView->Add(label_3_MSG);
+
+        labelButton_next= testAboutView::GetInstance()->init_button_next(267,320,Test_ViewMapper_t[id].viewid_str_next);
+        testgyroScrollView->Add(labelButton_next);
+        
+        Title= testAboutView::GetInstance()->init_title(125,45,"GYRO_TEST");
+        testgyroScrollView->Add(Title);
+
+
+        testgyroScrollView->SetTouchable(true);
+        testgyroScrollView->SetDraggable(true);
+
+#ifdef ENABLE_GYRO
+#ifdef ROTARYENCODER_MIXO
+        do_mixo_service_check_msg(MIXO_SERVICE_CMD_STOP_CHECK);
+#endif
+        gyro_start();
+#endif
+
+        uint32_t tick;
+        osStatus_t retTimer;
+        P_TEST_timer = osTimerNew((osTimerFunc_t)gyrodataTimerCallBackproc, osTimerPeriodic, NULL, NULL);
+        tick =2000;// osMs2Tick(1000);
+        retTimer = osTimerStart(P_TEST_timer, tick);
+        if (retTimer != osOK && P_TEST_timer != NULL) {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"StartCallTimer osTimerStart failed, ret = %lx!!", retTimer);
+            osTimerDelete(P_TEST_timer);
+            P_TEST_timer = NULL;
+            return false;
+        }
+        return true;
+    }
+
+    UIScrollView *testgyroView::testgyroInitIView(uint8_t id)
+    {
+        if (!testgyroScrollViewcrollViewinit(id))
+        {
+            return nullptr;
+        }
+        return testgyroScrollView;
+    }
+}
+
+// #endif
index 70451e5..9ddd3d8 100644 (file)
@@ -34,7 +34,7 @@ namespace OHOS {
 std::unordered_map<uint16_t, std::string> registeredDials{
 #ifdef CUSTOM_Z1
     {DEFAULT_DIAL_ID_0, "Z1"},
-#elif BOARD_W9
+#elif BOARD_N9
     {DEFAULT_DIAL_ID_0, "N9"},        
 #else
     {DEFAULT_DIAL_ID_0, "KUMI"}, 
index 5c27ec4..779c63a 100644 (file)
@@ -267,7 +267,7 @@ namespace OHOS
             .lineHeigh = LABEL_LINEHEIGHT,\r
         #ifdef CUSTOM_Z1\r
             .text = "Z1",\r
-        #elif BOARD_W9\r
+        #elif defined(BOARD_W9) || defined(BOARD_N9)\r
             .text = "Watch N9",\r
         #else\r
             .text = "Watch Soar",\r
@@ -313,7 +313,7 @@ namespace OHOS
             .fontSize = LABEL_FONTSIZE,\r
             .lineHeigh = LABEL_LINEHEIGHT,\r
             #if defined(SUPPORT_CHINA_MOBILE_DMP) || defined(SUPPORT_TELECOM_DMP)\r
-                #ifdef BOARD_W9\r
+                #if defined(BOARD_W9) || defined(BOARD_N9)\r
                 .text = "Watch N9 V1.0",\r
                 #else\r
                 .text = "Watch Soar V1.0",\r
@@ -624,7 +624,7 @@ namespace OHOS
         SystemAboutTheWatchScrollView->Add(HWVERTitle);\r
         /* -------------------------------------------------------------------------- */\r
         char * versionstr;\r
-#ifdef BOARD_W9\r
+#if defined(BOARD_W9) || defined(BOARD_N9)\r
         versionstr= "Watch V1.0";\r
 #else\r
         versionstr= "FD230 V1.0";\r
index cf559e7..7c067c5 100644 (file)
@@ -101,7 +101,7 @@ namespace OHOS
         ProductModelName->SetStyle(STYLE_LINE_HEIGHT, 30);                // 字体行高\r
         #ifdef CUSTOM_Z1\r
         ProductModelName->SetText("Z1");                          // 内容\r
-        #elif BOARD_W9\r
+        #elif defined(BOARD_W9) || defined(BOARD_N9)\r
         ProductModelName->SetText("Watch N9");                          // 内容\r
         #else\r
         ProductModelName->SetText("Watch Soar");                          // 内容\r
index 3352341..b2ac61c 100644 (file)
@@ -1543,7 +1543,7 @@ static void svr_ble_bt_gatts_characteristic_add_cb(uint8_t server_id, bt_uuid_t
         ble_cywee_store_report_handle(result->value_handle);\r
         // }\r
 \r
-        ble_cywee_store_recv_handle(69);\r
+        ble_cywee_store_recv_handle(73);\r
     }\r
 #endif\r
     return;\r
@@ -2180,7 +2180,7 @@ static void blesrv_service_check_task(void const *arg)
         uint16_t server_handle = mail.service_handle;\r
         uint32_t msg_len = mail.msg_len;\r
 \r
-        // WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP,"mail.msg_data:%X,g_blesrv_queue:%d ble_recv:%d %d %02X %02X %02X mail.msg_data: %02X %02X %02X\r\n",\r
+        // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"mail.msg_data:%X,g_blesrv_queue:%d ble_recv:%d %d %02X %02X %02X mail.msg_data: %02X %02X %02X\r\n",\r
         //     mail.msg_data,\r
         //     g_blesrv_queue,\r
         //     msg_len,\r
index dc51b1a..a08ef4c 100644 (file)
@@ -35,7 +35,7 @@ extern uint16_t g_ble_server_handle;
 
 #ifdef CUSTOM_Z1
 #define BLE_DEFAULT_NAME  "Z1"//"
-#elif BOARD_W9
+#elif defined(BOARD_W9) || defined(BOARD_N9)
 #define BLE_DEFAULT_NAME  "WATCH N9"//"N9
 #else
 #define BLE_DEFAULT_NAME  "WATCH Soar"//"FD230
index 5353981..48ba468 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: penglei 1624952103@qq.com\r
  * @Date: 2024-06-17 14:31:08\r
  * @LastEditors: penglei 1624952103@qq.com\r
- * @LastEditTime: 2025-06-06 17:11:43\r
+ * @LastEditTime: 2025-06-13 16:15:04\r
  * @FilePath: /FD230/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.c\r
  * @Description: \r
  * \r
@@ -2066,7 +2066,86 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint
                         &send_data,\r
                         1);\r
             }\r
+        case BLE_TEST_CMD_SOFT_TEST_SUB_MODE_GPS:\r
 \r
+            if (testitem == 0x01)\r
+            {\r
+                //定位\r
+                uint8_t send_data = 0;\r
+                bool flag = 0;\r
+                char tmp[1024]={0};\r
+                char time[10]={0};\r
+#ifdef SUPPORT_GNSS\r
+                gnss_start();\r
+                LOS_Msleep(100);\r
+                do{\r
+                    gps_data_t *gps_data = getGPSGlobaldata();\r
+                    if(gps_data == NULL)\r
+                    {\r
+                        PRINT("gps_data == NULL \n");\r
+                        return;\r
+                    }\r
+                    if (gps_data->last_gps_time_ms > 0)\r
+                    {\r
+                        memcpy_s(&send_gps_data,sizeof(gps_data_t),gps_data,sizeof(gps_data_t));\r
+                    }\r
+                    if(send_gps_data.status > 1)\r
+                    {\r
+                        flag = 1;\r
+                    }\r
+                    else\r
+                    {\r
+                        LOS_Msleep(1000);\r
+                        send_data++;\r
+                    }\r
+                    memset_s(tmp,sizeof(tmp),0,sizeof(tmp));        \r
+                    dump_location_data_to_factory(&send_gps_data,tmp,sizeof(tmp));\r
+                    memset_s(time,sizeof(time),0,sizeof(time));  \r
+                    sprintf_s(time,sizeof(time),"%d",send_data);\r
+                    strcat_s(tmp,sizeof(tmp),time);\r
+                    PRINT("send_gps_data.status : %d time : %d\n",send_gps_data.status,send_data);\r
+                    PRINT("tmp : %s size : %d\n",tmp,strlen(tmp));\r
+                    factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
+                        BLE_TEST_CMD_SOFT_TEST_SUB_MODE_GPS,\r
+                        0x01,\r
+                        (uint8_t*)tmp,\r
+                        strlen(tmp));\r
+                }while(send_data <= 2 * 60 && !flag);\r
+                // PRINT("定位超时 关闭GPS\n");\r
+                gnss_stop();\r
+#endif\r
+\r
+            } else if(testitem == 0x02)\r
+            {\r
+                //获取可见星 有效星 信号增益 定位精度\r
+                uint8_t send_data[7] = {0};\r
+#ifdef SUPPORT_GNSS\r
+                // if(send_gps_data)\r
+                {\r
+                    send_data[0] = send_gps_data.num_sats;\r
+                    send_data[1] = send_gps_data.th001_valid_star_count;\r
+                    send_data[2] = send_gps_data.th000_signal_vga;\r
+                    send_data[3] = (uint8_t)(((uint32_t)send_gps_data.th001_quality & 0xFF000000) >> 24);\r
+                    send_data[4] = (uint8_t)(((uint32_t)send_gps_data.th001_quality & 0x00FF0000) >> 16);\r
+                    send_data[5] = (uint8_t)(((uint32_t)send_gps_data.th001_quality & 0x0000FF00) >> 8);\r
+                    send_data[6] = (uint8_t)(((uint32_t)send_gps_data.th001_quality & 0x000000FF) >> 0);\r
+\r
+                    // PRINT("gps_data->num_sats : %d,gps_data->th001_valid_star_count : %d,gps_data->th000_signal_vga : %d,gps_data->th001_quality : %f\n",\r
+                    // send_gps_data.num_sats,send_gps_data.th001_valid_star_count,\r
+                    // send_gps_data.th000_signal_vga,send_gps_data.th001_quality\r
+                    // );\r
+                    // PRINT("%2X %2X %2X\r\n",send_data[0],send_data[1],send_data[2]);\r
+                    // PRINT("%2X %2X %2X %2X \r\n",send_data[3],send_data[4],send_data[5],send_data[6]);\r
+                }\r
+#endif\r
+                factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST,\r
+                        BLE_TEST_CMD_SOFT_TEST_SUB_MODE_GPS,\r
+                        0x02,\r
+                        send_data,\r
+                        sizeof(send_data));\r
+            }\r
+\r
+            break;\r
             break;\r
 \r
         default:\r
@@ -2106,7 +2185,7 @@ errcode_t factorytest_protocol_decode(uint8_t *buf, uint16_t event_size)
                 \r
             printf("crc16 0x%04X vs 0x%04X\n",crc16,crc16_2);\r
 \r
-            if( crc16 == crc16_2) //校验通过,开始正式解析\r
+            // if( crc16 == crc16_2) //校验通过,开始正式解析\r
             {\r
                 if(factorytest_mode_flag == 0 && header.submod != BLE_TEST_CMD_COMMON_SUB_MODE_SWITCH_MODE)\r
                     return ERRCODE_FAIL;\r
index 4abd635..3a5d7ad 100644 (file)
@@ -93,6 +93,8 @@ extern "C" {
 #define BLE_TEST_CMD_SOFT_TEST_SUB_MODE_CAT1  0x1A
 //软件测试 子模式ID  SPEAKER
 #define BLE_TEST_CMD_SOFT_TEST_SUB_MODE_SPEAKER  0x1B
+//软件测试 子模式ID  GPS
+#define BLE_TEST_CMD_SOFT_TEST_SUB_MODE_GPS  0x1D
 //软件测试 子模式ID  通讯录
 #define BLE_TEST_CMD_SOFT_TEST_SUB_MODE_CONTACTS  0x30
 //软件测试 子模式ID  支付宝
diff --git a/code/sdk/application/wearable/service/msg_center/brandy-native-js-n9/libmsg_center.a b/code/sdk/application/wearable/service/msg_center/brandy-native-js-n9/libmsg_center.a
new file mode 100644 (file)
index 0000000..d541fd8
Binary files /dev/null and b/code/sdk/application/wearable/service/msg_center/brandy-native-js-n9/libmsg_center.a differ
index f6543ab..f5b4e6d 100755 (executable)
@@ -1986,7 +1986,7 @@ uint32_t cat1_on(uint8_t *data, uint32_t data_len)
 \r
     errcode_t ret=0;\r
 \r
-#if defined (BOARD_L22) || defined (BOARD_W9)\r
+#if defined (BOARD_W9) || defined (BOARD_N9)\r
     ret=uapi_gpio_set_dir(S_AGPIO_L23,GPIO_DIRECTION_OUTPUT);\r
     if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L23,GPIO_DIRECTION_OUTPUT ret %d\n",ret);\r
     // ret=uapi_gpio_set_dir(S_AGPIO_L28,GPIO_DIRECTION_OUTPUT);\r
index 890878b..0820943 100755 (executable)
@@ -544,24 +544,25 @@ target = {
                     '-:ROTARYENCODER_HX3507',
                     '-:BOARD_FD230',
                     'BOARD_W9',
-                    # 'SUPPORT_GNSS',
-                    # 'DISABLE_UART_LOG',
-                    # 'CONFIG_GNSS_UART_WITH_FLOWCTRL',
-                    # 'DOWNLOAD_GNSS_SWITCH',
+                    'SUPPORT_GNSS',
+                    'DISABLE_UART_LOG',
+                    'CONFIG_GNSS_UART_WITH_FLOWCTRL',
+                    'DOWNLOAD_GNSS_SWITCH',
                     'TPTYPE_CST86XX',
                     'NANDFLASH_F35UQA',
-                    #'PPG_GH3X2X',
+                    'PPG_GH3X2X',
                     'GYRO_SH5001',
                     'ROTARYENCODER_MIXO',
+                    'ENABLE_BN02',
+                    'ENABLE_GYRO',
                     ],
                'ram_component': [
                         "gnss",
                         "gnss_sample",
-                        #"ppg_sensor_gh3x2x",
-                        "ppg_sensor_pah8009",
-                        #"bp_sensor",
-                        #'gyro',
-                        'ppg_hal',
+                        "ppg_sensor_gh3x2x",
+                        #"ppg_sensor_pah8009",
+                        "bp_sensor",
+                        'gyro',
                            ],
                'image_analysis': False,
                'fs_image_path':'w9',
@@ -586,6 +587,58 @@ target = {
             'NANDFLASH_F35UQA'            
         ]
     },
+
+    ################# n9 ############################
+    'brandy-native-js-n9': {
+        'base_target_name': 'brandy-native-js',
+        'defines': [
+                    '-:TPTYPE_FT6X46',
+                    '-:PPG_HX3695',
+                    '-:ROTARYENCODER_HX3507',
+                    '-:BOARD_FD230',
+                    'BOARD_N9',
+                    'SUPPORT_GNSS',
+                    'DISABLE_UART_LOG',
+                    'CONFIG_GNSS_UART_WITH_FLOWCTRL',
+                    'DOWNLOAD_GNSS_SWITCH',
+                    'TPTYPE_CST86XX',
+                    'NANDFLASH_F35UQA',
+                    #'PPG_GH3X2X',
+                    'GYRO_SH5001',
+                    'ROTARYENCODER_MIXO',
+                    'ENABLE_GYRO',
+                    ],
+               'ram_component': [
+                        "gnss",
+                        "gnss_sample",
+                        #"ppg_sensor_gh3x2x",
+                        "ppg_sensor_pah8009",
+                        #"bp_sensor",
+                        'gyro',
+                           ],
+               'image_analysis': False,
+               'fs_image_path':'n9',
+               'fs_image': True
+    },
+    'brandy-native-js-n9-r': {
+        'base_target_name': 'brandy-native-js-r',
+        #自定义配置项,选择硬件及功能参数
+        'defines': [
+            '-:TPTYPE_FT6X46',
+            'BOARD_N9',
+            'TPTYPE_CST86XX',
+            'NANDFLASH_F35UQA'
+        ],
+    },
+    'brandy-native-js-n9-ssb': {
+        'base_target_name': 'brandy-ssb',
+        #自定义配置项,选择硬件及功能参数
+        'defines': [
+            'BOARD_N9',
+            'GPIO_POWERON_FLASH',
+            'NANDFLASH_F35UQA'            
+        ]
+    },
 }
 
 target_group = {
@@ -608,6 +661,7 @@ target_group = {
     'pack_brandy_native_js_cm_ai': ['brandy-ssb', 'brandy-native-js-r', 'brandy-native-js-cm-ai'],
     'pack_brandy_native_js_4part': ['brandy-ssb', 'brandy-native-js-r-4part', 'brandy-native-js-4part'],
     'pack_brandy_native_js_w9': ['brandy-native-js-w9-ssb', 'brandy-native-js-w9-r', 'brandy-native-js-w9'],
+    'pack_brandy_native_js_n9': ['brandy-native-js-n9-ssb', 'brandy-native-js-n9-r', 'brandy-native-js-n9'],
     'pack_brandy_native_js_fd230': ['brandy-native-js-fd230-ssb', 'brandy-native-js-fd230-r', 'brandy-native-js-fd230'],
     'pack_brandy_xts': ['brandy-ssb', 'brandy-xts-r', 'brandy-xts'],
     'pack_brandy_native_js_oob128': ['brandy-ssb-oob128', 'brandy-native-js-r', 'brandy-native-js-oob128'],
index 71c2ea6..ed297d1 100644 (file)
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ccaf8aeb2a73734a10631405e462da7529ef592dc1f81403d60c1c5ebc373f4f
-size 43967616
+oid sha256:f45854c84d2648a7f2b51f9bddb38f3963f88ef15af8dc921be0b8be760c2a64
+size 43963392
index e31ef77..5a60880 100644 (file)
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:534b215d45d9485abe3a0307c18fb36e299383d8dedc8956d59587c02b8cdcac
-size 43967616
+oid sha256:ae52e6e007867f07fe7d782db762d39686fa952adbecdf7fc232aea2f1023191
+size 43963392
index 71c2ea6..de65c42 100644 (file)
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ccaf8aeb2a73734a10631405e462da7529ef592dc1f81403d60c1c5ebc373f4f
-size 43967616
+oid sha256:a317e355903aa113ed57ca69838e97c5e6edf1f9cbe9b22b0f7e91de60c9ad53
+size 43963392
index e31ef77..2ab92f1 100644 (file)
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:534b215d45d9485abe3a0307c18fb36e299383d8dedc8956d59587c02b8cdcac
-size 43967616
+oid sha256:7e383c66b84c89fb165eba71148fec946526964e9469ed0c4b7d679d057480dc
+size 43963392
index a474299..92725bf 100644 (file)
@@ -96,13 +96,8 @@ const hal_pio_config_t g_pio_function_config[PIN_MAX_NUMBER] = {
     { HAL_PIO_FUNC_EMMC, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },   // S_HGPIO15 emmc clk
 #endif
     { HAL_PIO_FUNC_SPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_MGPIO0   NC
-#ifdef BOARD_W9
     { HAL_PIO_FUNC_I2C2_M3, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },  // S_MGPIO1 I2C2 SCL Sensor 6轴 指南针 心率
     { HAL_PIO_FUNC_I2C2_M3, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },  // S_MGPIO2 I2C2 SDA Sensor
-#else
-    { HAL_PIO_FUNC_SPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_MGPIO1   NC
-    { HAL_PIO_FUNC_SPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_MGPIO2   NC
-#endif
     { HAL_PIO_FUNC_SPI0, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },    // S_MGPIO3   NC
 
 // #if (defined BRANDY_PRODUCT_EVB4)
@@ -122,13 +117,8 @@ const hal_pio_config_t g_pio_function_config[PIN_MAX_NUMBER] = {
     { HAL_PIO_FUNC_I2C0_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE }, // S_MGPIO12 I2C0 SDA
     { HAL_PIO_FUNC_I2C1_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE }, // S_MGPIO13 I2C1 SCL touch i2c
     { HAL_PIO_FUNC_I2C1_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE }, // S_MGPIO14  I2C1 SDA
-#ifdef BOARD_W9
     { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },  // S_MGPIO15 I2C2 SCL Sensor 6轴 指南针 心率
     { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },  // S_MGPIO16 I2C2 SDA Sensor
-#else
-    { HAL_PIO_FUNC_I2C2_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },  // S_MGPIO15 I2C2 SCL Sensor 6轴 指南针 心率
-    { HAL_PIO_FUNC_I2C2_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE },  // S_MGPIO16 I2C2 SDA Sensor
-#endif
     { HAL_PIO_FUNC_I2C3_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_MGPIO17 i2c3 SCL    smart pa\ 预留马达控制 \安全芯片
     { HAL_PIO_FUNC_I2C3_M1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },   // S_MGPIO18  I2C3 SDA
     { HAL_PIO_FUNC_UART1, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_DISABLE },    // S_MGPIO19 uart1 tx
@@ -225,7 +215,11 @@ const hal_pio_config_t g_pio_function_config[PIN_MAX_NUMBER] = {
 //   #else
     { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_DOWN, HAL_PIO_IE_DISABLE },   // S_AGPIO_R2     VIBR_PWM 马达控制脚 兼容预留马达驱动复位脚
 //   #endif
-    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE  },   // S_AGPIO_R3     NC   
+#ifdef BOARD_N9
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_ENBALE  },   // S_AGPIO_R3     NC   
+#else
+    { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE  }, 
+#endif
     { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_UP, HAL_PIO_IE_DISABLE  },    // S_AGPIO_R4     tp reset
     { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE  },   // S_AGPIO_R5     touch int
     { HAL_PIO_FUNC_GPIO, HAL_PIO_DRIVE_MAX, HAL_PIO_PULL_MAX, HAL_PIO_IE_ENBALE },    // S_AGPIO_R6     PRG_INT 心率中断
index 861e30c..504a0a9 100755 (executable)
@@ -369,7 +369,11 @@ static const system_mcu_perip_clk_t g_system_mcu_perp_clk_set_config[] = {
     {HAL_CLOCKS_APP_SPI2_MS_CLK, TURN_OFF},       // spi2 clock
     {HAL_CLOCKS_APP_UART_H0_CLK, TURN_ON},        // uart h0 clock
     {HAL_CLOCKS_APP_UART_H1_CLK, TURN_ON},        // uart h1 clock
+#ifdef BOARD_W9
+    {HAL_CLOCKS_APP_I2C0_CLK, TURN_ON},          // i2c0 clock
+#else
     {HAL_CLOCKS_APP_I2C0_CLK, TURN_OFF},          // i2c0 clock
+#endif
     {HAL_CLOCKS_APP_I2C1_CLK, TURN_ON},           // i2c1 clock
     {HAL_CLOCKS_APP_I2C2_CLK, TURN_ON},          // i2c2 clock
     {HAL_CLOCKS_APP_I2C3_CLK, TURN_ON},          // i2c3 clock
index aa54159..17856db 100755 (executable)
@@ -13,7 +13,7 @@
 #include "board_fpga.h"
 #elif PRE_ASIC
 
-#if defined(BOARD_W9)
+#if defined(BOARD_W9) || defined(BOARD_N9)
 #include "board_w9.h"
 #else
 #include "board_evb.h"
index 76a9af1..b1a8bd2 100644 (file)
@@ -21,3 +21,5 @@ add_subdirectory_if_exist(cywee)
 add_subdirectory_if_exist(a5133)
 add_subdirectory_if_exist(entest)
 add_subdirectory_if_exist(gnss)
+add_subdirectory_if_exist(bp)
+add_subdirectory_if_exist(gyro)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/bp/CMakeLists.txt b/code/sdk/drivers/peripheral/bp/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7ae07b3
--- /dev/null
@@ -0,0 +1,53 @@
+#===============================================================================
+# @brief    cmake file
+# Copyright (c) @CompanyNameMagicTag 2022-2023. All rights reserved.
+#===============================================================================
+set(COMPONENT_NAME "bp_sensor")
+
+set(SOURCES
+    ${CMAKE_CURRENT_SOURCE_DIR}/bn02/bn02.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/service/bp_at_cmd.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/service/bp_service.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/service/bp_ble_service.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/service/bp_tcp_server.c
+
+)
+
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}/bn02/
+    ${CMAKE_CURRENT_SOURCE_DIR}/service/
+    ${CMAKE_CURRENT_SOURCE_DIR}/lib/
+)
+
+set(PRIVATE_HEADER
+)
+
+set(PRIVATE_DEFINES
+    TARGET_NAME="${TARGET_COMMAND}"
+    BUILD_TIME="${BUILD_TIME}"
+)
+
+set(PUBLIC_DEFINES
+SUPPORT_AT_BP
+ENABLE_BN02
+)
+
+# use this when you want to add ccflags like -include xxx
+set(COMPONENT_PUBLIC_CCFLAGS
+)
+
+set(COMPONENT_CCFLAGS
+)
+
+set(WHOLE_LINK
+    true
+)
+
+set(MAIN_COMPONENT
+    false
+)
+
+find_library(LIB_PATH_BP lib/lib_hr_yll_v0.5.3.060325.a ${CMAKE_CURRENT_SOURCE_DIR})
+target_link_libraries(${TARGET_NAME} PRIVATE -Wl,--whole-archive ${LIB_PATH_BP} PRIVATE -Wl,--whole-archive)
+
+build_component()
diff --git a/code/sdk/drivers/peripheral/bp/bn02/bn02.c b/code/sdk/drivers/peripheral/bp/bn02/bn02.c
new file mode 100644 (file)
index 0000000..11a95ef
--- /dev/null
@@ -0,0 +1,260 @@
+/*\r
+ * @Author: penglei 1624952103@qq.com\r
+ * @Date: 2025-01-16 12:35:15\r
+ * @LastEditors: penglei 1624952103@qq.com\r
+ * @LastEditTime: 2025-06-12 16:37:28\r
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/bp/bn02/bn02.c\r
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE\r
+ */\r
+#include "stdint.h"\r
+#include "bn02.h"\r
+#include "custom_utils.h"\r
+#include "pinctrl_porting.h"\r
+#include "hal_gpio.h"\r
+#include "i2c.h"\r
+#include "pm_definition.h"\r
+#include "bp_ble_service.h"\r
+#include "bp_tcp_server.h"\r
+\r
+\r
+#define BN02_I2C_ADDR 0x05\r
+#define BN02_I2C_BUS I2C_BUS_0\r
+#define I2C_ADDR_BN02_W      0x0a\r
+#define I2C_ADDR_BN02_R      0x0b\r
+#define P_EN          S_AGPIO_L24\r
+#define P_INT         S_AGPIO_R3\r
+\r
+#define POWER_EN      S_AGPIO_R0\r
+\r
+#define BN02_FILE "user/userdata/bn02.bin"\r
+\r
+static int DATA_HANDLE = 1 << 24;\r
+\r
+static FILE *fp = NULL;\r
+\r
+static int data_cnt = 0;\r
+// static int data[16 * 5 * 60] = {0};\r
+\r
+// int data = ((rxByte[i] & 0xff) << 16)\r
+//         + ((rxByte[i + 1] & 0xff) << 8)\r
+//         + (rxByte[i + 2] & 0xff);\r
+// if (data >= DATA_HANDLE / 2) {\r
+//     data -= DATA_HANDLE;\r
+// }\r
+// 其中:DATA_HANDLE = 2^24\r
+\r
+\r
+bool Bn02_write_reg(uint8_t data)\r
+{\r
+       uint8_t cnt = pm_veto_get_id_cnt(PM_ID_BP);\r
+    if (cnt == 0) \r
+    {\r
+        uapi_pm_add_sleep_veto(PM_ID_BP);\r
+    }\r
+\r
+       i2c_data_t i2c_data;\r
+       i2c_data.send_buf = &data;\r
+    i2c_data.send_len = sizeof(data);\r
+    i2c_data.receive_buf = NULL;\r
+    i2c_data.receive_len = 0;\r
+       // custom_i2c_write_reg(BN02_I2C_ADDR, 0x00, 1, &data, 1, BN02_I2C_BUS);\r
+       errcode_t ret = uapi_i2c_master_write(BN02_I2C_BUS, BN02_I2C_ADDR, &i2c_data);\r
+       if (ret != ERRCODE_SUCC)\r
+        printf("i2c Write data write fail! ret=0x%x\n", ret);\r
+\r
+       cnt = pm_veto_get_id_cnt(PM_ID_BP);\r
+    if (cnt == 1) \r
+    {\r
+        uapi_pm_remove_sleep_veto(PM_ID_BP);\r
+    }\r
+\r
+    return 1;\r
+}\r
+\r
+bool Bn02_reads(uint8_t *data,int len)\r
+{\r
+\r
+       uint8_t cnt = pm_veto_get_id_cnt(PM_ID_BP);\r
+    if (cnt == 0) \r
+    {\r
+        uapi_pm_add_sleep_veto(PM_ID_BP);\r
+    }\r
+\r
+       i2c_data_t i2c_data;\r
+       i2c_data.send_buf = NULL;\r
+    i2c_data.send_len = 0;\r
+    i2c_data.receive_buf = data;\r
+    i2c_data.receive_len = len;\r
+       // custom_i2c_write_reg(BN02_I2C_ADDR, 0x00, 1, &data, 1, BN02_I2C_BUS);\r
+       errcode_t ret = uapi_i2c_master_read(BN02_I2C_BUS, BN02_I2C_ADDR, &i2c_data);\r
+       if (ret != ERRCODE_SUCC) \r
+        printf("i2c read data fail! ret=0x%x\n", ret);\r
+\r
+       cnt = pm_veto_get_id_cnt(PM_ID_BP);\r
+    if (cnt == 1) \r
+    {\r
+        uapi_pm_remove_sleep_veto(PM_ID_BP);\r
+    }\r
+\r
+       return 1;\r
+}\r
+\r
+static void delay_ms(int cnt)\r
+{\r
+       LOS_Mdelay(cnt);\r
+}\r
+\r
+void Bn02_Power_Ctrl(int onoff)\r
+{\r
+    if(onoff == 1)\r
+       {\r
+               uapi_pin_set_mode(POWER_EN, (pin_mode_t)HAL_PIO_FUNC_GPIO);\r
+               uapi_gpio_set_dir(POWER_EN, GPIO_DIRECTION_OUTPUT);\r
+               uapi_gpio_set_val(POWER_EN, GPIO_LEVEL_HIGH);\r
+               LOS_Mdelay(1);\r
+               uapi_pin_set_mode(P_EN, (pin_mode_t)HAL_PIO_FUNC_GPIO);\r
+               uapi_gpio_set_dir(P_EN, GPIO_DIRECTION_OUTPUT);\r
+               uapi_gpio_set_val(P_EN, GPIO_LEVEL_HIGH);\r
+               // delay_ms(20);\r
+               LOS_Mdelay(50);\r
+       }\r
+       else\r
+       {\r
+               uapi_pin_set_mode(P_EN, (pin_mode_t)HAL_PIO_FUNC_GPIO);\r
+               uapi_gpio_set_dir(P_EN, GPIO_DIRECTION_OUTPUT);\r
+               uapi_gpio_set_val(P_EN, GPIO_LEVEL_LOW);\r
+\r
+               uapi_pin_set_mode(POWER_EN, (pin_mode_t)HAL_PIO_FUNC_GPIO);\r
+               uapi_gpio_set_dir(POWER_EN, GPIO_DIRECTION_OUTPUT);\r
+               uapi_gpio_set_val(POWER_EN, GPIO_LEVEL_LOW);\r
+       }\r
+}\r
+\r
+void bn02_int_init(void)\r
+{\r
+       uapi_pin_set_ie(P_INT,HAL_PIO_IE_ENBALE);\r
+}\r
+\r
+void bn02_int_deinit(void)\r
+{\r
+       uapi_pin_set_ie(P_INT,HAL_PIO_IE_DISABLE);\r
+}\r
+\r
+void bn02_int_handle(void)\r
+{\r
+    uint8_t bn02_buf[48] = {0};\r
+       int i;\r
+       memset(bn02_buf,0,sizeof(bn02_buf));\r
+       Bn02_reads(bn02_buf,48);\r
+       int reply_data[16] = {0}; \r
+       int cnt = 0;\r
+       for(i = 0;i<48;i+=3,cnt++)\r
+       {\r
+               reply_data[cnt] = ((bn02_buf[i] & 0xff) << 16)\r
+        + ((bn02_buf[i + 1] & 0xff) << 8)\r
+        + (bn02_buf[i + 2] & 0xff);\r
+\r
+               if (reply_data[cnt] >= DATA_HANDLE / 2)\r
+                       reply_data[cnt] -= DATA_HANDLE;\r
+\r
+               printf("111data[%d]:%d\n",cnt,reply_data[cnt]);\r
+               // printf("0x%x 0x%x 0x%x 0x%x\n",i,bn02_buf[i],bn02_buf[i+1],bn02_buf[i+2],reply_data[cnt]);\r
+       }\r
+\r
+    // if(bn02_get_ble_status())\r
+    // {\r
+    //     bn02_replymsg(reply_data,cnt,1);\r
+    // }\r
+\r
+       // if(fp)\r
+       // {\r
+       //      data_cnt += cnt;\r
+       //      if(fwrite(bn02_buf,sizeof(int),cnt,fp) != cnt)\r
+       //              printf("bn02 fwrite failed\n");\r
+       //      else\r
+       //              printf("bn02 fwrite succed data_cnt:%d\n",cnt);\r
+       // }\r
+\r
+\r
+       // printf("data_cnt:%d\n",data_cnt);\r
+\r
+       \r
+       do_bp_tcp_server_send_data((void *)reply_data,cnt);\r
+\r
+       // if(data_cnt >= 16 * 5 * 60 && fp)\r
+       // {\r
+       //      int *data_array  = (int *)malloc(data_cnt * sizeof(int));\r
+\r
+       //      if (!data_array) \r
+       //      {\r
+       //              printf("内存分配失败\n");\r
+       //      }\r
+       //      else \r
+       //      {\r
+       //              int read_count = 0;\r
+\r
+       //              fseek(fp, 0, SEEK_SET);\r
+\r
+       //              while (read_count < data_cnt && fread(&data_array[read_count], sizeof(int), 1, fp) == 1)\r
+       //              {\r
+       //                      printf("%d ", data_array[read_count]);\r
+       //                      read_count++;\r
+                               \r
+       //                      if (read_count % 10 == 0)\r
+       //                              printf("\n");\r
+       //              }\r
+                               \r
+       //              printf("\n实际读取数据: %d 个\n", read_count);\r
+                       \r
+       //              if (feof(fp))\r
+       //                      printf("已读取所有数据\n");\r
+       //              else if (ferror(fp)) \r
+       //              {\r
+       //                      printf("读取数据时发生错误\n");\r
+       //                      free(data_array);\r
+       //                      data_array = NULL;\r
+       //              }\r
+\r
+\r
+                       // free(data_array);\r
+                       // data_array = NULL;\r
+                       \r
+                       // // 清空文件内容(将文件指针移到文件开头并截断文件)\r
+                       // fclose(fp);  // 关闭文件\r
+                       // if(remove(BN02_FILE) != 0)\r
+                       //      printf("remove %s failed\n",BN02_FILE);\r
+                       // else\r
+                       //      printf("remove %s succed\n",BN02_FILE);\r
+\r
+                       // bn02_stop();\r
+               // } \r
+       // } \r
+    \r
+}\r
+\r
+void bn02_start(void)\r
+{\r
+       Bn02_Power_Ctrl(1);\r
+       bn02_int_init();\r
+       Bn02_write_reg(BN02_START_CMD);\r
+       // data_cnt = 0;\r
+       // fp = fopen(BN02_FILE, "ab+");\r
+       // if(fp == NULL)\r
+       //      printf("open %s failed\n",BN02_FILE);\r
+       // else\r
+       //      printf("open %s succed\n",BN02_FILE);\r
+}\r
+\r
+void bn02_stop(void)\r
+{\r
+       bn02_int_deinit();\r
+       Bn02_write_reg(BN02_STOP_CMD);\r
+       Bn02_Power_Ctrl(0);\r
+\r
+       bp_tcp_data_clean();\r
+       // if(fp)\r
+       // {\r
+       //      fclose(fp);\r
+       //      fp = NULL;\r
+       // }\r
+}\r
diff --git a/code/sdk/drivers/peripheral/bp/bn02/bn02.h b/code/sdk/drivers/peripheral/bp/bn02/bn02.h
new file mode 100644 (file)
index 0000000..c4216a9
--- /dev/null
@@ -0,0 +1,32 @@
+/*\r
+ * @Author: penglei 1624952103@qq.com\r
+ * @Date: 2025-01-16 12:35:15\r
+ * @LastEditors: penglei 1624952103@qq.com\r
+ * @LastEditTime: 2025-01-16 14:55:48\r
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/bp/bn02/bn02.h\r
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE\r
+ */\r
+#ifndef _BN02_H_\r
+#define _BN02_H_\r
+\r
+enum\r
+{\r
+\r
+       BN02_INT_HANDLE,\r
+       BN02_INIT_ENABLE,\r
+       BN02_START,\r
+       BN02_POWER_DISABLE,\r
+       BN02_STOP,\r
+};\r
+\r
+#define BN02_START_CMD  0x04\r
+#define BN02_STOP_CMD   0x08\r
+\r
+void bn02_int_handle(void);\r
+\r
+void bn02_start(void);\r
+\r
+void bn02_stop(void);\r
+\r
+#endif // _HRS3300_H_\r
+\r
diff --git a/code/sdk/drivers/peripheral/bp/lib/lib_hr.h b/code/sdk/drivers/peripheral/bp/lib/lib_hr.h
new file mode 100644 (file)
index 0000000..f470a88
--- /dev/null
@@ -0,0 +1,150 @@
+#ifndef __LIB_EMOTION_H__\r
+#define __LIB_EMOTION_H__\r
+\r
+#ifdef __cplusplus\r
+extern "C"{\r
+#endif\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+\r
+#define SAMPLERATE 81          // sampling rate\r
+//#define SAMPLERATE 100\r
+#define SAMPLETIME 5           // sampling time (seconds) data of which will be processed every time\r
+#define EMOTIONTIME 60\r
+#define HRVTIME 300\r
+#define BPTIME 30\r
+#define DDTIME 20                      // measure duration of drinking degree\r
+#define SINGLETIME 5\r
+#define MAX_SLEEP_STATE 50\r
+\r
+\r
+/* Integer data types */\r
+#if ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) && \\r
+     (!defined(__ICC8051__) || (__ICC8051__ == 0)))\r
+#include <stdint.h>\r
+#else\r
+       typedef signed char int8_t;\r
+       typedef unsigned char uint8_t;\r
+       typedef signed short int16_t;\r
+       typedef unsigned short uint16_t;\r
+       typedef signed long int32_t;\r
+       typedef unsigned long uint32_t;\r
+       typedef unsigned long long uint64_t;\r
+#endif\r
+\r
+typedef struct\r
+{\r
+       short int x;\r
+       short int y;\r
+       short int z;\r
+} gsensor_data_t;\r
+\r
+typedef enum\r
+{\r
+       LS_STATE = 11,                          // light sleep\r
+       DS_STATE = 12,                          // deep sleep\r
+       REM_STATE = 2,                          // rapid eye movement\r
+} SLEEP_STATE_E;\r
+\r
+typedef struct\r
+{\r
+       uint16_t year;\r
+       uint8_t month;\r
+       uint8_t day;\r
+       uint8_t hour;\r
+       uint8_t minute;\r
+} sleep_time_t;\r
+\r
+typedef struct\r
+{\r
+       uint32_t duration;                      // the duration of corresponding state\r
+       SLEEP_STATE_E state;            // state\r
+} sleep_detail_data_t;\r
+\r
+typedef struct\r
+{\r
+       uint32_t total_sleep_time;                      // minutes\r
+       sleep_time_t begin_sleep_time;          // sleep_time_t\r
+       sleep_time_t end_sleep_time;\r
+       uint16_t state_count;                           // number of some sleep state\r
+       sleep_detail_data_t data[MAX_SLEEP_STATE];\r
+} sleep_data_t;\r
+\r
+typedef struct\r
+{\r
+       uint16_t hr;\r
+       uint32_t timestamp;             // timestamp in measuretime (s)\r
+} sleep_hr_t;\r
+\r
+\r
+typedef struct\r
+{\r
+       uint16_t sbp;\r
+       uint16_t dbp;\r
+       int32_t timestamp;              // timestamp in measuretime\r
+} bps_t;\r
+\r
+\r
+\r
+// base api (include callback function)\r
+typedef void (*extern_printf_cb_t)(const char* format, ...);\r
+unsigned int extern_printf_cb_reg(extern_printf_cb_t fun);\r
+int init_algorithm(unsigned char* buf, unsigned int len);\r
+\r
+\r
+// heart rate variability algorithm api (include callback function)\r
+typedef void (*extern_get_hr_run_time_cb_t)(int* type, int* sec);\r
+unsigned int extern_get_hr_run_time_cb_reg(extern_get_hr_run_time_cb_t fun);\r
+int get_hr(int data[], int datalen, int fs, int* hr);\r
+\r
+\r
+// emotion algorithm api\r
+int ppg_midvalue(int data[], int datalen, int fs, float Fm[25][8], int* fmlen);\r
+int get_emotion_pi(int data[], int datalen, int fs, int* emo, int* pi);\r
+int get_dd_index(int data[], int datalen, int fs, int* dd, int* hr);\r
+\r
+\r
+// blood pressure algorithm api\r
+int load_bp_model(unsigned char str_model[], const unsigned int str_model_len);\r
+int get_bp(int data[], int datalen, int fs, int* sbp, int* dbp);\r
+int load_gen_info(int height, int weight, int age, int gender);\r
+int get_bp_general(int data[], int datalen, int fs, int* sbp, int* dbp);\r
+\r
+\r
+// temperature algorithm api\r
+int get_core_temperature(int gender, int age, int weight, int height, int hr, float t_skin_0, float t_air, float phi_air, float* t_core);\r
+\r
+\r
+// sleep algorithm api (include callback function)\r
+typedef void (*extern_get_wear_state_cb_t)(uint8_t* worn);\r
+unsigned int extern_get_wear_state_cb_reg(extern_get_wear_state_cb_t fun);\r
+typedef void (*extern_get_inst_hr_cb_t)(uint8_t* hr, sleep_time_t* hr_time);\r
+unsigned int extern_get_inst_hr_cb_reg(extern_get_inst_hr_cb_t fun);\r
+void init_sleep_algo_ex(sleep_data_t* sdata, int gfs, int pfs);\r
+int get_sleep_data_ex(gsensor_data_t gdata[], const int glen, int pdata[], const int plen, const sleep_time_t curtime, sleep_data_t* sdata);\r
+\r
+\r
+// authentication api\r
+void request_validation(\r
+       const unsigned char fact[], const unsigned int fact_len,\r
+       const unsigned char imei[], const unsigned int imei_len,\r
+       unsigned char req_code[], unsigned int* req_code_len);\r
+\r
+int activate_algorithm(\r
+       const unsigned char req_code[], const unsigned int req_code_len,\r
+       const unsigned char key_code[], const unsigned int key_code_len);\r
+\r
+\r
+// version api\r
+void version_get_string(char* string, unsigned int* str_len);\r
+\r
+\r
+\r
+#ifdef __cplusplus  \r
+}\r
+#endif\r
+\r
+\r
+#endif\r
diff --git a/code/sdk/drivers/peripheral/bp/lib/lib_hr_yll_v0.5.3.060325.a b/code/sdk/drivers/peripheral/bp/lib/lib_hr_yll_v0.5.3.060325.a
new file mode 100644 (file)
index 0000000..65ce39c
Binary files /dev/null and b/code/sdk/drivers/peripheral/bp/lib/lib_hr_yll_v0.5.3.060325.a differ
diff --git a/code/sdk/drivers/peripheral/bp/lib/yyl_pfev01.h b/code/sdk/drivers/peripheral/bp/lib/yyl_pfev01.h
new file mode 100644 (file)
index 0000000..220ddea
--- /dev/null
@@ -0,0 +1,74 @@
+//\r
+// Created on 2021/12/22.\r
+//\r
+\r
+#ifndef YYLPFEV01_H\r
+#define YYLPFEV01_H\r
+\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <math.h>\r
+\r
+//#include "algo.h"\r
+\r
+#define OUTPUTDATALEN 120U\r
+#define LIMITEDPPGLEN 3000U\r
+#define LIMITOFMOTIONCAL 3\r
+\r
+\r
+ typedef struct\r
+ {\r
+       int32_t x;\r
+       int32_t y;\r
+       int32_t z;\r
+ }yylPFE_AxesData_t;\r
+\r
+ typedef struct\r
+ {\r
+       yylPFE_AxesData_t       axes;\r
+       int32_t                 ppgSample;\r
+ }yylPFE_InputData_t;\r
+\r
+\r
+#if 0\r
+typedef struct {\r
+    uint32_t         timestamp;\r
+    uint16_t         RRI;\r
+    uint32_t         areaUP;\r
+    uint16_t         areaUPBase;\r
+    uint16_t         areaUPHeight;\r
+    uint32_t         areaDOWN;\r
+    uint16_t         areaDOWNBase;\r
+    uint16_t         areaDOWNHeight;\r
+    uint16_t         motion;\r
+}yylPFE_OutputData;\r
+\r
+#else\r
+\r
+typedef struct {\r
+    uint32_t         timestamp;  \r
+    uint32_t         areaUP;\r
+    uint16_t         areaUPBase;\r
+    uint16_t         areaUPHeight;\r
+    uint32_t         areaDOWN;\r
+    uint16_t         areaDOWNBase;\r
+    uint16_t         areaDOWNHeight;\r
+    uint16_t         RRI;\r
+    uint16_t         motion;\r
+}yylPFE_OutputData;\r
+\r
+#endif\r
+// len >= 6870\r
+void YYL_Init_PFE(unsigned char* buf, unsigned int len);\r
+\r
+void YYL_Input_PFE(yylPFE_InputData_t *pInputData, int32_t hr);\r
+\r
+yylPFE_OutputData * YYL_Output_PFE(int32_t *outputLen);\r
+\r
+void YYL_Output_PFE_Array_Clear(void);\r
+\r
+char * YYL_PFE_Get_Current_Version(void);\r
+\r
+#endif //YYLPFEV01_H\r
diff --git a/code/sdk/drivers/peripheral/bp/service/bp_at_cmd.c b/code/sdk/drivers/peripheral/bp/service/bp_at_cmd.c
new file mode 100644 (file)
index 0000000..f9771b4
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-12-23 15:11:01
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-01-16 18:02:23
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/bp/HP4570/service/bp_at_cmd.c
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+#include "at_cmd_api.h"
+#include "pm_control.h"
+#include "debug_print.h"
+#include "bp_service.h"
+#include "custom_utils.h"
+
+#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
+#define BP_MAX_ARGC            8
+#define BP_MAX_ARGV_LEN        64
+
+#define BP_SUCCESS             0
+#define BP_FAILED              (-1)
+
+static int ConvertCmdToParam(uint8_t *para, uint32_t paraLen,
+        uint8_t argv[BP_MAX_ARGC][BP_MAX_ARGV_LEN], uint32_t* argc)
+{
+    uint32_t pos = 0;
+    *argc = 0;
+
+    for (uint32_t i = 0; i < paraLen; i++) {
+        if ((para[i] == ' ' || para[i] == '\n') && pos != 0) {
+            argv[*argc][pos] = '\0';
+            *argc += 1;
+            pos = 0;
+            if (*argc >= BP_MAX_ARGC) {
+                return BP_FAILED;
+            }
+        } else {
+            argv[*argc][pos] = para[i];
+            pos++;
+            if (pos >= BP_MAX_ARGV_LEN) {
+                return BP_FAILED;
+            }
+        }
+    }
+    if (pos != 0) {
+        *argc += 1;
+    }
+
+    return BP_SUCCESS;
+}
+
+static uint8_t g_bp_test_started = 0;
+static uint32_t bn02_test(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(strCommonCmd);
+    uint8_t argv[BP_MAX_ARGC][BP_MAX_ARGV_LEN] = { 0 };
+    uint32_t argc = 0;
+
+    int ret = ConvertCmdToParam(para, paraLen, argv, &argc);
+    if (ret != BP_SUCCESS) {
+        PRINT("BPTEST ATCMD Convert Command Failed\n");
+        return ERRCODE_FAIL;
+    }
+
+    if (argc != 1) {
+        PRINT("BPTEST ATCMD Set Parameter Failed argc %d\n",argc);
+        return ERRCODE_FAIL;
+    }
+    uint8_t start = (uint8_t)atoi((char*)argv[0]);
+    if (start == 1)
+    {
+        // if (g_bp_test_started == 1) 
+        // {
+        //     PRINT("SKIP bptest start, already start\r\n");
+        //     return 0;
+        // }
+        do_bp_service_check_msg(BP_SERVICE_CMD_START_CHECK);
+        g_bp_test_started = 1;
+    }else if (start == 2){
+        // if (g_bp_test_started == 0) 
+        // {
+        //     PRINT("SKIP bptest stop, already stopped\r\n");
+        //     return 0;
+        // }
+        do_bp_service_check_msg(BP_SERVICE_CMD_STOP_CHECK);
+        g_bp_test_started = 0 ;
+    }else if (start == 3){
+        // if (g_bp_test_started == 0) 
+        // {
+        //     PRINT("SKIP bptest stop, already stopped\r\n");
+        //     return 0;
+        // }
+        do_bp_service_check_msg(BP_SERVICE_CMD_TIMER_CHECK);
+        g_bp_test_started = 0 ;
+    }else{
+    }
+    return ERRCODE_SUCC;
+}
+static const at_cmd_table_t g_bp_cmd[] = {
+    { (char *)"AT^BN02TEST",      bn02_test, (char *)"1" },
+};
+
+at_cmd_table_t *get_bp_cmd_table(uint32_t *cmd_count)
+{
+    *cmd_count = ARRAY_COUNT(g_bp_cmd);
+    return (at_cmd_table_t *)g_bp_cmd;
+}
diff --git a/code/sdk/drivers/peripheral/bp/service/bp_at_cmd.h b/code/sdk/drivers/peripheral/bp/service/bp_at_cmd.h
new file mode 100644 (file)
index 0000000..3409d1d
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-12-18 10:23:22
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-01-16 15:07:33
+ * @FilePath: /sdk615/code/sdk/drivers/peripheral/rotary_encoder/hx3509/hx3509_at_cmd.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+/**
+ * Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved. \n
+ *
+ * Description: Provides at cmd register func \n
+ * Author: @CompanyNameTag \n
+ * History: \n
+ * 2022-07-20, Create file. \n
+ */
+#ifndef BP_AT_PROCESS_H
+#define BP_AT_PROCESS_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include "errcode.h"
+#include "soc_osal.h"
+#include "at_cmd_api.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+at_cmd_table_t *get_bp_cmd_table(uint32_t *cmd_count);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
diff --git a/code/sdk/drivers/peripheral/bp/service/bp_ble_service.c b/code/sdk/drivers/peripheral/bp/service/bp_ble_service.c
new file mode 100644 (file)
index 0000000..995dd8b
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2025-02-14 10:30:21
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-05-26 15:39:37
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/bp/service/bp_ble_service.c
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+#include "stdint.h"
+#include "bn02.h"
+#include "custom_utils.h"
+#include "bp_service.h"
+#include "bp_ble_service.h"
+#include "factorytestService.h"
+
+#define START_CODE 0x55
+#define PPG_DATA_SIZE 3
+#define PACKET_DATA_LENGTH (PPG_DATA_SIZE * 16)
+
+static uint8_t ble_status = 0;
+
+typedef struct ble_bp_data_t
+{
+    uint8_t start_code; //0x55
+    uint8_t main_func_code; //主功能码
+    uint8_t sub_func_code; //从功能码;
+    uint16_t  data_length; //标识和数据的长度之和
+    uint16_t flags; //标识
+    uint8_t* data;
+    uint8_t checksum; //验内容包括起始符、功能码、数据长度、标识、数据5个部分,取其和的最后8位作为校验和
+}ble_bp_data_t;
+
+
+static ble_bp_data_t ble_bp_data = {0};
+
+uint8_t bn02_get_ble_status(void)
+{
+    uint8_t status = ble_status;
+    return status;
+}
+
+uint8_t bn02_calculate_checksum(ble_bp_data_t frame) 
+{
+    uint8_t checksum = 0;
+    
+    checksum += frame.start_code;
+    
+    checksum += frame.main_func_code;
+    checksum += frame.sub_func_code;
+    
+    checksum += (frame.data_length >> 8) & 0xFF; // 高字节
+    checksum += frame.data_length & 0xFF;        // 低字节
+    
+    checksum += (frame.flags >> 8) & 0xFF;       // 高字节
+    checksum += frame.flags & 0xFF;              // 低字节
+    
+
+    for (uint16_t i = 0; i < (frame.data_length - 2); i++) {
+        checksum += frame.data[i];
+    }
+
+    checksum &= 0xFF;
+    
+    // printf("checksum : 0x%x\n", checksum);
+    return checksum;
+}
+
+errcode_t bn02_parse_frame(uint8_t *buf, uint16_t event_size)
+{
+    if(buf != NULL && event_size >= (1+2+2+2+1+1))
+    {
+        memset_s(ble_bp_data,0,sizeof(ble_bp_data),0);
+        
+        ble_bp_data.start_code = buf[0];
+        ble_bp_data.main_func_code =  buf[1];
+        ble_bp_data.sub_func_code = buf[2];
+        ble_bp_data.data_length = (buf[3] << 8) + buf[4];
+        ble_bp_data.flags = (buf[5] << 8) + buf[6];
+        ble_bp_data.data = &buf[7];
+
+        // printf("start_code : 0x%x, main_func_code : 0x%x, sub_func_code : 0x%x, data_length : 0x%x, flags : 0x%x, data : 0x%x\n",
+        // ble_bp_data.start_code,ble_bp_data.main_func_code,ble_bp_data.sub_func_code,ble_bp_data.data_length,ble_bp_data.flags,*ble_bp_data.data);
+
+        if(buf[8] != bn02_calculate_checksum(ble_bp_data))
+            return ERRCODE_FAIL;
+
+        ble_bp_data.sub_func_code += 0x80;
+
+        if(!(*ble_bp_data.data))
+        {
+            do_bp_service_check_msg(BP_SERVICE_CMD_START_CHECK);
+            ble_status = 1;
+        }
+
+        else
+        {   
+            do_bp_service_check_msg(BP_SERVICE_CMD_STOP_CHECK);
+            ble_status = 0;
+        }   
+
+
+    }
+    else
+    {
+        printf("buf is null or event_size < (1+2+2+2+1+1) \n");
+        return ERRCODE_FAIL;
+    }
+    return ERRCODE_SUCC;
+}
+
+errcode_t bn02_replymsg(uint8_t *input_data,uint16_t input_len,uint8_t flags)
+{
+    errcode_t ret;
+    ble_bp_data.data = input_data;
+    ble_bp_data.data_length = input_len + 2;
+
+    if((ble_bp_data.flags & 0x3FFF) < (1 << 14)) 
+        ble_bp_data.flags++;
+
+    if(flags) 
+    {
+        ble_bp_data.flags |= (1 << 15);
+    }
+
+    ble_bp_data.checksum = bn02_calculate_checksum(ble_bp_data);
+
+    // printf("start_code : 0x%x, main_func_code : 0x%x, sub_func_code : 0x%x, data_length : 0x%x, flags : 0x%x check_sum : 0x%x\n",
+    // ble_bp_data.start_code,ble_bp_data.main_func_code,ble_bp_data.sub_func_code,ble_bp_data.data_length,ble_bp_data.flags,ble_bp_data.checksum);
+
+    // for(int i = 0;i<48;i++)
+       // {
+       //      printf("reply:[%d]= 0x%x\n",i,ble_bp_data.data[i]);
+       // }
+
+    ret = ble_factorytest_server_send_input_report((uint8_t *)&ble_bp_data,sizeof(ble_bp_data));
+    // printf("ret : 0x%x \n",ret);
+    return ret;
+}
diff --git a/code/sdk/drivers/peripheral/bp/service/bp_ble_service.h b/code/sdk/drivers/peripheral/bp/service/bp_ble_service.h
new file mode 100644 (file)
index 0000000..ace1004
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2025-02-14 10:30:32
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-02-14 11:35:06
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/bp/service/bp_ble_service.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+#ifndef _BP_BLE_SERVICE_H_
+#define _BP_BLE_SERVICE_H_
+
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#include "stdint.h"
+#include "errcode.h"
+
+errcode_t bn02_replymsg(uint8_t *input_data,uint16_t input_len,uint8_t flags);
+errcode_t bn02_parse_frame(uint8_t *buf, uint16_t event_size);
+uint8_t bn02_get_ble_status(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/bp/service/bp_service.c b/code/sdk/drivers/peripheral/bp/service/bp_service.c
new file mode 100644 (file)
index 0000000..e8bf086
--- /dev/null
@@ -0,0 +1,133 @@
+#include "pinctrl.h"
+#include "debug_print.h"
+#include "rtc.h"
+#include "timer.h"
+#include "systick.h"
+
+#include "tcxo.h"
+
+#include "cmsis_os2.h"
+#include "input_app.h"
+#include "bp_service.h"
+#include "custom_utils.h"
+#include "bn02.h"
+
+// #include "custom_runtime.h"
+/***
+ * 其他cmd在Header里定义,对外开放
+*/
+
+#define BP_CHECK_MS 40
+
+osTimerId_t g_bp_service_timer = NULL;
+
+static bool g_bp_sensor_exist = false;
+
+static bool g_bat_timer_is_running = false;
+
+static unsigned long g_app_queue= 0xFFFFFFFF;
+
+static bool bp_service_running_stat = false;
+
+void do_bp_service_check_msg(int cmd);
+
+static void bp_service_check_timer_callback(void* data)
+{
+    do_bp_service_check_msg(BP_SERVICE_CMD_TIMER_CHECK);
+}
+
+void do_bp_service_check_msg(int cmd)
+{
+    int ret;
+    if (g_bp_sensor_exist == false)
+        return ;
+    common_notify_mail_t mail = {0};
+    mail.comm.app = cmd;
+    ret = osal_msg_queue_write_copy(g_app_queue, (void *)&mail,
+                                    sizeof(common_notify_mail_t), 0);
+    if (ret != OSAL_SUCCESS) {
+        PRINT("Error bp Check MSG 0x%02X send failed! err=0x%x! \r\n",cmd, ret);
+    }
+    
+}
+
+static void bp_service_check_task(void const *arg)
+{
+    unused(arg);
+    int32_t ret;
+    common_notify_mail_t mail;
+    uint32_t msgsize = (uint32_t)sizeof(common_notify_mail_t);
+    while (1) {
+        ret = osal_msg_queue_read_copy(g_app_queue, (void *)&mail, &msgsize,
+                                       OSAL_MSGQ_WAIT_FOREVER);
+        if (ret != OSAL_SUCCESS) {
+            continue;
+        }
+        if (mail.comm.app == BP_SERVICE_CMD_TIMER_CHECK) {
+            // PRINT("bn02_int_handle \n");
+            bn02_int_handle();
+        }else if (mail.comm.app == BP_SERVICE_CMD_START_CHECK){
+            // PRINT("bn02_start \n");
+            bn02_start();
+            // if(g_bp_service_timer)
+            //     osTimerStart(g_bp_service_timer,150);
+        }else if (mail.comm.app == BP_SERVICE_CMD_STOP_CHECK){
+            // PRINT("bn02_stop \n");
+            bn02_stop();
+            // if(g_bp_service_timer)
+            //     osTimerStop(g_bp_service_timer);
+        }
+    }
+}
+void create_bp_queue(void)
+{
+
+    if (osal_msg_queue_create("bp_service_queue", APP_BOARD_MSG_COUNT, &g_app_queue,
+                              0, sizeof(common_notify_mail_t)) != ERRCODE_SUCC) {
+        PRINT("[bp][service] app create mail fail\n");
+    }
+}
+
+#define BP_BOARD_TASK_SIZE   0x1000
+errcode_t uapi_bp_service_init(void)
+{
+    PRINT("uapi_bp_service_init !\r\n");
+
+    g_bp_sensor_exist = true;
+
+    app_task_definition_t taskcfg={0};
+    taskcfg.create_queue_handle = create_bp_queue;
+    taskcfg.attr.name="bp_service";
+    taskcfg.attr.priority = osPriorityBelowNormal4;
+    taskcfg.attr.stack_size = BP_BOARD_TASK_SIZE;
+    taskcfg.func = bp_service_check_task;
+    taskcfg.use_mem = USE_EXTEND_MEM;
+    
+    errcode_t ret=uapi_create_osThread_custom(&taskcfg);
+    if(ret != ERRCODE_SUCC)
+    {
+        PRINT("create bp_service failed %d!\r\n",ret);
+        return ERRCODE_FAIL;
+    }
+
+    // g_bp_service_timer = osTimerNew((osTimerFunc_t)bp_service_check_timer_callback, osTimerPeriodic, NULL, NULL);
+
+    return ERRCODE_SUCC;
+}
+
+void bp_int_callback(pin_t pin, uintptr_t param)
+{
+    // PRINT("bp_int_callback %d 0x%X\n",pin,param);
+    uapi_gpio_clear_interrupt(pin);
+    do_bp_service_check_msg(BP_SERVICE_CMD_TIMER_CHECK);
+}
+
+// void bp_service_service_resume(void)
+// {
+//     MMC_LOG("bp_service_service resume!\r\n");
+//     bp_service_check_timer_callback(0);
+// }
+// void bp_service_service_suspend(void)
+// {
+//     MMC_LOG("bp_service_service suspend!\r\n");
+// }
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/bp/service/bp_service.h b/code/sdk/drivers/peripheral/bp/service/bp_service.h
new file mode 100644 (file)
index 0000000..ba02c9a
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-12-23 15:11:01
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-01-16 17:39:43
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/charge/HP4570/service/charge_service.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+/**
+ * Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved. \n
+ *
+ * Description: Test adc header \n
+ * Author: @CompanyNameTag \n
+ * History: \n
+ * 2022-08-16, Create file. \n
+ */
+
+#ifndef BP_SERVICE_H__
+#define BP_SERVICE_H__
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#include "stdint.h"
+#include "errcode.h"
+
+#define BP_SERVICE_CMD_START_CHECK 0x12
+#define BP_SERVICE_CMD_STOP_CHECK 0x13
+#define BP_SERVICE_CMD_TIMER_CHECK 0x11
+
+errcode_t uapi_bp_service_init(void);
+void bp_int_callback(pin_t pin, uintptr_t param);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/bp/service/bp_tcp_server.c b/code/sdk/drivers/peripheral/bp/service/bp_tcp_server.c
new file mode 100644 (file)
index 0000000..fc8fd94
--- /dev/null
@@ -0,0 +1,536 @@
+#include "pinctrl.h"
+#include "debug_print.h"
+#include "rtc.h"
+#include "timer.h"
+#include "systick.h"
+
+#include "tcxo.h"
+
+#include "cmsis_os2.h"
+#include "input_app.h"
+#include "bp_service.h"
+#include "custom_utils.h"
+#include "bp_tcp_server.h"
+#include "custom_runtime.h"
+// #include "custom_runtime.h"
+/***
+ * 其他cmd在Header里定义,对外开放
+*/
+
+#define APP_KEY "d8d960b748738c2f29c676baa3f5be64"
+#define NAME "W9"
+#define URL_HEADER "https://test.aicaring.com/api/v0"
+
+#define MAX_CNT 16 * 5 * 60
+static unsigned long g_app_queue= 0xFFFFFFFF;
+
+static int *tcp_data = NULL;
+static int tcp_data_cnt = 0;
+
+const char base64_table[] = 
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    "abcdefghijklmnopqrstuvwxyz"
+    "0123456789+/";
+
+// {
+// "app_key": "1db74281ece314ba6bbc2b553222cd84",
+// "name": "RH303"
+// "firm": "魔方",
+// "device_code": "DA:19:72:F3:0A:89",
+// "model": "T11",
+// "sensor": {"model": "VC32", "fs": 100},
+// “sinklib_version": "v0.3.0.072522",
+// "request_code":
+// "6+m78fFJkFKu1mzhhL4jKRJTEhJMwvSJFlJhWIgRC8wfyB0HFw8JMURNQ6c3MP/U"
+// }
+
+int base64_encode(char *out, size_t out_len, size_t *out_size, const char *in, size_t in_len)
+{
+    if (out == NULL || out_len == 0 || out_size == NULL || in == NULL || in_len == 0) {
+        return -1;
+    }
+    
+    // 计算Base64编码后的最大长度: (in_len + 2) / 3 * 4
+    size_t max_out_len = (in_len + 2) / 3 * 4;
+    
+    // 检查输出缓冲区是否足够
+    if (max_out_len + 1 > out_len) {  // +1 for null terminator
+        return -2;
+    }
+    
+    uint32_t value = 0;
+    size_t i = 0, j = 0;
+    uint8_t bytes_remaining = 0;
+    
+    *out_size = 0;
+    
+    // 按3字节分组处理
+    while (i < in_len) {
+        // 读取3字节
+        value = 0;
+        bytes_remaining = 0;
+        
+        for (int k = 0; k < 3 && i < in_len; k++) {
+            value = (value << 8) | (uint8_t)in[i++];
+            bytes_remaining++;
+        }
+        
+        // 编码为4个Base64字符
+        switch (bytes_remaining) {
+            case 3:
+                out[j++] = base64_table[(value >> 18) & 0x3F];
+                out[j++] = base64_table[(value >> 12) & 0x3F];
+                out[j++] = base64_table[(value >> 6) & 0x3F];
+                out[j++] = base64_table[value & 0x3F];
+                break;
+                
+            case 2:
+                out[j++] = base64_table[(value >> 10) & 0x3F];
+                out[j++] = base64_table[(value >> 4) & 0x3F];
+                out[j++] = base64_table[(value << 2) & 0x3F];
+                out[j++] = '=';  // 填充等号
+                break;
+                
+            case 1:
+                out[j++] = base64_table[(value >> 2) & 0x3F];
+                out[j++] = base64_table[(value << 4) & 0x3F];
+                out[j++] = '=';  // 填充等号
+                out[j++] = '=';  // 填充等号
+                break;
+        }
+    }
+    
+    out[j] = '\0';  // 字符串终止符
+    *out_size = j;
+    return 0;
+}
+
+void get_request_code(char *req_code)
+{
+    uint32_t req_code_len = 0;
+    char* fact = "zhihuishixun";                // 获取厂商名字(不超过32个字节的字符串)
+    const unsigned int fact_len = strlen(fact);
+    char* imei = uapi_dev_runtime_get_cat1_imei();        // 获取设备号(12个字节字符串)
+    const unsigned int imei_len = strlen(imei);
+    request_validation((unsigned char*)fact, fact_len, (unsigned char*)imei, imei_len, (unsigned char*)req_code, &req_code_len);
+    printf("req_code:%s\n",req_code);
+}
+
+void get_active_code(void)
+{
+#if 0
+       char * data_ptr = NULL;
+       uint32_t data_len = 0;
+       char * encode_str = NULL;
+       uint32_t encode_len = 0;
+       uint32_t output_len = 0;
+       int temp_len = 0;
+       int json_data_len = 256;
+       char * json_data = NULL;
+
+       json_data = malloc(json_data_len);
+       if(json_data == NULL)
+           goto FAILED;
+    memset(json_data,0,json_data_len);
+
+       temp_len += sprintf(json_data + temp_len, "{\"app_key\":\"%s\",", APP_KEY);
+    temp_len += sprintf(json_data + temp_len, "{\"name\":\"%s\",", NAME);
+       temp_len += sprintf(json_data + temp_len, "\"firm\":\"%s\",", "HENGAI");
+
+    uint8_t btaddr[6] = {0};
+    uint32_t len = 6;
+    uapi_get_nv_btaddr(btaddr, &len);
+    uint8_t btaddr_str[64] = {0};
+    sprintf((char *)btaddr_str, "%02X:%02X:%02X:%02X:%02X:%02X", btaddr[0], btaddr[1], btaddr[2], btaddr[3], btaddr[4], btaddr[5]);
+
+    temp_len += sprintf(json_data + temp_len, "\"device_code\":\"%s\",", btaddr_str);
+    temp_len += sprintf(json_data + temp_len, "\"model\":\"%s\",", "T11");
+    temp_len += sprintf(json_data + temp_len, "\"sensor\":{\"model\":\"VC32\",\"fs\":%d},", 100);
+    temp_len += sprintf(json_data + temp_len, "\"sensor\":{\"model\":\"VC32\",\"fs\":%d},", 100);
+    temp_len += sprintf(json_data + temp_len, "\"sinklib_version\":\"%s\",", "v0.5.3.060325");
+
+
+    char req_code[64] = {0};
+    get_request_code(req_code);
+    temp_len += sprintf(json_data + temp_len, "\"request_code\":\"%s\"}", req_code);
+
+       printf("temp_len:%d\n",temp_len);
+
+       // base64 body
+       encode_len = temp_len * 3 / 2;
+       encode_str = malloc(encode_len);
+
+       if(encode_str == NULL)
+        goto FAILED;
+
+    memset(encode_str,0,encode_len);
+
+       if(0 != base64_encode(encode_str, encode_len, &output_len, json_data, temp_len))
+               goto FAILED;
+
+       
+       // content
+       data_len = output_len + 128;
+       data_ptr = malloc(data_len);
+       if(data_ptr == NULL)
+               goto FAILED;
+
+    memset(data_ptr,0,data_len);
+
+       sprintf(data_ptr, "[XT*YYYYYYYYYYYYYYY*%s*TCP_HTTP,POST,%s%s,,%s", URL_HEADER, "/sinklib/activation/feedback", encode_str);
+       data_len = strlen(data_ptr);
+
+    char *send_str = NULL;
+    int send_len = data_len + 64;
+    send_str = malloc(send_len);
+       if(send_str == NULL)
+               goto FAILED;
+
+       
+    char len_str[4] = {0};
+    sprintf(len_str, "%04x", data_len+8);
+    sprintf(send_str, "[XT*YYYYYYYYYYYYYYY*%s*TCP_HTTP%s]", len_str, data_ptr);
+    send_len = strlen(send_str);
+
+       mmi_protocol_fzd_action_tcp_http(data_ptr, data_len);
+       
+FAILED:
+    if(NULL != send_str)
+    {
+        lv_mem_free(send_str);
+        send_str = NULL;
+    }
+       if(NULL != json_data)
+       {
+               lv_mem_free(json_data);
+               json_data = NULL;
+       }
+       if(NULL != encode_str)
+       {
+               lv_mem_free(encode_str);
+               encode_str = NULL;
+       }
+       if(NULL != data_ptr)
+       {
+               lv_mem_free(data_ptr);
+               data_ptr = NULL;
+       }
+#endif
+}
+
+void bp_tcp_data_clean(void)
+{
+    if(tcp_data != NULL)
+    {
+        free(tcp_data);
+        tcp_data = NULL;
+        tcp_data_cnt = 0;
+    }
+}
+
+void do_bp_tcp_server_send_data(int *data,uint32_t len)
+{
+    if(data == NULL || len == 0)
+        return;
+
+    errcode_t ret;
+    bp_tcp_data_mail_t send_data = {0};
+    send_data.len = len;
+    send_data.data = (int *)malloc(len * sizeof(int));
+    if(send_data.data == NULL)
+    {
+        PRINT("malloc failed\n");
+        return;
+    }
+    memcpy_s(send_data.data,len * sizeof(int),data,len * sizeof(int));
+    uint32_t send_len = sizeof(send_data);
+
+    ret = osal_msg_queue_write_copy(g_app_queue, (void *)&send_data,
+                                    send_len, 0);
+    if (ret != OSAL_SUCCESS) {
+        PRINT("Error bp Check MSG 0x send failed! err=0x%x! \r\n", ret);
+    }
+
+    free(send_data.data);
+}
+
+// 数据开头标识:[
+// bid(需要登录后台申请)
+// 设备号0
+// 协议模块分割符:*
+// 消息内容(开头是命令,后面有内容用消息分割符逗号分割,没有则不需要逗号)
+// 消息长度(十六进制,4个字节,最大支持FFFF)
+// 消息分割符:,
+// 数据结尾标识:]
+
+
+
+void tcp_data_parse(char *rx_buffer, int len)
+{
+    if (len == 0 || rx_buffer == NULL || strlen(rx_buffer) != len)
+    {
+        printf("len  = 0 or rx_buffer == NULL, format error !\n");
+        return;
+    }
+
+    // printf("rx_buffer %s\n", rx_buffer);
+    // printf("rx_buffer %d\n", strlen(rx_buffer));
+    // printf("format error ! header:%c len:%d\n", rx_buffer[0], len);
+    // printf("format error ! tail:%c \n", rx_buffer[len-1]);
+
+    if (!(rx_buffer[0] == '[' && rx_buffer[len-1] == ']'))
+    {
+        printf("format error ! header:%c,tail:%c\n", 
+               (unsigned char)rx_buffer[0], 
+               (unsigned char)rx_buffer[len-1]);
+        return;
+    }
+
+    // 解析BID
+    char *bid_start = &rx_buffer[1];
+    char *bid_end = strchr(bid_start, '*');
+    if (bid_end == NULL) 
+    {
+        printf("Missing module delimiter\n");
+        return;
+    }
+
+    int bid_len = bid_end - bid_start;
+    char bid[20] = {0};
+    strncpy(bid, bid_start, bid_len);
+    bid[bid_len] = '\0';
+    
+    // 解析设备号
+    char *device_start = bid_end + 1;
+    char *device_end = strchr(device_start, '*');
+    if (device_end == NULL) {
+        printf("Missing module delimiter *\n");
+        return;
+    }
+    int device_len = device_end - device_start;
+    char device_id[64] = {0};
+    strncpy(device_id, device_start, device_len);
+    device_id[device_len] = '\0';
+    
+    // 解析长度字段 (4个十六进制字符 = 2字节)
+    char *len_start = device_end + 1;
+    char *len_end = strchr(len_start, '*');
+    if (len_end == NULL) {
+        printf("Missing module delimiter *\n");
+        return;
+    }
+    
+    // 验证长度格式
+    int len_len = len_end - len_start;
+    if (len_len != 4) {  // 4个十六进制字符
+        printf("Invalid length format (expected 4 characters, got %d)\n", len_len);
+        return;
+    }
+    
+    // 转换长度字符串为整数
+    uint16_t total_length;  // 使用16位整数存储2字节长度
+    sscanf(len_start, "%4hx", &total_length);  // 注意这里用%4hx,匹配4个十六进制字符
+    
+    // 解析命令和内容
+    char *cmd_start = len_end + 1;
+    char *content_start = strchr(cmd_start, ',');
+    
+    if (content_start != NULL) 
+    {
+        // 有内容的情况: [BID*DEVICE*LEN*COMMAND,CONTENT]
+        int cmd_len = content_start - cmd_start;
+        char command[64] = {0};
+        strncpy(command, cmd_start, cmd_len);
+        command[cmd_len] = '\0';
+        
+        // 解析内容 (不包括逗号)
+        int content_len = &rx_buffer[len-1] - content_start - 1;  // 不包含逗号
+        char content[128] = {0};
+        strncpy(content, content_start + 1, content_len);  // 从逗号后一位开始复制
+        content[content_len] = '\0';
+        
+        // 验证总长度 (从命令开始到消息结束的长度)
+        int actual_total_length = cmd_len + content_len + 1;  // +1 是因为内容的逗号也计入总长度
+        if (actual_total_length != total_length) {
+            printf("Length mismatch: declared %u, actual %d\n", 
+                   total_length, actual_total_length);
+            return;
+        }
+        
+        // 移除内容中的所有逗号
+        char filtered_content[128] = {0};
+        int j = 0;
+        for (int i = 0; content[i] != '\0'; i++) {
+            if (content[i] != ',') {
+                filtered_content[j++] = content[i];
+            }
+        }
+        
+        // 打印解析结果
+        printf("Parsed successfully:\n");
+        printf("BID: %s\n", bid);
+        printf("Device ID: %s\n", device_id);
+        printf("Command: %s\n", command);
+        printf("Content: %s\n", filtered_content);  // 打印不包含逗号的内容
+
+        if (strcmp(command, "blood") == 0) {
+            printf("blood start\n");
+#ifdef ENABLE_BN02
+            do_bp_service_check_msg(BP_SERVICE_CMD_START_CHECK);
+#endif
+        }
+    } 
+    else
+    {
+        // 无内容的情况: [BID*DEVICE*LEN*COMMAND]
+        int cmd_len = &rx_buffer[len-1] - cmd_start;
+        char command[64] = {0};
+        strncpy(command, cmd_start, cmd_len);
+        command[cmd_len] = '\0';
+        
+        // 验证命令长度 (无内容时,长度字段表示命令长度)
+        if (cmd_len != total_length) {
+            printf("Command length mismatch: declared %u, actual %d\n", 
+                   total_length, cmd_len);
+            return;
+        }
+        
+        // 打印解析结果
+        printf("Parsed successfully:\n");
+        printf("BID: %s\n", bid);
+        printf("Device ID: %s\n", device_id);
+        printf("Command: %s\n", command);
+        printf("No content\n");
+
+
+        if (strcmp(command, "blood") == 0) {
+            printf("blood start\n");
+#ifdef ENABLE_BN02
+            do_bp_service_check_msg(BP_SERVICE_CMD_START_CHECK);
+#endif
+        }
+    }
+}
+
+static void bp_tcp_server_recv_task(void const *arg)
+{
+    // char rx_buffer[512];
+    // char tx_buffer[256];
+
+    // socklen_t addrLen = sizeof(filesourceAddr);
+    while (1) {
+
+    //         // printf("recv ENTER\r\n");
+            
+       //              memset(rx_buffer, 0, sizeof(rx_buffer));
+    //         int len = recvfrom(g_listen_sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *)&filesourceAddr, &addrLen);
+    //         // Error occured during receiving
+    //         printf("file recv len:%d rx_buffer:%s\r\n",len,rx_buffer);
+    //         if (len < 0) {
+    //             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"len < 0 , recv failed: errno %d\n", errno);
+    //             // break;
+    //             continue;
+    //         } else if (len == 0) {
+    //             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"len == 0\n");
+    //             // break;
+    //             continue;
+    //         }
+    //         // Data received
+    //         rx_buffer[len] = '\0'; // Null-terminate whatever we received and treat like a string
+    //         // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"Received %d bytes, rx_buffer: %s\n", len, rx_buffer);
+    //         tcp_data_parse(rx_buffer, len);
+
+        }
+}
+
+static void tcp_data_handler(int *data,int len)
+{
+    if(tcp_data == NULL)
+    {
+        tcp_data = (int *)malloc(MAX_CNT * sizeof(int));
+        if(tcp_data == NULL)
+        {
+            PRINT("malloc failed\n");
+            return;
+        }
+    }
+    // printf("len:%d\n",len);
+    memcpy_s(tcp_data + tcp_data_cnt,len * sizeof(int),data,len * sizeof(int));
+
+    // for(int i = tcp_data_cnt; i < tcp_data_cnt+len; i ++)
+    // {
+    //     printf("222data[%d]:%d\n",i,tcp_data[i]);
+    // }
+
+    tcp_data_cnt += len;
+
+
+
+    if(tcp_data_cnt >= MAX_CNT)
+    {
+        // for(int i = 0; i < tcp_data_cnt; i ++)
+        // {
+        //     printf("data[%d]:%d\n",i,tcp_data[i]);
+        // }
+        tcp_data_cnt = 0;
+        memset((void*)tcp_data,0,MAX_CNT * sizeof(int));
+    }
+}
+
+static void bp_tcp_server_send_task(void const *arg)
+{
+    unused(arg);
+    errcode_t ret;
+
+    bp_tcp_data_mail_t mail = {0};
+    uint32_t msgsize = sizeof(bp_tcp_data_mail_t);
+
+    while (1) {
+        ret = osal_msg_queue_read_copy(g_app_queue, (void *)&mail, &msgsize,
+                                       OSAL_MSGQ_WAIT_FOREVER);
+        if (ret != OSAL_SUCCESS) {
+            continue;
+        }
+
+        tcp_data_handler((int *)mail.data,mail.len);
+        // for(int i = 0; i < mail.len; i ++)
+        // {
+        //     printf("222data[%d]:%d\n",i,mail.data[i]);
+        // }
+        
+    }
+}
+
+void create_bp_tcp_queue(void)
+{
+
+    if (osal_msg_queue_create("bp_tcp_service_queue", APP_BOARD_MSG_COUNT, &g_app_queue,
+                              0, sizeof(bp_tcp_data_mail_t)) != ERRCODE_SUCC) {
+        PRINT("[bp][service] app create mail fail\n");
+    }
+}
+
+#define BP_BOARD_TASK_SIZE   0x1000
+errcode_t uapi_bp_tcp_server_init(void)
+{
+    PRINT("uapi_bp_tcp_server_init !\r\n");
+
+    app_task_definition_t taskcfg={0};
+    taskcfg.create_queue_handle = create_bp_tcp_queue;
+    taskcfg.attr.name="bp_tcp_server_send_task";
+    taskcfg.attr.priority = osPriorityBelowNormal4;
+    taskcfg.attr.stack_size = BP_BOARD_TASK_SIZE;
+    taskcfg.func = bp_tcp_server_send_task;
+    taskcfg.use_mem = USE_EXTEND_MEM;
+    
+    errcode_t ret=uapi_create_osThread_custom(&taskcfg);
+    if(ret != ERRCODE_SUCC)
+    {
+        PRINT("create bp_service failed %d!\r\n",ret);
+        return ERRCODE_FAIL;
+    }
+
+    // g_bp_service_timer = osTimerNew((osTimerFunc_t)bp_service_check_timer_callback, osTimerPeriodic, NULL, NULL);
+
+    return ERRCODE_SUCC;
+}
diff --git a/code/sdk/drivers/peripheral/bp/service/bp_tcp_server.h b/code/sdk/drivers/peripheral/bp/service/bp_tcp_server.h
new file mode 100644 (file)
index 0000000..b20a90a
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2025-02-14 10:30:32
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-06-12 17:17:47
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/bp/service/bp_ble_service.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+#ifndef _BP_TCP_SERVER_H_
+#define _BP_TCP_SERVER_H_
+
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#include "stdint.h"
+#include "errcode.h"
+
+typedef struct {
+    int *data;
+    uint32_t len;
+} bp_tcp_data_mail_t;
+
+
+void do_bp_tcp_server_send_data(int *data,uint32_t len);
+void tcp_data_parse(char *rx_buffer, int len);
+void bp_tcp_data_clean(void);
+void test_algorithm(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
index f489d7c..e5e2e36 100644 (file)
@@ -158,10 +158,11 @@ void ble_cywee_server_init(uint8_t server_id)
 //协议接收client下发的数据接口
 void cywee_recv_cmd_data(uint8_t *buf, uint16_t event_size,uint16_t handle)
 {
-    if(buf != NULL)
-        printf("cywee_recv_cmd_data len %d , handle 0x%X ,*buf 0x%02X\r\n",event_size,handle,*buf);
+    if(buf == NULL)
+        return;
+        // printf("cywee_recv_cmd_data len %d , handle 0x%X ,*buf 0x%02X\r\n",event_size,handle,*buf);
     /****此处为接收指令,处理后反馈结果的参考**/
-    // cywee_log_switch(*buf);
+    cywee_log_switch(*buf);
     /*****参考结束****/
 }
 
index ac9ac6a..66e3109 100644 (file)
 #include "battery_hal.h"
 #include "sleep/include/SleepModelC.h"
 #include "custom_save_runtime.h"
+#ifdef SUPPORT_GNSS
+#include "gnss_ctl.h"
+#include "NMEA0183.h"
+#endif
 
 #define AP_ENABLE_DML_SDO_LISTEN
 
@@ -840,6 +844,46 @@ void cywee_time_sync(void)
     uapi_create_folder(dir_path);
 }
 
+void cywee_gnss_update(void)
+{
+#ifdef SUPPORT_GNSS
+    gps_data_t *gps_data = getGPSGlobaldata();
+    if(gps_data == NULL)
+    {
+        CWM_OS_dbgPrintf("gps_data == NULL \n");
+        return;
+    }
+
+    if(gps_data->status < 1)
+    {
+        CWM_OS_dbgPrintf("gps_data->status < 1 \n");
+        return;
+    }
+
+    memset(&csd, 0, sizeof(CUSTOM_GNSS));
+    csd.sensorType = CUSTOM_GNSS;
+    csd.dData[0] = gps_data->location.lat;//latitude (degrees)  (range: -90~90);  //纬度
+    csd.dData[1] = gps_data->location.lng;//longitude (degrees) (range: -180~180) //经度
+    csd.dData[2] =  gps_data->location.alt;//altitude   (meters)  //海拔
+    csd.dData[3] = gps_data->ground_course;//bearing  (heading in degrees)  //方位角
+    csd.dData[4] = gps_data->ground_speed;//speed (m/s) //速度
+    csd.dData[5] = gps_data->hdop;//Horizontal_Accuracy (meters) //水平精度
+    csd.dData[6] = gps_data->vdop;//Vertical_Accuracy (meters) //垂直精度
+    csd.dData[7] = 0;  //水平精度衰减因子
+    csd.dData[8] = 0; //垂直精度衰减因子
+    CWM_CustomSensorInput(&csd); 
+
+    CWM_OS_dbgPrintf("gps_data->location.lat:%f\n",gps_data->location.lat);
+    CWM_OS_dbgPrintf("gps_data->location.lng:%f\n",gps_data->location.lng);
+    CWM_OS_dbgPrintf("gps_data->location.alt:%f\n",gps_data->location.alt);
+    CWM_OS_dbgPrintf("gps_data->ground_course:%f\n",gps_data->ground_course);
+    CWM_OS_dbgPrintf("gps_data->ground_speed:%f\n",gps_data->ground_speed);
+    CWM_OS_dbgPrintf("gps_data->hdop:%f\n",gps_data->hdop);
+    CWM_OS_dbgPrintf("gps_data->vdop:%f\n",gps_data->vdop);
+
+#endif
+}
+
 void cywee_hrs_update(int hrs_data)
 {
     // hrs = hrs_data;
@@ -1206,6 +1250,21 @@ void CWM_AP_SensorListen(pSensorEVT_t sensorEVT) {
                     hrs_mode_state = 0;
                     uapi_save_runtime_log(RUNTIME_LOG_OXYGEN_SPORT_MEASURE_END);
                 }
+            }
+            if((int)sensorEVT->fData[1] == CUSTOM_GNSS)
+            {
+                CWM_OS_dbgPrintf("CUSTOM_GNSS !!! \r\n");
+#ifdef SUPPORT_GNSS
+                if((int)sensorEVT->fData[2] == 1)
+                {
+
+                    gnss_start();
+                }
+                else
+                {
+                    gnss_stop();
+                }
+#endif
             }
              break;
         case IDX_ALGO_SHAKE:
index 1a35706..51810a8 100644 (file)
@@ -29,19 +29,7 @@ extern "C" {
  */\r
 #define TIOT_PIN_NONE        0xFFFFFFFFU\r
 \r
-#ifdef BOARD_U8\r
-#define TIOT_UART_PORT  UART_BUS_0\r
-#define TIOT_PIN_WAKEUP_HOST_NUM    S_AGPIO_L31    /* 用于唤醒HOST. */\r
-#define TIOT_PIN_WAKEUP_GNSS_NUM    TIOT_PIN_NONE    /* 用于 唤醒GNSS. */\r
-#define TIOT_PIN_POWER      S_AGPIO_L30     /* 用于开启GNSS. */\r
-\r
-#define TIOT_PIN_UART_TX    S_MGPIO19\r
-#define TIOT_PIN_UART_RX    S_MGPIO20\r
-#define TIOT_PIN_UART_CTS   S_MGPIO22\r
-#define TIOT_PIN_UART_RTS   S_MGPIO21\r
-#define TIOT_PINMUX HAL_PIO_FUNC_UART1\r
-\r
-#elif defined(BOARD_L22) || defined(BOARD_W9)\r
+#if defined(BOARD_W9) || defined(BOARD_N9)\r
 #define TIOT_UART_PORT  UART_BUS_1\r
 #define TIOT_PIN_WAKEUP_HOST_NUM    S_AGPIO_L15    /* 用于唤醒HOST. */\r
 #define TIOT_PIN_WAKEUP_GNSS_NUM    S_HGPIO0    /* 用于 唤醒GNSS. */\r
index e59debb..799aa77 100644 (file)
@@ -10,6 +10,7 @@
 #include "tiot_service_interface.h"\r
 #include "pm_definition.h"\r
 #include "gnss_ctl.h"\r
+#include "cywee_hal.h"\r
 \r
 #define COLDSTART_FIXMODEGPS_NMEAALL_SAMPLE        0\r
 #define AUTOSTART_FIXMODEALL_NMEADEF_SAMPLE        1\r
@@ -115,39 +116,39 @@ int32_t CfgColdStartFixModeGpsNmeaAll(tiot_handle handle)
     // 配置启动模式:冷启动模式。\r
     int32_t ret = tiot_service_write(handle, cfgColdStartCmd, sizeof(cfgColdStartCmd));\r
     if (ret < 0) {\r
-        printf("\nerror: cfgColdStartCmd error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: cfgColdStartCmd error: %d\n", ret);\r
         return 0;\r
     }\r
 \r
     // 配置使能的GNSS星座:GPS。\r
     ret = tiot_service_write(handle, cfgFixModeAllCmd, sizeof(cfgFixModeAllCmd));\r
     if (ret < 0) {\r
-        printf("\nerror: cfgFixModeAllCmd error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: cfgFixModeAllCmd error: %d\n", ret);\r
         return 0;\r
     }\r
 \r
     // 配置上报NMEA类型:PNT/ZDA/VTG/RMC/GSV/GSA/GLL/GGA。\r
     ret = tiot_service_write(handle, cfgNmeaAllCmd, sizeof(cfgNmeaAllCmd));\r
     if (ret < 0) {\r
-        printf("\nerror: cfgNmeaAllCmd error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: cfgNmeaAllCmd error: %d\n", ret);\r
         return 0;\r
     }\r
 \r
     ret = tiot_service_write(handle, CFG_TRK_LPW_DISABLE, sizeof(CFG_TRK_LPW_DISABLE));\r
     if (ret < 0) {\r
-        printf("\nerror: CFG_TRK_LPW_DISABLE error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: CFG_TRK_LPW_DISABLE error: %d\n", ret);\r
         return 0;\r
     }\r
 \r
     ret = tiot_service_write(handle, CFG_ACQ_LPW_DISABLE, sizeof(CFG_ACQ_LPW_DISABLE));\r
     if (ret < 0) {\r
-        printf("\nerror: CFG_ACQ_LPW_DISABLE error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: CFG_ACQ_LPW_DISABLE error: %d\n", ret);\r
         return 0;\r
     }\r
 \r
     ret = tiot_service_write(handle, CFG_ANTIJAM_ENABLE, sizeof(CFG_ANTIJAM_ENABLE));\r
     if (ret < 0) {\r
-        printf("\nerror: CFG_ANTIJAM_ENABLE error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: CFG_ANTIJAM_ENABLE error: %d\n", ret);\r
         return 0;\r
     }\r
     return 1;\r
@@ -161,33 +162,33 @@ int32_t CfgAutoStartFixModeAllNmeaDefault(tiot_handle handle)
     // 配置启动模式:自动模式。\r
     int32_t ret = tiot_service_write(handle, cfgAutoStartCmd, sizeof(cfgAutoStartCmd));\r
     if (ret < 0) {\r
-        printf("\nerror: cfgAutoStartCmd error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: cfgAutoStartCmd error: %d\n", ret);\r
         return 0;\r
     }\r
 \r
     // 配置使能的GNSS星座:QZSS/GAL/BDS/GLO/GPS。\r
     ret = tiot_service_write(handle, cfgFixModeAllCmd, sizeof(cfgFixModeAllCmd));\r
     if (ret < 0) {\r
-        printf("\nerror: cfgFixModeAllCmd error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: cfgFixModeAllCmd error: %d\n", ret);\r
         return 0;\r
     }\r
 \r
     // 配置上报NMEA类型:RMC/GGA。\r
     ret = tiot_service_write(handle, cfgNmeaDefaultCmd, sizeof(cfgNmeaDefaultCmd));\r
     if (ret < 0) {\r
-        printf("\nerror: cfgNmeaDefaultCmd error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: cfgNmeaDefaultCmd error: %d\n", ret);\r
         return 0;\r
     }\r
 \r
     ret = tiot_service_write(handle, CFG_TRK_LPW_DISABLE, sizeof(CFG_TRK_LPW_DISABLE));\r
     if (ret < 0) {\r
-        printf("\nerror: CFG_TRK_LPW_DISABLE error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: CFG_TRK_LPW_DISABLE error: %d\n", ret);\r
         return 0;\r
     }\r
 \r
     ret = tiot_service_write(handle, CFG_ACQ_LPW_DISABLE, sizeof(CFG_ACQ_LPW_DISABLE));\r
     if (ret < 0) {\r
-        printf("\nerror: CFG_ACQ_LPW_DISABLE error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: CFG_ACQ_LPW_DISABLE error: %d\n", ret);\r
         return 0;\r
     }\r
     return 1;\r
@@ -199,7 +200,7 @@ static int32_t QryVersion(tiot_handle handle)
     // 查询版本号\r
     int32_t ret = tiot_service_write(handle, qryVersion, sizeof(qryVersion));\r
     if (ret < 0) {\r
-        printf("\nerror: QryVersion error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: QryVersion error: %d\n", ret);\r
         return 0;\r
     }\r
     return 1;\r
@@ -216,10 +217,10 @@ static int32_t StartGnss(tiot_handle handle)
     // 启动GNSS\r
     int32_t ret = tiot_service_write(handle, startCmd, sizeof(startCmd));\r
     if (ret < 0) {\r
-        printf("\nerror: start gnss error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: start gnss error: %d\n", ret);\r
         return 0;\r
     }\r
-    printf("\nstart gnss\n");\r
+    CWM_OS_dbgPrintf("\nstart gnss\n");\r
     return 1;\r
 }\r
 \r
@@ -228,10 +229,10 @@ static int32_t StopGnss(tiot_handle handle)
     // 停止GNSS\r
     int32_t ret = tiot_service_write(handle, stopCmd, sizeof(stopCmd));\r
     if (ret < 0) {\r
-        printf("\nerror: stop gnss error: %d\n", ret);\r
+        CWM_OS_dbgPrintf("\nerror: stop gnss error: %d\n", ret);\r
         return 0;\r
     }\r
-    printf("\nstop gnss\n");\r
+    CWM_OS_dbgPrintf("\nstop gnss\n");\r
     return 1;\r
 }\r
 \r
@@ -242,7 +243,7 @@ static void ListenGnssData(tiot_handle handle)
     for (;;) {  // 写日志条件\r
 \r
         if (i >= LISTEN_DATA_MAX_LINES) {\r
-            printf("\ncnt enough\n");\r
+            CWM_OS_dbgPrintf("\ncnt enough\n");\r
             break;\r
         }\r
         if (g_gnss_stopflag == 1)\r
@@ -256,7 +257,7 @@ static void ListenGnssData(tiot_handle handle)
             if (type[0] == MSG_TYPE_ASCII) {\r
                 g_gnssServiceBuff[ret] = '\0';\r
                 char* pbuf=(char *)&g_gnssServiceBuff[MSG_CONTENT_IDX];\r
-                printf("%s\n", pbuf);\r
+                CWM_OS_dbgPrintf("%s\n", pbuf);\r
                 if (g_is_gnss_logon)\r
                     fprintf(g_gnssLogFp, "%s\n", pbuf);\r
                 for (int index=0;index < ret ;index++)\r
@@ -264,7 +265,7 @@ static void ListenGnssData(tiot_handle handle)
                     if (decode_nmea(pbuf[index])==1)\r
                     {\r
                         // dump_location_data(&g_global_gpsData);\r
-                        printf("decode_nmea done\r\n");\r
+                        CWM_OS_dbgPrintf("decode_nmea done\r\n");\r
                     }\r
                 }\r
             }\r
@@ -300,10 +301,10 @@ int GnssLogEnable(bool enable)
 \r
 void GnssServerStart(void)\r
 {\r
-    printf("\nenter gnss samples\n");\r
+    CWM_OS_dbgPrintf("\nenter gnss samples\n");\r
     if(g_is_gnss_poweron == 1)\r
     {\r
-        printf("gnss already on\r\n");\r
+        CWM_OS_dbgPrintf("gnss already on\r\n");\r
         return ;\r
     }\r
     uapi_pm_add_sleep_veto(PM_ID_SYS);\r
@@ -316,7 +317,7 @@ void GnssServerStart(void)
     // Step1: init\r
     int32_t ret = tiot_service_init();\r
     if (ret != 0) {\r
-        printf("\ntiot service init fail\n");\r
+        CWM_OS_dbgPrintf("\ntiot service init fail\n");\r
         g_is_gnss_poweron = 0;\r
         g_gnss_stopflag = 1;\r
     }\r
@@ -326,21 +327,21 @@ void GnssServerStart(void)
     {\r
         g_gnssLogFp = fopen("/user/log/gnss.log", "w");\r
         if (g_gnssLogFp == NULL) {\r
-            printf("\nerror: open log file error\n");\r
+            CWM_OS_dbgPrintf("\nerror: open log file error\n");\r
             return;\r
         }\r
     }\r
-    printf("\nbefore open tiot service\n");\r
+    CWM_OS_dbgPrintf("\nbefore open tiot service\n");\r
 \r
     // Step2: power on gnss\r
     tiot_handle handle = tiot_service_open("gn71", NULL);\r
     if (handle == 0) {\r
-        printf("\nopen tiot service fail\n");\r
+        CWM_OS_dbgPrintf("\nopen tiot service fail\n");\r
         g_is_gnss_poweron = 0;\r
         g_gnss_stopflag = 1;\r
         return;\r
     }\r
-    printf("\nopen tiot service success\n");\r
+    CWM_OS_dbgPrintf("\nopen tiot service success\n");\r
 \r
     int32_t cfgRet;\r
     // ---- loop ----------\r
@@ -354,7 +355,7 @@ void GnssServerStart(void)
             if (cfgRet == 0) {\r
                 continue;\r
             }\r
-            printf("\ncfg sample id:%u\n", g_gnssSamplesCfg[i].sampleId);\r
+            CWM_OS_dbgPrintf("\ncfg sample id:%u\n", g_gnssSamplesCfg[i].sampleId);\r
             QryVersion(handle);\r
 \r
             // Step4: start gnss\r
@@ -386,5 +387,5 @@ void GnssServerStart(void)
     #endif\r
     uapi_pm_remove_sleep_veto(PM_ID_SYS);\r
     g_is_gnss_poweron=0;\r
-    printf("\nfinish gnss samples\n");\r
+    CWM_OS_dbgPrintf("\nfinish gnss samples\n");\r
 }
\ No newline at end of file
index ce8914b..ed33383 100644 (file)
 #include "gpio.h"
 #include "uart_gnss.h"
 #include "gnss_sample.h"
+#include "cywee_hal.h"
 
 errcode_t gnss_power_on(void)
 {
 
-     errcode_t ret=0;
-#if defined(BOARD_U8)
-/*
-S_AGPIO_L23  GPS_BAT_ON
-S_AGPIO_L30  GPS_PWRON
-S_AGPIO_L28    GPS_1V8
-*/
-    ret=uapi_gpio_set_dir(S_AGPIO_L23,GPIO_DIRECTION_OUTPUT);
-    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L23,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
-    ret=uapi_gpio_set_dir(S_AGPIO_L30,GPIO_DIRECTION_OUTPUT);
-    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L30,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
-    ret=uapi_gpio_set_dir(S_AGPIO_L28,GPIO_DIRECTION_OUTPUT);
-    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L28,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
-
-    ret=uapi_gpio_set_val(S_AGPIO_L28 , GPIO_LEVEL_HIGH);   // gps V3.3 sw en
-    PRINT("GPS_1V8 set_value S_AGPIO_L28  GPIO_LEVEL_HIGH ret %d\n",ret);
-
-    ret=uapi_gpio_set_val(S_AGPIO_L23, GPIO_LEVEL_HIGH);   // crystal sw
-    PRINT("GPS_BAT_ON  set_value S_AGPIO_L23 GPIO_LEVEL_HIGH  ret %d\n",ret);
-  
-    ret=uapi_gpio_set_val(S_AGPIO_L30, GPIO_LEVEL_LOW);   //gps reset
-    PRINT("GPS_PWREN set_value S_AGPIO_L30 GPIO_LEVEL_LOW ret %d\n",ret);
-    osDelay(1000);
-    ret=uapi_gpio_set_val(S_AGPIO_L30, GPIO_LEVEL_HIGH);   //gps reset
-    PRINT("GPS_PWREN set_value S_AGPIO_L30 GPIO_LEVEL_HIGH ret %d\n",ret);
-
-
-#elif defined (BOARD_L22) || defined (BOARD_W9)
+    errcode_t ret=0;
+#if defined (BOARD_W9) || defined(BOARD_N9)
 
     ret=uapi_gpio_set_dir(S_AGPIO_L16,GPIO_DIRECTION_OUTPUT);
-    PRINT("set_dir S_AGPIO_L16,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    CWM_OS_dbgPrintf("set_dir S_AGPIO_L16,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
 
     ret=uapi_gpio_set_dir(S_AGPIO_L32,GPIO_DIRECTION_OUTPUT);
-    PRINT("set_dir S_AGPIO_L32,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    CWM_OS_dbgPrintf("set_dir S_AGPIO_L32,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
     ret=uapi_gpio_set_dir(S_AGPIO_L20,GPIO_DIRECTION_OUTPUT);
-    PRINT("set_dir S_AGPIO_L20,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    CWM_OS_dbgPrintf("set_dir S_AGPIO_L20,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
     ret=uapi_gpio_set_dir(S_AGPIO_R9,GPIO_DIRECTION_OUTPUT);
-    PRINT("set_dir S_AGPIO_R9,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    CWM_OS_dbgPrintf("set_dir S_AGPIO_R9,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
     ret=uapi_gpio_set_dir(S_HGPIO0,GPIO_DIRECTION_OUTPUT);
-    PRINT("set_dir S_HGPIO0,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    CWM_OS_dbgPrintf("set_dir S_HGPIO0,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
 
     ret=uapi_gpio_set_val(S_HGPIO0, GPIO_LEVEL_HIGH);   // crystal sw
-    PRINT("GPS_CRYSTAL set_value S_HGPIO0 GPIO_LEVEL_HIGH ret %d\n",ret);
+    CWM_OS_dbgPrintf("GPS_CRYSTAL set_value S_HGPIO0 GPIO_LEVEL_HIGH ret %d\n",ret);
     
     ret=uapi_gpio_set_val(S_AGPIO_L20, GPIO_LEVEL_HIGH);   // gps V1.8 sw en
-    PRINT("GPS_1V8 set_value S_AGPIO_L20 GPIO_LEVEL_HIGH ret %d\n",ret);
+    CWM_OS_dbgPrintf("GPS_1V8 set_value S_AGPIO_L20 GPIO_LEVEL_HIGH ret %d\n",ret);
 
     ret=uapi_gpio_set_val(S_AGPIO_R9, GPIO_LEVEL_HIGH);   // gps V3.3 sw en
-    PRINT("GPS_BAT_ON set_value S_AGPIO_R9 GPIO_LEVEL_HIGH ret %d\n",ret);
+    CWM_OS_dbgPrintf("GPS_BAT_ON set_value S_AGPIO_R9 GPIO_LEVEL_HIGH ret %d\n",ret);
 
     ret=uapi_gpio_set_val(S_AGPIO_L32, GPIO_LEVEL_LOW);   //gps reset
-    PRINT("GPS_PWREN set_value S_AGPIO_L32 GPIO_LEVEL_LOW ret %d\n",ret);
+    CWM_OS_dbgPrintf("GPS_PWREN set_value S_AGPIO_L32 GPIO_LEVEL_LOW ret %d\n",ret);
 
     osDelay(1000);
 
     ret=uapi_gpio_set_val(S_AGPIO_L32, GPIO_LEVEL_HIGH);   //gps reset
-    PRINT("GPS_PWREN set_value S_AGPIO_L32 GPIO_LEVEL_HIGH ret %d\n",ret);
+    CWM_OS_dbgPrintf("GPS_PWREN set_value S_AGPIO_L32 GPIO_LEVEL_HIGH ret %d\n",ret);
 
     // ret=uapi_gpio_set_val(S_AGPIO_L16, GPIO_LEVEL_HIGH);   // crystal sw
-    // PRINT("SWITCH uart to GPS set_value S_AGPIO_L16 GPIO_LEVEL_HIGH ret %d\n",ret);
+    // CWM_OS_dbgPrintf("SWITCH uart to GPS set_value S_AGPIO_L16 GPIO_LEVEL_HIGH ret %d\n",ret);
    
 
 #endif
@@ -103,57 +78,35 @@ S_AGPIO_L28    GPS_1V8
 errcode_t gnss_power_off(void)
 {
     
-     errcode_t ret=0;
-#if defined(BOARD_U8)
-/*
-S_AGPIO_L23  GPS_BAT_ON
-S_AGPIO_L30  GPS_PWRON
-S_AGPIO_L28    GPS_1V8
-*/
-    ret=uapi_gpio_set_dir(S_AGPIO_L23,GPIO_DIRECTION_OUTPUT);
-    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L23,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
-    ret=uapi_gpio_set_dir(S_AGPIO_L30,GPIO_DIRECTION_OUTPUT);
-    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L30,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
-    ret=uapi_gpio_set_dir(S_AGPIO_L28,GPIO_DIRECTION_OUTPUT);
-    if (ret != ERRCODE_SUCC)  PRINT("set_dir S_AGPIO_L28,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
-
-    ret=uapi_gpio_set_val(S_AGPIO_L23, GPIO_LEVEL_HIGH);   // crystal sw
-    PRINT("GPS_BAT_ON  set_value S_AGPIO_L23 GPIO_LEVEL_HIGH  ret %d\n",ret);
-
-    ret=uapi_gpio_set_val(S_AGPIO_L28 , GPIO_LEVEL_HIGH);   // gps V3.3 sw en
-    PRINT("GPS_1V8 set_value S_AGPIO_L28  GPIO_LEVEL_HIGH ret %d\n",ret);
-
-    ret=uapi_gpio_set_val(S_AGPIO_L30, GPIO_LEVEL_LOW);   //gps reset
-    PRINT("GPS_PWRON set_value S_AGPIO_L30 GPIO_LEVEL_LOW ret %d\n",ret);
+    errcode_t ret=0;
 
-  
-#elif defined (BOARD_L22) || defined (BOARD_W9)
+#if defined (BOARD_W9) || defined(BOARD_N9)
 
     ret=uapi_gpio_set_dir(S_AGPIO_L16,GPIO_DIRECTION_OUTPUT);
-    PRINT("set_dir S_AGPIO_L16,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    CWM_OS_dbgPrintf("set_dir S_AGPIO_L16,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
     ret=uapi_gpio_set_dir(S_AGPIO_L32,GPIO_DIRECTION_OUTPUT);
-    PRINT("set_dir S_AGPIO_L32,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    CWM_OS_dbgPrintf("set_dir S_AGPIO_L32,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
     ret=uapi_gpio_set_dir(S_AGPIO_L20,GPIO_DIRECTION_OUTPUT);
-    PRINT("set_dir S_AGPIO_L20,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    CWM_OS_dbgPrintf("set_dir S_AGPIO_L20,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
     ret=uapi_gpio_set_dir(S_AGPIO_R9,GPIO_DIRECTION_OUTPUT);
-    PRINT("set_dir S_AGPIO_R9,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    CWM_OS_dbgPrintf("set_dir S_AGPIO_R9,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
     ret=uapi_gpio_set_dir(S_HGPIO0,GPIO_DIRECTION_OUTPUT);
-    PRINT("set_dir S_HGPIO0,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    CWM_OS_dbgPrintf("set_dir S_HGPIO0,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
 
     ret=uapi_gpio_set_val(S_HGPIO0, GPIO_LEVEL_HIGH);   // crystal sw
-    PRINT("GPS_CRYSTAL set_value S_HGPIO0 GPIO_LEVEL_HIGH ret %d\n",ret);
+    CWM_OS_dbgPrintf("GPS_CRYSTAL set_value S_HGPIO0 GPIO_LEVEL_HIGH ret %d\n",ret);
     
     ret=uapi_gpio_set_val(S_AGPIO_L20, GPIO_LEVEL_HIGH);   // gps V1.8 sw en
-    PRINT("GPS_1V8 set_value S_AGPIO_L20 GPIO_LEVEL_HIGH ret %d\n",ret);
+    CWM_OS_dbgPrintf("GPS_1V8 set_value S_AGPIO_L20 GPIO_LEVEL_HIGH ret %d\n",ret);
 
     ret=uapi_gpio_set_val(S_AGPIO_R9, GPIO_LEVEL_HIGH);   // gps V3.3 sw en
-    PRINT("GPS_BAT_ON set_value S_AGPIO_R9 GPIO_LEVEL_HIGH ret %d\n",ret);
+    CWM_OS_dbgPrintf("GPS_BAT_ON set_value S_AGPIO_R9 GPIO_LEVEL_HIGH ret %d\n",ret);
 
     ret=uapi_gpio_set_val(S_AGPIO_L32, GPIO_LEVEL_LOW);   //gps reset
-    PRINT("GPS_PWRON set_value S_AGPIO_L32 GPIO_LEVEL_LOW ret %d\n",ret);
+    CWM_OS_dbgPrintf("GPS_PWRON set_value S_AGPIO_L32 GPIO_LEVEL_LOW ret %d\n",ret);
 
     // ret=uapi_gpio_set_val(S_AGPIO_L16, GPIO_LEVEL_LOW);   // crystal sw
-    // PRINT("SWITCH uart to download set_value S_AGPIO_L16 GPIO_LEVEL_LOW ret %d\n",ret);
+    // CWM_OS_dbgPrintf("SWITCH uart to download set_value S_AGPIO_L16 GPIO_LEVEL_LOW ret %d\n",ret);
   
 #endif
     return ERRCODE_SUCC;
@@ -191,15 +144,15 @@ errcode_t download_gnss_switch(DOWNLOAD_GPS_SWITCH_T download_gps_switch)
 {
     errcode_t ret=ERRCODE_SUCC;
     ret=uapi_gpio_set_dir(S_AGPIO_L16,GPIO_DIRECTION_OUTPUT);
-    PRINT("set_dir S_AGPIO_L16,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
+    CWM_OS_dbgPrintf("set_dir S_AGPIO_L16,GPIO_DIRECTION_OUTPUT ret %d\n",ret);
     
     if (download_gps_switch == SWITCH_TO_GNSS)
     {
         ret=uapi_gpio_set_val(S_AGPIO_L16, GPIO_LEVEL_HIGH);   // crystal sw
-        PRINT("SWITCH uart to GNSS set_value S_AGPIO_L16 GPIO_LEVEL_HIGH ret %d\n",ret);  
+        CWM_OS_dbgPrintf("SWITCH uart to GNSS set_value S_AGPIO_L16 GPIO_LEVEL_HIGH ret %d\n",ret);  
     }else{
         ret=uapi_gpio_set_val(S_AGPIO_L16, GPIO_LEVEL_LOW);   // crystal sw
-        PRINT("SWITCH uart to download set_value S_AGPIO_L16 GPIO_LEVEL_LOW ret %d\n",ret);
+        CWM_OS_dbgPrintf("SWITCH uart to download set_value S_AGPIO_L16 GPIO_LEVEL_LOW ret %d\n",ret);
     }
     return ret;
 }
\ No newline at end of file
index 63d4b91..024893b 100644 (file)
@@ -216,7 +216,7 @@ void gnss_receive_handler(uint8_t *buffer, int32_t size)
 }
 
 #define GNSS_CMD_TASK_MSG_COUNT 128
-#define GNSS_CMD_TASK_SIZE (0x1000)
+#define GNSS_CMD_TASK_SIZE (0x800*2)
 #define GNSS_CMD_TASK_PRIO 4
 void create_gnss_uart_queue(void)
 {
diff --git a/code/sdk/drivers/peripheral/gyro/CMakeLists.txt b/code/sdk/drivers/peripheral/gyro/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6811030
--- /dev/null
@@ -0,0 +1,45 @@
+#===============================================================================
+# @brief    cmake file
+# Copyright (c) @CompanyNameMagicTag 2023-2023. All rights reserved.
+#===============================================================================
+set(COMPONENT_NAME "gyro")
+
+set(SOURCES ${SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/sh5001/sh5001.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/service/gyro_at_cmd.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/service/gyro_service.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/service/gyro_hal.c
+)
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}/sh5001
+    ${CMAKE_CURRENT_SOURCE_DIR}/service
+)
+set(PUBLIC_DEFINES
+    SUPPORT_AT_GYRO
+    ENABLE_GYRO
+)
+
+set(PRIVATE_HEADER
+)
+
+set(PRIVATE_DEFINES
+)
+
+# use this when you want to add ccflags like -include xxx
+set(COMPONENT_PUBLIC_CCFLAGS
+)
+
+set(COMPONENT_CCFLAGS
+    -Wno-incompatible-function-pointer-types
+    -Wno-unused-function
+)
+
+set(WHOLE_LINK
+    true
+)
+
+set(MAIN_COMPONENT
+    false
+)
+
+build_component()
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gyro/service/gyro_at_cmd.c b/code/sdk/drivers/peripheral/gyro/service/gyro_at_cmd.c
new file mode 100644 (file)
index 0000000..ef0237f
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-12-16 20:49:09
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-05-12 17:47:30
+ * @FilePath: /sdk615/code/sdk/drivers/peripheral/GYRO/service/lqbp_at_cmd.c
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+#include "at_cmd_api.h"
+#include "pm_control.h"
+#include "gyro_service.h"
+#include "gyro_hal.h"
+
+#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
+#define GYRO_MAX_ARGC            8
+#define GYRO_MAX_ARGV_LEN        64
+
+#define GYRO_SUCCESS             0
+#define GYRO_FAILED              (-1)
+
+static int ConvertCmdToParam(uint8_t *para, uint32_t paraLen,
+        uint8_t argv[GYRO_MAX_ARGC][GYRO_MAX_ARGV_LEN], uint32_t* argc)
+{
+    uint32_t pos = 0;
+    *argc = 0;
+
+    for (uint32_t i = 0; i < paraLen; i++) {
+        if ((para[i] == ' ' || para[i] == '\n') && pos != 0) {
+            argv[*argc][pos] = '\0';
+            *argc += 1;
+            pos = 0;
+            if (*argc >= GYRO_MAX_ARGC) {
+                return GYRO_FAILED;
+            }
+        } else {
+            argv[*argc][pos] = para[i];
+            pos++;
+            if (pos >= GYRO_MAX_ARGV_LEN) {
+                return GYRO_FAILED;
+            }
+        }
+    }
+    if (pos != 0) {
+        *argc += 1;
+    }
+
+    return GYRO_SUCCESS;
+}
+
+static uint32_t gyro_start_test(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(strCommonCmd);
+    UNUSED(paraLen);
+    UNUSED(para);
+    gyro_start();
+    return ERRCODE_SUCC;
+}
+static uint32_t gyro_stop_test(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(strCommonCmd);
+    UNUSED(paraLen);
+    UNUSED(para);
+    gyro_stop();
+    return ERRCODE_SUCC;
+}
+static const at_cmd_table_t g_gyro_cmd[] = {
+    { (char *)"AT^GYROTESTSTART",      gyro_start_test, (char *)"1" },
+    { (char *)"AT^GYROTESTSTOP",      gyro_stop_test, (char *)"1" },
+};
+
+at_cmd_table_t *get_gyro_cmd_table(uint32_t *cmd_count)
+{
+    *cmd_count = ARRAY_COUNT(g_gyro_cmd);
+    return (at_cmd_table_t *)g_gyro_cmd;
+}
diff --git a/code/sdk/drivers/peripheral/gyro/service/gyro_at_cmd.h b/code/sdk/drivers/peripheral/gyro/service/gyro_at_cmd.h
new file mode 100644 (file)
index 0000000..e6bd34c
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-12-16 20:49:19
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-01-04 16:47:46
+ * @FilePath: /sdk615/code/sdk/drivers/peripheral/GYRO002TA/service/gyro_at_cmd.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+/**
+ * Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved. \n
+ *
+ * Description: Provides at cmd register func \n
+ * Author: @CompanyNameTag \n
+ * History: \n
+ * 2022-07-20, Create file. \n
+ */
+#ifndef GYRO_AT_PROCESS_H
+#define GYRO_AT_PROCESS_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include "errcode.h"
+#include "soc_osal.h"
+#include "at_cmd_api.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+at_cmd_table_t *get_gyro_cmd_table(uint32_t *cmd_count);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
diff --git a/code/sdk/drivers/peripheral/gyro/service/gyro_hal.c b/code/sdk/drivers/peripheral/gyro/service/gyro_hal.c
new file mode 100644 (file)
index 0000000..9e0f083
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2025-05-12 09:59:09
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-05-12 17:45:29
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/gyro/service/gyro_hal.c
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AEin
+ */
+#include <stdio.h>
+#include <stdbool.h>
+#include "gyro_hal.h"
+
+#ifdef GYRO_SH5001
+#include "sh5001.h"
+#endif
+
+void gyro_power_on(void)
+{
+#ifdef GYRO_SH5001
+    if(SH5001_init() == SH5001_TRUE)
+        printf("sh5001 init successful \n");
+    else
+        printf("sh5001 init failed \n");
+
+    if(SH5001_SwitchPowerMode(SH5001_NORMAL_MODE) == SH5001_TRUE)
+        printf("sh5001 start successful \n");
+    else
+        printf("sh5001 start failed \n");
+#endif
+}
+
+void gyro_power_off(void)
+{
+#ifdef GYRO_SH5001
+    if(SH5001_SwitchPowerMode(SH5001_POWERDOWN_MODE) == SH5001_TRUE)
+        printf("sh5001 stop successful \n");
+    else
+        printf("sh5001 stop failed \n");
+#endif   
+}
+
+void gyro_check(void)
+{
+#ifdef GYRO_SH5001
+    SH5001_ReadFIFO();
+#endif
+}
+
+bool gyro_check_exist(void)
+{
+#ifdef GYRO_SH5001
+    if(gyro_get_chip_id() != SH5001_ID)
+        return false;
+    else
+        return true;
+#endif 
+    return false;
+}
+
+gyro_data_t gyro_get_data(void)
+{
+    gyro_data_t data = {0};
+#ifdef GYRO_SH5001
+    data = sh5001_get_gyro_data();
+    // printf("%.3f %.3f %.3f\r\n",data.x,data.y,data.z);
+#endif 
+    return data;
+}
+
+uint8_t gyro_get_chip_id(void)
+{
+#ifdef GYRO_SH5001
+    return SH5001_get_chip_id();
+#endif 
+    return 0;
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gyro/service/gyro_hal.h b/code/sdk/drivers/peripheral/gyro/service/gyro_hal.h
new file mode 100644 (file)
index 0000000..2e73248
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2025-05-12 10:00:46
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-05-23 14:14:26
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/gyro/service/gyro_hal.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+#ifndef GYRO_HAL_H__
+#define GYRO_HAL_H__
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#include "stdint.h"
+#include "errcode.h"
+#include <stdbool.h>
+
+typedef struct {
+    float x;
+    float y;
+    float z;
+} gyro_data_t;
+
+
+void gyro_power_on(void);
+void gyro_power_off(void);
+void gyro_check(void);
+gyro_data_t gyro_get_data(void);
+uint8_t gyro_get_chip_id(void);
+bool gyro_check_exist(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gyro/service/gyro_service.c b/code/sdk/drivers/peripheral/gyro/service/gyro_service.c
new file mode 100644 (file)
index 0000000..51e46ee
--- /dev/null
@@ -0,0 +1,136 @@
+
+#include "debug_print.h"
+#include "soc_osal.h"
+#include "tcxo.h"
+#include "irmalloc.h"
+#include "errcode.h"
+#include "common_def.h"
+#include "tcxo.h"
+#include "input_app.h"
+#include "cmsis_os2.h"
+#include "custom_utils.h"
+#include "gyro_hal.h"
+#include "gyro_service.h"
+#ifdef ROTARYENCODER_MIXO
+#include "mixo_service.h"
+#endif
+// #include "custom_runtime.h"
+/***
+ * 其他cmd在Header里定义,对外开放
+*/
+#define GYRO_SERVICE_CMD_TIMER_CHECK 0x11
+
+static bool g_gyro_service_initialled = false;
+
+
+static bool g_gyro_sensor_exist = false;
+
+
+static unsigned long g_app_queue= 0xFFFFFFFF;
+
+
+void do_gyro_service_check_msg(int cmd);
+
+void do_gyro_service_check_msg(int cmd)
+{
+    int ret;
+    if (g_gyro_sensor_exist == false)
+        return ;
+    common_notify_mail_t mail = {0};
+    mail.comm.app = cmd;
+    ret = osal_msg_queue_write_copy(g_app_queue, (void *)&mail,
+                                    sizeof(common_notify_mail_t), 0);
+    if (ret != OSAL_SUCCESS) {
+        PRINT("Error gyro Check MSG 0x%02X send failed! err=0x%x! \r\n",cmd, ret);
+    }
+    
+}
+
+static void gyro_service_check_task(void const *arg)
+{
+    unused(arg);
+    int32_t ret;
+    common_notify_mail_t mail;
+    uint32_t msgsize = (uint32_t)sizeof(common_notify_mail_t);
+    while (1) {
+        ret = osal_msg_queue_read_copy(g_app_queue, (void *)&mail, &msgsize,
+                                       OSAL_MSGQ_WAIT_FOREVER);
+        if (ret != OSAL_SUCCESS) {
+            continue;
+        }
+
+        if (mail.comm.app == GYRO_SERVICE_CMD_TIMER_CHECK) {
+            gyro_check();
+        }else if (mail.comm.app == GYRO_SERVICE_CMD_START_CHECK){
+            gyro_power_on();
+        }else if (mail.comm.app == GYRO_SERVICE_CMD_STOP_CHECK){
+            gyro_power_off();
+        }
+
+
+    }
+}
+void create_gyro_queue(void)
+{
+
+    if (osal_msg_queue_create("gyro_service_queue", APP_BOARD_MSG_COUNT, &g_app_queue,
+                              0, sizeof(common_notify_mail_t)) != ERRCODE_SUCC) {
+        PRINT("[gyro][service] app create mail fail\n");
+    }
+}
+
+#define GYRO_BOARD_TASK_SIZE   0x500
+errcode_t uapi_gyro_service_init(void)
+{
+    PRINT("uapi_gyro_service_init !\r\n");
+
+    if(!gyro_check_exist())
+    {
+        //TODO 设置陀螺仪检测是否存在标识
+        PRINT("gyro not found!\r\n");
+        return ERRCODE_FAIL;
+    }
+    g_gyro_sensor_exist = true;
+
+    gyro_power_off();
+
+    app_task_definition_t taskcfg={0};
+    taskcfg.create_queue_handle = create_gyro_queue;
+    taskcfg.attr.name="gyro_service";
+    taskcfg.attr.priority = osPriorityBelowNormal4;
+    taskcfg.attr.stack_size = GYRO_BOARD_TASK_SIZE;
+    taskcfg.func = gyro_service_check_task;
+    taskcfg.use_mem = USE_EXTEND_MEM;
+    
+    errcode_t ret=uapi_create_osThread_custom(&taskcfg);
+    if(ret != ERRCODE_SUCC)
+    {
+        PRINT("create gyro_service failed %d!\r\n",ret);
+        return ERRCODE_FAIL;
+    }
+
+    return ERRCODE_SUCC;
+}
+
+void gyro_int_callback(pin_t pin, uintptr_t param)
+{
+    // PRINT("gyro_int_callback %d 0x%X\n",pin,param);
+    uapi_gpio_clear_interrupt(pin);
+    do_gyro_service_check_msg(GYRO_SERVICE_CMD_TIMER_CHECK);
+}
+
+void gyro_start(void)
+{
+    do_gyro_service_check_msg(GYRO_SERVICE_CMD_START_CHECK);
+#ifdef ROTARYENCODER_MIXO
+    mixo_stop();
+#endif
+}
+
+void gyro_stop(void)
+{
+    do_gyro_service_check_msg(GYRO_SERVICE_CMD_STOP_CHECK);
+#ifdef ROTARYENCODER_MIXO
+    mixo_start();
+#endif
+}
diff --git a/code/sdk/drivers/peripheral/gyro/service/gyro_service.h b/code/sdk/drivers/peripheral/gyro/service/gyro_service.h
new file mode 100644 (file)
index 0000000..3dd1288
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-12-23 15:12:01
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-05-12 17:47:11
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/gyro/service/gyro_service.h
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+/**
+ * Copyright (c) @CompanyNameMagicTag 2022-2022. All rights reserved. \n
+ *
+ * Description: Test adc header \n
+ * Author: @CompanyNameTag \n
+ * History: \n
+ * 2022-08-16, Create file. \n
+ */
+
+#ifndef GYRO_SERVICE_H__
+#define GYRO_SERVICE_H__
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#include "stdint.h"
+#include "errcode.h"
+#include "platform_core.h"
+
+#define GYRO_SERVICE_CMD_START_CHECK 0x12
+#define GYRO_SERVICE_CMD_STOP_CHECK 0x13
+
+errcode_t uapi_gyro_service_init(void);
+void uapi_gyro_service_deinit(void);
+void do_gyro_service_check_msg(int cmd);
+void gyro_int_callback(pin_t pin, uintptr_t param);
+void gyro_start(void);
+void gyro_stop(void);
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gyro/sh5001/sh5001.c b/code/sdk/drivers/peripheral/gyro/sh5001/sh5001.c
new file mode 100644 (file)
index 0000000..27035be
--- /dev/null
@@ -0,0 +1,3086 @@
+/******************************************************************\r
+* Senodia 6D IMU(Gyroscope+Accelerometer) SH5001 driver, By Senodia AE@20220505;\r
+*\r
+*\r
+* 1. SH5001_init() : SH5001 initialize function\r
+* 2. SH5001_GetImuData( ... ): SH5001 read gyro and accel data function\r
+* 3. SH5001_GetTempData(): SH5001 read termperature function\r
+* 4. delay_ms(x): delay x millisecond.\r
+* 5. SH5001_initFIFO(): initialize FIFO function\r
+* 6. SH5001_ReadFIFO(): read FIFO data\r
+*      \r
+******************************************************************/\r
+\r
+#include "sh5001.h"\r
+#include "custom_utils.h"\r
+#include "los_base.h"\r
+\r
+// 32-bit version number represented as major[31:16].minor[15:0]\r
+#define SH5001_MAJOR        1\r
+#define SH5001_MINOR       01\r
+#define SH5001_REV         31\r
+#define MCU_VERSION_SH5001  ((SH5001_MAJOR<<16) | (SH5001_MINOR<<8) | SH5001_REV)\r
+\r
+#define SH5001_I2C_BUS I2C_BUS_2\r
+\r
+static gyro_data_t gyro_data = {0};\r
+\r
+/******************************************************************\r
+* Description: I2C or SPI bus interface functions      and delay time function\r
+*\r
+* Parameters: \r
+*   devAddr: I2C device address, modify the macro(SH5001_ADDRESS @SH5001.h) based on your I2C function.                                                  \r
+*            If SPI interface, please ingnore the parameter.\r
+*   regAddr: register address\r
+*   readLen: data length to read\r
+*   *readBuf: data buffer to read; If using FIFO function, the max buffer size is 1024; \r
+*   writeLen: data length to write\r
+*   *writeBuf: data buffer to write\r
+*      \r
+* Note: I2C interface, define USER_INTERFACE_I2C (1)\r
+*       SPI interface, define USER_INTERFACE_I2C (0)\r
+*              SPI 3 Wire interface, define SH5001_SPI_3WIRE_MODE (1)\r
+*              SPI 4 Wire interface, define SH5001_SPI_3WIRE_MODE (0)\r
+*      \r
+******************************************************************/\r
+#define USER_INTERFACE_I2C             (1)\r
+\r
+#if USER_INTERFACE_I2C\r
+\r
+unsigned char I2C_ReadNBytes(  unsigned char devAddr, \r
+                                unsigned char regAddr, \r
+                                unsigned short readLen, \r
+                                unsigned char *readBuf)\r
+{\r
+       //your I2C interface code:\r
+       //......\r
+       custom_i2c_read_regs(devAddr, regAddr, 1, readBuf, readLen,SH5001_I2C_BUS);\r
+       return (SH5001_TRUE);\r
+}\r
+\r
+unsigned char I2C_WriteNBytes( unsigned char devAddr, \r
+                                unsigned char regAddr, \r
+                                unsigned short writeLen, \r
+                                unsigned char *writeBuf)\r
+{\r
+       //your I2C interface code:\r
+       //......\r
+       custom_i2c_write_reg(devAddr, regAddr, 1, writeBuf, writeLen,SH5001_I2C_BUS);\r
+       return (SH5001_TRUE);\r
+}                                                                                                                              \r
+\r
+IMU_read    SH5001_read     = I2C_ReadNBytes;\r
+IMU_write   SH5001_write    = I2C_WriteNBytes;\r
+\r
+#else\r
+\r
+#define SH5001_SPI_3WIRE_MODE  (0)\r
+\r
+unsigned char SPI_readNBytes ( unsigned char devAddr, \r
+                                unsigned char regAddr, \r
+                                unsigned short readLen, \r
+                                unsigned char *readBuf)\r
+{\r
+       //your SPI interface code:\r
+\r
+       //For example:  \r
+       //unsigned char u8Data;         \r
+       //devAddr = devAddr;    \r
+       //u8Data = (regAddr > 0x7F) ? 0x01 : 0x00;\r
+       //SPIWrite(SH5001_SPI_REG_ACCESS, &u8Data, 1);\r
+       \r
+       //SPIRead((regAddr | 0x80), readBuf, readLen);  \r
+       return (SH5001_TRUE);\r
+}\r
+\r
+unsigned char SPI_writeNBytes( unsigned char devAddr, \r
+                                unsigned char regAddr, \r
+                                unsigned short writeLen, \r
+                                unsigned char *writeBuf)\r
+{\r
+       //your SPI interface code:\r
+       \r
+       //For example: \r
+       //unsigned char u8Data; \r
+       //devAddr = devAddr;    \r
+       //u8Data = (regAddr > 0x7F) ? 0x01 : 0x00;\r
+       //SPIWrite(SH5001_SPI_REG_ACCESS, &u8Data, 1);\r
+       \r
+       //SPIWrite((regAddr & 0x7F), writeBuf, writeLen);\r
+       return (SH5001_TRUE);\r
+}                                                                                                                              \r
+\r
+IMU_read       SH5001_read             = SPI_readNBytes;\r
+IMU_write      SH5001_write    = SPI_writeNBytes;\r
+\r
+#endif\r
+\r
+\r
+static void delay_ms(unsigned short mSecond)\r
+{  \r
+       //your delay code(mSecond: millisecond):\r
+       //......\r
+       LOS_Mdelay(mSecond);\r
+       // HAL_Delay(mSecond);\r
+} \r
+\r
+\r
+#if SH5001_OIS_ENABLE\r
+unsigned char SH5001_OIS_read( unsigned char devAddr,\r
+                                unsigned char regAddr,\r
+                                unsigned short readLen,\r
+                                unsigned char *readBuf)\r
+{\r
+       //your SPI interface code:\r
+\r
+\r
+       //SPIRead((regAddr | 0x80), readBuf, readLen);\r
+       return (SH5001_TRUE);\r
+}\r
+\r
+#endif\r
+\r
+\r
+/******************************************************************\r
+* Description: Local Variable          \r
+******************************************************************/\r
+\r
+\r
+/******************************************************************\r
+* Description: Local Function Prototypes               \r
+******************************************************************/\r
+static void SH5001_ModuleReset(void);\r
+static void SH5001_Acc_Config(unsigned char accODR, \r
+                              unsigned char accRange, \r
+                              unsigned char accCutOffFreq,\r
+                              unsigned char accFilter,\r
+                              unsigned char accByPass);\r
+\r
+static void SH5001_Gyro_Config(        unsigned char gyroODR, \r
+                                unsigned char gyroRange, \r
+                                unsigned char gyroCutOffFreq,\r
+                                unsigned char gyroFilter,\r
+                                unsigned char gyroByPass);\r
+\r
+static void SH5001_TimeStamp_Config(unsigned char timeStampODR, \r
+                                       unsigned char timeStampEnable);\r
+\r
+static void SH5001_Temp_Config(        unsigned char tempODR, \r
+                                unsigned char tempEnable);                                                                                                                                                                                                     \r
+\r
+       \r
+\r
+static void SH5001_SoftReset(void)\r
+{\r
+       unsigned char regData = 0;\r
+\r
+       regData = 0x01;\r
+       SH5001_write(SH5001_ADDRESS, 0x2B, 1, &regData);\r
+       regData = 0x73;\r
+       SH5001_write(SH5001_ADDRESS, 0x00, 1, &regData);\r
+\r
+       delay_ms(50);\r
+}\r
+\r
+static void SH5001_DriveStart(void)\r
+{\r
+       unsigned char regData = 0;\r
+       //Driver start\r
+       regData = 0x01;\r
+       SH5001_write(SH5001_ADDRESS, 0x2B, 1, &regData);\r
+\r
+       delay_ms(2);\r
+\r
+       regData = 0x00;\r
+       SH5001_write(SH5001_ADDRESS, 0x2B, 1, &regData);\r
+\r
+       delay_ms(1);\r
+\r
+}\r
+\r
+static void SH5001_ADCReset(void)\r
+{\r
+    unsigned char regData = 0;\r
+\r
+       regData = 0x08;\r
+       SH5001_write(SH5001_ADDRESS, 0x30, 1, &regData);\r
+\r
+       regData = 0x00;\r
+       SH5001_write(SH5001_ADDRESS, 0xD2, 1, &regData);\r
+\r
+       regData = 0x6B;\r
+       SH5001_write(SH5001_ADDRESS, 0xD1, 1, &regData);\r
+\r
+       regData = 0x02;\r
+       SH5001_write(SH5001_ADDRESS, 0xD5, 1, &regData);\r
+       delay_ms(5);\r
+\r
+       regData = 0x68;\r
+       SH5001_write(SH5001_ADDRESS, 0xD1, 1, &regData);\r
+       delay_ms(2);\r
+\r
+       regData = 0x00;\r
+       SH5001_write(SH5001_ADDRESS, 0xD5, 1, &regData);\r
+\r
+       regData = 0x00;\r
+       SH5001_write(SH5001_ADDRESS, 0x30, 1, &regData);\r
+\r
+       regData = 0x08;\r
+       SH5001_write(SH5001_ADDRESS, 0x30, 1, &regData);\r
+\r
+       regData = 0xE0;\r
+       SH5001_write(SH5001_ADDRESS, 0xD8, 1, &regData);\r
+\r
+       delay_ms(5);\r
+\r
+       regData = 0x00;\r
+       SH5001_write(SH5001_ADDRESS, 0xD8, 1, &regData);\r
+\r
+       regData = 0x00;\r
+       SH5001_write(SH5001_ADDRESS, 0x30, 1, &regData);\r
+}\r
+\r
+static void SH5001_CVAReset(void)\r
+{\r
+       unsigned char regData = 0;\r
+\r
+       regData = 0x12;\r
+       SH5001_write(SH5001_ADDRESS, 0xCD, 1, &regData);\r
+       regData = 0x12;\r
+       SH5001_write(SH5001_ADDRESS, 0xCE, 1, &regData);\r
+       regData = 0x12;\r
+       SH5001_write(SH5001_ADDRESS, 0xCF, 1, &regData);\r
+\r
+       delay_ms(1);\r
+\r
+       regData = 0x2;\r
+       SH5001_write(SH5001_ADDRESS, 0xCD, 1, &regData);\r
+       regData = 0x2;\r
+       SH5001_write(SH5001_ADDRESS, 0xCE, 1, &regData);\r
+       regData = 0x2;\r
+       SH5001_write(SH5001_ADDRESS, 0xCF, 1, &regData);\r
+\r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: reset some internal modules;\r
+*\r
+* Parameters: void     \r
+*                                              \r
+* return:      void\r
+*                                                                                                                              \r
+******************************************************************/\r
+static void SH5001_ModuleReset(void)\r
+{\r
+       unsigned char regData = 0;      \r
+       \r
+       // soft reset\r
+       SH5001_SoftReset();\r
+\r
+#if SH5001_SPI_3WIRE_MODE\r
+       SH5001_SPI_Config(SH5001_SPI_3_WIRE);\r
+#endif \r
+\r
+       //Driver start\r
+       SH5001_DriveStart();\r
+\r
+       \r
+       // ADC reset\r
+       SH5001_ADCReset();\r
+\r
+       //CVA Reset\r
+       SH5001_CVAReset();\r
+\r
+       delay_ms(250);\r
+}      \r
+\r
+\r
+/******************************************************************\r
+* Description: 1.set accelerometer parameters;\r
+*               2.accCutOffRreq = accODR * 0.40 or accODR * 0.25 or accODR * 0.11 or accODR * 0.04 or accODR * 0.02;\r
+*\r
+* Parameters:  accODR                  accRange                accCutOffFreq           accFilter                               accByPass\r
+*               SH5001_ACC_ODR_1000HZ  SH5001_ACC_RANGE_16G    SH5001_ACC_ODRX040              SH5001_ACC_FILTER_EN    SH5001_ACC_BYPASS_EN\r
+*               SH5001_ACC_ODR_500HZ   SH5001_ACC_RANGE_8G             SH5001_ACC_ODRX025              SH5001_ACC_FILTER_DIS   SH5001_ACC_BYPASS_DIS\r
+*               SH5001_ACC_ODR_250HZ   SH5001_ACC_RANGE_4G             SH5001_ACC_ODRX011\r
+*               SH5001_ACC_ODR_125HZ   SH5001_ACC_RANGE_2G             SH5001_ACC_ODRX004\r
+*               SH5001_ACC_ODR_63HZ                                                            SH5001_ACC_ODRX002\r
+*               SH5001_ACC_ODR_31HZ\r
+*               SH5001_ACC_ODR_16HZ\r
+*               SH5001_ACC_ODR_2000HZ\r
+*               SH5001_ACC_ODR_4000HZ\r
+*               SH5001_ACC_ODR_8000HZ\r
+*  \r
+* return:      void\r
+*\r
+******************************************************************/\r
+unsigned char storeAccODR;\r
+static void SH5001_Acc_Config(unsigned char accODR, \r
+                              unsigned char accRange, \r
+                              unsigned char accCutOffFreq,\r
+                              unsigned char accFilter,\r
+                              unsigned char accByPass)\r
+{\r
+    unsigned char regData = 0; \r
+       \r
+       // enable acc digital filter and bypass or not\r
+       SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF0, 1, &regData);\r
+       regData = (regData & 0xFCU) | accFilter | accByPass;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF0, 1, &regData);\r
+       \r
+       // set acc ODR range\r
+       SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF1, 1, &regData);\r
+       regData = (regData & 0x80U) | accODR | accRange;\r
+       storeAccODR = regData;\r
+       //regData = (regData & 0x80U)| accRange | accODR;\r
+       //regData = (regData & 0x80U)| 0x38;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF1, 1, &regData);\r
+       \r
+       // set acc low pass filter cut-off frequency\r
+       SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, &regData);\r
+       regData = (regData & 0xF0U) | accCutOffFreq;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, &regData);\r
+\r
+}\r
+\r
+\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.set accelerometer parameters;\r
+*               2.accCutOffRreq = accODR * 0.40 or accODR * 0.25 or accODR * 0.11 or accODR * 0.04 or accODR * 0.02;\r
+*\r
+* Parameters:  accODR                  accRange                accCutOffFreq           accOisEnable\r
+\r
+* return:      void\r
+*\r
+******************************************************************/\r
+static void SH5001_Acc_OIS_Config(unsigned char accODR,\r
+                              unsigned char accRange,\r
+                              unsigned char accCutOffFreq,\r
+                              unsigned char accOisEnable)\r
+{\r
+    unsigned char regData = 0;\r
+\r
+       regData = accODR | accRange | accCutOffFreq | accOisEnable;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_OIS_ACC_CONF, 1, &regData);\r
+\r
+}\r
+\r
+/******************************************************************\r
+* Description: 1.set gyroscope parameters;\r
+*               2.gyroCutOffRreq is at Page 33 of SH5001 datasheet.\r
+*\r
+* Parameters:   gyroODR                gyroRangeX,Y,Z          gyroCutOffFreq      gyroFilter                          gyroByPass\r
+*               SH5001_GYRO_ODR_800HZ  SH5001_GYRO_RANGE_125   SH5001_GYRO_ODRX00      SH5001_GYRO_FILTER_EN   SH5001_GYRO_BYPASS_EN\r
+*               SH5001_GYRO_ODR_400HZ  SH5001_GYRO_RANGE_250   SH5001_GYRO_ODRX01      SH5001_GYRO_FILTER_DIS  SH5001_GYRO_BYPASS_DIS\r
+*               SH5001_GYRO_ODR_200HZ  SH5001_GYRO_RANGE_500   SH5001_GYRO_ODRX02\r
+*               SH5001_GYRO_ODR_100HZ  SH5001_GYRO_RANGE_1000  SH5001_GYRO_ODRX03\r
+*               SH5001_GYRO_ODR_50HZ   SH5001_GYRO_RANGE_2000\r
+*               SH5001_GYRO_ODR_25HZ\r
+*               SH5001_GYRO_ODR_1600HZ\r
+*               SH5001_GYRO_ODR_3200HZ\r
+*               SH5001_GYRO_ODR_6400HZ\r
+*               SH5001_GYRO_ODR_12800HZ\r
+*               SH5001_GYRO_ODR_25600HZ\r
+*       \r
+*               gyroOnOff\r
+*               SH5001_GYRO_OFF_INACT\r
+*               SH5001_GYRO_ON_INACT\r
+* return:      void\r
+*\r
+******************************************************************/\r
+/*\r
+static void SH5001_Gyro_Config(        unsigned char gyroODR, \r
+                                unsigned char gyroRange, \r
+                                unsigned char gyroCutOffFreq,\r
+                                unsigned char gyroFilter,\r
+                                unsigned char gyroByPass,\r
+                                unsigned char gyroOnOff)\r
+{\r
+    unsigned char regData = 0; \r
+       \r
+       // enable gyro digital filter\r
+       SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, &regData);\r
+       regData = (regData & 0x7CU) | gyroFilter | gyroByPass | gyroOnOff;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, &regData);\r
+       \r
+       // set gyro ODR\r
+       SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF1, 1, &regData);\r
+       regData = (regData & 0xF0U) | gyroODR;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF1, 1, &regData);\r
+       \r
+       // set gyro low pass filter cut-off frequency\r
+       SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF2, 1, &regData);\r
+       regData = (regData & 0xFCU) | gyroCutOffFreq;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF2, 1, &regData);\r
+               \r
+\r
+       // set gyro range\r
+       SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF3, 1, &regData);\r
+       regData = (regData & 0xF8U) | gyroRange;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF3, 1, &regData);            \r
+\r
+}\r
+\r
+*/\r
+static void SH5001_Gyro_Config(        unsigned char gyroODR,\r
+                                unsigned char gyroRange,\r
+                                unsigned char gyroCutOffFreq,\r
+                                unsigned char gyroFilter,\r
+                                unsigned char gyroByPass)\r
+{\r
+    unsigned char regData = 0;\r
+\r
+       // enable gyro digital filter\r
+       SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, &regData);\r
+       regData = (regData & 0x7CU) | gyroFilter | gyroByPass;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, &regData);\r
+\r
+       // set gyro ODR Range\r
+       SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF1, 1, &regData);\r
+       regData = (regData & 0x80U) | gyroODR | gyroRange;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF1, 1, &regData);\r
+\r
+       // set gyro low pass filter cut-off frequency\r
+       SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF2, 1, &regData);\r
+       regData = (regData & 0xF0U) | gyroCutOffFreq;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF2, 1, &regData);\r
+\r
+}\r
+\r
+//Jin: Modify \r
+/*  */\r
+\r
+\r
+static void SH5001_Gyro_OIS_Config(    unsigned char gyroODR,\r
+                                unsigned char gyroRange,\r
+                                unsigned char gyroCutOffFreq,\r
+                                unsigned char gyroOisEnable)\r
+{\r
+    unsigned char regData = 0;\r
+\r
+       regData = gyroODR | gyroRange | gyroCutOffFreq | gyroOisEnable;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_OIS_GYRO_CONF, 1, &regData);\r
+\r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: set time stamp parameters;\r
+*\r
+* Parameters:  timeStampODR                    timeStampEnable\r
+*               SH5001_TS_ODR_25KHZ            SH5001_TS_EN\r
+*               SH5001_TS_ODR_1KHZ             SH5001_TS_DIS           \r
+*\r
+* return:      void\r
+*                                                      \r
+******************************************************************/\r
+static void SH5001_TimeStamp_Config(unsigned char timeStampODR, \r
+                                       unsigned char timeStampEnable)\r
+{\r
+    unsigned char regData = 0; \r
+       \r
+       // config time stamp\r
+       SH5001_read(SH5001_ADDRESS, SH5001_TIMESTAMP_CONF, 1, &regData);\r
+       regData = (regData & 0x9FU) | timeStampODR | timeStampEnable;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_TIMESTAMP_CONF, 1, &regData);\r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: set temperature parameters;\r
+*\r
+* Parameters:  tempODR                   tempEnable\r
+*               SH5001_TEMP_ODR_500HZ    SH5001_TEMP_EN\r
+*               SH5001_TEMP_ODR_250HZ    SH5001_TEMP_DIS\r
+*               SH5001_TEMP_ODR_125HZ          \r
+*               SH5001_TEMP_ODR_63HZ           \r
+*\r
+* return:      void\r
+*                                                      \r
+******************************************************************/\r
+static void SH5001_Temp_Config(        unsigned char tempODR, \r
+                                unsigned char tempEnable)\r
+{\r
+    unsigned char regData = 0; \r
+       \r
+       // enable temperature, set ODR\r
+       SH5001_read(SH5001_ADDRESS, SH5001_TEMP_CONF0, 1, &regData);\r
+       regData = (regData & 0xF8U) | tempODR | tempEnable;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_TEMP_CONF0, 1, &regData);\r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: read temperature parameters;\r
+*\r
+* Parameters:  void    \r
+*              \r
+* return:      temperature data(deg);\r
+* \r
+******************************************************************/\r
+float SH5001_GetTempData(void)\r
+{\r
+    unsigned char regData[2] = {0};    \r
+    unsigned short int tempref[2] = {0};\r
+       \r
+       // read temperature data, unsigned 12bits;   SH5001_TEMP_CONF2..SH5001_TEMP_CONF1\r
+       SH5001_read(SH5001_ADDRESS, SH5001_TEMP_CONF1, 2, &regData[0]);\r
+       tempref[0] = ((unsigned short int)(regData[1] & 0x0FU) << 8U) | regData[0];\r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_TEMP_ZL, 2, &regData[0]);\r
+       tempref[1] = ((unsigned short int)(regData[1] & 0x0FU) << 8U) | regData[0];     \r
+       \r
+       return ( (((float)(tempref[1] - tempref[0]))/14.0f) + 25.0f );\r
+}\r
+\r
+\r
+\r
+/******************************************************************\r
+* Description: enable or disable INT, mapping interrupt to INT pin or INT1 pin\r
+*\r
+* Parameters:   intType                 intEnable               intPinSel\r
+*               SH5001_INT_LOWG         SH5001_INT_EN                  SH5001_INT_MAP_INT0\r
+*               SH5001_INT_HIGHG        SH5001_INT_DIS         SH5001_INT_MAP_INT1\r
+*               SH5001_INT_INACT                         \r
+*               SH5001_INT_ACT\r
+*               SH5001_INT_DOUBLE_TAP\r
+*               SH5001_INT_SINGLE_TAP\r
+*               SH5001_INT_FLAT\r
+*               SH5001_INT_ORIENTATION\r
+*                              SH5001_INT_TAP (Only INT/INT1 Map)\r
+*                              SH5001_INT_SMD\r
+*               SH5001_INT_FIFO_WATERMARK\r
+*               SH5001_INT_GYRO_READY\r
+*               SH5001_INT_ACC_READY\r
+*               SH5001_INT_FREE_FALL\r
+*               SH5001_INT_UP_DOWN_Z\r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_INT_Enable(        unsigned short intType, \r
+                        unsigned char intEnable, \r
+                        unsigned char intPinSel)\r
+{\r
+  unsigned char regData[2] = {0};      \r
+  unsigned short int u16IntVal = 0; \r
+       \r
+       // Z axis change between UP to DOWN\r
+       if((intType & 0x0040U) == SH5001_INT_UP_DOWN_Z)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_ORIEN_INTCONF0, 1, &regData[0]);\r
+               regData[0] = (intEnable == SH5001_INT_EN) \\r
+                     ? (regData[0] & 0xBFU) : (regData[0] | 0x40U);\r
+               SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INTCONF0, 1, &regData[0]);\r
+       }       \r
+       \r
+       if(intType & 0xFF3FU)\r
+       {       \r
+               // enable or disable INT\r
+               SH5001_read(SH5001_ADDRESS, SH5001_INT_ENABLE0, 2, &regData[0]); \r
+    \r
+               u16IntVal = ((unsigned short int)regData[0] << 8U) | regData[1]; \r
+               \r
+               u16IntVal = u16IntVal & 0xFF1FU;\r
+               u16IntVal = (intEnable == SH5001_INT_EN) \\r
+                    ? (u16IntVal | intType) : (u16IntVal & ~intType);          \r
+                \r
+               regData[0] = (unsigned char)(u16IntVal >> 8U);\r
+               regData[1] = (unsigned char)(u16IntVal);                \r
+               //SH5001_write(SH5001_ADDRESS, SH5001_INT_ENABLE0, 2, &regData[0]);\r
+               SH5001_write(SH5001_ADDRESS, SH5001_INT_ENABLE0, 1, &regData[0]);\r
+               SH5001_write(SH5001_ADDRESS, SH5001_INT_ENABLE1, 1, &regData[1]);\r
+                               \r
+               // mapping interrupt to INT0 pin or INT1 pin\r
+               SH5001_read(SH5001_ADDRESS, SH5001_INT_PIN_MAP0, 2, &regData[0]);\r
+               u16IntVal = ((unsigned short int)regData[0] << 8U) | regData[1];\r
+    \r
+               u16IntVal = u16IntVal & 0xFF3FU;\r
+        u16IntVal = (intPinSel == SH5001_INT_MAP_INT1) \\r
+                    ? (u16IntVal | intType) : (u16IntVal & ~intType);  \r
+               \r
+               regData[0] = (unsigned char)(u16IntVal >> 8U);\r
+               regData[1] = (unsigned char)(u16IntVal);\r
+               SH5001_write(SH5001_ADDRESS, SH5001_INT_PIN_MAP0, 1, &regData[0]);\r
+               SH5001_write(SH5001_ADDRESS, SH5001_INT_PIN_MAP1, 1, &regData[1]);\r
+       }       \r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.config INT function\r
+*               2.intCount is valid only when intLatch is equal to SH5001_INT_NO_LATCH;\r
+*\r
+* Parameters:   intLevel                                       intLatch                                        intClear                                        \r
+*               SH5001_INT_LEVEL_HIGH          SH5001_INT_NO_LATCH                     SH5001_INT_CLEAR_ANY\r
+*               SH5001_INT_LEVEL_LOW           SH5001_INT_LATCH                        SH5001_INT_CLEAR_STATUS\r
+*\r
+*               intTime\r
+*               Unit: 2mS\r
+*\r
+*                              int1Mode                                        int0Mode\r
+*               SH5001_INT1_NORMAL                     SH5001_INT0_NORMAL\r
+*               SH5001_INT1_OD                         SH5001_INT0_OD\r
+*\r
+*                              int1OE                                          int0OE\r
+*                              SH5001_INT1_OUTPUT                      SH5001_INT0_OUTPUT\r
+*                              SH5001_INT1_INPUT                       SH5001_INT1_INPUT\r
+*\r
+* return:      void\r
+* \r
+******************************************************************/\r
+\r
+\r
+void SH5001_INT_Config(        unsigned char intLevel,\r
+                        unsigned char intLatch,\r
+                        unsigned char intClear,\r
+                        unsigned char intTime,\r
+                        unsigned char int1Mode,\r
+                        unsigned char int0Mode,\r
+                        unsigned char int1OE,\r
+                        unsigned char int0OE)\r
+{\r
+       unsigned char regData = 0;\r
+\r
+       //SH5001_read(SH5001_ADDRESS, SH5001_INT_CONF, 1, &regData);\r
+\r
+    regData = (intLevel == SH5001_INT0_LEVEL_LOW) \\r
+              ? (regData | SH5001_INT0_LEVEL_LOW) : (regData & SH5001_INT0_LEVEL_HIGH);\r
+\r
+    regData = (intLatch == SH5001_INT_NO_LATCH) \\r
+              ? (regData | SH5001_INT_NO_LATCH) : (regData & SH5001_INT_LATCH);\r
+\r
+    regData = (intClear == SH5001_INT_CLEAR_ANY) \\r
+              ? (regData | SH5001_INT_CLEAR_ANY) : (regData & SH5001_INT_CLEAR_STATUS);\r
+\r
+    regData = (int1Mode == SH5001_INT1_OD) \\r
+              ? (regData | SH5001_INT1_OD) : (regData & SH5001_INT1_NORMAL);\r
+\r
+    regData = (int1OE == SH5001_INT1_OUTPUT) \\r
+              ? (regData | SH5001_INT1_OUTPUT) : (regData & SH5001_INT1_INPUT);\r
+\r
+    regData = (int0Mode == SH5001_INT0_OD) \\r
+              ? (regData | SH5001_INT0_OD) : (regData & SH5001_INT0_NORMAL);\r
+\r
+    regData = (int0OE == SH5001_INT0_OUTPUT) \\r
+              ? (regData | SH5001_INT0_OUTPUT) : (regData & SH5001_INT0_INPUT);\r
+\r
+       SH5001_write(SH5001_ADDRESS, SH5001_INT_CONF, 1, &regData);\r
+\r
+       if(intLatch == SH5001_INT_NO_LATCH)\r
+       {\r
+               regData = intTime;\r
+               SH5001_write(SH5001_ADDRESS, SH5001_INT_LIMIT, 1, &regData);\r
+       }\r
+}\r
+\r
+\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.config INT0 & INT1 function\r
+*\r
+* Parameters:  int1Mode                                        int0Mode\r
+*               SH5001_INT1_NORMAL                     SH5001_INT0_NORMAL\r
+*               SH5001_INT1_OD                         SH5001_INT0_OD\r
+*\r
+*                              int1OE                                          int0OE          \r
+*                              SH5001_INT1_OUTPUT                      SH5001_INT0_OUTPUT\r
+*                              SH5001_INT1_INPUT                       SH5001_INT1_INPUT\r
+*\r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_INT_Output_Config( unsigned char int1Mode,\r
+                                                               unsigned char int0Mode,\r
+                                                               unsigned char int1OE,\r
+                                                               unsigned char int0OE)\r
+{\r
+       unsigned char regData = 0;       \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_INT_CONF, 1, &regData);\r
+               \r
+       regData = (int1Mode == SH5001_INT1_OD) \\r
+              ? (regData | SH5001_INT1_OD) : (regData & SH5001_INT1_NORMAL);\r
+       \r
+       regData = (int1OE == SH5001_INT1_OUTPUT) \\r
+              ? (regData | SH5001_INT1_OUTPUT) : (regData & SH5001_INT1_INPUT);\r
+  \r
+       regData = (int0Mode == SH5001_INT0_OD) \\r
+              ? (regData | SH5001_INT0_OD) : (regData & SH5001_INT0_NORMAL);\r
+       \r
+       regData = (int0OE == SH5001_INT0_OUTPUT) \\r
+              ? (regData | SH5001_INT0_OUTPUT) : (regData & SH5001_INT1_INPUT);                        \r
+       \r
+       SH5001_write(SH5001_ADDRESS, SH5001_INT_CONF, 1, &regData);      \r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: orientation config;\r
+*\r
+* Parameters:  orientBlockMode                         orientMode                              orientTheta\r
+*               SH5001_ORIENT_BLOCK_MODE0      SH5001_ORIENT_SYMM                      (1 Byte)\r
+*               SH5001_ORIENT_BLOCK_MODE1      SH5001_ORIENT_HIGH_ASYMM\r
+*               SH5001_ORIENT_BLOCK_MODE2      SH5001_ORIENT_LOW_ASYMM\r
+*               SH5001_ORIENT_BLOCK_MODE3\r
+*\r
+*               orientG1point5                         orientSlope                                     orientHyst\r
+*               (2 Bytes)                                      (2 Bytes)                                       (2 Bytes)\r
+*              \r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_INT_Orient_Config( unsigned char   orientBlockMode,\r
+                                unsigned char  orientMode,\r
+                                unsigned char  orientTheta,\r
+                                unsigned short orientG1point5,\r
+                                unsigned short         orientSlope,\r
+                                unsigned short         orientHyst)\r
+{\r
+       unsigned char regData[2] = {0}; \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_ORIEN_INTCONF0, 1, &regData[0]);\r
+       regData[0] |= (regData[0] & 0xC0U) | (orientTheta & 0x3FU); \r
+       SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INTCONF0, 1, &regData[0]);\r
+\r
+       SH5001_read(SH5001_ADDRESS, SH5001_ORIEN_INTCONF1, 1, &regData[0]);\r
+       regData[0] |= (regData[0] & 0xF0U) | (orientBlockMode & 0x0CU) | (orientMode & 0x03U);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INTCONF1, 1, &regData[0]);\r
+       \r
+       regData[0] = (unsigned char)orientG1point5;\r
+       regData[1] = (unsigned char)(orientG1point5 >> 8U);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INT_1G5_LOW, 2, &regData[0]);\r
+       \r
+       regData[0] = (unsigned char)orientSlope;\r
+       regData[1] = (unsigned char)(orientSlope >> 8U);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INT_SLOPE_LOW, 2, &regData[0]);       \r
+       \r
+       regData[0] = (unsigned char)orientHyst;\r
+       regData[1] = (unsigned char)(orientHyst >> 8U);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INT_HYST_LOW, 2, &regData[0]);         \r
+}\r
+\r
+\r
+\r
+// Jin: flatTimeTH 200,400,800,000, sure? \r
+\r
+/******************************************************************\r
+* Description: flat INT time threshold, unit: mS;\r
+*\r
+* Parameters:  flatTimeTH                                      flatTanHeta2\r
+*               SH5001_FLAT_TIME_200MS         0 ~ 63\r
+*               SH5001_FLAT_TIME_400MS\r
+*               SH5001_FLAT_TIME_800MS\r
+*               SH5001_FLAT_TIME_000MS\r
+*              \r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_INT_Flat_Config(unsigned char flatTimeTH, \r
+                                                       unsigned char flatTanHeta2)\r
+{\r
+       unsigned char regData = 0;      \r
+  \r
+    SH5001_read(SH5001_ADDRESS, SH5001_ORIEN_INTCONF1, 1, &regData);   \r
+    regData = (regData & 0xF3U) | SH5001_ORIENT_BLOCK_MODE1;\r
+    SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INTCONF1, 1, &regData);  \r
+  \r
+    SH5001_read(SH5001_ADDRESS, SH5001_FLAT_INT_CONF, 1, &regData);    \r
+       regData =  (flatTimeTH & 0xC0U) | (flatTanHeta2 & 0x3FU);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_FLAT_INT_CONF, 1, &regData);                \r
+}      \r
+\r
+// Jin: Act  and inAct function --- actIntClear ?\r
+\r
+/******************************************************************\r
+* Description: activity INT config;\r
+*                              actIntThres: 1 LSB is 0.24mg@+/-2G, 0.48mg@+/-4G, 0.97mg@+/-8G, 1.95mg@+/-16G\r
+*\r
+* Parameters:  actEnDisIntX                    actEnDisIntY                    actEnDisIntZ\r
+*               SH5001_ACT_X_INT_EN            SH5001_ACT_Y_INT_EN             SH5001_ACT_Z_INT_EN\r
+*               SH5001_ACT_X_INT_DIS   SH5001_ACT_Y_INT_DIS    SH5001_ACT_Z_INT_DIS\r
+*                                                              \r
+*                                                              \r
+*               actTimeNum             actIntThres             actLinkStatus                           actIntClear                                             \r
+*               (1 Byte)               (2 Byte2)               SH5001_LINK_PRE_STA                     SH5001_ACT_INACT_CLR_STATUS1\r
+*                                                                              SH5001_LINK_PRE_STA_NO          SH5001_ACT_INACT_CLR_STATUS3\r
+*\r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_INT_Act_Config(    unsigned char actEnDisIntX,\r
+                            unsigned char actEnDisIntY,\r
+                            unsigned char actEnDisIntZ,\r
+                            unsigned char actTimeNum,\r
+                            unsigned short actIntThres,\r
+                            unsigned char actLinkStatus,\r
+                            unsigned char actIntClear)\r
+{\r
+       unsigned char regData[2] = {0}; \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_ACT_INACT_INT_CONF, 1, &regData[0]); \r
+       regData[0] |= (regData[0] & 0x8FU) | actEnDisIntX | actEnDisIntY | actEnDisIntZ;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACT_INACT_INT_CONF, 1, &regData[0]);        \r
+       \r
+       regData[0] = (unsigned char)actIntThres;\r
+       regData[1] = (unsigned char)(actIntThres >> 8U);\r
+       //SH5001_write(SH5001_ADDRESS, SH5001_ACT_INT_THRESHOLDL, 2, &regData[0]);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACT_INT_THRESHOLDL, 1, &regData[0]);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACT_INT_THRESHOLDH, 1, &regData[1]);\r
+\r
+       regData[0] = actTimeNum;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACT_INT_TIME, 1, &regData[0]);\r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_ACT_INACT_INT_LINK, 1, &regData[0]); \r
+       regData[0] |= (regData[0] & 0x7EU) | actLinkStatus | actIntClear;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACT_INACT_INT_LINK, 1, &regData[0]);           \r
+}      \r
+\r
+\r
+/******************************************************************\r
+* Description: inactivity INT config;\r
+*\r
+* Parameters:  inactEnDisIntX              inactEnDisIntY                              inactEnDisIntZ\r
+*               SH5001_INACT_X_INT_EN          SH5001_INACT_Y_INT_EN           SH5001_INACT_Z_INT_EN\r
+*               SH5001_INACT_X_INT_DIS     SH5001_INACT_Y_INT_DIS          SH5001_INACT_Z_INT_DIS\r
+*                                                                                                                              \r
+*               inactLinkStatus                                inactTimeMs                                     inactIntThres\r
+*               SH5001_LINK_PRE_STA                    Unit: mS                                        (2 Bytes)                               \r
+*               SH5001_LINK_PRE_STA_NO\r
+*\r
+*               inactG1                                                inactIntClear\r
+*               (2 Bytes)                                      SH5001_ACT_INACT_CLR_STATUS1\r
+*                                                                                      SH5001_ACT_INACT_CLR_STATUS3\r
+*\r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_INT_Inact_Config(  unsigned char inactEnDisIntX,\r
+                                unsigned char inactEnDisIntY,\r
+                                unsigned char inactEnDisIntZ,\r
+                                unsigned char inactLinkStatus,\r
+                                unsigned char inactTimeMs,\r
+                                unsigned short inactIntThres,\r
+                                unsigned short inactG1,\r
+                                unsigned char inactIntClear)\r
+{\r
+       unsigned char regData = 0;      \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_ACT_INACT_INT_CONF, 1, &regData);            \r
+       regData |= (regData & 0xF8U) | inactEnDisIntX | inactEnDisIntY | inactEnDisIntZ;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACT_INACT_INT_CONF, 1, &regData);   \r
+       \r
+       regData = (unsigned char)inactIntThres;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_INACT_INT_THRESHOLDL, 1, &regData);\r
+       regData = (unsigned char)(inactIntThres >> 8U);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_INACT_INT_THRESHOLDH, 1, &regData); \r
+               \r
+       regData = inactTimeMs;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_INACT_INT_TIME, 1, &regData);       \r
+       \r
+       /*\r
+       regData = (unsigned char)inactG1;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_INACT_INT_1G_REFL, 1, &regData);\r
+       regData = (unsigned char)(inactG1 >> 8U);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_INACT_INT_1G_REFH, 1, &regData);    \r
+               \r
+       SH5001_read(SH5001_ADDRESS, SH5001_ACT_INACT_INT_LINK, 1, &regData);    \r
+       regData |= (regData & 0x7EU) | inactLinkStatus | inactIntClear;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACT_INACT_INT_LINK, 1, &regData);           \r
+       */\r
+}      \r
+\r
+\r
+/******************************************************************\r
+* Description: 1.tap INT config;\r
+*                              2.tapIntThres is between 0 and 8191;\r
+*               3.tapWaitTimeWindowMs is more than tapWaitTimeMs;\r
+*\r
+* Parameters:  tapEnDisIntX                            tapEnDisIntY                            tapEnDisIntZ\r
+*               SH5001_TAP_X_INT_EN                    SH5001_TAP_Y_INT_EN                     SH5001_TAP_Z_INT_EN\r
+*               SH5001_TAP_X_INT_DIS           SH5001_TAP_Y_INT_DIS            SH5001_TAP_Z_INT_DIS\r
+*                                                                                                                              \r
+*               tapIntThres            tapTimeMs           tapWaitTimeMs               tapWaitTimeWindowMs\r
+*               (13 bits)              Unit: mS                Unit: mS                                Unit: 2mS\r
+*                                                              \r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_INT_Tap_Config(    unsigned char tapEnDisIntX,\r
+                            unsigned char tapEnDisIntY,\r
+                            unsigned char tapEnDisIntZ,\r
+                            unsigned char tapIntThres,\r
+                            unsigned char tapTimeMs,\r
+                            unsigned char tapWaitTimeMs,\r
+                            unsigned char tapWaitTimeWindowMs)\r
+{\r
+       unsigned char regData = 0;              \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_ACT_INACT_INT_LINK, 1, &regData);    \r
+       regData |= (regData & 0xF1U) | tapEnDisIntX | tapEnDisIntY | tapEnDisIntZ;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACT_INACT_INT_LINK, 1, &regData);                                                                                                                                                   \r
+                                                                                                                                                       \r
+       regData = (unsigned char)tapIntThres; \r
+       SH5001_write(SH5001_ADDRESS, SH5001_TAP_INT_THRESHOLDL, 1, &regData);\r
+       SH5001_read(SH5001_ADDRESS, SH5001_TAP_INT_THRESHOLDH, 1, &regData);\r
+       regData = ((unsigned char)(tapIntThres >> 8U) & 0x1FU) | (regData & 0xE0U); \r
+       SH5001_write(SH5001_ADDRESS, SH5001_TAP_INT_THRESHOLDH, 1, &regData);\r
+       \r
+       regData = tapTimeMs; \r
+       SH5001_write(SH5001_ADDRESS, SH5001_TAP_INT_DURATION, 1, &regData);     \r
+       \r
+       regData = tapWaitTimeMs; \r
+       SH5001_write(SH5001_ADDRESS, SH5001_TAP_INT_LATENCY, 1, &regData);      \r
+\r
+       regData = tapWaitTimeWindowMs; \r
+       SH5001_write(SH5001_ADDRESS, SH5001_DTAP_INT_WINDOW, 1, &regData);        \r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.SMD INT config;\r
+*                              2.smdBlockTimeS:0-0.5S;         1-1.0S;         2-1.5S;         3-2.0S;\r
+*                                                              4-3.0S;         5-4.0S;         6-5.0S;         7-6.0S;\r
+*                                                              8-7.0S;         9-8.0S;         A-9.0S;         B-10S;\r
+*                                                              C-12S;          D-14S;          E-15S;          F-16S;\r
+*\r
+*               3.smdProofTimeS:0-0.2S;                1-0.25S;        2-0.3S;         3-0.4S;\r
+*                                                              4-0.5S;         5-0.6S;         6-0.7S;         7-0.8S;\r
+*                                                              8-0.9S;         9-1.0S;         A-1.2S;         B-1.5S;\r
+*                                                              C-1.8S;         D-2.1S;         E-2.4S;         F-2.8S;\r
+*\r
+* Parameters:  smdThres                smdBlockTimeS           smdProofTimeS\r
+*                              2 Bytes                 Unit: S                         Unit: S\r
+*\r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_INT_SMD_Config(    unsigned short smdThres,\r
+                            unsigned char smdBlockTimeS,\r
+                                                       unsigned char smdProofTimeS)\r
+{\r
+       unsigned char regData[2] = {0};         \r
+                                               \r
+       regData[0] = (unsigned char)smdThres; \r
+       regData[1] = (unsigned char)(smdThres >> 8U); \r
+       SH5001_write(SH5001_ADDRESS, SH5001_SMD_INT_THRESHOLDL, 2, &regData[0]);        \r
+\r
+       regData[0] |= (unsigned char)((smdBlockTimeS & 0xF0U) << 4U) | (smdProofTimeS & 0xF0U);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_HIGHG_INT_CONF, 1, &regData[0]);    \r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.highG INT config;\r
+*                              2.highGThres is between 0 and 8191;\r
+*               3.highGThres: x=0.5mG@2G, x=1mG@4G, x=2mG@8G, x=4mG@16G\r
+*\r
+* Parameters:  highGEnDisIntX              highGEnDisIntY              highGEnDisIntZ                          \r
+*               SH5001_HIGHG_X_INT_EN          SH5001_HIGHG_Y_INT_EN           SH5001_HIGHG_Z_INT_EN           \r
+*               SH5001_HIGHG_X_INT_DIS         SH5001_HIGHG_Y_INT_DIS          SH5001_HIGHG_Z_INT_DIS\r
+*                      \r
+*               highGEnDisIntAll                       highGThres                                      highGTimeMs\r
+*               SH5001_HIGHG_ALL_INT_EN                Unit: x*8mG                             Unit: 2mS\r
+*               SH5001_HIGHG_ALL_INT_DIS       (13 bits)\r
+*\r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_INT_HighG_Config(  unsigned char highGEnDisIntX,\r
+                                unsigned char highGEnDisIntY,\r
+                                unsigned char highGEnDisIntZ,\r
+                                unsigned char highGEnDisIntAll,\r
+                                unsigned short highGThres,\r
+                                unsigned char highGTimeMs)\r
+{\r
+       unsigned char regData[2] = {0};         \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_HIGHG_INT_CONF, 1, &regData[0]);     \r
+       regData[0] |= (regData[0] & 0x0FU) | highGEnDisIntX | highGEnDisIntY | highGEnDisIntZ | highGEnDisIntAll;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_HIGHG_INT_CONF, 1, &regData[0]);            \r
+                               \r
+       SH5001_read(SH5001_ADDRESS, SH5001_HIGHG_INT_THRESHOLDL, 2, &regData[0]);                       \r
+       regData[0] = (unsigned char)highGThres; \r
+       regData[1] = (regData[1] & 0xE0U) | ((unsigned char)(highGThres >> 8U) & 0x1FU); \r
+       SH5001_write(SH5001_ADDRESS, SH5001_HIGHG_INT_THRESHOLDL, 2, &regData[0]);      \r
+                       \r
+       regData[0] = highGTimeMs; \r
+       SH5001_write(SH5001_ADDRESS, SH5001_HIGHG_INT_TIME, 1, &regData[0]);     \r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.lowG INT config;\r
+*                              2.lowGThres is between 0 and 8191;\r
+*               3.lowGThres: x=0.5mG@2G or x=1mG@4G or x=2mG@8G or x=4mG@16G\r
+*\r
+* Parameters:  lowGEnDisIntAll             lowGThres           lowGTimeMs\r
+*               SH5001_LOWG_ALL_INT_EN         Unit: x*8mG             Unit: 2mS\r
+*               SH5001_LOWG_ALL_INT_DIS                (13 bits)\r
+*\r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_INT_LowG_Config(   unsigned char lowGEnDisIntAll,\r
+                                unsigned short lowGThres,\r
+                                unsigned char lowGTimeMs)\r
+{\r
+       unsigned char regData[2] = {0};         \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_HIGHG_INT_CONF, 1, &regData[0]);     \r
+       regData[0] |= (regData[0] & 0xFEU) | lowGEnDisIntAll;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_HIGHG_INT_CONF, 1, &regData[0]);    \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_LOWG_INT_THRESHOLDL, 2, &regData[0]);        \r
+       regData[0] = (unsigned char)lowGThres; \r
+       regData[1] = (regData[1] & 0xE0U) | ((unsigned char)(lowGThres >> 8U) & 0x1FU);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_LOWG_INT_THRESHOLDL, 2, &regData[0]);       \r
+       \r
+       regData[0] = lowGTimeMs; \r
+       SH5001_write(SH5001_ADDRESS, SH5001_LOWG_INT_TIME, 1, &regData[0]);             \r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.freeFall INT config;\r
+*               2.freeFallThres: x=0.5mG@2G or x=1mG@4G or x=2mG@8G or x=4mG@16G\r
+*\r
+* Parameters:  freeFallThres   freeFallTimeMs\r
+*               Unit: x*8mG            Unit: 2mS\r
+*\r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_INT_FreeFall_Config(       unsigned char freeFallThres,\r
+                                    unsigned char freeFallTimeMs)\r
+{\r
+       unsigned char regData = 0;\r
+       \r
+       regData = freeFallThres; \r
+       SH5001_write(SH5001_ADDRESS, SH5001_FREEFALL_INT_THRES, 1, &regData);   \r
+       \r
+       regData = freeFallTimeMs; \r
+       SH5001_write(SH5001_ADDRESS, SH5001_FREEFALL_INT_TIME, 1, &regData);                                                                                                                                                                            \r
+}\r
+\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.read INT status0\r
+*\r
+* Parameters:  void\r
+*\r
+* return:      unsigned short\r
+*                      bit 13: Tap, Single or Double Tap Interrupt status      \r
+*                      bit 12: SMD Interrupt status\r
+*           bit 11: FIFO Watermark Interrupt status                                                    \r
+*           bit 10: Gyro Data Ready Interrupt status\r
+*           bit 9: Acc Data Ready Interrupt status\r
+*           bit 8: Free-fall Interrupt status \r
+*           bit 7: Low-G Interrupt status\r
+*           bit 6: High-G Interrupt status\r
+*           bit 5: Inactivity Interrupt status\r
+*           bit 4: Activity Interrupt status\r
+*           bit 3: Double Tap Interrupt status \r
+*           bit 2: Single Tap Interrupt status\r
+*           bit 1: Flat Interrupt status\r
+*           bit 0: Orientation Interrupt status \r
+*               0: Not Active\r
+*               1: Active\r
+*\r
+******************************************************************/\r
+unsigned short SH5001_INT_Read_Status01(void)\r
+{\r
+       unsigned char regData[3] = {0};\r
+\r
+       SH5001_read(SH5001_ADDRESS, SH5001_INT_STA0, 3, &regData[0]);\r
+\r
+       return( ((unsigned short)(regData[1] & 0x3FU) << 8U) | regData[0] );\r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.read INT status2\r
+*\r
+* Parameters:  void\r
+*\r
+* return:      unsigned char\r
+*           bit 7: High-G Sign\r
+*               0: Positive\r
+*               1: Negative\r
+*           bit 6: High-G X-axis Interrupt status\r
+*           bit 5: High-G Y-axis Interrupt status\r
+*           bit 4: High-G Z-axis Interrupt status\r
+*               0: No Active\r
+*               1: Active\r
+*           bit 3: Reserved\r
+*           bit 2: Reserved\r
+*           bit 1: Reserved\r
+*           bit 0: Low-G Interrupt status\r
+*               0: Not Active\r
+*               1: Active\r
+*\r
+******************************************************************/\r
+unsigned char SH5001_INT_Read_Status2(void)\r
+{\r
+       unsigned char regData = 0;      \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_INT_STA2, 1, &regData);      \r
+\r
+       return( (regData & 0xF1U));\r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.read INT status3\r
+*\r
+* Parameters:  void\r
+*\r
+* return:      unsigned char\r
+*           bit 7: Activity-Inactivity Sign\r
+*               0: Positive\r
+*               1: Negative\r
+*           bit 6: Activity-Inactivity X-axis Interrupt Status\r
+*           bit 5: Activity-Inactivity Y-axis Interrupt Status\r
+*           bit 4: Activity-Inactivity Z-axis Interrupt Status\r
+*               0: No Active\r
+*               1: Active\r
+*                      bit 3: Sign of acceleration that trigger Single or Double Tap Interrup\r
+*               0: Positive\r
+*               1: Negative\r
+*                      bit 2: Whether Single or Double Tap Interrupt is triggered by X axis\r
+*                      bit 1: Whether Single or Double Tap Interrupt is triggered by Y axis\r
+*                      bit 0: Whether Single or Double Tap Interrupt is triggered by Z axis\r
+*               0: No\r
+*               1: Yes\r
+******************************************************************/\r
+unsigned char SH5001_INT_Read_Status3(void)\r
+{\r
+       unsigned char regData = 0;      \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_INT_STA3, 1, &regData);      \r
+\r
+       return(regData);\r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.read INT status4\r
+*\r
+* Parameters:  void\r
+*\r
+* return:      unsigned char\r
+*           bit 7: Reserved\r
+*           bit 6: Reserved\r
+*           bit 5: Reserved\r
+*           bit 4: Reserved\r
+*           bit 3: Reserved\r
+*           bit 2: Orientation Interrupt Value of Z-axis\r
+*               0: Upward\r
+*               1: Downward\r
+*           bit 1..0: Orientation Interrupt Value of X and Y-axis\r
+*               00: Landscape left\r
+*               01: Landscape right\r
+*               10: Portrait upside down\r
+*               11: Portrait upright\r
+*\r
+******************************************************************/\r
+unsigned char SH5001_INT_Read_Status4(void)\r
+{\r
+       unsigned char regData = 0;      \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_INT_STA4, 1, &regData);      \r
+\r
+       return(regData & 0x07U);\r
+}\r
+\r
+\r
+\r
+/******************************************************************\r
+* Description: reset FIFO controller;\r
+*\r
+* Parameters:  fifoMode\r
+*               SH5001_FIFO_MODE_DIS\r
+*               SH5001_FIFO_MODE_FIFO\r
+*               SH5001_FIFO_MODE_STREAM\r
+*               SH5001_FIFO_MODE_TRIGGER\r
+*\r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_FIFO_Mode_Set(unsigned char fifoMode)\r
+{\r
+       unsigned char regData = 0;              \r
+\r
+       SH5001_read(SH5001_ADDRESS, SH5001_FIFO_CONF0, 1, &regData);\r
+       regData &= 0x7F;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF0, 1, &regData);\r
+       \r
+       regData = fifoMode & 0x03;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF0, 1, &regData);\r
+}\r
+\r
+void SH5001_FIFO_Reset(void)\r
+{\r
+       unsigned char regData = 0;\r
+\r
+       SH5001_read(SH5001_ADDRESS, SH5001_FIFO_CONF0, 1, &regData);\r
+       regData |= 0x80;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF0, 1, &regData);\r
+}\r
+\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.FIFO down sample frequency config;\r
+*               2.fifoAccFreq: accODR*1/2, *1/4, *1/8, *1/16, *1/32, *1/64, *1/128, *1/256\r
+*               3.fifoGyroFreq:        gyroODR*1/2, *1/4, *1/8, *1/16, *1/32, *1/64, *1/128, *1/256\r
+*\r
+* Parameters:  fifoAccDownSampleEnDis          fifoAccFreq/fifoGyroFreq        fifoGyroDownSampleEnDis\r
+*               SH5001_FIFO_ACC_DOWNS_EN       SH5001_FIFO_FREQ_X1_2           SH5001_FIFO_GYRO_DOWNS_EN\r
+*               SH5001_FIFO_ACC_DOWNS_DIS      SH5001_FIFO_FREQ_X1_4           SH5001_FIFO_GYRO_DOWNS_DIS\r
+*                                                                                      SH5001_FIFO_FREQ_X1_8\r
+*                                                                                      SH5001_FIFO_FREQ_X1_16\r
+*                                                                                      SH5001_FIFO_FREQ_X1_32\r
+*                                                                                      SH5001_FIFO_FREQ_X1_64\r
+*                                                                                      SH5001_FIFO_FREQ_X1_128\r
+*                                                                                      SH5001_FIFO_FREQ_X1_256\r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_FIFO_Freq_Config(  unsigned char fifoAccDownSampleEnDis,\r
+                                unsigned char fifoAccFreq,\r
+                                unsigned char fifoGyroDownSampleEnDis,\r
+                                unsigned char fifoGyroFreq)\r
+{\r
+       unsigned char regData = 0;              \r
+       \r
+       regData |= fifoAccDownSampleEnDis | fifoGyroDownSampleEnDis;\r
+       regData |= (fifoAccFreq << 4) | fifoGyroFreq;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF4, 1, &regData); \r
+}\r
+\r
+\r
+// Jin: fifoWaterMarkLevel???\r
+/******************************************************************\r
+* Description: 1.config data type in FIFO;\r
+*               2.fifoWaterMarkLevel <= channelNum*2*(INT(1024/(channelNum*2))-1)\r
+*                 eg. fifomode = SH5001_FIFO_ACC_X_EN | SH5001_FIFO_ACC_Y_EN | SH5001_FIFO_ACC_Z_EN\r
+*                     then fifoWaterMarkLevel maximum is 1014\r
+*\r
+* Parameters:  fifoMode                                                fifoWaterMarkLevel\r
+                               SH5001_FIFO_TIMESTAMP_EN                <=1024                            \r
+*               SH5001_FIFO_EXT_Z_EN\r
+*               SH5001_FIFO_EXT_Y_EN\r
+*               SH5001_FIFO_EXT_X_EN                                                   \r
+*               SH5001_FIFO_TEMPERATURE_EN                                                     \r
+*               SH5001_FIFO_GYRO_Z_EN                                                  \r
+*               SH5001_FIFO_GYRO_Y_EN                                          \r
+*               SH5001_FIFO_GYRO_X_EN\r
+*               SH5001_FIFO_ACC_Z_EN\r
+*               SH5001_FIFO_ACC_Y_EN\r
+*               SH5001_FIFO_ACC_X_EN\r
+*               SH5001_FIFO_ALL_DIS\r
+*                                                                                                                      \r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_FIFO_Data_Config(  unsigned short fifoMode,\r
+                                unsigned short fifoWaterMarkLevel)\r
+{\r
+       unsigned char regData = 0;\r
+       \r
+       if(fifoWaterMarkLevel > 1024U)\r
+       {\r
+               fifoWaterMarkLevel = 1024U;\r
+       }\r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_FIFO_CONF2, 1, &regData);\r
+       regData = (regData & 0x88U) \\r
+              | ((unsigned char)(fifoMode >> 8U) & 0x70U) \\r
+              | (((unsigned char)(fifoWaterMarkLevel >> 8U)) & 0x07U);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF2, 1, &regData);\r
+\r
+       regData = (unsigned char)fifoMode;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF3, 1, &regData);\r
+       \r
+       regData = (unsigned char)fifoWaterMarkLevel;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF1, 1, &regData);            \r
+}\r
+\r
+\r
+\r
+/******************************************************************\r
+* Description: 1. read Fifo status and fifo entries count\r
+*\r
+* Parameters:  *fifoEntriesCount, store fifo entries count, less than or equal to 1024;\r
+*\r
+*                                                                                                                      \r
+* return:      unsigned char\r
+*           bit 7: 0\r
+*           bit 6: 0\r
+*           bit 5: Whether FIFO Watermark has been reached\r
+*           bit 4: Whether FIFO is full\r
+*           bit 3: Whether FIFO is empty\r
+*               0: No\r
+*               1: Yes\r
+*           bit 2: 0\r
+*           bit 1: 0\r
+*           bit 0: 0\r
+*\r
+*\r
+******************************************************************/\r
+unsigned char SH5001_FIFO_Read_Status(unsigned short int *fifoEntriesCount)\r
+{\r
+       unsigned char regData[2] = {0};         \r
+\r
+       SH5001_read(SH5001_ADDRESS, SH5001_FIFO_STA0, 2, &regData[0]);\r
+\r
+       *fifoEntriesCount = ((unsigned short int)(regData[1] & 0x0FU) << 8U) | regData[0];\r
+\r
+       \r
+       return (regData[1] & 0x70U);\r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: 1. read Fifo data\r
+*\r
+* Parameters:  *fifoReadData           fifoDataLength\r
+*               data                           data length\r
+*                                                                                                                      \r
+* return:      void\r
+*\r
+*\r
+******************************************************************/\r
+void SH5001_FIFO_Read_Data(unsigned char *fifoReadData, unsigned short int fifoDataLength)\r
+{\r
+    if(fifoDataLength == 0)\r
+       {\r
+               return;\r
+       } \r
+    \r
+       if(fifoDataLength > 1024U)\r
+       {\r
+               fifoDataLength = 1024U;\r
+       } \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_FIFO_DATA, fifoDataLength, fifoReadData);\r
+       /*\r
+    while(fifoDataLength--)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_FIFO_DATA, 1, fifoReadData);\r
+               fifoReadData++;\r
+       }  \r
+       */\r
+}      \r
+\r
+\r
+/******************************************************************\r
+* Description: reset Mater I2C;\r
+*\r
+* Parameters:  void\r
+*                                                                                                                      \r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_MI2C_Reset(void)\r
+{\r
+       unsigned char regData = 0;              \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);\r
+       regData |= 0x80U;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);\r
+       regData &= 0x7FU;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);   \r
+       \r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.master I2C config;\r
+*               2.master I2C clock frequency is (1MHz/(6+3*mi2cFreq));\r
+*               3.mi2cSlaveAddr: slave device address, 7 bits;\r
+*\r
+*\r
+* Parameters:  mi2cReadMode                                    mi2cODR                                                 mi2cFreq\r
+*               SH5001_MI2C_READ_MODE_AUTO             SH5001_MI2C_READ_ODR_200HZ              <=15\r
+*               SH5001_MI2C_READ_MODE_MANUAL   SH5001_MI2C_READ_ODR_100HZ\r
+*                                                                                              SH5001_MI2C_READ_ODR_50HZ               \r
+*                                                                                              SH5001_MI2C_READ_ODR_25HZ                                                                                                                                                                                       \r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_MI2C_Bus_Config(   unsigned char mi2cReadMode,\r
+                                unsigned char mi2cODR,\r
+                                unsigned char mi2cFreq)\r
+{\r
+       unsigned char regData = 0;              \r
+       \r
+       if(mi2cFreq > 15U)\r
+       {\r
+               mi2cFreq = 15U;\r
+       }\r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF1, 1, &regData);\r
+       regData = (regData & 0xC0U) | (mi2cODR & 0x30U) | mi2cFreq;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF1, 1, &regData);   \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);\r
+       regData = (regData & 0xBFU) | mi2cReadMode;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);           \r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.master I2C address and command config;\r
+*               2.mi2cSlaveAddr: slave device address, 7 bits;\r
+*\r
+* Parameters:  mi2cSlaveAddr           mi2cSlaveCmd            mi2cReadMode\r
+*               (1 Byte)                       (1 Byte)                        SH5001_MI2C_READ_MODE_AUTO\r
+*                                                       SH5001_MI2C_READ_MODE_MANUAL\r
+*                                                                                                                                                                              \r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_MI2C_Cmd_Config(   unsigned char mi2cSlaveAddr,\r
+                                unsigned char mi2cSlaveCmd,\r
+                                unsigned char mi2cReadMode)\r
+{\r
+       unsigned char regData = 0;      \r
+\r
+       SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);\r
+       regData = (regData & 0xBFU) | mi2cReadMode;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);\r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CMD0, 1, &regData);\r
+       regData |= (mi2cSlaveAddr << 1U);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CMD0, 1, &regData);\r
+       SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CMD1, 1, &mi2cSlaveCmd);                                                                                                                                                                                                                                                                                                                       \r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.master I2C write data fucntion;\r
+*               2.mi2cWriteData: write data;\r
+*\r
+* Parameters:  mi2cWriteData\r
+*                                                                                                                                                                              \r
+* return:      SH5001_TRUE or SH5001_FALSE\r
+* \r
+******************************************************************/\r
+unsigned char SH5001_MI2C_Write(unsigned char mi2cWriteData)\r
+{\r
+       unsigned char regData = 0;      \r
+       unsigned char i = 0;\r
+\r
+       SH5001_write(SH5001_ADDRESS, SH5001_MI2C_WR, 1, &mi2cWriteData);\r
+               \r
+       //Master I2C enable, write-operation\r
+       SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);\r
+       regData = (regData & 0xFCU) | 0x02U;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);\r
+       \r
+       // wait write-operation to end\r
+       while(i++ < 20U)\r
+       {       \r
+               SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);\r
+               if(regData & 0x30U)\r
+                       break;\r
+       }\r
+               \r
+       if((regData & 0x30U) == SH5001_MI2C_SUCCESS)\r
+       {\r
+               return (SH5001_TRUE);   \r
+       }       \r
+       else\r
+       {\r
+               return (SH5001_FALSE);  \r
+       }               \r
+}                                                                                                                              \r
+\r
+\r
+/******************************************************************\r
+* Description: 1.master I2C read data fucntion;\r
+*               2.*mi2cReadData: read data;\r
+*\r
+* Parameters:  *mi2cReadData\r
+*                                                                                                                                                                              \r
+* return:      SH5001_TRUE or SH5001_FALSE\r
+* \r
+******************************************************************/\r
+unsigned char SH5001_MI2C_Read(unsigned char *mi2cReadData)\r
+{\r
+       unsigned char regData = 0;                      \r
+       unsigned char i = 0;\r
+               \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);\r
+       if((regData & 0x40U) == 0)\r
+       {       \r
+               //Master I2C enable, read-operation\r
+               regData |= 0x03U;\r
+               SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);\r
+       }\r
+       \r
+       // wait read-operation to end\r
+       while(i++ < 20U)\r
+       {       \r
+               SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);\r
+               if(regData & 0x30U)\r
+                       break;\r
+       }       \r
+\r
+       SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, &regData);\r
+       if((regData & 0x30U) == SH5001_MI2C_SUCCESS)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_MI2C_RD, 1, &regData);\r
+               *mi2cReadData = regData;\r
+               \r
+               return (SH5001_TRUE);   \r
+       }       \r
+       else\r
+       {\r
+               return (SH5001_FALSE);  \r
+       }               \r
+}      \r
+\r
+\r
+/******************************************************************\r
+* Description: 1.SPI interface config;  Default: SH5001_SPI_4_WIRE\r
+*\r
+* Parameters:  spiInterfaceMode\r
+*               SH5001_SPI_3_WIRE\r
+*               SH5001_SPI_4_WIRE\r
+*\r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_SPI_Config(        unsigned char spiInterfaceMode)\r
+{\r
+       #if 0\r
+       unsigned char regData = 0;              \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_SPI_CONF, 1, &regData);      \r
+       regData = (regData & 0xDFU) | spiInterfaceMode;\r
+       #endif\r
+       unsigned char regData = spiInterfaceMode;\r
+\r
+       SH5001_write(SH5001_ADDRESS, SH5001_SPI_CONF, 1, &regData);\r
+} \r
+\r
+\r
+/******************************************************************\r
+* Description: 1.I2C interface config;  Default: SH5001_I2C_EN\r
+*\r
+* Parameters:  i2cInterfaceEnDis\r
+*               SH5001_I2C_EN\r
+*               SH5001_I2C_DIS\r
+*\r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_I2C_Config(unsigned char i2cInterfaceEnDis)\r
+{\r
+       unsigned char regData = 0;              \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_I2C_CONF, 1, &regData);      \r
+       regData = (regData & 0x7FU) | i2cInterfaceEnDis;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_I2C_CONF, 1, &regData);\r
+} \r
+\r
+\r
+\r
+// Jin\r
+/******************************************************************\r
+* Description: 1.I2C loop mode config;\r
+*                              2.SH5001_I2C_LP_06BYTE: ACC_X ACC_Y ACC_Z\r
+*                              3.SH5001_I2C_LP_12BYTE: ACC_X ACC_Y ACC_Z GYRO_X GYRO_Y GYRO_Z\r
+*                              4.SH5001_I2C_LP_14BYTE: ACC_X ACC_Y ACC_Z GYRO_X GYRO_Y GYRO_Z TEMPERATURE\r
+*\r
+* Parameters:  i2cReadLoopMode\r
+*               SH5001_I2C_LP_06BYTE\r
+*               SH5001_I2C_LP_12BYTE\r
+*                              SH5001_I2C_LP_14BYTE\r
+*                              SH5001_I2C_LP_DISABLE\r
+*\r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_I2C_LP_Config(unsigned char i2cReadLoopMode)\r
+{\r
+       unsigned char regData = 0;              \r
+       \r
+       SH5001_read(SH5001_ADDRESS, SH5001_I2C_CONF, 1, &regData);      \r
+       regData = (regData & 0xF8U) | i2cReadLoopMode;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_I2C_CONF, 1, &regData);\r
+} \r
+\r
+\r
+/******************************************************************\r
+* Description: 1.OIS SPI interface config;  Default: SH5001_OIS_SPI_DIS\r
+*\r
+* Parameters:  oisSpiInterfaceMode             oisSpiInterfaceEnDis\r
+*               SH5001_OIS_SPI_3WIRE   SH5001_OIS_SPI_EN\r
+*               SH5001_OIS_SPI_4WIRE   SH5001_OIS_SPI_DIS\r
+*\r
+* return:      void\r
+* \r
+******************************************************************/\r
+\r
+void SH5001_OIS_SPI_Config(unsigned char oisSpiInterfaceEnDis)\r
+{\r
+  unsigned char regData = 0;\r
+\r
+  SH5001_read(SH5001_ADDRESS, SH5001_OIS_SPI_CONF, 1, &regData);\r
+  regData = (regData & 0xEFU) | oisSpiInterfaceEnDis;\r
+  SH5001_write(SH5001_ADDRESS, SH5001_OIS_SPI_CONF, 1, &regData);\r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description: 1.Switch SH5001 power mode;\r
+*               2.SH5001_NORMAL_MODE\r
+*                              3.SH5001_ACC_HP_MODE\r
+*               4.SH5001_ACC_LP_MODE\r
+*                              5.SH5001_POWERDOWN_MODE\r
+*\r
+* Parameters:   powerMode\r
+*               SH5001_NORMAL_MODE\r
+*               SH5001_ACC_HP_MODE\r
+*                              SH5001_ACC_LP_MODE\r
+*               SH5001_POWERDOWN_MODE\r
+*\r
+* return:      SH5001_FALSE or SH5001_TRUE\r
+*\r
+******************************************************************/\r
+unsigned char SH5001_SwitchPowerMode(unsigned char powerMode)\r
+{\r
+\r
+       int i = 0;\r
+       unsigned char reg_addr[SH5001_POWMODE_REG_NUM] = { 0x30, 0x20, 0x2B, 0xBD, 0xD9, 0xD1, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8};\r
+       unsigned char reg_data_normal[SH5001_POWMODE_REG_NUM] = { 0x08, 0x23, 0x00, 0x0C, 0x99, 0x68, 0x00, 0x00, 0x01, 0x50, 0x00};\r
+       unsigned char reg_data_acc_hp[SH5001_POWMODE_REG_NUM] = { 0x08, 0x23, 0x01, 0x0C, 0x98, 0x6B, 0x00, 0x7A, 0xFF, 0xFC, 0x00};\r
+       unsigned char reg_data_acc_lp[SH5001_POWMODE_REG_NUM] = { 0x08, 0xA1, 0x01, 0x0E, 0x98, 0x6B, 0x90, 0xFA, 0xFF, 0xFC, 0x00};\r
+       unsigned char reg_data_powerdown[SH5001_POWMODE_REG_NUM] = { 0x08, 0xA1, 0x01, 0x0E, 0x98, 0x6B, 0xF1, 0xFE, 0xFF, 0xFC, 0xE2};\r
+       unsigned char accODR = SH5001_ACC_ODR_2000HZ;\r
+    unsigned char regData = 0;\r
+\r
+       if(powerMode > 0x03)\r
+       {\r
+               return (SH5001_FALSE);\r
+       }\r
+\r
+       switch(powerMode)\r
+       {\r
+       case SH5001_NORMAL_MODE:\r
+\r
+               SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, &regData);\r
+               regData = regData & 0x7F;\r
+               SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, &regData);\r
+\r
+               SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF1, 1, &storeAccODR);\r
+               for(i = 0; i < SH5001_POWMODE_REG_NUM; i++)\r
+               {\r
+                       SH5001_write(SH5001_ADDRESS, reg_addr[i], 1, &reg_data_normal[i]);\r
+               }\r
+\r
+               SH5001_DriveStart();\r
+               SH5001_ADCReset();\r
+               SH5001_CVAReset();\r
+               delay_ms(100);// or discard 10\r
+\r
+               return (SH5001_TRUE);\r
+\r
+       case SH5001_ACC_HP_MODE:\r
+\r
+               SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, &regData);\r
+               regData = regData | 0x80;\r
+               SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, &regData);\r
+\r
+               SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF1, 1, &storeAccODR);\r
+               for(i = 0; i < SH5001_POWMODE_REG_NUM; i++)\r
+               {\r
+                       SH5001_write(SH5001_ADDRESS, reg_addr[i], 1, &reg_data_acc_hp[i]);\r
+               }\r
+\r
+               delay_ms(30); // or discard 2\r
+\r
+               return (SH5001_TRUE);\r
+\r
+       case SH5001_ACC_LP_MODE:\r
+\r
+               SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, &regData);\r
+               regData = regData & 0x7F;\r
+               SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, &regData);\r
+\r
+               regData = (storeAccODR & 0xF0) | accODR;\r
+               SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF1, 1, &regData);\r
+               for(i = 0; i < SH5001_POWMODE_REG_NUM; i++)\r
+               {\r
+                       SH5001_write(SH5001_ADDRESS, reg_addr[i], 1, &reg_data_acc_lp[i]);\r
+               }\r
+\r
+               delay_ms(30); // or discard 2\r
+               return (SH5001_TRUE);\r
+\r
+       case SH5001_POWERDOWN_MODE:\r
+\r
+               for(i = 0; i < SH5001_POWMODE_REG_NUM; i++)\r
+               {\r
+                       SH5001_write(SH5001_ADDRESS, reg_addr[i], 1, &reg_data_powerdown[i]);\r
+               }\r
+\r
+               return (SH5001_TRUE);\r
+\r
+       default:\r
+               return (SH5001_FALSE);\r
+       }\r
+}\r
+\r
+/******************************************************************\r
+* Description: 1. fast compensate offset\r
+*\r
+* Parameters:   SH5001Positon\r
+*               SH5001_X_UP\r
+*               SH5001_X_DOWN\r
+*                              SH5001_Y_UP\r
+*               SH5001_Y_DOWN\r
+*                              SH5001_Z_UP\r
+*               SH5001_Z_DOWN\r
+*\r
+* return:      SH5001_FALSE or SH5001_TRUE\r
+*\r
+******************************************************************/\r
+void SH5001_FastOffsetComp(unsigned char SH5001Positon)\r
+{\r
+  unsigned char regData = 0;\r
+    \r
+  switch(SH5001Positon)\r
+    {\r
+  case SH5001_X_UP:\r
+    regData = 0x90U;\r
+    break;\r
+  case SH5001_X_DOWN:\r
+    regData = 0x91U;\r
+    break;  \r
+  case SH5001_Y_UP:\r
+    regData = 0x92U;\r
+    break;\r
+  case SH5001_Y_DOWN:\r
+    regData = 0x93U;\r
+    break;     \r
+  case SH5001_Z_UP:\r
+    regData = 0x94U;\r
+    break;\r
+  case SH5001_Z_DOWN:\r
+    regData = 0x95U;\r
+    break; \r
+  default:\r
+    regData = 0x94U;\r
+    break;\r
+  }\r
+  \r
+//  SH5001_write(SH5001_ADDRESS, SH5001_FAST_COMP, 1, &regData);\r
+}  \r
+\r
+\r
+#ifdef SH5001_ACTIVITY_INT\r
+\r
+void SH5001_Init_Activity_Int(void)\r
+{\r
+\r
+       unsigned char regData = 0;\r
+\r
+       SH5001_INT_Config(SH5001_INT0_LEVEL_HIGH,\r
+                      SH5001_INT_LATCH, //SH5001_INT_NO_LATCH, SH5001_INT_LATCH\r
+                      SH5001_INT_CLEAR_STATUS,  //SH5001_INT_CLEAR_ANY, SH5001_INT_CLEAR_STATUS\r
+                      1,\r
+                      SH5001_INT1_NORMAL,\r
+                      SH5001_INT0_NORMAL,\r
+                      SH5001_INT1_OUTPUT,\r
+                      SH5001_INT0_OUTPUT);\r
+\r
+       SH5001_INT_Act_Config(SH5001_ACT_X_INT_EN,\r
+       SH5001_ACT_Y_INT_EN,\r
+       SH5001_ACT_Z_INT_EN,\r
+       2,\r
+       20,\r
+       SH5001_LINK_PRE_STA_NO,\r
+       SH5001_ACT_INACT_CLR_STATUS1);\r
+\r
+       SH5001_INT_Enable(SH5001_INT_ACT,\r
+                      SH5001_INT_EN,\r
+                      SH5001_INT_MAP_INT0);\r
+       //TODO\r
+       SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, &regData);\r
+       regData = regData & 0x7F;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, &regData);\r
+\r
+       SH5001_read(SH5001_ADDRESS, 0xBD, 1, &regData);\r
+       regData = (regData & 0x7F);\r
+       SH5001_write(SH5001_ADDRESS, 0xBD, 1, &regData);\r
+}\r
+\r
+#endif\r
+\r
+#ifdef SH5001_DATA_READY_INT\r
+void SH5001_Init_Data_Ready_Int(void)\r
+{\r
+\r
+       unsigned char regData = 0;\r
+\r
+       SH5001_INT_Config(SH5001_INT0_LEVEL_HIGH,\r
+                      SH5001_INT_LATCH, //SH5001_INT_NO_LATCH, SH5001_INT_LATCH\r
+                      SH5001_INT_CLEAR_STATUS,  //SH5001_INT_CLEAR_ANY, SH5001_INT_CLEAR_STATUS\r
+                      1,\r
+                      SH5001_INT1_NORMAL,\r
+                      SH5001_INT0_NORMAL,\r
+                      SH5001_INT1_OUTPUT,\r
+                      SH5001_INT0_OUTPUT);\r
+\r
+       SH5001_INT_Enable(SH5001_INT_ACC_READY, //SH5001_INT_GYRO_READY SH5001_INT_ACC_READY\r
+                      SH5001_INT_EN,\r
+                      SH5001_INT_MAP_INT0);\r
+\r
+}\r
+\r
+#endif\r
+\r
+/******************************************************************\r
+* Description:         1. SH5001 initialization FIFO\r
+*               2. INT mode\r
+*               3. Enable ACC_X, ACC_Y, ACC_Z, GYRO_X, GYRO_Y, GYRO_Z\r
+*\r
+* Parameters:  void\r
+*\r
+* return:      void\r
+*\r
+******************************************************************/\r
+void SH5001_InitFIFO(void)\r
+{  \r
+\r
+       SH5001_INT_Config(SH5001_INT0_LEVEL_HIGH,\r
+                      SH5001_INT_LATCH, //SH5001_INT_NO_LATCH, SH5001_INT_LATCH\r
+                      SH5001_INT_CLEAR_STATUS,  //SH5001_INT_CLEAR_ANY, SH5001_INT_CLEAR_STATUS\r
+                      1,\r
+                      SH5001_INT1_NORMAL,\r
+                      SH5001_INT0_NORMAL,\r
+                      SH5001_INT1_OUTPUT,\r
+                      SH5001_INT0_OUTPUT);\r
+\r
+       SH5001_FIFO_Reset();\r
+\r
+       SH5001_FIFO_Freq_Config(SH5001_FIFO_ACC_DOWNS_DIS,\r
+                            SH5001_FIFO_FREQ_X1_32,\r
+                            SH5001_FIFO_GYRO_DOWNS_DIS,\r
+                            SH5001_FIFO_FREQ_X1_32);\r
+\r
+    SH5001_FIFO_Data_Config(SH5001_FIFO_ACC_X_EN\r
+                            | SH5001_FIFO_ACC_Y_EN\r
+                            | SH5001_FIFO_ACC_Z_EN\r
+                            | SH5001_FIFO_GYRO_X_EN\r
+                            | SH5001_FIFO_GYRO_Y_EN\r
+                            | SH5001_FIFO_GYRO_Z_EN,\r
+                            120);\r
+\r
+    SH5001_FIFO_Mode_Set(SH5001_FIFO_MODE_FIFO);\r
+\r
+       SH5001_INT_Enable(SH5001_INT_FIFO_WATERMARK,\r
+                      SH5001_INT_EN, \r
+                      SH5001_INT_MAP_INT0);\r
+\r
+}\r
+\r
+\r
+\r
+/******************************************************************\r
+* Description:         1. SH5001 read ACC_X, ACC_Y, ACC_Z, GYRO_X, GYRO_Y, GYRO_Z @FIFO\r
+*               2. clear FIFO Watermark INT\r
+*\r
+* Parameters:  void\r
+*\r
+* return:      void\r
+*\r
+******************************************************************/\r
+void SH5001_ReadFIFO(void)\r
+{\r
+       unsigned short fifoEntriesCount = 0;\r
+       unsigned char fifoData[SH5001_FIFO_BUFFER] = {0};\r
+       unsigned short i = 0, j = 0, dataGroup = 0;\r
+       short accData[3], gyroData[3];\r
+       unsigned char regData = 0;\r
+\r
+       // read FIFO entries count\r
+       SH5001_FIFO_Read_Status(&fifoEntriesCount);\r
+\r
+       dataGroup = (unsigned short)(fifoEntriesCount/SH5001_WATERMARK_DIV);\r
+       fifoEntriesCount = dataGroup * SH5001_WATERMARK_DIV;\r
+\r
+       SH5001_FIFO_Read_Data(fifoData, fifoEntriesCount);\r
+\r
+       // printf("fc %d\r\n", fifoEntriesCount);\r
+\r
+       for(i = 0; i < dataGroup; i++) \r
+       {                               \r
+               accData[0] = ((short)fifoData[j+1] << 8) | fifoData[j];\r
+               accData[1] = ((short)fifoData[j+3] << 8) | fifoData[j+2];\r
+               accData[2] = ((short)fifoData[j+5] << 8) | fifoData[j+4];       \r
+               gyroData[0] = ((short)fifoData[j+7] << 8) | fifoData[j+6];\r
+               gyroData[1] = ((short)fifoData[j+9] << 8) | fifoData[j+8];\r
+               gyroData[2] = ((short)fifoData[j+11] << 8) | fifoData[j+10];    \r
+\r
+               gyro_data.x = (float)gyroData[0];\r
+               gyro_data.y = (float)gyroData[1];\r
+               gyro_data.z = (float)gyroData[2];\r
+\r
+               // printf("%d %d %d %d %d %d\r\n", accData[0], accData[1], accData[2],gyroData[0], gyroData[1], gyroData[2]);\r
+       \r
+               j = j + SH5001_WATERMARK_DIV;\r
+       }       \r
+    \r
+        \r
+    // clear INT    \r
+   SH5001_INT_Read_Status01();\r
+\r
+\r
+}  \r
+\r
+ #define SH5001_REGISTER_SETTING_TOTAL 18\r
+static int sh5001DumpReg(void)\r
+{\r
+       int i = 0;\r
+       int ret = 0;\r
+       uint8_t reg = 0;\r
+       uint8_t regData = 0;\r
+\r
+       //uint8_t SH5001Reg[SH5001_REGISTER_SETTING_TOTAL]      =       {0x20, 0x21,0x22, 0x23, 0x24, 0x25};\r
+\r
+       //uint8_t SH5001Reg[SH5001_REGISTER_SETTING_TOTAL]      =       {0x20, 0x21,0x22, 0x23, 0x24, 0x25, 0x40, 0x41, 0x42, 0x43, 0x66}; //FIFO wm int\r
+       uint8_t SH5001Reg[SH5001_REGISTER_SETTING_TOTAL]        =       {0x20, 0x21,0x22, 0x23, 0x24, 0x25,0x40, 0x41, 0x42, 0x43, 0x66, 0x4D, 0x4E,  0x54,0x55, 0x56, 0xBD};  //Activity int\r
+\r
+       //uint8_t SH3001Reg[SH3001_REGISTER_SETTING_TOTAL]      =       {0x28, 0x29, 0x2B, 0x23, 0x26, 0xdd}; //lpf setting\r
+       // uint8_t SH3001Reg[SH3001_REGISTER_SETTING_TOTAL]     =       {0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,0x2A, 0x2B};\r
+       //uint8_t SH3001Reg[SH3001_REGISTER_SETTING_TOTAL]      =       {0x22, 0x23, 0x24, 0x25, 0x26, 0x35,0x36,0x37, 0x38,0x39};\r
+       //uint8_t ST3001RegData[SH3001_REGISTER_SETTING_TOTAL] = {0x00,0x1F,0x00,0x2B,0x00};\r
+       //uint8_t SH3001INTFIFOReg[SH3001_REGISTER_SETTING_TOTAL]       =       {0x35, 0x36, 0x37, 0x38, 0x39, 0x40,0x41,0x44, 0x45,0x46, 0x47, 0x4d,0x79,0x7A,0x0F,0x8F,0x9F,0xAF};\r
+       //uint8_t SH3001Reg[SH3001_REGISTER_SETTING_TOTAL]      =       {0x35, 0x36, 0x37, 0x38, 0x39, 0x40,0x41,0x42, 0x43,0x44, 0x45,0x46, 0x47, 0xFE};\r
+       //uint8_t SH3001Reg[SH3001_REGISTER_SETTING_TOTAL]      =       {0x20, 0x21, 0x0c, 0x0d};\r
+\r
+       for( i = 0 ; i < SH5001_REGISTER_SETTING_TOTAL ; i++ )\r
+       {\r
+\r
+               //read\r
+               reg = SH5001Reg[i];\r
+\r
+               ret = SH5001_read(SH5001_ADDRESS, reg, 1, &regData);\r
+               if(ret != 0)\r
+               {\r
+                       printf("Senodia Dump Reg 0x%x read error\r\n", reg);\r
+                       return -1;\r
+               }\r
+\r
+               printf("Senodia DR >>>>> 0x%x = 0x%x\r\n", reg, regData);\r
+\r
+       }\r
+\r
+\r
+       return ret;\r
+\r
+}\r
+\r
+static void SH5001_IMU_Data_Stablize(void)\r
+{\r
+       unsigned char regData = 0;\r
+\r
+       //TODO Three times maybe\r
+       //acc\r
+       SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF0, 1, &regData);\r
+       regData &= 0xFE;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF0, 1, &regData);\r
+       regData |= 0x1;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF0, 1, &regData);\r
+\r
+\r
+       //gyro\r
+       SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, &regData);\r
+       regData &= 0xFE;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, &regData);\r
+       regData |= 0x1;\r
+       SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, &regData);\r
+}\r
+\r
+static void SH5001_OSC_FREQ(void)\r
+{\r
+       unsigned char regData = 0;\r
+\r
+       SH5001_read(SH5001_ADDRESS, 0xDA, 1, &regData);\r
+       if((regData & 0x07) != 0x07)\r
+       {\r
+               regData |= 0x07;\r
+               SH5001_write(SH5001_ADDRESS, 0xDA, 1, &regData);\r
+       }\r
+\r
+}\r
+\r
+#if SENODIA_VDD_3V3\r
+short v3_acc[3] = {0};\r
+unsigned char use_otp_comp = 0;\r
+\r
+void SH5001_Get_Otpoffset(short vacc[3])\r
+{\r
+       unsigned char regData[3]={0};\r
+       unsigned char data = 0;\r
+\r
+       //entry otp read mode\r
+       data = 0x72;\r
+       SH5001_write(SH5001_ADDRESS, 0x02, 1, &data);\r
+\r
+       //read otp page\r
+       data = 0;\r
+       SH5001_read(SH5001_ADDRESS, 0x0, 1, &data);\r
+       printf("otp page data:0x%x\n", data);\r
+       if(data == 0x70){\r
+               //exit otp mode\r
+               data = 0x71;\r
+               SH5001_write(SH5001_ADDRESS, 0x03, 1, &data);\r
+\r
+               //entry otp page 2\r
+               data = 0x70;\r
+               SH5001_write(SH5001_ADDRESS, 0x05, 1, &data);\r
+\r
+               //entry otp read mode\r
+               data = 0x72;\r
+               SH5001_write(SH5001_ADDRESS, 0x02, 1, &data);\r
+\r
+       }\r
+       //otp read data\r
+       SH5001_read(SH5001_ADDRESS, 0x08, 3, regData);\r
+\r
+       //exit otp mode\r
+       data = 0x71;\r
+       SH5001_write(SH5001_ADDRESS, 0x03, 1, &data);\r
+\r
+       if(regData[0] == 0x5f && regData[1] == 0x0 && regData[2] == 0x48)\r
+               use_otp_comp = 0;\r
+       else\r
+               use_otp_comp = 1;\r
+       printf("use_otp_comp:%d\n", use_otp_comp);\r
+       vacc[0] = ((signed char)regData[0]) * 8;\r
+       vacc[1] = ((signed char)regData[1]) * 8;\r
+       vacc[2] = ((signed char)regData[2]) * 8;\r
+       printf("%d %d %d %d %d %d \r\n", regData[0], regData[1], regData[2], vacc[0], vacc[1], vacc[2]);\r
+}\r
+#endif\r
+/******************************************************************\r
+* Description:         SH5001 initialization function\r
+*\r
+* Parameters:  void\r
+*                                                                                                                                                                              \r
+* return:      SH5001_TRUE or SH5001_FALSE\r
+*\r
+******************************************************************/\r
+\r
+uint8_t SH5001_get_chip_id(void)\r
+{\r
+       unsigned char regData = 0;\r
+       unsigned char i = 0;\r
+\r
+       // SH5001 chipID = 0xA1;        \r
+       while((regData != 0xA1U) && (i++ < 3U))\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_CHIP_ID, 1, &regData);       \r
+               if((i == 3) && (regData != 0xA1U))\r
+               {\r
+                       printf("SH5001 init fail, Chip ID = 0x%x\r\n", regData);\r
+                       return SH5001_FALSE;\r
+               }       \r
+       }\r
+       printf("SH5001 Chip ID = 0x%x\r\n", regData);\r
+       return regData;\r
+}\r
+\r
+unsigned char SH5001_init(void) \r
+{\r
+       unsigned char regData = 0;\r
+       unsigned char i = 0;\r
+\r
+#if SH5001_SPI_3WIRE_MODE\r
+       SH5001_SPI_Config(SH5001_SPI_3_WIRE);\r
+#endif\r
+\r
+       // SH5001 chipID = 0xA1;        \r
+       while((regData != 0xA1U) && (i++ < 3U))\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_CHIP_ID, 1, &regData);       \r
+               if((i == 3) && (regData != 0xA1U))\r
+               {\r
+                       printf("SH5001 init fail, Chip ID = 0x%x\r\n", regData);\r
+                       return SH5001_FALSE;\r
+               }       \r
+       }\r
+       printf("SH5001 Chip ID = 0x%x\r\n", regData);\r
+               \r
+       // reset internal module, don't modify it\r
+       SH5001_ModuleReset();   \r
+\r
+       SH5001_OSC_FREQ();\r
+\r
+       #if SH5001_OIS_ENABLE\r
+       SH5001_OIS_SPI_Config(SH5001_OIS_SPI_EN);\r
+       #endif\r
+\r
+       // 500Hz, 16G, cut off Freq(BW)=500*0.25Hz=125Hz, enable filter;\r
+       SH5001_Acc_Config(SH5001_ACC_ODR_125HZ, \r
+                    SH5001_ACC_RANGE_16G, //SH5001_ACC_RANGE_8G  SH5001_ACC_RANGE_16G\r
+                    SH5001_ACC_ODRX040,\r
+                    SH5001_ACC_FILTER_EN,\r
+                    SH5001_ACC_BYPASS_EN);\r
+\r
+       printf("SH5001 acc config ok\r\n");\r
+\r
+       // 800Hz, X\Y\Z 2000deg/s, cut off Freq(BW)=291Hz, enable filter;\r
+       SH5001_Gyro_Config(     SH5001_GYRO_ODR_125HZ,\r
+                      SH5001_GYRO_RANGE_2000,\r
+                      SH5001_GYRO_ODRX040,\r
+                      SH5001_GYRO_FILTER_EN,\r
+                      SH5001_GYRO_BYPASS_EN);\r
+\r
+       SH5001_IMU_Data_Stablize();\r
+\r
+       #if SH5001_OIS_ENABLE\r
+       SH5001_Acc_OIS_Config(SH5001_ACC_OIS_ODR_1000HZ,\r
+               SH5001_ACC_OIS_RANGE_8G,\r
+               SH5001_ACC_OIS_ODRX004,\r
+               SH5001_ACC_OIS_ENABLE);\r
+\r
+       SH5001_Gyro_OIS_Config(SH5001_GYRO_OIS_ODR_8000HZ,\r
+               SH5001_GYRO_OIS_RANGE_2000,\r
+               SH5001_GYRO_OIS_ODRX004,\r
+               SH5001_GYRO_OIS_ENABLE);\r
+       #endif\r
+\r
+       #if SH5001_TS_ENABLE\r
+       SH5001_TimeStamp_Config(SH5001_TS_ODR_1KHZ, SH5001_TS_EN);\r
+       #endif\r
+\r
+       // temperature ODR is 63Hz, enable temperature measurement\r
+       SH5001_Temp_Config(SH5001_TEMP_ODR_63HZ, SH5001_TEMP_EN);\r
+\r
+       //sh5001DumpReg();\r
+       #ifdef SH5001_FIFO_WM_INT\r
+       SH5001_InitFIFO();\r
+       #endif\r
+\r
+       #ifdef SH5001_ACTIVITY_INT\r
+       SH5001_Init_Activity_Int();\r
+       #endif\r
+\r
+       #ifdef SH5001_DATA_READY_INT\r
+       SH5001_Init_Data_Ready_Int();\r
+       #endif\r
+\r
+#if SENODIA_VDD_3V3\r
+       SH5001_Get_Otpoffset(v3_acc);\r
+#endif\r
+       //sh5001DumpReg();\r
+       //sh5001DumpRegAll();\r
+\r
+       return SH5001_TRUE;\r
+}\r
+\r
+\r
+\r
+/******************************************************************\r
+* Description:         Read SH5001 gyroscope and accelerometer data\r
+*\r
+* Parameters:  accData[3]: acc X,Y,Z;  gyroData[3]: gyro X,Y,Z;\r
+*                                                                                                                                                                              \r
+* return:      void\r
+* \r
+******************************************************************/\r
+void SH5001_GetImuData( short accData[3], short gyroData[3] )\r
+{\r
+       unsigned char regData[12]={0};  \r
+               \r
+       SH5001_read(SH5001_ADDRESS, SH5001_ACC_XL, 12, regData); \r
+  \r
+       accData[0] = ((short)regData[1] << 8) | regData[0];\r
+       accData[1] = ((short)regData[3] << 8) | regData[2];\r
+       accData[2] = ((short)regData[5] << 8) | regData[4];             \r
+       \r
+       gyroData[0] = ((short)regData[7] << 8) | regData[6];\r
+       gyroData[1] = ((short)regData[9] << 8) | regData[8];\r
+       gyroData[2] = ((short)regData[11] << 8) | regData[10];\r
+\r
+#if SENODIA_VDD_3V3\r
+       if(use_otp_comp){\r
+               accData[0] -= v3_acc[0];\r
+               accData[1] -= v3_acc[1];\r
+               accData[2] -= v3_acc[2];\r
+       }\r
+#endif\r
+\r
+       printf("%d %d %d %d %d %d\r\n", accData[0], accData[1], accData[2], gyroData[0], gyroData[1], gyroData[2]);\r
+}\r
+\r
+void SH5001_OIS_GetTS(int timestamp[1])\r
+{\r
+       unsigned char regData[3]={0};\r
+\r
+       SH5001_read(SH5001_ADDRESS, 0xE, 3, regData);\r
+\r
+       timestamp[0] = ((int)regData[2] << 16) | ((int)regData[1] << 8) | regData[0];\r
+\r
+}\r
+\r
+#if SH5001_OIS_ENABLE\r
+void SH5001_OIS_GetImuData( short accData[3], short gyroData[3] )\r
+{\r
+       unsigned char regData[12]={0};\r
+       int i = 0;\r
+\r
+       SH5001_OIS_read(SH5001_ADDRESS, SH5001_ACC_XL, 12, regData);\r
+\r
+       accData[0] = ((short)regData[1] << 8) | regData[0];\r
+       accData[1] = ((short)regData[3] << 8) | regData[2];\r
+       accData[2] = ((short)regData[5] << 8) | regData[4];\r
+\r
+       gyroData[0] = ((short)regData[7] << 8) | regData[6];\r
+       gyroData[1] = ((short)regData[9] << 8) | regData[8];\r
+       gyroData[2] = ((short)regData[11] << 8) | regData[10];\r
+\r
+       //printf("%d %d %d %d %d %d\r\n", accData[0], accData[1], accData[2], gyroData[0], gyroData[1], gyroData[2]);\r
+}\r
+#endif\r
+\r
+#define SH5001_OFFSET_REG_NUM 13\r
+void offset_comp_save_reg(float offset[3])\r
+{\r
+       unsigned char offsetData[SH5001_OFFSET_REG_NUM] = {0};\r
+\r
+       short offset_otp[3] = {0};\r
+       short gain_otp[3] = {0};\r
+       unsigned int range = 1;\r
+\r
+       int offset_temp[3] = {0};\r
+       short offset_new[3] = {0};\r
+       unsigned short s_offset_new[3] = {0};\r
+\r
+       unsigned char i;\r
+\r
+\r
+       unsigned char offsetRegister[SH5001_OFFSET_REG_NUM] = { 0x8C, 0x8D, 0x8E, 0x8F, 0x98, 0x99, 0x9A, 0x9B, 0xA4, 0xA5 , 0xA6,\r
+       0xA7, 0x24};\r
+\r
+       for(i=0; i<SH5001_OFFSET_REG_NUM; i++)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, offsetRegister[i], 1, &offsetData[i]);\r
+               #ifdef SH5001_OT_DEBUG\r
+               printf("0x%x = 0x%x\r\n", offsetRegister[i], offsetData[i]);\r
+               #endif\r
+       }\r
+       #ifdef SH5001_OT_DEBUG\r
+       printf("n offset %f %f %f \r\n", offset[0], offset[1],offset[2]);\r
+       #endif\r
+\r
+       offset_otp[0] = ((short)offsetData[3] << 8) | offsetData[2];\r
+       offset_otp[1] = ((short)offsetData[7] << 8) | offsetData[6];\r
+       offset_otp[2] = ((short)offsetData[11] << 8) | offsetData[10];\r
+\r
+       gain_otp[0] = ((short)offsetData[1] << 8) | offsetData[0];\r
+       gain_otp[1] = ((short)offsetData[5] << 8) | offsetData[4];\r
+       gain_otp[2] = ((short)offsetData[9] << 8) | offsetData[8];\r
+\r
+       #ifdef SH5001_OT_DEBUG\r
+       printf("offset_otp %d %d %d \r\n", offset_otp[0], offset_otp[1],offset_otp[2]);\r
+       printf("gain_otp %d %d %d \r\n", gain_otp[0], gain_otp[1],gain_otp[2]);\r
+       #endif\r
+\r
+       offsetData[12] = (offsetData[12] & 0x70) >> 4;\r
+\r
+       if(offsetData[12] != 0)\r
+       {\r
+                       for(i=0; i < offsetData[12] + 7; i++)\r
+                       {\r
+                               range = range * 2;\r
+                       }\r
+       }\r
+\r
+       #ifdef SH5001_OT_DEBUG\r
+       printf("range %d \r\n", range);\r
+       #endif\r
+\r
+       for(i = 0; i < 3; i++)\r
+       {\r
+               offset_temp[i] = offset_otp[i] + (int)(offset[i] * ((float)range) / ((float)gain_otp[i]));  //\r
+               //offset_new[i] = offset_otp[i] + (offset[i] * range / gain_otp[i]);  //\r
+       }\r
+\r
+       if(offset_temp[0] > 32767)\r
+               offset_temp[0] = 32767;\r
+       else if(offset_temp[0] < -32768)\r
+               offset_temp[0] = -32768;\r
+       if(offset_temp[1] > 32767)\r
+               offset_temp[1] = 32767;\r
+       else if(offset_temp[1] < -32768)\r
+               offset_temp[1] = -32768;\r
+       if(offset_temp[2] > 32767)\r
+               offset_temp[2] = 32767;\r
+       else if(offset_temp[2] < -32768)\r
+               offset_temp[2] = -32768;\r
+\r
+       offset_new[0] = (short)offset_temp[0];\r
+       offset_new[1] = (short)offset_temp[1];\r
+       offset_new[2] = (short)offset_temp[2];\r
+\r
+       #ifdef SH5001_OT_DEBUG\r
+       printf("offset_new %d %d %d \r\n", offset_new[0], offset_new[1],offset_new[2]);\r
+       #endif\r
+\r
+       s_offset_new[0] = (unsigned short)offset_new[0];\r
+       s_offset_new[1] = (unsigned short)offset_new[1];\r
+       s_offset_new[2] = (unsigned short)offset_new[2];\r
+\r
+       offsetData[3] = (unsigned char)((s_offset_new[0] & 0xFF00)>>8);\r
+       offsetData[7] = (unsigned char)((s_offset_new[1] & 0xFF00)>>8);\r
+       offsetData[11] = (unsigned char)((offset_new[2] & 0xFF00)>>8);\r
+       offsetData[2] = (unsigned char)((s_offset_new[0] & 0x00FF));\r
+       offsetData[6] = (unsigned char)((s_offset_new[1] & 0x00FF));\r
+       offsetData[10] = (unsigned char)((s_offset_new[2] & 0x00FF));\r
+\r
+       #ifdef SH5001_OT_DEBUG\r
+       printf("offsetData %x %x %x %x %x %x\r\n", offsetData[2], offsetData[3],offsetData[6], offsetData[7], offsetData[10], offsetData[11]);\r
+  #endif\r
+\r
+       SH5001_write(SH5001_ADDRESS, 0x8E, 1, &offsetData[2]);\r
+       SH5001_write(SH5001_ADDRESS, 0x8F, 1, &offsetData[3]);\r
+       SH5001_write(SH5001_ADDRESS, 0x9A, 1, &offsetData[6]);\r
+       SH5001_write(SH5001_ADDRESS, 0x9B, 1, &offsetData[7]);\r
+       SH5001_write(SH5001_ADDRESS, 0xA6, 1, &offsetData[10]);\r
+       SH5001_write(SH5001_ADDRESS, 0xA7, 1, &offsetData[11]);\r
+\r
+       //for test\r
+       #if 0\r
+       for(i=0; i<SH5001_OFFSET_REG_NUM; i++)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, offsetRegister[i], 1, &offsetData[i]);\r
+               #ifdef SH5001_OT_DEBUG\r
+               printf("read back 0x%x = 0x%x\r\n", offsetRegister[i], offsetData[i]);\r
+               #endif\r
+       }\r
+       #endif\r
+}\r
+\r
+#define SH5001_TEMPCOMP_REG_NUM 10\r
+void temp_comp_save_reg(float k[3])\r
+{\r
+       unsigned char tempCompData[SH5001_OFFSET_REG_NUM] = {0};\r
+\r
+       signed char beta_otp[3] = {0};\r
+       short gain_otp[3] = {0};\r
+       unsigned int range = 1;\r
+\r
+       unsigned char  beta_new[3] = {0};\r
+       signed char  s_beta_new[3] = {0};\r
+       int  s_beta_temp[3] = {0};\r
+\r
+       unsigned char i;\r
+\r
+       unsigned char tempCompRegister[SH5001_OFFSET_REG_NUM] = { 0x8C, 0x8D,  0x98, 0x99,  0xA4, 0xA5 , 0x92,0x9e,0xAA, 0x24};\r
+\r
+       for(i=0; i<SH5001_TEMPCOMP_REG_NUM; i++)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, tempCompRegister[i], 1, &tempCompData[i]);\r
+               #ifdef SH5001_OT_DEBUG\r
+               printf("0x%x = 0x%x\r\n", tempCompRegister[i], tempCompData[i]);\r
+               #endif\r
+       }\r
+\r
+       for(i=0; i<3; i++)\r
+       {\r
+               k[i] = k[i] * 16.4 / 14.0; // deg/c  to lsb/lsb  range2000dps\r
+       }\r
+\r
+       #ifdef SH5001_OT_DEBUG\r
+       printf("k %f %f %f \r\n", k[0], k[1],k[2]);\r
+       #endif\r
+\r
+       gain_otp[0] = ((short)tempCompData[1] << 8) | tempCompData[0];\r
+       gain_otp[1] = ((short)tempCompData[3] << 8) | tempCompData[2];\r
+       gain_otp[2] = ((short)tempCompData[5] << 8) | tempCompData[4];\r
+\r
+       //TODO unsigned to signed\r
+       beta_otp[0] = ((signed char)tempCompData[6]);\r
+       beta_otp[1] = ((signed char)tempCompData[7]);\r
+       beta_otp[2] = ((signed char)tempCompData[8]);\r
+\r
+       tempCompData[9] = (tempCompData[9] & 0x70) >> 4;\r
+\r
+       #ifdef SH5001_OT_DEBUG\r
+       printf("gain_otp %d %d %d \r\n", gain_otp[0], gain_otp[1],gain_otp[2]);\r
+       printf("temp_otp %d %d %d \r\n", beta_otp[0], beta_otp[1],beta_otp[2]);\r
+       printf("range 0x%x \r\n", tempCompData[9]);\r
+       #endif\r
+\r
+       if(tempCompData[9] != 0)\r
+       {\r
+                       for(i=0; i < tempCompData[9] + 14; i++)\r
+                       {\r
+                               range = range * 2;\r
+                       }\r
+       }\r
+\r
+       #ifdef SH5001_OT_DEBUG\r
+       printf("range222 %d \r\n", range);\r
+       #endif\r
+  //TODO\r
+       for(i = 0; i < 3; i++)\r
+       {\r
+               s_beta_temp[i] = beta_otp[i] - (int)(k[i] * ((float)range) / ((float)gain_otp[i]));\r
+               #ifdef SH5001_OT_DEBUG\r
+                       printf("beta_ 111 %f %d\r\n", k[i] * range / gain_otp[i], (int)(k[i] * range / gain_otp[i]));\r
+               #endif\r
+       }\r
+\r
+       if(s_beta_temp[0] > 127)\r
+               s_beta_temp[0] = 127;\r
+       else if(s_beta_temp[0] < -128)\r
+               s_beta_temp[0] = -128;\r
+       if(s_beta_temp[1] > 127)\r
+               s_beta_temp[1] = 127;\r
+       else if(s_beta_temp[1] < -128)\r
+               s_beta_temp[1] = -128;\r
+       if(s_beta_temp[2] > 127)\r
+               s_beta_temp[2] = 127;\r
+       else if(s_beta_temp[2] < -128)\r
+               s_beta_temp[2] = -128;\r
+\r
+       s_beta_new[0] = (char)s_beta_temp[0];\r
+       s_beta_new[1] = (char)s_beta_temp[1];\r
+       s_beta_new[2] = (char)s_beta_temp[2];\r
+\r
+       beta_new[0] = (unsigned char)s_beta_new[0];\r
+       beta_new[1] = (unsigned char)s_beta_new[1];\r
+       beta_new[2] = (unsigned char)s_beta_new[2];\r
+\r
+       #ifdef SH5001_OT_DEBUG\r
+       printf("s_beta_new %d %d %d \r\n", s_beta_new[0], s_beta_new[1],s_beta_new[2]);\r
+       printf("beta_new %x %x %x \r\n", beta_new[0], beta_new[1],beta_new[2]);\r
+    #endif\r
+\r
+       SH5001_write(SH5001_ADDRESS, 0x92, 1, &beta_new[0]);\r
+       SH5001_write(SH5001_ADDRESS, 0x9e, 1, &beta_new[1]);\r
+       SH5001_write(SH5001_ADDRESS, 0xAA, 1, &beta_new[2]);\r
+}\r
+\r
+#define SH5001_ACC_REG_NUM 4\r
+void acc_temp_comp_save_reg(float k[3])\r
+{\r
+       unsigned char tempCompData[SH5001_ACC_REG_NUM] = {0};\r
+       signed char beta_otp[3] = {0};\r
+       short gain_otp[3] = {0};\r
+       unsigned int range = 1;\r
+       float rangek = 1;\r
+       unsigned char beta_new[3] = {0};\r
+       signed char s_beta_new[3] = {0};\r
+       int s_beta_temp[3] = {0};\r
+       unsigned char i;\r
+       unsigned char tempCompRegister[SH5001_ACC_REG_NUM] = {0x71, 0x7c, 0x88, 0x21};\r
+       for(i=0; i<SH5001_ACC_REG_NUM; i++)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, tempCompRegister[i], 1, &tempCompData[i]);\r
+               #ifdef SH5001_OT_DEBUG\r
+               printf("0x%x = 0x%x\r\n", tempCompRegister[i], tempCompData[i]);\r
+               #endif\r
+       }\r
+       beta_otp[0] = ((signed char)tempCompData[0]);\r
+       beta_otp[1] = ((signed char)tempCompData[1]);\r
+       beta_otp[2] = ((signed char)tempCompData[2]);\r
+       tempCompData[3] = (tempCompData[3] & 0x70) >> 4;\r
+       #ifdef SH5001_OT_DEBUG\r
+       printf("temp_otp %d %d %d \r\n", beta_otp[0], beta_otp[1],beta_otp[2]);\r
+       printf("range 0x%x \r\n", tempCompData[3]);\r
+       #endif\r
+       if(tempCompData[3] != 0)\r
+       {\r
+                       for(i=0; i < 6 - tempCompData[3]; i++)\r
+                       {\r
+                               range = range * 2;\r
+                       }\r
+       }\r
+       for(i=0; i<3; i++)\r
+       {\r
+               k[i] = k[i] * range * 2.048 / 14;\r
+       }\r
+       #ifdef SH5001_OT_DEBUG\r
+       printf("k %f %f %f \r\n", k[0], k[1],k[2]);\r
+       #endif\r
+       if(tempCompData[3] != 0)\r
+       {\r
+                       for(i=0; i < tempCompData[3] + 1; i++)\r
+                       {\r
+                               rangek = rangek * 2;\r
+                       }\r
+       }\r
+       #ifdef SH5001_OT_DEBUG\r
+       printf("range222 %f \r\n", rangek);\r
+       #endif\r
+       for(i = 0; i < 3; i++)\r
+       {\r
+               s_beta_temp[i] = beta_otp[i] - (int)(k[i] * rangek);\r
+               #ifdef SH5001_OT_DEBUG\r
+               printf("beta_111 %f %d\r\n", k[i] * rangek , (int)(k[i] * rangek));\r
+               #endif\r
+       }\r
+       if(s_beta_temp[0] > 127)\r
+               s_beta_temp[0] = 127;\r
+       else if(s_beta_temp[0] < -128)\r
+               s_beta_temp[0] = -128;\r
+       if(s_beta_temp[1] > 127)\r
+               s_beta_temp[1] = 127;\r
+       else if(s_beta_temp[1] < -128)\r
+               s_beta_temp[1] = -128;\r
+       if(s_beta_temp[2] > 127)\r
+               s_beta_temp[2] = 127;\r
+       else if(s_beta_temp[2] < -128)\r
+               s_beta_temp[2] = -128;\r
+       s_beta_new[0] = (char)s_beta_temp[0];\r
+       s_beta_new[1] = (char)s_beta_temp[1];\r
+       s_beta_new[2] = (char)s_beta_temp[2];\r
+       beta_new[0] = (unsigned char)s_beta_new[0];\r
+       beta_new[1] = (unsigned char)s_beta_new[1];\r
+       beta_new[2] = (unsigned char)s_beta_new[2];\r
+       #ifdef SH5001_OT_DEBUG\r
+       printf("s_beta_new %d %d %d \r\n", s_beta_new[0], s_beta_new[1],s_beta_new[2]);\r
+       printf("beta_new %x %x %x \r\n", beta_new[0], beta_new[1],beta_new[2]);\r
+    #endif\r
+       SH5001_write(SH5001_ADDRESS, 0x71, 1, &beta_new[0]);\r
+       SH5001_write(SH5001_ADDRESS, 0x7c, 1, &beta_new[1]);\r
+       SH5001_write(SH5001_ADDRESS, 0x88, 1, &beta_new[2]);\r
+}\r
+\r
+#define SH5001_QUAD_REG_NUM 10\r
+#define SH5001_QUAD_DEBUG\r
+\r
+void sh5001_gyro_trim_quad(unsigned char quadval[6])\r
+{\r
+  short S_Gyro_Quad[3] = {0};\r
+  short C_Gyro_Quad[3] = {0};\r
+  unsigned char quadData[SH5001_QUAD_REG_NUM] = {0};\r
+  int sumGyroData[3] = {0};\r
+  short avgGyroData[3] = {0};\r
+  short GyroData[3] = {0};\r
+  unsigned char temp[6]= {0};\r
+  unsigned char i;\r
+  double Slope[3] = {560, 560, 560};\r
+\r
+  unsigned char quadRegister[SH5001_QUAD_REG_NUM] = {0x8B, 0x97, 0xA3, 0xD9,  0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC};\r
+  unsigned char RegWrt_1[SH5001_QUAD_REG_NUM] = {0xFF, 0xFF, 0xFF, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\r
+\r
+  for(i=0; i<SH5001_QUAD_REG_NUM; i++)\r
+  {\r
+    SH5001_read(SH5001_ADDRESS, quadRegister[i], 1, &quadData[i]);\r
+    #ifdef SH5001_QUAD_DEBUG\r
+    printf("quadRegister RegWrt_1 raw 0x%x:0x%x\r\n",quadRegister[i], quadData[i]);\r
+    #endif\r
+  }\r
+\r
+  for(i=0; i<4; i++)\r
+  {\r
+    SH5001_write(SH5001_ADDRESS, quadRegister[i], 1, &RegWrt_1[i]);\r
+  }\r
+\r
+  delay_ms(80);\r
+\r
+  for(i=20; i>0; i--)\r
+  {\r
+    delay_ms(1);\r
+\r
+    SH5001_read(SH5001_ADDRESS, 0x06, 6, temp);\r
+    GyroData[0]=((short)(temp[1]<<8))|temp[0];\r
+    GyroData[1]=((short)(temp[3]<<8))|temp[2];\r
+    GyroData[2]=((short)(temp[5]<<8))|temp[4];\r
+\r
+    sumGyroData[0] += GyroData[0];\r
+    sumGyroData[1] += GyroData[1];\r
+    sumGyroData[2] += GyroData[2];\r
+\r
+    #ifdef SH5001_QUAD_DEBUG\r
+    printf("sumGyroData %d %d %d\r\n",GyroData[0], GyroData[1], GyroData[2]);\r
+    #endif\r
+  }\r
+\r
+  for(i = 0; i < 3; i++)\r
+  {\r
+    avgGyroData[i] = sumGyroData[i] / 20;\r
+  }\r
+\r
+  #ifdef SH5001_QUAD_DEBUG\r
+  printf("avgGyroData %d %d %d\r\n",avgGyroData[0], avgGyroData[1], avgGyroData[2]);\r
+  #endif\r
+\r
+  for (i = 0; i < 3; i++)\r
+  {\r
+      S_Gyro_Quad[i] = (quadData[i + 7] & 0x04) >> 2;\r
+      C_Gyro_Quad[i] = quadData[i + 4] + (quadData[i + 7] & 0x03) * 256;\r
+\r
+      #ifdef SH5001_QUAD_DEBUG\r
+      printf("raw S_Gyro_Quad[%d] : %d  C_Gyro_Quad[%d]: %d  \r\n",i, S_Gyro_Quad[i], i, C_Gyro_Quad[i]);\r
+      #endif\r
+\r
+      C_Gyro_Quad[i] = (S_Gyro_Quad[i] == 0) ? C_Gyro_Quad[i]: (C_Gyro_Quad[i] * (-1) - 1);\r
+      C_Gyro_Quad[i] = (int)(C_Gyro_Quad[i] - avgGyroData[i] / Slope[i]);\r
+\r
+      S_Gyro_Quad[i] = C_Gyro_Quad[i] >= 0 ? 0 : 1;\r
+      C_Gyro_Quad[i] = C_Gyro_Quad[i] >= 0 ? C_Gyro_Quad[i]: (C_Gyro_Quad[i] * (-1) - 1);\r
+\r
+      RegWrt_1[i + 4] = C_Gyro_Quad[i] & 0x00FF;\r
+      RegWrt_1[i + 7] = (quadData[i + 7] & 0xF8) + S_Gyro_Quad[i] * 4 + ((C_Gyro_Quad[i] & 0x0300) >> 8);\r
+\r
+  }\r
+  #ifdef SH5001_QUAD_DEBUG\r
+  printf("mod S_Gyro_Quad %d %d %d C_Gyro_Quad %d %d %d RegWrt_1 %d %d %d %d %d %d\r\n",S_Gyro_Quad[0],\r
+  S_Gyro_Quad[1],S_Gyro_Quad[2],C_Gyro_Quad[0],C_Gyro_Quad[1],C_Gyro_Quad[2], RegWrt_1[4], RegWrt_1[5], RegWrt_1[6], RegWrt_1[7], RegWrt_1[8], RegWrt_1[9]);\r
+  #endif\r
+\r
+\r
+  //TODO Save Reg\r
+  for(i=0; i<6; i++) {\r
+    SH5001_write(SH5001_ADDRESS, quadRegister[i + 4], 1, &RegWrt_1[i + 4]);\r
+    quadval[i] = RegWrt_1[i + 4];\r
+  }\r
+\r
+  for(i=0; i<4; i++)\r
+    SH5001_write(SH5001_ADDRESS, quadRegister[i], 1, &quadData[i]);\r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description:         SH5001 Acc self-test function\r
+*\r
+* Parameters:  void\r
+*\r
+* return:      SH3001_TRUE or SH3001_FALSE\r
+*\r
+******************************************************************/\r
+\r
+#define  SH5001_ACC_SELFTEST_REGNUM 7\r
+#define  SH5001_ACC_SELFTEST_DEBUG\r
+\r
+unsigned char SH5001_AccSelfTest(void)\r
+{\r
+       unsigned char regAddr[SH5001_ACC_SELFTEST_REGNUM] = {0x21, 0x69, 0x74, 0x80, 0xB9, 0xBA, 0xBB};\r
+       unsigned char regInit[SH5001_ACC_SELFTEST_REGNUM] = {0x30, 0xFF, 0xFF, 0xFF, 0x40, 0x45, 0x45};\r
+       unsigned char regBack[SH5001_ACC_SELFTEST_REGNUM] = {0};\r
+       unsigned char accTemp[6] = {0};\r
+       signed int accSum[3] = {0};\r
+       signed short accAvg1[3] = {0}, accAvg2[3] = {0};\r
+       unsigned char i = 0;\r
+       signed short accRange[3] = {0};\r
+\r
+\r
+       for(i=0; i<SH5001_ACC_SELFTEST_REGNUM; i++)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, regAddr[i], 1, &regBack[i]);\r
+       }\r
+\r
+       for(i=0; i<SH5001_ACC_SELFTEST_REGNUM; i++)\r
+       {\r
+               SH5001_write(SH5001_ADDRESS, regAddr[i], 1, &regInit[i]);\r
+       }\r
+\r
+       delay_ms(100);\r
+\r
+       i = 0;\r
+       while(i++ < 20)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_ACC_XL, 6, accTemp);\r
+               accSum[0] += ((short)accTemp[1] << 8) | accTemp[0];\r
+               accSum[1] += ((short)accTemp[3] << 8) | accTemp[2];\r
+               accSum[2] += ((short)accTemp[5] << 8) | accTemp[4];\r
+\r
+               #ifdef SH5001_ACC_SELFTEST_DEBUG\r
+               printf("bf %d %d %d\r\n", ((short)accTemp[1] << 8) | accTemp[0], ((short)accTemp[3] << 8) | accTemp[2], ((short)accTemp[5] << 8) | accTemp[4]);\r
+               #endif\r
+       }\r
+       accAvg1[0] = accSum[0]/20;\r
+       accAvg1[1] = accSum[1]/20;\r
+       accAvg1[2] = accSum[2]/20;\r
+\r
+\r
+       accTemp[0] = 0x60;\r
+       SH5001_write(SH5001_ADDRESS, 0xB9, 1, &accTemp[0]);\r
+       accTemp[0] = 0x65;\r
+       SH5001_write(SH5001_ADDRESS, 0xBA, 1, &accTemp[0]);\r
+       accTemp[0] = 0x65;\r
+       SH5001_write(SH5001_ADDRESS, 0xBB, 1, &accTemp[0]);\r
+\r
+       delay_ms(100);\r
+\r
+       accSum[0] = 0;\r
+       accSum[1] = 0;\r
+       accSum[2] = 0;\r
+       i = 0;\r
+       while(i++ < 20)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_ACC_XL, 6, accTemp);\r
+               accSum[0] += ((short)accTemp[1] << 8) | accTemp[0];\r
+               accSum[1] += ((short)accTemp[3] << 8) | accTemp[2];\r
+               accSum[2] += ((short)accTemp[5] << 8) | accTemp[4];\r
+               #ifdef SH5001_ACC_SELFTEST_DEBUG\r
+               printf("af %d %d %d\r\n", ((short)accTemp[1] << 8) | accTemp[0], ((short)accTemp[3] << 8) | accTemp[2], ((short)accTemp[5] << 8) | accTemp[4]);\r
+               #endif\r
+       }\r
+       accAvg2[0] = accSum[0]/20;\r
+       accAvg2[1] = accSum[1]/20;\r
+       accAvg2[2] = accSum[2]/20;\r
+\r
+\r
+       for(i=0; i<SH5001_ACC_SELFTEST_REGNUM; i++)\r
+       {\r
+               SH5001_write(SH5001_ADDRESS, regAddr[i], 1, &regBack[i]);\r
+       }\r
+\r
+       accRange[0] = accAvg2[0] - accAvg1[0];\r
+       accRange[1] = accAvg2[1] - accAvg1[1];\r
+       accRange[2] = accAvg2[2] - accAvg1[2];\r
+\r
+       #ifdef SH5001_ACC_SELFTEST_DEBUG\r
+       printf("accdiff %d %d %d\r\n", accRange[0],accRange[1] ,accRange[2]);\r
+       #endif\r
+\r
+       if(((accRange[0] > 3900) && (accRange[0] < 9200))\r
+       && ((accRange[1] > 4100) && (accRange[1] < 9600))\r
+       && ((accRange[2] > 4500) && (accRange[2] < 10900)))\r
+       {\r
+               return(SH5001_TRUE);\r
+       }\r
+       else\r
+       {\r
+               return(SH5001_FALSE);\r
+       }\r
+}\r
+\r
+\r
+/******************************************************************\r
+* Description:         SH5001 Gyro self-test function\r
+*\r
+* Parameters:  void\r
+*\r
+* return:      SH3001_TRUE or SH3001_FALSE\r
+*\r
+******************************************************************/\r
+\r
+#define SH5001_GYRO_SELFTEST_REGNUM 11\r
+#define  SH5001_GYRO_SELFTEST_DEBUG\r
+\r
+unsigned char SH5001_GyroSelfTest(void)\r
+{\r
+       unsigned char regAddr[SH5001_GYRO_SELFTEST_REGNUM] = {0x24, 0x8B, 0x97, 0xA3, 0xCA, 0xCB, 0xCC, 0xCD,\\r
+                                                               0xCE, 0xCF, 0xD9};\r
+       unsigned char regInit[SH5001_GYRO_SELFTEST_REGNUM] = {0x60, 0xFF, 0xFF, 0xFF, 0x60, 0x60, 0x60, 0x02,\\r
+                                                               0x02, 0x02, 0x91};\r
+       unsigned char regBack[SH5001_GYRO_SELFTEST_REGNUM] = {0};\r
+       unsigned char gyroTemp[6] = {0};\r
+       signed int gyroSum[3] = {0};\r
+       signed short gyroAvg1[3] = {0}, gyroAvg2[3] = {0};\r
+       unsigned char i = 0;\r
+       signed short gyroRange[3] = {0};\r
+\r
+       for(i=0; i<SH5001_GYRO_SELFTEST_REGNUM; i++)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, regAddr[i], 1, &regBack[i]);\r
+       }\r
+\r
+       for(i=0; i<SH5001_GYRO_SELFTEST_REGNUM; i++)\r
+       {\r
+               SH5001_write(SH5001_ADDRESS, regAddr[i], 1, &regInit[i]);\r
+       }\r
+\r
+       //Gyro x\r
+       gyroTemp[0] = 0x15;\r
+       SH5001_write(SH5001_ADDRESS, 0xCD, 1, &gyroTemp[0]);\r
+       gyroTemp[0] = 0x02;\r
+       SH5001_write(SH5001_ADDRESS, 0xCE, 1, &gyroTemp[0]);\r
+       gyroTemp[0] = 0x02;\r
+       SH5001_write(SH5001_ADDRESS, 0xCF, 1, &gyroTemp[0]);\r
+\r
+       delay_ms(50);\r
+\r
+       i = 0;\r
+       while(i++ < 20)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_GYRO_XL, 2, gyroTemp);\r
+               gyroSum[0] += ((short)gyroTemp[1] << 8) | gyroTemp[0];\r
+               #ifdef SH5001_GYRO_SELFTEST_DEBUG\r
+               printf("Gx bf %d \r\n", (signed short)(((short)gyroTemp[1] << 8) | gyroTemp[0]));\r
+               #endif\r
+       }\r
+       gyroAvg1[0] = gyroSum[0]/20;\r
+\r
+       gyroTemp[0] = 0x14;\r
+       SH5001_write(SH5001_ADDRESS, 0xCD, 1, &gyroTemp[0]);\r
+       gyroTemp[0] = 0x02;\r
+       SH5001_write(SH5001_ADDRESS, 0xCE, 1, &gyroTemp[0]);\r
+       gyroTemp[0] = 0x02;\r
+       SH5001_write(SH5001_ADDRESS, 0xCF, 1, &gyroTemp[0]);\r
+\r
+       delay_ms(50);\r
+\r
+       gyroSum[0] = 0;\r
+\r
+       i = 0;\r
+       while(i++ < 20)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_GYRO_XL, 2, gyroTemp);\r
+               gyroSum[0] += ((short)gyroTemp[1] << 8) | gyroTemp[0];\r
+\r
+               #ifdef SH5001_GYRO_SELFTEST_DEBUG\r
+               printf("Gx af %d \r\n", (signed short)(((short)gyroTemp[1] << 8) | gyroTemp[0]));\r
+               #endif\r
+       }\r
+       gyroAvg2[0] = gyroSum[0]/20;\r
+\r
+       //gyro y\r
+       gyroTemp[0] = 0x02;\r
+       SH5001_write(SH5001_ADDRESS, 0xCD, 1, &gyroTemp[0]);\r
+       gyroTemp[0] = 0x15;\r
+       SH5001_write(SH5001_ADDRESS, 0xCE, 1, &gyroTemp[0]);\r
+       gyroTemp[0] = 0x02;\r
+       SH5001_write(SH5001_ADDRESS, 0xCF, 1, &gyroTemp[0]);\r
+\r
+       delay_ms(50);\r
+\r
+       i = 0;\r
+       while(i++ < 20)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_GYRO_YL, 2, gyroTemp);\r
+               gyroSum[1] += ((short)gyroTemp[1] << 8) | gyroTemp[0];\r
+\r
+               #ifdef SH5001_GYRO_SELFTEST_DEBUG\r
+               printf("Gy bf %d \r\n", (signed short)(((short)gyroTemp[1] << 8) | gyroTemp[0]));\r
+               #endif\r
+       }\r
+       gyroAvg1[1] = gyroSum[1]/20;\r
+\r
+       gyroTemp[0] = 0x02;\r
+       SH5001_write(SH5001_ADDRESS, 0xCD, 1, &gyroTemp[0]);\r
+       gyroTemp[0] = 0x14;\r
+       SH5001_write(SH5001_ADDRESS, 0xCE, 1, &gyroTemp[0]);\r
+       gyroTemp[0] = 0x02;\r
+       SH5001_write(SH5001_ADDRESS, 0xCF, 1, &gyroTemp[0]);\r
+\r
+       delay_ms(50);\r
+\r
+       gyroSum[1] = 0;\r
+\r
+       i = 0;\r
+       while(i++ < 20)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_GYRO_YL, 2, gyroTemp);\r
+               gyroSum[1] += ((short)gyroTemp[1] << 8) | gyroTemp[0];\r
+\r
+               #ifdef SH5001_GYRO_SELFTEST_DEBUG\r
+               printf("Gy af %d \r\n", (signed short)(((short)gyroTemp[1] << 8) | gyroTemp[0]));\r
+               #endif\r
+\r
+       }\r
+       gyroAvg2[1] = gyroSum[1]/20;\r
+\r
+       //gyro z\r
+       gyroTemp[0] = 0x02;\r
+       SH5001_write(SH5001_ADDRESS, 0xCD, 1, &gyroTemp[0]);\r
+       gyroTemp[0] = 0x02;\r
+       SH5001_write(SH5001_ADDRESS, 0xCE, 1, &gyroTemp[0]);\r
+       gyroTemp[0] = 0x15;\r
+       SH5001_write(SH5001_ADDRESS, 0xCF, 1, &gyroTemp[0]);\r
+\r
+       delay_ms(50);\r
+\r
+       i = 0;\r
+       while(i++ < 20)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_GYRO_ZL, 2, gyroTemp);\r
+               gyroSum[2] += ((short)gyroTemp[1] << 8) | gyroTemp[0];\r
+               #ifdef SH5001_GYRO_SELFTEST_DEBUG\r
+               printf("Gz bf %d \r\n", (signed short)(((short)gyroTemp[1] << 8) | gyroTemp[0]));\r
+               #endif\r
+       }\r
+       gyroAvg1[2] = gyroSum[2]/20;\r
+\r
+       gyroTemp[0] = 0x02;\r
+       SH5001_write(SH5001_ADDRESS, 0xCD, 1, &gyroTemp[0]);\r
+       gyroTemp[0] = 0x02;\r
+       SH5001_write(SH5001_ADDRESS, 0xCE, 1, &gyroTemp[0]);\r
+       gyroTemp[0] = 0x14;\r
+       SH5001_write(SH5001_ADDRESS, 0xCF, 1, &gyroTemp[0]);\r
+\r
+       delay_ms(50);\r
+\r
+       gyroSum[2] = 0;\r
+\r
+       i = 0;\r
+       while(i++ < 20)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_GYRO_ZL, 2, gyroTemp);\r
+               gyroSum[2] += ((short)gyroTemp[1] << 8) | gyroTemp[0];\r
+               #ifdef SH5001_GYRO_SELFTEST_DEBUG\r
+               printf("Gz af %d\r\n", (signed short)(((short)gyroTemp[1] << 8) | gyroTemp[0]));\r
+               #endif\r
+       }\r
+       gyroAvg2[2] = gyroSum[2]/20;\r
+\r
+       for(i=0; i<SH5001_GYRO_SELFTEST_REGNUM; i++)\r
+       {\r
+               SH5001_write(SH5001_ADDRESS, regAddr[i], 1, &regBack[i]);\r
+       }\r
+\r
+       #ifdef SH5001_GYRO_SELFTEST_DEBUG\r
+       printf("G b average %d %d %d\r\n", gyroAvg1[0],gyroAvg1[1] ,gyroAvg1[2]);\r
+       printf("G a average %d %d %d\r\n", gyroAvg2[0],gyroAvg2[1] ,gyroAvg2[2]);\r
+       #endif\r
+\r
+       gyroRange[0] = gyroAvg2[0] - gyroAvg1[0];\r
+       gyroRange[1] = gyroAvg2[1] - gyroAvg1[1];\r
+       gyroRange[2] = gyroAvg2[2] - gyroAvg1[2];\r
+\r
+       #ifdef SH5001_GYRO_SELFTEST_DEBUG\r
+       printf("Gyro diff %d %d %d\r\n", gyroRange[0],gyroRange[1] ,gyroRange[2]);\r
+       #endif\r
+\r
+       if(((gyroRange[0] > -4500) && (gyroRange[0] < 7100))\r
+               && ((gyroRange[1] > -6900) && (gyroRange[1] < 8200))\r
+               && ((gyroRange[2] > -9300) && (gyroRange[2] < 4600)))\r
+       {\r
+               return(SH5001_TRUE);\r
+       }\r
+       else\r
+       {\r
+               return(SH5001_FALSE);\r
+       }\r
+}\r
+\r
+void sh5001_adc_phase(void)\r
+{\r
+       unsigned char addr = 0xD0;\r
+       unsigned char regData;\r
+\r
+       SH5001_read(SH5001_ADDRESS, addr, 1, &regData);\r
+       //printf("0xD0 = 0x%x\r\n", regData);\r
+\r
+       if((regData & 0x02) == 0x02)\r
+               regData &= 0xFD;\r
+       else\r
+               regData |= 0x02;\r
+       SH5001_write(SH5001_ADDRESS, addr, 1, &regData);\r
+       //printf("0xD0 = 0x%x\r\n", regData);\r
+\r
+}\r
+\r
+#define SH5001_GYRO_ADC_S1_REGNUM 5\r
+#define SH5001_GYRO_ADC_S2_REGNUM 1\r
+//#define SH5001_GYRO_ADC__DEBUG\r
+int adc_count = 0;\r
+int err_count = 0;\r
+void SH5001_Get_Adc_Polarity(short gyroPolarity[3])\r
+{\r
+       unsigned char regAddrS1[SH5001_GYRO_ADC_S1_REGNUM] = {0xA3, 0xC6, 0xCC, 0xCF, 0xD0};\r
+       unsigned char regInitS1[SH5001_GYRO_ADC_S1_REGNUM] = {0xFF, 0x00, 0x69, 0x1A, 0x0A};\r
+       unsigned char regAddrS2[SH5001_GYRO_ADC_S2_REGNUM] = {0xD0};\r
+       unsigned char regInitS2[SH5001_GYRO_ADC_S2_REGNUM] = {0x08};\r
+       unsigned char regBackS1[SH5001_GYRO_ADC_S1_REGNUM] = {0};\r
+       unsigned char gyroTemp[6] = {0};\r
+       signed int gyroSum[3] = {0};\r
+       signed short gyroAvg1[3] = {0}, gyroAvg2[3] = {0};\r
+       unsigned char i = 0;\r
+       //signed short gyroPolarity[3] = {0};\r
+\r
+       for(i=0; i<SH5001_GYRO_ADC_S1_REGNUM; i++)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, regAddrS1[i], 1, &regBackS1[i]);\r
+       }\r
+\r
+       for(i=0; i<SH5001_GYRO_ADC_S1_REGNUM; i++)\r
+       {\r
+               SH5001_write(SH5001_ADDRESS, regAddrS1[i], 1, &regInitS1[i]);\r
+       }\r
+\r
+       delay_ms(50);\r
+\r
+       i = 0;\r
+       while(i++ < 20)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_GYRO_XL, 6, gyroTemp);\r
+               gyroSum[0] += (signed short)((short)gyroTemp[1] << 8) | gyroTemp[0];\r
+               gyroSum[1] += (signed short)((short)gyroTemp[3] << 8) | gyroTemp[2];\r
+               gyroSum[2] += (signed short)((short)gyroTemp[5] << 8) | gyroTemp[4];\r
+               #ifdef SH5001_GYRO_ADC__DEBUG\r
+               printf("bf %d %d %d\r\n", (signed short)(((short)gyroTemp[1] << 8) | gyroTemp[0]), (signed short)(((short)gyroTemp[3] << 8) | gyroTemp[2]), (signed short)(((short)gyroTemp[5] << 8) | gyroTemp[4]));\r
+               #endif\r
+       }\r
+       gyroAvg1[0] = gyroSum[0]/20;\r
+       gyroAvg1[1] = gyroSum[1]/20;\r
+       gyroAvg1[2] = gyroSum[2]/20;\r
+\r
+       for(i=0; i<SH5001_GYRO_ADC_S2_REGNUM; i++)\r
+       {\r
+               SH5001_write(SH5001_ADDRESS, regAddrS2[i], 1, &regInitS2[i]);\r
+       }\r
+\r
+       delay_ms(50);\r
+\r
+       gyroSum[0] = 0;\r
+       gyroSum[1] = 0;\r
+       gyroSum[2] = 0;\r
+       i = 0;\r
+\r
+       while(i++ < 20)\r
+       {\r
+               SH5001_read(SH5001_ADDRESS, SH5001_GYRO_XL, 6, gyroTemp);\r
+               gyroSum[0] += (signed short)((short)gyroTemp[1] << 8) | gyroTemp[0];\r
+               gyroSum[1] += (signed short)((short)gyroTemp[3] << 8) | gyroTemp[2];\r
+               gyroSum[2] += (signed short)((short)gyroTemp[5] << 8) | gyroTemp[4];\r
+\r
+               #ifdef SH5001_GYRO_ADC__DEBUG\r
+               printf("af %d %d %d\r\n", (signed short)(((short)gyroTemp[1] << 8) | gyroTemp[0]), (signed short)(((short)gyroTemp[3] << 8) | gyroTemp[2]), (signed short)(((short)gyroTemp[5] << 8) | gyroTemp[4]));\r
+               #endif\r
+       }\r
+\r
+       gyroAvg2[0] = gyroSum[0]/20;\r
+       gyroAvg2[1] = gyroSum[1]/20;\r
+       gyroAvg2[2] = gyroSum[2]/20;\r
+\r
+       for(i=0; i<SH5001_GYRO_ADC_S1_REGNUM; i++)\r
+       {\r
+               SH5001_write(SH5001_ADDRESS, regAddrS1[i], 1, &regBackS1[i]);\r
+       }\r
+\r
+       gyroPolarity[0] = gyroAvg2[0] - gyroAvg1[0];\r
+       gyroPolarity[1] = gyroAvg2[1] - gyroAvg1[1];\r
+       gyroPolarity[2] = gyroAvg2[2] - gyroAvg1[2];\r
+       adc_count++;\r
+       #ifdef SH5001_GYRO_ADC__DEBUG\r
+       printf("gyroPolarity %d %d %d %d %d\r\n", adc_count, err_count, gyroPolarity[0],gyroPolarity[1] ,gyroPolarity[2]);\r
+       #endif\r
+\r
+       if(gyroPolarity[2] < 0)\r
+       {\r
+               err_count++;\r
+       }\r
+\r
+}\r
+\r
+int sh5001_get_version(void)\r
+{\r
+       return MCU_VERSION_SH5001;\r
+}\r
+\r
+gyro_data_t sh5001_get_gyro_data(void)\r
+{\r
+    gyro_data_t data = gyro_data;\r
+       return data;\r
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/gyro/sh5001/sh5001.h b/code/sdk/drivers/peripheral/gyro/sh5001/sh5001.h
new file mode 100644 (file)
index 0000000..08cd2cd
--- /dev/null
@@ -0,0 +1,700 @@
+#ifndef __SH5001_H \r
+#define __SH5001_H\r
+\r
+#include "gyro_hal.h"\r
+\r
+#define SH5001_FIFO_WM_INT\r
+//#define SH5001_ACTIVITY_INT\r
+//#define SH5001_DATA_READY_INT\r
+\r
+/******************************************************************\r
+*      SH5001 I2C address Macro Definition \r
+*\r
+*   (7bit):    (0x37)011 0111@SDO=1;    (0x36)011 0110@SDO=0;\r
+******************************************************************/\r
+#define SH5001_ADDRESS                         (0x36U)         \r
+#define SENODIA_VDD_3V3 1\r
+#define SH5001_ID                      0xA1\r
+\r
+/******************************************************************\r
+*      SH5001 Registers Macro Definitions \r
+******************************************************************/\r
+#define SH5001_ACC_XL                          (0x00U)\r
+#define SH5001_ACC_XH                          (0x01U)\r
+#define SH5001_ACC_YL                          (0x02U)\r
+#define SH5001_ACC_YH                          (0x03U)\r
+#define SH5001_ACC_ZL                          (0x04U)\r
+#define SH5001_ACC_ZH                          (0x05U)\r
+#define SH5001_GYRO_XL                         (0x06U)\r
+#define SH5001_GYRO_XH                         (0x07U)\r
+#define SH5001_GYRO_YL                         (0x08U)\r
+#define SH5001_GYRO_YH                         (0x09U)\r
+#define SH5001_GYRO_ZL                         (0x0AU)\r
+#define SH5001_GYRO_ZH                         (0x0BU)\r
+#define SH5001_TEMP_ZL                         (0x0CU)\r
+#define SH5001_TEMP_ZH                         (0x0DU)\r
+#define SH5001_TIMESTAMP_L                     (0x0EU)\r
+#define SH5001_TIMESTAMP_M                     (0x0FU)\r
+#define SH5001_TIMESTAMP_H                     (0x10U)\r
+#define SH5001_INT_STA0                                (0x16U)\r
+#define SH5001_INT_STA1                                (0x17U)\r
+#define SH5001_INT_STA2                                (0x18U)\r
+#define SH5001_INT_STA3                                (0x19U)\r
+#define SH5001_INT_STA4                                (0x1AU)\r
+#define SH5001_FIFO_STA0                       (0x1BU)\r
+#define SH5001_FIFO_STA1                       (0x1CU)\r
+#define SH5001_FIFO_DATA                       (0x1DU)\r
+\r
+#define SH5001_CHIP_ID                         (0x1FU)\r
+\r
+#define SH5001_ACC_CONF0                       (0x20U)\r
+#define SH5001_ACC_CONF1                       (0x21U)\r
+#define SH5001_ACC_CONF2                       (0x22U)\r
+\r
+#define SH5001_GYRO_CONF0                      (0x23U)\r
+#define SH5001_GYRO_CONF1                      (0x24U)\r
+#define SH5001_GYRO_CONF2                      (0x25U)\r
+\r
+#define SH5001_OIS_ACC_CONF                    (0x26U)\r
+#define SH5001_OIS_GYRO_CONF           (0x27U)\r
+\r
+#define SH5001_TEMP_CONF0                      (0x28U)\r
+#define SH5001_ACC_DOWNSAMPLE          (0x28U)\r
+#define SH5001_TEMP_CONF1                      (0x29U)\r
+#define SH5001_TEMP_CONF2                      (0x2AU)\r
+#define SH5001_TIMESTAMP_CONF          (0x2AU)\r
+\r
+#define SH5001_POWER_MODE                      (0x30U)\r
+#define SH5001_POWER_MODE_PWM          (0x31U)\r
+\r
+#define SH5001_I2C_CONF                                (0x34U)\r
+#define SH5001_SPI_CONF                                (0x34U)\r
+#define SH5001_I2C_READ_LOOP           (0x34U)\r
+#define SH5001_OIS_SPI_CONF                    (0x34U)\r
+\r
+\r
+#define SH5001_FIFO_CONF0                      (0x35U)\r
+#define SH5001_FIFO_CONF1                      (0x36U)\r
+#define SH5001_FIFO_CONF2                      (0x37U)\r
+#define SH5001_FIFO_CONF3                      (0x38U)\r
+#define SH5001_FIFO_CONF4                      (0x39U)\r
+\r
+#define SH5001_MI2C_CONF0                      (0x3AU)\r
+#define SH5001_MI2C_CONF1                      (0x3BU)\r
+#define SH5001_MI2C_CMD0                       (0x3CU)\r
+#define SH5001_MI2C_CMD1                       (0x3DU)\r
+#define SH5001_MI2C_WR                         (0x3EU)\r
+#define SH5001_MI2C_RD                         (0x3FU)\r
+\r
+#define SH5001_INT_ENABLE0                     (0x40U)\r
+#define SH5001_INT_ENABLE1                     (0x41U)\r
+#define SH5001_INT_CONF                                (0x42U)\r
+#define SH5001_INT_LIMIT                       (0x43U)\r
+#define SH5001_ORIEN_INTCONF0          (0x44U)\r
+#define SH5001_ORIEN_INTCONF1          (0x45U)\r
+#define SH5001_ORIEN_INT_1G5_LOW       (0x46U)\r
+#define SH5001_ORIEN_INT_1G5_HIGH      (0x47U)\r
+#define SH5001_ORIEN_INT_SLOPE_LOW     (0x48U)\r
+#define SH5001_ORIEN_INT_SLOPE_HIGH    (0x49U)\r
+#define SH5001_ORIEN_INT_HYST_LOW      (0x4AU)\r
+#define SH5001_ORIEN_INT_HYST_HIGH     (0x4BU)\r
+\r
+#define SH5001_FLAT_INT_CONF           (0x4CU)\r
+\r
+#define SH5001_ACT_INACT_INT_CONF      (0x4DU)\r
+#define SH5001_ACT_INACT_INT_LINK      (0x4EU)\r
+#define SH5001_ACT_INT_THRESHOLDL      (0x54U)\r
+#define SH5001_ACT_INT_THRESHOLDH      (0x55U)\r
+#define SH5001_ACT_INT_TIME                    (0x56U)\r
+\r
+#define SH5001_INACT_INT_THRESHOLDL    (0x57U)\r
+#define SH5001_INACT_INT_THRESHOLDH    (0x58U)\r
+#define SH5001_INACT_INT_TIME          (0x59U)\r
+\r
+#define SH5001_SMD_INT_THRESHOLDL      (0x5AU)\r
+#define SH5001_SMD_INT_THRESHOLDH      (0x5BU)\r
+#define SH5001_SMD_INT_TIME                    (0x5CU)\r
+\r
+#define SH5001_TAP_INT_CONF                    (0x4EU)\r
+#define SH5001_TAP_INT_THRESHOLDL      (0x4FU)\r
+#define SH5001_TAP_INT_THRESHOLDH      (0x50U)\r
+#define SH5001_TAP_INT_DURATION                (0x51U)\r
+#define SH5001_TAP_INT_LATENCY         (0x52U)\r
+#define SH5001_DTAP_INT_WINDOW         (0x53U)\r
+\r
+#define SH5001_HIGHG_INT_CONF          (0x5DU)\r
+#define SH5001_HIGHG_INT_THRESHOLDL    (0x5EU)\r
+#define SH5001_HIGHG_INT_THRESHOLDH    (0x5FU)\r
+#define SH5001_HIGHG_INT_TIME          (0x60U)\r
+\r
+#define SH5001_LOWG_INT_CONF           (0x5DU)\r
+#define SH5001_LOWG_INT_THRESHOLDL     (0x61U)\r
+#define SH5001_LOWG_INT_THRESHOLDH     (0x62U)\r
+#define SH5001_LOWG_INT_TIME           (0x63U)\r
+\r
+#define SH5001_FREEFALL_INT_THRES      (0x64U)\r
+#define SH5001_FREEFALL_INT_TIME       (0x65U)\r
+\r
+#define SH5001_INT_PIN_MAP0                    (0x66U)\r
+#define SH5001_INT_PIN_MAP1                    (0x67U)\r
+\r
+#define SH5001_SPI_REG_ACCESS          (0x7FU)\r
+#define SH5001_AUX_I2C_CONF                    (0xFDU)\r
+\r
+#define SH5001_PIN_PP_CONF0                    (0xFDU)\r
+#define SH5001_PIN_PP_CONF1                    (0xFEU)\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+/******************************************************************\r
+*      ACC Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_ACC_ODR_1000HZ  (0x00U)  //TODO need to set ref datasheet\r
+#define SH5001_ACC_ODR_500HZ   (0x01U)\r
+#define SH5001_ACC_ODR_250HZ   (0x02U)\r
+#define SH5001_ACC_ODR_125HZ   (0x03U)\r
+\r
+#define SH5001_ACC_ODR_2000HZ  (0x08U)\r
+#define SH5001_ACC_ODR_4000HZ  (0x09U)\r
+#define SH5001_ACC_ODR_8000HZ  (0x0AU)\r
+\r
+#define SH5001_ACC_RANGE_4G            (0x10U)\r
+#define SH5001_ACC_RANGE_8G            (0x20U)\r
+#define SH5001_ACC_RANGE_16G   (0x30U)\r
+//#define SH5001_ACC_RANGE_32G (0x40U)\r
+\r
+#define SH5001_ACC_ODRX040             (0x00U)\r
+#define SH5001_ACC_ODRX036             (0x01U)\r
+#define SH5001_ACC_ODRX032             (0x02U)\r
+#define SH5001_ACC_ODRX028             (0x03U)\r
+#define SH5001_ACC_ODRX024             (0x04U)\r
+#define SH5001_ACC_ODRX020             (0x05U)\r
+#define SH5001_ACC_ODRX016             (0x06U)\r
+#define SH5001_ACC_ODRX014             (0x07U)\r
+#define SH5001_ACC_ODRX012             (0x08U)\r
+#define SH5001_ACC_ODRX010             (0x09U)\r
+#define SH5001_ACC_ODRX008             (0x0aU)\r
+#define SH5001_ACC_ODRX006             (0x0bU)\r
+#define SH5001_ACC_ODRX004             (0x0cU)\r
+#define SH5001_ACC_ODRX003             (0x0dU)\r
+#define SH5001_ACC_ODRX002             (0x0eU)\r
+#define SH5001_ACC_ODRX001             (0x0fU)\r
+\r
+#define SH5001_ACC_FILTER_EN   (0x01U)\r
+#define SH5001_ACC_FILTER_DIS  (0x00U)\r
+#define SH5001_ACC_BYPASS_EN   (0x02U)\r
+#define SH5001_ACC_BYPASS_DIS  (0x00U)\r
+\r
+\r
+/******************************************************************\r
+*      GYRO Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_GYRO_ODR_1000HZ (0x00U)\r
+#define SH5001_GYRO_ODR_500HZ  (0x01U)\r
+#define SH5001_GYRO_ODR_250HZ  (0x02U)\r
+#define SH5001_GYRO_ODR_125HZ  (0x03U)\r
+#define SH5001_GYRO_ODR_2000HZ (0x08U)\r
+#define SH5001_GYRO_ODR_4000HZ (0x09U)\r
+#define SH5001_GYRO_ODR_8000HZ (0x0AU)\r
+#define SH5001_GYRO_ODR_16000HZ        (0x0BU)\r
+\r
+\r
+\r
+#define SH5001_GYRO_RANGE_31   (0x00U)\r
+#define SH5001_GYRO_RANGE_62   (0x10U)\r
+#define SH5001_GYRO_RANGE_125  (0x20U)\r
+#define SH5001_GYRO_RANGE_250  (0x30U)\r
+#define SH5001_GYRO_RANGE_500  (0x40U)\r
+#define SH5001_GYRO_RANGE_1000 (0x50U)\r
+#define SH5001_GYRO_RANGE_2000 (0x60U)\r
+#define SH5001_GYRO_RANGE_4000 (0x70U)\r
+\r
+#define SH5001_GYRO_ODRX040            (0x00U)\r
+#define SH5001_GYRO_ODRX036            (0x01U)\r
+#define SH5001_GYRO_ODRX032            (0x02U)\r
+#define SH5001_GYRO_ODRX028            (0x03U)\r
+#define SH5001_GYRO_ODRX024            (0x04U)\r
+#define SH5001_GYRO_ODRX020            (0x05U)\r
+#define SH5001_GYRO_ODRX016            (0x06U)\r
+#define SH5001_GYRO_ODRX014            (0x07U)\r
+#define SH5001_GYRO_ODRX012            (0x08U)\r
+#define SH5001_GYRO_ODRX010            (0x09U)\r
+#define SH5001_GYRO_ODRX008            (0x0aU)\r
+#define SH5001_GYRO_ODRX006            (0x0bU)\r
+#define SH5001_GYRO_ODRX004            (0x0cU)\r
+#define SH5001_GYRO_ODRX003            (0x0dU)\r
+#define SH5001_GYRO_ODRX002            (0x0eU)\r
+#define SH5001_GYRO_ODRX001            (0x0fU)\r
+\r
+#define SH5001_GYRO_FILTER_EN  (0x01U)\r
+#define SH5001_GYRO_FILTER_DIS (0x00U)\r
+#define SH5001_GYRO_BYPASS_EN  (0x02U)\r
+#define SH5001_GYRO_BYPASS_DIS (0x00U)\r
+\r
+#define SH5001_GYRO_OFF_INACT   (0x80U)\r
+#define SH5001_GYRO_ON_INACT    (0x00U)\r
+\r
+/******************************************************************\r
+*      Time Stamp Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_TS_ODR_25KHZ            (0x20U)\r
+#define SH5001_TS_ODR_1KHZ             (0x00U)\r
+#define SH5001_TS_EN                   (0x40U)\r
+#define SH5001_TS_DIS                  (0x00U)\r
+\r
+/******************************************************************\r
+*      Temperature Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_TEMP_ODR_500HZ  (0x00U)\r
+#define SH5001_TEMP_ODR_250HZ  (0x02U)\r
+#define SH5001_TEMP_ODR_125HZ  (0x04U)\r
+#define SH5001_TEMP_ODR_63HZ   (0x06U)\r
+\r
+#define SH5001_TEMP_EN                 (0x01U)\r
+#define SH5001_TEMP_DIS                        (0x00U)\r
+\r
+/******************************************************************\r
+*      INT Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_INT_LOWG                                (0x8000U)\r
+#define SH5001_INT_HIGHG                       (0x4000U)\r
+#define SH5001_INT_INACT                       (0x2000U)\r
+#define SH5001_INT_ACT                         (0x1000U)\r
+#define SH5001_INT_DOUBLE_TAP          (0x0800U)\r
+#define SH5001_INT_SINGLE_TAP          (0x0400U)\r
+#define SH5001_INT_FLAT                                (0x0200U)\r
+#define SH5001_INT_ORIENTATION         (0x0100U)\r
+#define SH5001_INT_TAP                         (0x0020U)\r
+#define SH5001_INT_SMD                         (0x0010U)\r
+#define SH5001_INT_FIFO_WATERMARK      (0x0008U)\r
+#define SH5001_INT_GYRO_READY          (0x0004U)\r
+#define SH5001_INT_ACC_READY           (0x0002U)\r
+#define SH5001_INT_FREE_FALL           (0x0001U)\r
+#define SH5001_INT_UP_DOWN_Z           (0x0040U)\r
+\r
+#define SH5001_INT_EN                          (0x01U)\r
+#define SH5001_INT_DIS                         (0x00U)\r
+\r
+#define SH5001_INT_MAP_INT1                    (0x01U)\r
+#define SH5001_INT_MAP_INT0                    (0x00U)\r
+\r
+#define SH5001_INT0_LEVEL_LOW          (0x80U)\r
+#define SH5001_INT0_LEVEL_HIGH         (0x7FU)\r
+#define SH5001_INT_NO_LATCH                    (0x40U)\r
+#define SH5001_INT_LATCH                       (0xBFU)\r
+#define SH5001_INT_CLEAR_ANY           (0x10U)\r
+#define SH5001_INT_CLEAR_STATUS            (0xEFU)\r
+#define SH5001_INT1_OD                         (0x08U)\r
+#define SH5001_INT1_NORMAL                     (0xF7U)\r
+#define SH5001_INT1_OUTPUT                     (0x04U)\r
+#define SH5001_INT1_INPUT                      (0xFBU)\r
+#define SH5001_INT0_OD                         (0x02U)\r
+#define SH5001_INT0_NORMAL                     (0xFDU)\r
+#define SH5001_INT0_OUTPUT                     (0x01U)\r
+#define SH5001_INT0_INPUT                      (0xFEU)\r
+\r
+\r
+/******************************************************************\r
+*      Orientation Blocking Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_ORIENT_BLOCK_MODE0      (0x00U)\r
+#define SH5001_ORIENT_BLOCK_MODE1      (0x04U)\r
+#define SH5001_ORIENT_BLOCK_MODE2      (0x08U)\r
+#define SH5001_ORIENT_BLOCK_MODE3      (0x0CU)\r
+\r
+#define SH5001_ORIENT_SYMM                     (0x00U)\r
+#define SH5001_ORIENT_HIGH_ASYMM       (0x01U)\r
+#define SH5001_ORIENT_LOW_ASYMM                (0x02U)\r
+\r
+\r
+/******************************************************************\r
+*      Flat Time Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_FLAT_TIME_200MS         (0x00U)\r
+#define SH5001_FLAT_TIME_400MS         (0x40U)\r
+#define SH5001_FLAT_TIME_800MS         (0x80U)\r
+#define SH5001_FLAT_TIME_000MS         (0xC0U)\r
+\r
+/******************************************************************\r
+*      ACT and INACT Int Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_ACT_X_INT_EN            (0x40U)\r
+#define SH5001_ACT_X_INT_DIS   (0x00U)\r
+#define SH5001_ACT_Y_INT_EN            (0x20U)\r
+#define SH5001_ACT_Y_INT_DIS   (0x00U)\r
+#define SH5001_ACT_Z_INT_EN            (0x10U)\r
+#define SH5001_ACT_Z_INT_DIS   (0x00U)\r
+\r
+#define SH5001_INACT_X_INT_EN  (0x04U)\r
+#define SH5001_INACT_X_INT_DIS (0x00U)\r
+#define SH5001_INACT_Y_INT_EN  (0x02U)\r
+#define SH5001_INACT_Y_INT_DIS (0x00U)\r
+#define SH5001_INACT_Z_INT_EN  (0x01U)\r
+#define SH5001_INACT_Z_INT_DIS (0x00U)\r
+\r
+\r
+#define SH5001_LINK_PRE_STA            (0x01U)\r
+#define SH5001_LINK_PRE_STA_NO (0x00U)\r
+\r
+#define SH5001_ACT_INACT_CLR_STATUS1   (0x00U)\r
+#define SH5001_ACT_INACT_CLR_STATUS3   (0x80U)\r
+\r
+/******************************************************************\r
+*      TAP Int Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_TAP_X_INT_EN            (0x08U)\r
+#define SH5001_TAP_X_INT_DIS   (0x00U)\r
+#define SH5001_TAP_Y_INT_EN            (0x04U)\r
+#define SH5001_TAP_Y_INT_DIS   (0x00U)\r
+#define SH5001_TAP_Z_INT_EN            (0x02U)\r
+#define SH5001_TAP_Z_INT_DIS   (0x00U)\r
+\r
+\r
+/******************************************************************\r
+*      HIGHG Int Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_HIGHG_ALL_INT_EN                (0x80U)\r
+#define SH5001_HIGHG_ALL_INT_DIS       (0x00U)\r
+#define SH5001_HIGHG_X_INT_EN          (0x40U)\r
+#define SH5001_HIGHG_X_INT_DIS         (0x00U)\r
+#define SH5001_HIGHG_Y_INT_EN          (0x20U)\r
+#define SH5001_HIGHG_Y_INT_DIS         (0x00U)\r
+#define SH5001_HIGHG_Z_INT_EN          (0x10U)\r
+#define SH5001_HIGHG_Z_INT_DIS         (0x00U)\r
+\r
+\r
+/******************************************************************\r
+*      LOWG Int Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_LOWG_ALL_INT_EN         (0x01U)\r
+#define SH5001_LOWG_ALL_INT_DIS                (0x00U)\r
+\r
+\r
+/******************************************************************\r
+*      SPI Interface Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_SPI_3_WIRE      (0x20U)\r
+#define SH5001_SPI_4_WIRE      (0x00U)\r
+\r
+\r
+/******************************************************************\r
+*      I2C Interface Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_I2C_DIS                         (0x80U)\r
+#define SH5001_I2C_EN                          (0x00U)\r
+\r
+//Jin\r
+#define SH5001_I2C_LP_06BYTE           (0x04U)\r
+#define SH5001_I2C_LP_12BYTE           (0x02U)\r
+#define SH5001_I2C_LP_14BYTE           (0x01U)\r
+#define SH5001_I2C_LP_DISABLE          (0x00U)\r
+\r
+/******************************************************************\r
+*      OIS SPI Interface Config Macro Definitions \r
+******************************************************************/\r
+//#define SH5001_OIS_SPI_3WIRE         (0x00U)\r
+//#define SH5001_OIS_SPI_4WIRE         (0x40U)\r
+#define SH5001_OIS_SPI_EN                      (0x10U)\r
+#define SH5001_OIS_SPI_DIS                     (0x00U)\r
+\r
+#define SH5001_ACC_OIS_ENABLE          (0x80U)\r
+#define SH5001_ACC_OIS_DISABLE (0x00U)\r
+\r
+#define SH5001_ACC_OIS_RANGE_4G                (0x10U)\r
+#define SH5001_ACC_OIS_RANGE_8G                (0x20U)\r
+#define SH5001_ACC_OIS_RANGE_16G       (0x30U)\r
+\r
+#define SH5001_ACC_OIS_ODRX008         (0x0CU)\r
+#define SH5001_ACC_OIS_ODRX004         (0x08U)\r
+#define SH5001_ACC_OIS_ODRX002         (0x04U)\r
+#define SH5001_ACC_OIS_ODRX000         (0x00U)  //bypass\r
+\r
+\r
+#define SH5001_ACC_OIS_ODR_1000HZ      (0x00U)  //TODO need to set ref datasheet\r
+#define SH5001_ACC_OIS_ODR_2000HZ      (0x01U)\r
+#define SH5001_ACC_OIS_ODR_4000HZ      (0x02U)\r
+#define SH5001_ACC_OIS_ODR_8000HZ      (0x03U)\r
+\r
+\r
+\r
+\r
+#define SH5001_GYRO_OIS_ENABLE         (0x80U)\r
+#define SH5001_GYRO_OIS_DISABLE                (0x00U)\r
+\r
+#define SH5001_GYRO_OIS_RANGE_31       (0x00U)\r
+#define SH5001_GYRO_OIS_RANGE_62       (0x10U)\r
+#define SH5001_GYRO_OIS_RANGE_125      (0x20U)\r
+#define SH5001_GYRO_OIS_RANGE_250      (0x30U)\r
+#define SH5001_GYRO_OIS_RANGE_500      (0x40U)\r
+#define SH5001_GYRO_OIS_RANGE_1000     (0x50U)\r
+#define SH5001_GYRO_OIS_RANGE_2000     (0x60U)\r
+#define SH5001_GYRO_OIS_RANGE_4000     (0x70U)\r
+\r
+#define SH5001_GYRO_OIS_ODRX008                (0x0CU)\r
+#define SH5001_GYRO_OIS_ODRX004                (0x08U)\r
+#define SH5001_GYRO_OIS_ODRX002                (0x04U)\r
+#define SH5001_GYRO_OIS_ODRX000                (0x00U)  //bypass\r
+\r
+#define SH5001_GYRO_OIS_ODR_1000HZ     (0x00U)\r
+#define SH5001_GYRO_OIS_ODR_2000HZ     (0x01U)\r
+#define SH5001_GYRO_OIS_ODR_4000HZ     (0x02U)\r
+#define SH5001_GYRO_OIS_ODR_8000HZ     (0x03U)\r
+\r
+\r
+\r
+\r
+/******************************************************************\r
+*      FIFO Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_FIFO_MODE_DIS           (0x00U)\r
+#define SH5001_FIFO_MODE_FIFO          (0x01U)\r
+#define SH5001_FIFO_MODE_STREAM                (0x02U)\r
+#define SH5001_FIFO_MODE_TRIGGER       (0x03U)\r
+\r
+#define SH5001_FIFO_ACC_DOWNS_EN       (0x80U)\r
+#define SH5001_FIFO_ACC_DOWNS_DIS      (0x00U)\r
+#define SH5001_FIFO_GYRO_DOWNS_EN      (0x08U)\r
+#define SH5001_FIFO_GYRO_DOWNS_DIS     (0x00U)\r
+\r
+#define SH5001_FIFO_FREQ_X1_2          (0x00U)\r
+#define SH5001_FIFO_FREQ_X1_4          (0x01U)\r
+#define SH5001_FIFO_FREQ_X1_8          (0x02U)\r
+#define SH5001_FIFO_FREQ_X1_16         (0x03U)\r
+#define SH5001_FIFO_FREQ_X1_32         (0x04U)\r
+#define SH5001_FIFO_FREQ_X1_64         (0x05U)\r
+#define SH5001_FIFO_FREQ_X1_128                (0x06U)\r
+#define SH5001_FIFO_FREQ_X1_256                (0x07U)\r
+\r
+#define SH5001_FIFO_TIMESTAMP_EN       (0x4000U)\r
+#define SH5001_FIFO_EXT_Z_EN           (0x2000U)\r
+#define SH5001_FIFO_EXT_Y_EN           (0x1000U)\r
+#define SH5001_FIFO_EXT_X_EN           (0x0080U)\r
+#define SH5001_FIFO_TEMPERATURE_EN     (0x0040U)\r
+#define SH5001_FIFO_GYRO_Z_EN          (0x0020U)\r
+#define SH5001_FIFO_GYRO_Y_EN          (0x0010U)\r
+#define SH5001_FIFO_GYRO_X_EN          (0x0008U)\r
+#define SH5001_FIFO_ACC_Z_EN           (0x0004U)\r
+#define SH5001_FIFO_ACC_Y_EN           (0x0002U)\r
+#define SH5001_FIFO_ACC_X_EN           (0x0001U)\r
+#define SH5001_FIFO_ALL_DIS                    (0x0000U)\r
+\r
+/******************************************************************\r
+*      AUX I2C Config Macro Definitions \r
+******************************************************************/\r
+#define SH5001_MI2C_NORMAL_MODE                        (0x00U)\r
+#define SH5001_MI2C_BYPASS_MODE                        (0x01U)\r
+\r
+#define SH5001_MI2C_READ_ODR_200HZ         (0x00U)\r
+#define SH5001_MI2C_READ_ODR_100HZ         (0x10U)\r
+#define SH5001_MI2C_READ_ODR_50HZ              (0x20U)\r
+#define SH5001_MI2C_READ_ODR_25HZ              (0x30U)\r
+\r
+#define SH5001_MI2C_FAIL                               (0x20U)\r
+#define SH5001_MI2C_SUCCESS                            (0x10U)\r
+\r
+#define SH5001_MI2C_READ_MODE_AUTO             (0x40U)\r
+#define SH5001_MI2C_READ_MODE_MANUAL   (0x00U)\r
+\r
+\r
+/******************************************************************\r
+*      Fast offset compensation Macro Definitions \r
+******************************************************************/\r
+#define SH5001_X_UP     (0x00U)\r
+#define SH5001_X_DOWN   (0x01U)\r
+#define SH5001_Y_UP     (0x02U)\r
+#define SH5001_Y_DOWN   (0x03U)\r
+#define SH5001_Z_UP     (0x04U)\r
+#define SH5001_Z_DOWN   (0x05U)\r
+\r
+\r
+/******************************************************************\r
+*      Other Macro Definitions \r
+******************************************************************/\r
+#define SH5001_TRUE            (0U)\r
+#define SH5001_FALSE   (1U)\r
+\r
+#define SH5001_CALI_REG_NUM 8\r
+#define SH5001_POWMODE_REG_NUM 11\r
+#define SH5001_NORMAL_MODE             (0x00)\r
+#define SH5001_ACC_HP_MODE             (0x01)\r
+#define SH5001_ACC_LP_MODE             (0x02)\r
+#define SH5001_POWERDOWN_MODE  (0x03)\r
+\r
+// FIFO Mode DIV = FIFO channel * 2;\r
+#define SH5001_WATERMARK_DIV    (12U)                  \r
+//#define SH5001_FIFO_BUFFER      (1024U)\r
+#define SH5001_FIFO_BUFFER      (500U)\r
+\r
+\r
+/***************************************************************************\r
+*       Type Definitions                                              \r
+****************************************************************************/\r
+typedef unsigned char (*IMU_read)(     unsigned char devAddr, \r
+                                    unsigned char regAddr, \r
+                                    unsigned short readLen, \r
+                                    unsigned char *readBuf);\r
+\r
+typedef unsigned char (*IMU_write)(    unsigned char devAddr, \r
+                                    unsigned char regAddr, \r
+                                    unsigned short writeLen, \r
+                                    unsigned char *writeBuf);\r
+\r
+\r
+\r
+\r
+/***************************************************************************\r
+        Exported Functions                                           \r
+****************************************************************************/                                                                                                                                                                                                                                                  \r
+                                                                                                                                                                       \r
+extern unsigned char SH5001_init(void);\r
+extern void SH5001_GetImuData( short accData[3], short gyroData[3] );\r
+extern float SH5001_GetTempData(void);                                                                                                                                 \r
+extern unsigned char SH5001_SwitchPowerMode(unsigned char powerMode);          \r
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               \r
+                                                                                                                                               \r
+\r
+// interrupt related fucntions\r
+extern void SH5001_INT_Enable( unsigned short intType, \r
+                                                               unsigned char intEnable, \r
+                                                               unsigned char intPinSel);\r
+\r
+extern void SH5001_INT_Config( unsigned char intLevel,\r
+                        unsigned char intLatch,\r
+                        unsigned char intClear,\r
+                        unsigned char intTime,\r
+                        unsigned char int1Mode,\r
+                        unsigned char int0Mode,\r
+                        unsigned char int1OE,\r
+                        unsigned char int0OE);\r
+\r
+extern void SH5001_INT_Output_Config(  unsigned char int1Mode,\r
+                                                                               unsigned char int0Mode,\r
+                                                                               unsigned char int1OE,\r
+                                                                               unsigned char int0OE);                                                          \r
+                                                               \r
+extern void SH5001_INT_Orient_Config(  unsigned char   orientBlockMode,\r
+                                                                               unsigned char   orientMode,\r
+                                                                               unsigned char   orientTheta,\r
+                                                                               unsigned short  orientG1point5,\r
+                                                                               unsigned short  orientSlope,\r
+                                                                               unsigned short  orientHyst);                                                            \r
+                                                               \r
+extern void SH5001_INT_Flat_Config(    unsigned char flatTimeTH, \r
+                                                                       unsigned char flatTanHeta2);                                                            \r
+                                                               \r
+extern void SH5001_INT_Act_Config(     unsigned char actEnDisIntX,\r
+                                       unsigned char actEnDisIntY,\r
+                                       unsigned char actEnDisIntZ,\r
+                                       unsigned char actTimeNum,\r
+                                       unsigned short actIntThres,\r
+                                       unsigned char actLinkStatus,\r
+                                       unsigned char actIntClear);                                                             \r
+\r
+extern void SH5001_INT_Inact_Config(   unsigned char inactEnDisIntX,\r
+                                               unsigned char inactEnDisIntY,\r
+                                               unsigned char inactEnDisIntZ,\r
+                                               unsigned char inactLinkStatus,\r
+                                               unsigned char inactTimeMs,\r
+                                               unsigned short inactIntThres,\r
+                                               unsigned short inactG1,\r
+                                               unsigned char inactIntClear);\r
+\r
+extern void SH5001_INT_Tap_Config(     unsigned char tapEnDisIntX,\r
+                                                                       unsigned char tapEnDisIntY,\r
+                                                                       unsigned char tapEnDisIntZ,\r
+                                                                       unsigned char tapIntThres,\r
+                                                                       unsigned char tapTimeMs,\r
+                                                                       unsigned char tapWaitTimeMs,\r
+                                                                       unsigned char tapWaitTimeWindowMs);\r
+\r
+extern void SH5001_INT_SMD_Config(     unsigned short smdThres,\r
+                                       unsigned char smdBlockTimeS,\r
+                                                                       unsigned char smdProofTimeS);                                                                   \r
+\r
+extern void SH5001_INT_HighG_Config(   unsigned char highGEnDisIntX,\r
+                                                                               unsigned char highGEnDisIntY,\r
+                                                                               unsigned char highGEnDisIntZ,\r
+                                                                               unsigned char highGEnDisIntAll,\r
+                                                                               unsigned short highGThres,\r
+                                                                               unsigned char highGTimeMs);\r
+\r
+extern void SH5001_INT_LowG_Config(    unsigned char lowGEnDisIntAll,\r
+                                                                       unsigned short lowGThres,\r
+                                                                       unsigned char lowGTimeMs);\r
+\r
+extern void SH5001_INT_FreeFall_Config(        unsigned char freeFallThres,\r
+                                                                               unsigned char freeFallTimeMs);\r
+\r
+extern unsigned short SH5001_INT_Read_Status01(void);\r
+\r
+extern unsigned char SH5001_INT_Read_Status2(void);\r
+\r
+extern unsigned char SH5001_INT_Read_Status3(void);\r
+\r
+extern unsigned char SH5001_INT_Read_Status4(void);\r
+                                                               \r
+                       \r
+// Fifo related fucntions\r
+extern void SH5001_FIFO_Reset(void);\r
+\r
+extern void SH5001_FIFO_Freq_Config(   unsigned char fifoAccDownSampleEnDis,\r
+                                                                               unsigned char fifoAccFreq,\r
+                                                                               unsigned char fifoGyroDownSampleEnDis,\r
+                                                                               unsigned char fifoGyroFreq);\r
+                                                                               \r
+extern void SH5001_FIFO_Data_Config(   unsigned short fifoMode,\r
+                                                                               unsigned short fifoWaterMarkLevel);                                                                             \r
+                                                                               \r
+extern unsigned char SH5001_FIFO_Read_Status(unsigned short int *fifoEntriesCount);                                                                            \r
+                                                                               \r
+extern void SH5001_FIFO_Read_Data(     unsigned char *fifoReadData, \r
+                                                                       unsigned short int fifoDataLength);                                                                             \r
+                       \r
+\r
+// Master I2C related fucntions\r
+extern void SH5001_MI2C_Reset(void);\r
+\r
+extern void SH5001_MI2C_Bus_Config(    unsigned char mi2cReadMode,\r
+                                                                       unsigned char mi2cODR,\r
+                                                                       unsigned char mi2cFreq);                        \r
+                       \r
+extern void SH5001_MI2C_Cmd_Config(    unsigned char mi2cSlaveAddr,\r
+                                                                       unsigned char mi2cSlaveCmd,\r
+                                                                       unsigned char mi2cReadMode);                    \r
+                       \r
+extern unsigned char SH5001_MI2C_Write(unsigned char mi2cWriteData);                   \r
+                       \r
+extern unsigned char SH5001_MI2C_Read(unsigned char *mi2cReadData);\r
+\r
+                                                                                                                                                                                                                                                                                                                                                                                                               \r
+// SPI interface related fucntions\r
+extern void SH5001_SPI_Config(unsigned char spiInterfaceMode);\r
+\r
+\r
+// I2C interface related fucntions\r
+extern void SH5001_I2C_Config( unsigned char i2cInterfaceEnDis);\r
+\r
+extern void SH5001_I2C_LP_Config(unsigned char i2cReadLoopMode);\r
+\r
+\r
+// OIS SPI interface related fucntions\r
+extern void SH5001_OIS_SPI_Config(unsigned char oisSpiInterfaceEnDis);\r
+\r
+\r
+// fast offset compensation function\r
+extern void SH5001_FastOffsetComp(unsigned char SH5001Positon);                  \r
+ \r
+    \r
+// Read FIFO data functions\r
+extern void SH5001_initFIFO(void);                                    \r
+    \r
+extern void SH5001_ReadFIFO(void);      \r
+\r
+unsigned char SH5001_get_chip_id(void);\r
+gyro_data_t sh5001_get_gyro_data(void);\r
+#endif\r
+\r
index eb54055..8d7d2d2 100644 (file)
@@ -88,7 +88,7 @@ const lcd_cmd_sequ g_common_cmd_display_off[] = {
 
 /* display off sequence for common lcd */
 const lcd_cmd_sequ g_common_466x466_cmd_display_off[] = {
-#ifdef BOARD_W9
+#if defined(BOARD_W9) || defined(BOARD_N9)
     {1, 2, {0xfe, 0x00}, 0},   /* select default cmd page */
     {1, 1, {0x28}, 10},         /* display off */
     {1, 1, {0x10}, 120},       /* sleep in */
index 1bf3f37..edd794d 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: penglei 1624952103@qq.com
  * @Date: 2024-12-07 15:32:08
  * @LastEditors: penglei 1624952103@qq.com
- * @LastEditTime: 2025-06-06 10:36:23
+ * @LastEditTime: 2025-06-07 17:32:58
  * @FilePath: /FD230/code/sdk/drivers/peripheral/lcd/lcd_private.c
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -45,7 +45,7 @@ static void lcd_drv_power_off(void)
     uapi_gpio_set_dir(VCI_LCD_GPIO, GPIO_DIRECTION_OUTPUT);
     uapi_gpio_set_val(VCI_LCD_GPIO, GPIO_LEVEL_LOW);
     #endif
-#ifndef BOARD_W9
+#if !defined(BOARD_W9) || !defined(BOARD_N9)
     uapi_tcxo_delay_ms(10); /* delay 10 ms */
 #endif
     int resetvalue = uapi_gpio_get_output_val(RESET_LCD_GPIO);
index bf1e1b2..410ba6b 100644 (file)
@@ -2,4 +2,5 @@ add_subdirectory_if_exist(service)
 add_subdirectory_if_exist(hx3695)
 add_subdirectory_if_exist(ppgBleService)
 add_subdirectory_if_exist(hal)
-add_subdirectory_if_exist(pah8009)
\ No newline at end of file
+add_subdirectory_if_exist(pah8009)
+add_subdirectory_if_exist(gh3x2x)
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/CMakeLists.txt b/code/sdk/drivers/peripheral/ppg/gh3x2x/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1cea5b7
--- /dev/null
@@ -0,0 +1,57 @@
+#===============================================================================
+# @brief    cmake file
+# Copyright (c) @CompanyNameMagicTag 2022-2023. All rights reserved.
+#===============================================================================
+set(COMPONENT_NAME "ppg_sensor_gh3x2x")
+
+if("PPG_GH3X2X" IN_LIST DEFINES)
+
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}/inc
+)
+
+set(SOURCES ${SOURCES}
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/gh3x2x_afe_adt.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/gh3x2x_afe_agc.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/gh3x2x_afe_demo.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/gh3x2x_afe_drv.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/gh3x2x_afe_lead_off.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/gh3x2x_afe_user.c
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/gh3x2x_hal.c
+)
+
+else()
+set(SOURCES ${SOURCES}
+)
+set(PUBLIC_HEADER
+    ${CMAKE_CURRENT_SOURCE_DIR}
+)
+endif()
+
+
+set(PRIVATE_HEADER
+)
+
+set(PRIVATE_DEFINES
+)
+
+set(PUBLIC_DEFINES
+)
+
+# use this when you want to add ccflags like -include xxx
+set(COMPONENT_PUBLIC_CCFLAGS
+)
+
+set(COMPONENT_CCFLAGS
+)
+
+set(WHOLE_LINK
+    true
+)
+
+set(MAIN_COMPONENT
+    false
+)
+
+build_component()
+
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_adt.h b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_adt.h
new file mode 100644 (file)
index 0000000..d165a76
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef _GH3X2X_AFE_ADT_H_\r
+#define _GH3X2X_AFE_ADT_H_\r
+#include "gh3x2x_afe_drv.h"\r
+ \r
+\r
+#define __HARD_ADT_WAER_ON_THRD__               8600000\r
+#define __HARD_ADT_WAER_OFF_THRD__              8538608\r
+#define __HARD_ADT_WAER_ON_DIFF_THRD__          100000\r
+\r
+\r
+\r
+typedef enum\r
+{\r
+    WEAR_DETECT_WEAR_ON = 0,   /**< detect wear on */\r
+    WEAR_DETECT_WEAR_OFF,      /**< detect wear off */\r
+} EMWearDetectType;\r
+\r
+typedef enum\r
+{\r
+    WEAR_STATUS_WEAR_ON = 0,   /**< detect wear on */\r
+    WEAR_STATUS_WEAR_OFF,      /**< detect wear off */\r
+} EMWearStatus;\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+GS8  GH3x2xAdtAlgoInit(void);\r
+GS8 GH3x2xAdtAlgoDeinit(void);\r
+void GH3x2xAdtAlgoExe(GU32* punRawdata,EMWearStatus* pemWearStatus);\r
+\r
+\r
+\r
+\r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_agc.h b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_agc.h
new file mode 100644 (file)
index 0000000..ae3bd7b
--- /dev/null
@@ -0,0 +1,264 @@
+#ifndef _GH3X2X_AFE_AGC_H_\r
+#define _GH3X2X_AFE_AGC_H_\r
+#include "gh3x2x_afe_drv.h"\r
+#include <string.h> \r
+\r
+\r
+#define __SUPPORT_SOFT_AGC_CONFIG__          1\r
+#define GH3X2X_NEW_AGC_SLOT_NUM_LIMIT       (8)\r
+#define GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT   (32-8)\r
+\r
+#define  GH3X2X_LED_AGC_DISABLE             (0)\r
+#define  GH3X2X_LED_AGC_ENABLE              (1)\r
+\r
+\r
+/// led agc adc num max\r
+#define  GH3X2X_AGC_ADC_NUM_MAX             (4u)\r
+\r
+/// led agc gain limit number\r
+#define  GH3X2X_AGC_LIMIT_NUM_MAX           (4u)\r
+\r
+/// raw data base line value\r
+#define  GH3X2X_DATA_BASE_LINE              (8388608)   //2^23 \r
+\r
+/// sys sample rate, 32kHz\r
+#define  GH3X2X_SYS_SAMPLE_RATE             (32000)\r
+ \r
+/* slot register ctrl index */\r
+#define  GH3X2X_SLOT_REG_CTRL_0             (0)    /**< slot x ctrl 0 reg */\r
+#define  GH3X2X_SLOT_REG_CTRL_1             (1)    /**< slot x ctrl 1 reg */\r
+#define  GH3X2X_SLOT_REG_CTRL_2             (2)    /**< slot x ctrl 2 reg */\r
+#define  GH3X2X_SLOT_REG_CTRL_3             (3)    /**< slot x ctrl 3 reg */\r
+#define  GH3X2X_SLOT_REG_CTRL_4             (4)    /**< slot x ctrl 4 reg */\r
+#define  GH3X2X_SLOT_REG_CTRL_5             (5)    /**< slot x ctrl 5 reg */\r
+#define  GH3X2X_SLOT_REG_CTRL_6             (6)    /**< slot x ctrl 6 reg */\r
+#define  GH3X2X_SLOT_REG_CTRL_7             (7)    /**< slot x ctrl 7 reg */\r
+#define  GH3X2X_SLOT_REG_CTRL_8             (8)    /**< slot x ctrl 8 reg */\r
+#define  GH3X2X_SLOT_REG_CTRL_9             (9)    /**< slot x ctrl 9 reg */\r
+#define  GH3X2X_SLOT_REG_CTRL_10            (10)   /**< slot x ctrl 10 reg */\r
+#define  GH3X2X_SLOT_REG_CTRL_11            (11)   /**< slot x ctrl 11 reg */\r
+#define  GH3X2X_SLOT_REG_CTRL_12            (12)   /**< slot x ctrl 12 reg */\r
+#define  GH3X2X_SLOT_REG_CTRL_13            (13)   /**< slot x ctrl 13 reg */\r
+\r
+#define GH3X2X_BG_LEVEL_BIT_MASK            (0x0030)\r
+#define GH3X2X_ADC_BG_CANCEL_32_UA          (0x0)\r
+#define GH3X2X_ADC_BG_CANCEL_64_UA          (0x1)\r
+#define GH3X2X_ADC_BG_CANCEL_128_UA         (0x2)\r
+#define GH3X2X_ADC_BG_CANCEL_256_UA         (0x3)\r
+\r
+/// amb slot select\r
+#define GH3X2X_AGC_AMB_SLOT_DISABLE         (0x0)\r
+#define GH3X2X_AGC_AMB_SLOT_USER_DEFINED    (0x1)\r
+#define GH3X2X_AGC_AMB_SLOT_FOLLOW_CFG      (0x2)\r
+\r
+/// get bits data\r
+#define GH3X2X_GET_REG_BITS_U16(reg_data, lsb, msb)       (((reg_data) & ((0xFFFF << (lsb)) & \\r
+                                                            (0xFFFF >> (15 - (msb))))) >> (lsb))\r
+\r
+/// set bits data\r
+#define GH3X2X_SET_REG_BITS_U16(reg, lsb, msb, value)     ((reg) = (((reg) & ((0xFFFF << (lsb)) ^ \\r
+                                                                  (0xFFFF >> (15 - (msb))))) | ((value) << (lsb))))\r
+\r
+/// get adc gain\r
+#define GH3X2X_GET_ADC_GAIN(reg_data, adc_no)             GH3X2X_GET_REG_BITS_U16((reg_data), ((adc_no) * 4), \\r
+                                                                ((adc_no) * 4 + 3))\r
+\r
+/// set adc gain\r
+#define GH3X2X_SET_ADC_GAIN(reg_data, adc_no, gain)       GH3X2X_SET_REG_BITS_U16((reg_data), ((adc_no) * 4), \\r
+                                                                ((adc_no) * 4 + 3), (gain))\r
+\r
+/// get bg cancel i_dacfs\r
+#define GH3X2X_GET_BGC_I_DACFS(reg_data, adc_no)          GH3X2X_GET_REG_BITS_U16((reg_data), ((adc_no) << 1), \\r
+                                                                ((adc_no) * 2 + 1))\r
+\r
+/// set bg cancel i_dacfs\r
+#define GH3X2X_SET_BGC_I_DACFS(reg_data, adc_no, i_dacfs) GH3X2X_SET_REG_BITS_U16((reg_data), ((adc_no) * 2), \\r
+                                                              ((adc_no) * 2 + 1), (i_dacfs))\r
+                                                                                         \r
+#define ABS(x) ((x) > 0 ? (x) : -(x))\r
+\r
+/// transfer int to float\r
+#define GH3X2X_TRANS_INT_TO_FLOAT           (1.0f)\r
+\r
+/// agc calc seconds (250ms)\r
+#define GH3X2X_AGC_CALC_SECONDS             (0.25f)\r
+\r
+/// agc bgc donw cnt, 5s\r
+#define GH3X2X_AGC_BGC_DOWN_CNT             (20)\r
+\r
+/// slot tia gain val min\r
+#define GH3X2X_AGC_GAIN_MIN_VAL             (0)\r
+\r
+/// slot tia gain val max, 5s, equal (GH3X2X_SLOT_TIA_GAIN_VAL_MAX - 1)\r
+#define GH3X2X_AGC_GAIN_MAX_VAL             (12)\r
+\r
+/// Less than thr, include rawdata < thr\r
+#define GH3X2X_AGC_EXCD_FLAG_LESS           (0x01)\r
+\r
+/// greater than thr, include rawdatamix > thr | rawdata > thr\r
+#define GH3X2X_AGC_EXCD_FLAG_GREATER        (0x06)\r
+\r
+/// AGC failure reason\r
+#define GH3X2X_AGC_FAILURE_REASON_1         (0x1) \r
+#define GH3X2X_AGC_FAILURE_REASON_2         (0x2)\r
+#define GH3X2X_AGC_FAILURE_REASON_4         (0x4)\r
+#define GH3X2X_AGC_FAILURE_REASON_5         (0x5)\r
+#define GH3X2X_AGC_FAILURE_REASON_6         (0x6)\r
+\r
+#define GH3X2X_AGC_CHECK_EN_BITS(x)         (((x) & (0x03 << 8)) != 0)      /**< check enable bits of ctrl3 */\r
+#define GH3X2X_AGC_GET_SRC_BITS(x)          (((x) >> 6) & 0x03)             /**< get agc src bits of ctrl3 */\r
+#define GH3X2X_AGC_CHECK_BG_2X2_BITS(x)     (((x) & (0x03 << 4)) == 0x03)   /**< check 2x2 bg lvl bits of ctrl3 */\r
+#define GH3X2X_AGC_SET_SRC_BITS(x, n)       (((x) & 0xFF3Fu) | ((n) << 6u)) /**< set agc src bits of ctrl3 */\r
+\r
+#define GH3X2X_AGC_GET_DONE_FAIL_BIT(x, i)  (((x) >> (i)) & 0x01)           /**< get tune done/fail bit of flag */\r
+#define GH3X2X_AGC_REG_BIT(x, i)            (((x) >> (i)) & 0x01)           /**< get reg bit value */\r
+#define GH3X2X_AGC_GET_RESULT_BITS(x, i)    (((x) >> (i)) & 0x07)           /**< get result bits of flag  */\r
+#define GH3X2X_AGC_RESULT_BITS_SIZE         (3u)                           /**< one result 3 bits size of flag  */\r
+\r
+#define GH3X2X_FRAME_FLAG_NUM                     8\r
+#define GH3X2X_AGC_MAIN_SLOT_NUM                  8\r
+\r
+/**\r
+ * @brief soft lead result\r
+ */\r
+typedef struct\r
+{\r
+    GU8 uchAmbSampleEn  : 2;                /**< AMB sampling enable */\r
+    GU8 uchAmbSlot      : 3;                /**< slot of amb sampling */\r
+    GU8 uchRes          : 3;                /**< reserved */\r
+} STAmbSlotCtrl;\r
+ \r
+ /**\r
+ * @brief gain limit\r
+ */\r
+typedef struct\r
+{\r
+    GU8 uchGainLimitBg32uA  : 4;          /**< gain limit bg current */\r
+    GU8 uchGainLimitBg64uA  : 4;          \r
+    GU8 uchGainLimitBg128uA : 4;        \r
+    GU8 uchGainLimitBg256uA : 4;\r
+} STSoftAgcGainLimit;\r
+\r
+ /**\r
+  * @brief soft agc parameter\r
+  */\r
+typedef struct\r
+{\r
+    GU8 uchSlotxSoftAgcAdjEn;              /**< soft agc enable */\r
+    GU8 uchSlotxSoftBgAdjEn;               /**< soft bg cancel adjust enable */\r
+    STAmbSlotCtrl stAmbSlotCtrl;           /**< amb slot ctrl */\r
+    GU8 uchRes0;                           /**< reserved */\r
+    GU8 uchSpo2RedSlotCfgEn;\r
+    GU8 uchSpo2IrSlotCfgEn;\r
+    STSoftAgcGainLimit stSoftAgcGainLimit; /**< soft gain limit */\r
+    GU32 unAgcTrigThd_H;                   /**< trig threshold(high) of soft agc */\r
+    GU32 unAgcTrigThd_L;                   /**< trig threshold(low) of soft agc */\r
+    GU32 unAgcRestrainThd_H;               /**< restrain threshold(high) of soft agc */\r
+    GU32 unAgcRestrainThd_L;               /**< restrain threshold(low) of soft agc */\r
+} STSoftAgcCfg;\r
+\r
+\r
+\r
+typedef struct\r
+{\r
+    GU8 uchEnable;\r
+    GU8 uchSpo2ChnlIndex;      //0: is not spo2 channel   N(N > 0):  is spo2 channl  \r
+    GU8 uchSlotAdc;\r
+    GU8  uchCurrentTiaGain;\r
+    GU8  uchCurrentDrv;\r
+    GU8  uchTiaGainUpLimit;\r
+    GU8  uchHaveBakRegFlag;\r
+    GU8  uchBakRegAgcEn;\r
+    GU8  uchBakRegAgcSrc;\r
+    GU8  uchBakRegLedCurrentMin;\r
+    GU8  uchBakRegLedCurrentMax;\r
+    GU8  uchBakTiaGain;\r
+} STGh3x2xNewAgcMainChnlInfo;\r
+\r
+typedef struct \r
+{\r
+    GU16 Sat_CheckCnt[GH3X2X_AGC_MAIN_SLOT_NUM];  /* num of data checked*/\r
+    GU16 Sat_cnt[GH3X2X_AGC_MAIN_SLOT_NUM]; /* sat num of each channel*/\r
+    GU8 Sat_flag; /* sat flag one bit each channel*/\r
+} STGh3x2xNewAgcMainChnlSat;\r
+\r
+typedef struct\r
+{\r
+    GU32 unMaxRawdata;\r
+    GU32 unMinRawdata;\r
+    GU32 unSumAdjust;     //  cacluate drv current and gain\r
+    GU32 unSumTrige;      //  judge whether AGC\r
+    GU32 unRawdataMean;\r
+    GU32 unLastRawdataMean;\r
+    GU16 usSampleRate;\r
+    GU16 usAnalysisCnt;   // numble of nalysis data\r
+    GU8 uchHaveAgcAtLastReadPrd;    //0: no agc action at last fifo read period  1: have agc action at last fifo read preiod\r
+    GU8 uchDropFlag;\r
+} STGh3x2xNewAgcMainChnlMeanInfo;\r
+\r
+typedef struct\r
+{\r
+    GU8  uchIniteFirst;   // inite first time   0:yes   1:not\r
+    GU8  uchSeconsCnt;    // \r
+} STGh3x2xNewAgcMainChnlIdaelAdjInfo;\r
+\r
+typedef struct\r
+{\r
+    GU32 unLastRawdata;\r
+    GU32 unLastLastRawdata;\r
+    GU32 unRawdataSum;\r
+    GU16 usAnalysisCnt;\r
+    GU16 usMoreThanUpLimitPointCnt;\r
+    GU16 usMoreThanUpLimitPointCntForBiggerGain;\r
+    GU16 usTrigeUpLimitForBiggerGain;   //  rawdate/256\r
+    GU8 uchEn;\r
+    GU8 uchSlotAdcNo;\r
+    GU8 uchCurrentGain;\r
+}STGh3x2xNewAgcSubChnlRxInfo;\r
+\r
+\r
+void GH3X2X_LedAgcReset(void);\r
+void GH3X2X_LedAgcPramWrite(GU16 usRegAddr, GU16 usRegData);\r
+void GH3X2X_LedAgcInit(STGh3x2xAgcInfo *STGh3x2xAgcInfo);\r
+void GH3X2X_LedAgc_Close(void);\r
+void GH3X2X_LedAgc_Open(void);\r
+void Gh3x2xNewAgcSubChnlModuleReset(void);\r
+GU8 GH3x2xNewAgcSetNewSubChnl(GU8 uchSlotNo, GU8 uchRxEn, STGh3x2xAgcInfo *STGh3x2xAgcInfo);\r
+void GH3X2X_LedAgcProcess(GU8* puchReadFifoBuffer, GU16 usFifoLen, STGh3x2xAgcInfo *STGh3x2xAgcInfo);\r
+void GH3X2X_LedAgcInit(STGh3x2xAgcInfo *STGh3x2xAgcInfo);\r
+void GH3X2X_LedAgcPramConfig(STSoftAgcCfg* stSoftAgcCfg);\r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_demo.h b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_demo.h
new file mode 100644 (file)
index 0000000..e1d45e9
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef __GH3X2X_AFE_DEMO_H__\r
+#define __GH3X2X_AFE_DEMO_H__\r
+#include "gh3x2x_afe_drv.h"\r
+\r
+/**\r
+ * @brief channel map for function id\r
+ */\r
+#define GH3X2X_FUNC_OFFSET_ADT              (0)    /**<0 ADT FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_HR               (1)    /**<1 HR FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_HRV              (2)    /**<2 HRV FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_HSM              (3)    /**<3 HSM FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_FPBP             (4)    /**<4 BPD FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_PWA              (5)    /**<5 PFA FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_SPO2             (6)    /**<6 SPO2 FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_ECG              (7)    /**<7 ECG FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_PWTT             (8)    /**<8 PWTT FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_SOFT_ADT_GREEN   (9)    /**<9 SOFT ADT GREEN FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_BT               (10)   /**<10 BT FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_RESP             (11)   /**<11 RESP FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_AF               (12)   /**<12 AF ADT FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_TEST1            (13)   /**<13 TEST1 FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_TEST2            (14)   /**<14 TEST2 ADT FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_SOFT_ADT_IR      (15)   /**<15 SOFT ADT IR FUNC_OFFSET */\r
+#define GH3X2X_FUNC_OFFSET_RS0              (16)   /**<16 */\r
+#define GH3X2X_FUNC_OFFSET_RS1              (17)   /**<17 */\r
+#define GH3X2X_FUNC_OFFSET_RS2              (18)   /**<18 */\r
+#define GH3X2X_FUNC_OFFSET_LEAD_DET         (19)   /**<19 */\r
+#define GH3X2X_FUNC_OFFSET_MAX              (20) \r
+\r
+/* Function mode. */\r
+#define   GH3X2X_NO_FUNCTION                        (0)                                             /**<0x00000000 NO function */\r
+#define   GH3X2X_FUNCTION_ADT                       ((0x1) << (GH3X2X_FUNC_OFFSET_ADT))             /**<0x00000001 ADT function */\r
+#define   GH3X2X_FUNCTION_HR                        ((0x1) << (GH3X2X_FUNC_OFFSET_HR))              /**<0x00000002 HR function */\r
+#define   GH3X2X_FUNCTION_HRV                       ((0x1) << (GH3X2X_FUNC_OFFSET_HRV))             /**<0x00000004 HRV function */\r
+#define   GH3X2X_FUNCTION_HSM                       ((0x1) << (GH3X2X_FUNC_OFFSET_HSM))             /**<0x00000008 HSM function */\r
+#define   GH3X2X_FUNCTION_FPBP                      ((0x1) << (GH3X2X_FUNC_OFFSET_FPBP))            /**<0x00000010 FPBP function */\r
+#define   GH3X2X_FUNCTION_PWA                       ((0x1) << (GH3X2X_FUNC_OFFSET_PWA))             /**<0x00000020 PWA function */\r
+#define   GH3X2X_FUNCTION_SPO2                      ((0x1) << (GH3X2X_FUNC_OFFSET_SPO2))            /**<0x00000040 SPO2 function */\r
+#define   GH3X2X_FUNCTION_ECG                       ((0x1) << (GH3X2X_FUNC_OFFSET_ECG))             /**<0x00000080 ECG function */\r
+#define   GH3X2X_FUNCTION_PWTT                      ((0x1) << (GH3X2X_FUNC_OFFSET_PWTT))            /**<0x00000100 PWTT function */\r
+#define   GH3X2X_FUNCTION_SOFT_ADT_GREEN            ((0x1) << (GH3X2X_FUNC_OFFSET_SOFT_ADT_GREEN))  /**<0x00000200 SOFT ADT GREEN function */\r
+#define   GH3X2X_FUNCTION_BT                        ((0x1) << (GH3X2X_FUNC_OFFSET_BT))              /**<0x00000400 BT function */\r
+#define   GH3X2X_FUNCTION_RESP                      ((0x1) << (GH3X2X_FUNC_OFFSET_RESP))            /**<0x00000800 RESP function */\r
+#define   GH3X2X_FUNCTION_AF                        ((0x1) << (GH3X2X_FUNC_OFFSET_AF))              /**<0x00001000 AF function */\r
+#define   GH3X2X_FUNCTION_TEST1                     ((0x1) << (GH3X2X_FUNC_OFFSET_TEST1))           /**<0x00002000 TEST1 function */\r
+#define   GH3X2X_FUNCTION_TEST2                     ((0x1) << (GH3X2X_FUNC_OFFSET_TEST2))           /**<0x00004000 TEST2 function */\r
+#define   GH3X2X_FUNCTION_SOFT_ADT_IR               ((0x1) << (GH3X2X_FUNC_OFFSET_SOFT_ADT_IR))     /**<0x00008000 SOFT ADT IR function */\r
+#define   GH3X2X_FUNCTION_RS0                       ((0x1) << (GH3X2X_FUNC_OFFSET_RS0))\r
+#define   GH3X2X_FUNCTION_RS1                       ((0x1) << (GH3X2X_FUNC_OFFSET_RS1))\r
+#define   GH3X2X_FUNCTION_RS2                       ((0x1) << (GH3X2X_FUNC_OFFSET_RS2))\r
+#define   GH3X2X_FUNCTION_LEAD_DET                  ((0x1) << (GH3X2X_FUNC_OFFSET_LEAD_DET))\r
+\r
+#define   GH3X2X_ADT_FUNC_ENABLE                     (1)\r
+#define   GH3X2X_ECG_FUNC_ENABLE                     (1)\r
+\r
+#define   GH3X2X_ECG_SLOT_NUM                        (0)\r
+#define   GH3X2X_ADT_SLOT_NUM                        (1)\r
+\r
+#define   GH3X2X_ADT_ADC_NUM                         (0)\r
+\r
+#define   GH3X2X_ECG_DOWN_FS                        (250) //ecg fs:800, 320, 256\r
+#define   GH3X2X_ECG_FS                             (320) //down sample ecg fs: 500 OR 250\r
+#define   GH3X2X_PPG_DOWN_FS                        (250) //down sample ppg fs:\r
+\r
+void GH3X2X_DemoLedAgcPramConfig(void);\r
+\r
+#endif\r
+\r
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_drv.h b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_drv.h
new file mode 100644 (file)
index 0000000..95f900c
--- /dev/null
@@ -0,0 +1,453 @@
+/**\r
+ * @copyright (c) 2003 - 2022, Goodix Co., Ltd. All rights reserved.\r
+ *\r
+ * @file    gh3x2x_afe_drv.h\r
+ *\r
+ * @brief   gh3x2x afe driver functions\r
+ *\r
+ * @version v3.2.4.6\r
+ *\r
+ * @author  Gooidx Iot Team\r
+ *\r
+ */\r
+#ifndef __GH3X2X_AFE_DRV_H__\r
+#define __GH3X2X_AFE_DRV_H__\r
+\r
+#include "gh3x2x_afe_user.h"\r
+#include "gh3x2x_afe_version.h"\r
+#include <stdint.h>\r
+\r
+#ifndef GH3X2X_AFE_UNUSED_VAR\r
+#define GH3X2X_AFE_UNUSED_VAR(X) ((void)(X))\r
+#endif  // GH3X2X_AFE_UNUSED_VAR\r
+\r
+\r
+#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */\r
+  #ifndef __weak\r
+    #define __weak   __attribute__((weak))\r
+  #endif /* __weak */\r
+  #ifndef __packed\r
+    #define __packed __attribute__((__packed__))\r
+  #endif /* __packed */\r
+#endif /* __GNUC__ */\r
+\r
+\r
+\r
+\r
+\r
+\r
+/* type redefine */\r
+typedef unsigned char       GU8;    /**< 8bit unsigned integer type */\r
+typedef signed char         GS8;    /**< 8bit signed integer type */\r
+typedef unsigned short      GU16;   /**< 16bit unsigned integer type */\r
+typedef signed short        GS16;   /**< 16bit signed integer type */\r
+typedef int                 GS32;   /**< 32bit signed integer type */\r
+typedef unsigned int        GU32;   /**< 32bit unsigned integer type */\r
+typedef float               GF32;   /**< float type */\r
+typedef double              GD64;   /**< double type */\r
+typedef char                GCHAR;  /**< char type */\r
+typedef unsigned char       GBOOL; \r
+typedef long long           GS64;   /**< 64bit signed integer type */\r
+\r
+\r
+\r
+\r
+#define GH3020_ID                           (0x00)\r
+#define GH3026_ID                           (0x01)\r
+\r
+#define GH3220_ID                           (0x03)\r
+\r
+#define GH3X2X_MP_DISABLE                   (0)\r
+#define GH3X2X_MP_ENABLE                    (1)\r
+\r
+/********************* communication interface type******************************/\r
+#define GH3X2X_AFE_COM_INTERFACE_SPI  0\r
+#define GH3X2X_AFE_COM_INTERFACE_I2C  1\r
+\r
+\r
+/*********************  spi type ************************************************/\r
+#define GH3X2X_AFE_SPI_SOFTWARE_CS        0\r
+#define GH3X2X_AFE_SPI_HARDWEAR_CS        1\r
+\r
+\r
+/*********************  chip process type ***************************************/\r
+#define GH3X2X_AFE_PRO_BY_INT             0\r
+#define GH3X2X_AFE_PRO_BY_POLLING         1\r
+\r
+/*********************  chip reset type ***************************************/\r
+#define GH3X2X_AFE_RESET_HARDWARE         0\r
+#define GH3X2X_AFE_RESET_SOFTWARE         1         \r
+\r
+\r
+\r
+#define GH3X2X_AFE_SPI_CS_CTRL_LOW        0\r
+#define GH3X2X_AFE_SPI_CS_CTRL_HIGH       1\r
+\r
+\r
+\r
+\r
+#define GH3X2X_AFE_CMD_SLEEP  0xC4\r
+#define GH3X2X_AFE_CMD_WAKEUP 0xC3\r
+#define GH3X2X_AFE_CMD_RESET  0xC2\r
+#define GH3X2X_AFE_SPI_CMD_WRITE              (0xF0)\r
+#define GH3X2X_AFE_SPI_CMD_READ               (0xF1)\r
+\r
+\r
+\r
+#define   GH3X2X_AFE_RET_OK                             (0)             /**< there is no error */\r
+#define   GH3X2X_AFE_RET_GENERIC_ERROR                  (-1)            /**< a generic error happens */\r
+\r
+// special reg addr\r
+#define   GH3X2X_AFE_FIFO_REG_ADDR                      (0xAAAA)    /**< fifo reg addr */\r
+#define   GH3X2X_AFE_I2C_CMD_ADDR                       (0xDDDD)    /**< i2c cmd reg addr */\r
+\r
+\r
+#define GH3X2X_AFE_SPI_END_DELAY_X_US         (3)\r
+#define GH3X2X_AFE_SPI_WAIT_DELAY_X_US        (4)\r
+\r
+#define GH3X2X_AFE_WAKE_UP_CMD_DELAY_X_US   (500)\r
+#define GH3X2X_AFE_HARD_RESET_DELAY_X_US    (100)\r
+\r
+/// null val\r
+#define   GH3X2X_PTR_NULL                           ((void *) 0)\r
+\r
+\r
+\r
+#define GH3X2X_AFE_CHANGE_BYTE_U16(x)                  ((((u16)(((u8*)(&x))[0]))<<8) + ((u16)(((u8 *)(&x))[1])))\r
+/// get high byte from word\r
+#define   GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(sValue)    ((GU8)(((sValue) >> 8) & 0xFFU))\r
+/// get low byte from word\r
+#define   GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(sValue)     ((GU8)((sValue) & 0xFFU))\r
+#define   GH3X2X_AFE_MAKEUP_WORD(uchHighByte, uchLowByte)              ((GU16)(((((GU16)(uchHighByte)) << 8)& 0xFF00) |\\r
+                                                                            (((GU16)(uchLowByte))& 0x00FF)))\r
+\r
+/// makeup dword from bytes\r
+#define   GH3X2X_AFE_MAKEUP_DWORD(uchByte3, uchByte2, uchByte1, uchByte0)     (((((GU32)(uchByte3)) << 24) & 0xFF000000U)|\\r
+                                                                          ((((GU32)(uchByte2)) << 16) & 0x00FF0000U) |\\r
+                                                                          ((((GU32)(uchByte1)) << 8) & 0x0000FF00U) |\\r
+                                                                          (((GU32)(uchByte0)) & 0x000000FFU))\r
+\r
+\r
+/// rawdata clear all flag\r
+#define   GH3X2X_RAWDATA_CLEAR_ALL_FLAG(x)              ((x) & 0x00FFFFFF)\r
+\r
+\r
+/// macro of val get bits\r
+#define   GH3X2X_AFE_VAL_GET_BIT(x, b)          ((x) &= (b))\r
+\r
+\r
+\r
+#define GH3X2X_AFE_EVENT_BIT(x)   ((GU16)1 << x)\r
+\r
+\r
+\r
+#define GH3X2X_AFE_REG_IS_VALID(x)             ((x) <= 0x0780)\r
+/// macro of val clear bits\r
+#define   GH3X2X_VAL_CLEAR_BIT(x, b)        ((x) &= (~(b)))\r
+/// macro of val set bits\r
+#define   GH3X2X_VAL_SET_BIT(x, b)          ((x) |= (b))\r
+\r
+\r
+#define GH3X2X_PIN_STATUS_CS_0_MISO_0   (0)\r
+#define GH3X2X_PIN_STATUS_CS_1_MISO_0   (1)\r
+#define GH3X2X_PIN_STATUS_CS_0_MISO_1   (2)\r
+#define GH3X2X_PIN_STATUS_CS_1_MISO_1   (3)\r
+\r
+\r
+/// get byte3 from dword\r
+#define   GH3X2X_AFE_GET_BYTE3_FROM_DWORD(unValue)      ((GU8)(((unValue) >> 24) & 0x000000FFU))\r
+/// get byte2 from dword\r
+#define   GH3X2X_AFE_GET_BYTE2_FROM_DWORD(unValue)      ((GU8)(((unValue) >> 16) & 0x000000FFU))\r
+/// get byte1 from dword\r
+#define   GH3X2X_AFE_GET_BYTE1_FROM_DWORD(unValue)      ((GU8)(((unValue) >> 8) & 0x000000FFU))\r
+/// get byte0 from dword\r
+#define   GH3X2X_AFE_GET_BYTE0_FROM_DWORD(unValue)      ((GU8)((unValue) & 0x000000FFU))\r
+\r
+/// macro of val set bits\r
+#define   GH3X2X_VAL_SET_BIT(x, b)          ((x) |= (b))\r
+\r
+/// macro of clear bits\r
+#define   GH3X2X_CLEAR_BIT(x, b)            ((x) & (~(b)))\r
+\r
+/// macro of val clear bits\r
+#define   GH3X2X_VAL_CLEAR_BIT(x, b)        ((x) &= (~(b)))\r
+\r
+/// macro of val get bits\r
+#define   GH3X2X_VAL_GET_BIT(x, b)          ((x) &= (b))\r
+\r
+\r
+#define GH3X2X_AFE_I2C_DEVICE_BASE        (0x28)\r
+#define GH3X2X_AFE_I2C_DEVICE_ADDR        (GH3X2X_AFE_I2C_DEVICE_BASE | (GH3X2X_AFE_I2C_DEVICE_CTRL_PIN_STATUS << 1))\r
+\r
+\r
+#define   GH3X2X_AFE_FIFO_RAWDATA_SIZE                           (4)\r
+#define   GH3X2X_AFE_SLOT_ADC_NUM_BITS                       (0xF8)\r
+#define   GH3X2X_AFE_CHANNEL_MAP_GET(x)                     ((x) & GH3X2X_AFE_SLOT_ADC_NUM_BITS)\r
+\r
+/// number of channel map id\r
+#define  CHANNEL_MAP_ID_NUM                               (32)\r
+/// number of channel map id\r
+#define  CHANNEL_SLOT_NUM                                 (8)\r
+\r
+\r
+/**\r
+ * @brief register struct\r
+ */\r
+typedef struct\r
+{\r
+    GU16 usRegAddr;     /**< register address */\r
+    GU16 usRegData;     /**< register val */\r
+} STGH3X2X_AFEReg;\r
+\r
+typedef struct\r
+{\r
+    GU8 uchAddrOffset;\r
+    GU8 uchMsb;\r
+    GU8 uchLsb;\r
+} STGh3x2xAgcReg;\r
+\r
+typedef struct\r
+{\r
+    /// save gain\r
+               GU8  uchTiaGainRecord[CHANNEL_MAP_ID_NUM];\r
+               GU8  uchTiaGainAfterSoftAgc[CHANNEL_MAP_ID_NUM];\r
+               /// save current of drv0 and drv1\r
+               GU16  uchDrvCurrentAfterSoftAgc[CHANNEL_SLOT_NUM];\r
+               GU16 uchDrvCurrentRecord[CHANNEL_SLOT_NUM];\r
+} STGh3x2xAgcInfo;\r
+\r
+extern void GH3X2X_AFE_SpiSendCmd(GU8 uchCmd);\r
+extern void GH3X2X_AFE_SpiWriteReg(GU16 usRegAddr, GU16 usRegValue);\r
+extern GU16 GH3X2X_AFE_SpiReadReg(GU16 usRegAddr);\r
+extern void GH3X2X_AFE_SpiReadRegs(GU16 usRegAddr, GU16 *pusRegValueBuffer, GU8 uchLen);\r
+\r
+extern void GH3X2X_AFE_SpiWriteRegHardwareCs(GU16 usRegAddr, GU16 usRegValue);\r
+extern void GH3X2X_AFE_SpiReadRegsHardwareCs(GU16 usRegAddr, GU16 *pusRegValueBuffer, GU8 uchLen);\r
+extern GU16 GH3X2X_AFE_SpiReadRegHardwareCs(GU16 usRegAddr);\r
+extern void GH3X2X_AFE_I2cWriteReg(GU16 usRegAddr, GU16 usRegValue);\r
+extern GU16 GH3X2X_AFE_I2cReadReg(GU16 usRegAddr);\r
+extern void GH3X2X_I2cReadRegs(GU16 usRegAddr, GU16 *pusRegValueArr, GU8 uchLen);\r
+extern void GH3X2X_AFE_Reset(void);\r
+extern void GH3X2X_AFE_SpiSendCmdHardwareCs(GU8 uchCmd);\r
+extern void GH3X2X_AFE_I2cSendCmd(GU8 uchCmd);\r
+\r
+\r
+/****************  cmd/read/write  funciton define **************************/\r
+#if(GH3X2X_AFE_COM_INTERFACE_TYPE == GH3X2X_AFE_COM_INTERFACE_SPI)\r
+#if(GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS)\r
+#define GH3X2X_AFE_SEND_CMD(cmd)                                               GH3X2X_AFE_SpiSendCmd(cmd)\r
+#define GH3X2X_AFE_WRITE_REG(usRegAddr,  usRegValue)                           GH3X2X_AFE_SpiWriteReg(usRegAddr, usRegValue)\r
+#define GH3X2X_AFE_READ_REG(usRegAddr)                                         GH3X2X_AFE_SpiReadReg(usRegAddr)\r
+#define GH3X2X_AFE_READ_FIFO(buf, len)                                         GH3X2X_AFE_SpiReadFifo(buf, len)\r
+#define GH3X2X_AFE_READ_REGS(usRegAddr,pusRegValueBuffer,uchLen)               GH3X2X_AFE_SpiReadRegs(usRegAddr,pusRegValueBuffer,uchLen)\r
+#else\r
+#define GH3X2X_AFE_SEND_CMD(cmd)                                               GH3X2X_AFE_SpiSendCmdHardwareCs(cmd)\r
+#define GH3X2X_AFE_WRITE_REG(usRegAddr,  usRegValue)                           GH3X2X_AFE_SpiWriteRegHardwareCs(usRegAddr, usRegValue)\r
+#define GH3X2X_AFE_READ_REG(usRegAddr)                                         GH3X2X_AFE_SpiReadRegHardwareCs(usRegAddr)\r
+#define GH3X2X_AFE_READ_FIFO(buf, len)                                         GH3X2X_AFE_SpiReadFifoHardwareCs(buf, len)\r
+#define GH3X2X_AFE_READ_REGS(usRegAddr,pusRegValueBuffer,uchLen)               GH3X2X_AFE_SpiReadRegsHardwareCs(usRegAddr,pusRegValueBuffer,uchLen)\r
+\r
+#endif\r
+#else\r
+#define GH3X2X_AFE_SEND_CMD(cmd)                                                GH3X2X_AFE_I2cSendCmd(cmd)\r
+#define GH3X2X_AFE_WRITE_REG(usRegAddr,  usRegValue)                            GH3X2X_AFE_I2cWriteReg(usRegAddr, usRegValue)\r
+#define GH3X2X_AFE_READ_REG(usRegAddr)                                          GH3X2X_AFE_I2cReadReg(usRegAddr)\r
+#define GH3X2X_AFE_READ_FIFO(buf, len)                                          GH3X2X_AFE_I2cReadFifo(buf, len)\r
+#define GH3X2X_AFE_READ_REGS(usRegAddr,pusRegValueBuffer,uchLen)                GH3X2X_I2cReadRegs(usRegAddr,pusRegValueBuffer,uchLen)\r
+\r
+#endif\r
+\r
+\r
+/***************************** GH3X2X event *************************************************/\r
+\r
+#define GH3X2X_AFE_EVENT_COM_READY                    (0)\r
+#define GH3X2X_AFE_EVENT_LEAD_ON                      (1)\r
+#define GH3X2X_AFE_EVENT_LEAD_OFF                     (2)\r
+#define GH3X2X_AFE_EVENT_FAST_RECOVER_DONE            (3)\r
+#define GH3X2X_AFE_EVENT_ADC_DONE                     (4)\r
+#define GH3X2X_AFE_EVENT_FIFO_FULL                    (5)\r
+#define GH3X2X_AFE_EVENT_FIFO_OV                      (6)\r
+#define GH3X2X_AFE_EVENT_FIFO_UN                      (7)\r
+#define GH3X2X_AFE_EVENT_LED_TUNE_FAIL     (8)\r
+#define GH3X2X_AFE_EVENT_LED_TUNE_DONE     (9)\r
+#define GH3X2X_AFE_EVENT_WEAR_ON           (10)\r
+#define GH3X2X_AFE_EVENT_WEAR_OFF          (11)\r
+#define GH3X2X_AFE_EVENT_SLOT_TIME_OUT     (12)\r
+#define GH3X2X_AFE_EVENT_SAMPLE_RATE_ERROR (13)\r
+#define GH3X2X_AFE_EVENT_ERSET             (14)\r
+\r
+\r
+\r
+\r
+\r
+\r
+/***************************** GH3X2X registers *********************************************/\r
+\r
+\r
+#define GH3X2X_AFE_REG_INT_EVENT_ADDR                          0x0508\r
+#define GH3X2X_AFE_REG_FIFO_USE_ADDR                           0x050A\r
+#define GH3X2X_AFE_REG_CHIP_READY_CODE_REG_ADDR                0x0036\r
+#define GH3X2X_AFE_REG_SLOT_TMR0_REG_ADDR                      0x01EC\r
+#define GH3X2X_AFE_REG_INT_EVENT_EN_ADDR                       0x0502\r
+\r
+#define GH3X2X_AFE_REG_SLOT_EN_ADDR                            0x0108\r
+\r
+\r
+#define GH3X2X_AFE_REG_START_ADDR                              0x0000\r
+#define GH3X2X_AFE_REG_START_MSB                               0\r
+#define GH3X2X_AFE_REG_START_LSB                               0\r
+\r
+\r
+/**************************** GH3X2X ppg control reg index ***********************************************/\r
+#define GH3X2X_AFE_PPG_CTRL_REG_AGC_EN                     0\r
+#define GH3X2X_AFE_PPG_CTRL_REG_LED_CURRENT_UP_LIMIT       1\r
+#define GH3X2X_AFE_PPG_CTRL_REG_LED_CURRENT_DOWN_LIMIT     2\r
+#define GH3X2X_AFE_PPG_CTRL_REG_LED_CURRENT_DRV0           3\r
+#define GH3X2X_AFE_PPG_CTRL_REG_LED_CURRENT_DRV1           4\r
+#define GH3X2X_AFE_PPG_CTRL_REG_TIA_GAIN_RX0               5\r
+#define GH3X2X_AFE_PPG_CTRL_REG_TIA_GAIN_RX1               6\r
+#define GH3X2X_AFE_PPG_CTRL_REG_TIA_GAIN_RX2               7\r
+#define GH3X2X_AFE_PPG_CTRL_REG_TIA_GAIN_RX3               8\r
+#define GH3X2X_AFE_PPG_CTRL_REG_AGC_SRC                    9\r
+#define GH3X2X_AFE_PPG_CTRL_REG_BG_CANCEL_RX0              10\r
+#define GH3X2X_AFE_PPG_CTRL_REG_BG_CANCEL_RX1              11\r
+#define GH3X2X_AFE_PPG_CTRL_REG_BG_CANCEL_RX2              12\r
+#define GH3X2X_AFE_PPG_CTRL_REG_BG_CANCEL_RX3              13\r
+#define GH3X2X_AFE_PPG_CTRL_REG_SR_MULIPLIPER              14\r
+#define GH3X2X_AFE_PPG_CTRL_ECG_PPG_RX_EN                  15\r
+\r
+#define  GH3X2X_DRV0_FULL_SCAL_CURRENT_LSB          (4)\r
+#define  GH3X2X_DRV0_FULL_SCAL_CURRENT_MSB          (5)\r
+\r
+#define  GH3X2X_DRV1_FULL_SCAL_CURRENT_LSB          (0)\r
+#define  GH3X2X_DRV1_FULL_SCAL_CURRENT_MSB          (1)\r
+\r
+#define  GH3X2X_WHO_AM_I_LSB                        (5)\r
+#define  GH3X2X_WHO_AM_I_MSB                        (7)\r
+\r
+#define  GH3X2X_EFUSE_MODE_LSB                      (0)\r
+#define  GH3X2X_EFUSE_MODE_MSB                      (1)\r
+\r
+#define  GH3X2X_EFUSE_CHOOSE_LSB                    (2)\r
+#define  GH3X2X_EFUSE_CHOOSE_MSB                    (3)\r
+\r
+#define  GH3X2X_EFUSE_START_LSB                     (4)\r
+#define  GH3X2X_EFUSE_START_MSB                     (4)\r
+\r
+#define  GH3X2X_EFUSE_CLK_EN_LSB                    (5)\r
+#define  GH3X2X_EFUSE_CLK_EN_MSB                    (5)\r
+\r
+\r
+\r
+\r
+#define   GH3X2X_LED_DRV_AD_REG_REG_ADDR                (0x0692)\r
+#define   GH3X2X_WHO_AM_I_REG_ADDR                      (0x0724)\r
+\r
+\r
+// efuse_ctrl block, start addr: 0x0700\r
+#define   GH3X2X_EFUSE_CTRL_CMD_REG_ADDR                (0x0700)\r
+#define   GH3X2X_EFUSE_CTRL_PASSWORD_REG_ADDR           (0x0702)\r
+#define   GH3X2X_EFUSE_CTRL_TIMING_CFG_0_REG_ADDR       (0x0704)\r
+#define   GH3X2X_EFUSE_CTRL_TIMING_CFG_1_REG_ADDR       (0x0706)\r
+#define   GH3X2X_EFUSE_CTRL_WDATA_0_REG_ADDR            (0x0708)\r
+#define   GH3X2X_EFUSE_CTRL_WDATA_1_REG_ADDR            (0x070A)\r
+#define   GH3X2X_EFUSE_CTRL_WDATA_2_REG_ADDR            (0x070C)\r
+#define   GH3X2X_EFUSE_CTRL_WDATA_3_REG_ADDR            (0x070E)\r
+#define   GH3X2X_EFUSE_CTRL_RDATA_0_REG_ADDR            (0x0710)\r
+#define   GH3X2X_EFUSE_CTRL_RDATA_1_REG_ADDR            (0x0712)\r
+#define   GH3X2X_EFUSE_CTRL_RDATA_2_REG_ADDR            (0x0714)\r
+#define   GH3X2X_EFUSE_CTRL_RDATA_3_REG_ADDR            (0x0716)\r
+#define   GH3X2X_EFUSE_CTRL_STATUS_REG_ADDR             (0x0718)\r
+#define   GH3X2X_EFUSE_CTRL_REG_MODE_REG_ADDR           (0x071A)\r
+  \r
+\r
+extern GU8 g_uchGh3x2xAfeIntCallBackIsCalled;\r
+\r
+\r
+extern void GH3X2X_AFE_SetNeedWakeUpGh3x2xFlag(GU8 uchFlag);\r
+extern void hal_gh3x2x_afe_DelayUs(GU16 usUsec);\r
+extern void hal_gh3x2x_afe_DelayMs(GU16 usMsec);\r
+\r
+extern void hal_gh3x2x_afe_i2c_init(void);\r
+extern GU8 hal_gh3x2x_afe_i2c_write(GU8 device_id, const GU8 write_buffer[], GU16 length);\r
+extern GU8 hal_gh3x2x_afe_i2c_read(GU8 device_id, const GU8 write_buffer[], GU16 write_length, GU8 read_buffer[], GU16 read_length);\r
+\r
+extern void hal_gh3x2x_afe_spi_init(void);\r
+extern GU8 hal_gh3x2x_afe_spi_write(GU8 write_buffer[], GU16 length);\r
+extern GU8 hal_gh3x2x_afe_spi_read(GU8 read_buffer[], GU16 length);\r
+extern GU8 hal_gh3x2x_afe_spi_write_F1_and_read(GU8 read_buffer[], GU16 length);\r
+extern void hal_gh3x2x_afe_spi_cs_ctrl(GU8 cs_pin_level);\r
+\r
+extern void hal_gh3x2x_afe_reset_pin_init(void);\r
+extern void hal_gh3x2x_afe_reset_pin_ctrl(GU8 pin_level);\r
+\r
+extern void hal_gh3x2x_afe_int_init(void);\r
+extern void hal_gh3x2x_afe_int_handler_call_back(void);\r
+\r
+extern void GH3X2X_AFE_Log(GCHAR *log_string);\r
+\r
+\r
+\r
+\r
+\r
+extern void GH3X2X_AFE_ChipPro(void);\r
+extern void GH3X2X_AFE_Init(void);\r
+extern void GH3X2X_AFE_StartSampling(GU8 SlotCfgEnable);\r
+extern void GH3X2X_AFE_StopSampling(void);\r
+extern void GH3X2X_AFE_SwitchSlot(GU8 SlotCfgEnable);\r
+\r
+extern void GH3x2xSetPpgCtrlReg(GU8 uchPpgCtrlReg,  GU8 uchSlot, GU16 usValue);\r
+extern GU16 GH3x2xGetPpgCtrlReg(GU8 uchPpgCtrlReg,  GU8 uchSlot);\r
+\r
+GU16 GH3X2X_AFE_SetLedDrvCurrent(GU8 uchCurrent_mA, GU8 uchDrvNum, GS8 chECODE);\r
+GF32 GH3X2X_AFE_GetLedDrvCurrent(GU16 usDrvCode, GU8 uchDrvNum, GS8 chECODE);\r
+void GH3X2X_AFE_GetEfuseCode(GS8* pchLedDrvEcode,GS8* pchTiaEcode,GS8* pchEcgEcode);\r
+GF32 GH3X2X_AFE_GetTiaCalCode(GS8 chECODE);\r
+GF32 GH3X2X_AFE_GetEcgCalCode(GS8 chECODE);\r
+GCHAR *GH3X2X_GetAfeLibVersion(void);\r
+GU8 GH3X2X_AFE_GetChipId(void);\r
+GS8 GH3X2X_AFE_CheckChipId(void);\r
+void GH3X2X_AFE_LoadEfuse(GU8* puchEfuseBuffer,GU16 EfuseByteLen);\r
+GS8 GH3X2X_AFE_CheckEfuseCrc(void);\r
+void GH3X2X_AFE_WriteRegBitField(GU16 usRegAddr, GU8 uchLsb, GU8 uchMsb, GU16 usValue);\r
+GU16 GH3X2X_AFE_ReadRegBitField(GU16 usRegAddr, GU8 uchLsb, GU8 uchMsb);\r
+GU8 GH3X2X_AFE_GetSoftEvent(void);\r
+void GH3X2X_AFE_SetSoftEvent(GU32 unEvent);\r
+void GH3X2X_AFE_ClearSoftEvent(GU32 unEvent);\r
+void GH3X2X_AFE_StartFunction(GU32 unFuncMode);\r
+\r
+void GH3x2x_AFESetAgcReg(GU8 uchAgcReg,  GU8 uchSlot, GU16 usValue);\r
+GU16 GH3x2x_AFEGetAgcReg(GU8 uchAgcReg,  GU8 uchSlot);\r
+void *GH3X2X_Memcpy(void *pDest, const void *pSrc, GU32 unByteSize);\r
+void *GH3X2X_Memset(void* pDest, GCHAR chVal, GU32 unByteSize);\r
+void GH3X2X_RecordAgcInfo(void);\r
+void GH3X2X_UpdateAgcInfo(void);\r
+\r
+void gh3x2x_control(char* mode, uint8_t enable);\r
+\r
+/*********************************************** master-slaver interface lib function *********************************/\r
+#define GH3X2X_INFO_LOG(...)                    do {\\r
+                                                char GH3X2X_AFE_GH3X2X_INFO_LOG[128] = {0};\\r
+                                                snprintf(GH3X2X_AFE_GH3X2X_INFO_LOG, 128, __VA_ARGS__);\\r
+                                                GH3X2X_AFE_Log((char *)GH3X2X_AFE_GH3X2X_INFO_LOG);\\r
+                                            } while(0)\r
+\r
+\r
+\r
+\r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_ecg.h b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_ecg.h
new file mode 100644 (file)
index 0000000..50d3c8d
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef __GH3X2X_AFE_ECG_H__\r
+#define __GH3X2X_AFE_ECG_H__\r
+#include "gh3x2x_afe_drv.h"\r
+\r
+/**\r
+ * @brief Downsample Function\r
+*/\r
+typedef enum\r
+{\r
+       DOWNSAMPLE_ECG = 0,\r
+       DOWNSAMPLE_PPG,\r
+}EmDownSampleFunction;\r
+\r
+/**\r
+ * @brief Downsample type\r
+*/\r
+typedef enum\r
+{\r
+       DOWNSAMPLE_DEFAULT = 0,\r
+       DOWNSAMPLE_800HZ_TO_500HZ = 1,\r
+       DOWNSAMPLE_800HZ_TO_250HZ = 2,\r
+       DOWNSAMPLE_400HZ_TO_250HZ = 3,\r
+       DOWNSAMPLE_320HZ_TO_250HZ = 4,\r
+       DOWNSAMPLE_256HZ_TO_250HZ = 5,\r
+}EmDownSampleType;\r
+\r
+typedef struct\r
+{\r
+    GS32 snRsXbuf[100/1 + 1];\r
+    GS32 snBufHead;\r
+    GS32 snRsFirState;\r
+    GU32 nRsIcounter;\r
+    GU32 nRrsDcounter;\r
+    GU8 uchFlagFrPrev;\r
+    GU32 nRsLastRaw;\r
+    GU32 fDownStep;\r
+    GU8  uchLinearInterState;\r
+    GU8  uchLinearDataUpdate;\r
+} STGh3x2xRsInfo;\r
+\r
+\r
+typedef struct\r
+{\r
+    GS32 snCounter;\r
+    GS32 sniqCounter;\r
+    long long snniVal;\r
+    long long snnqVal;\r
+    GU8 uchFlagFrPrev;\r
+    GU8 uchFastRecoryHistory;\r
+    long long snniqAmp[5];\r
+} STGh3x2xSoftLeadOffDetInfo;\r
+\r
+\r
+typedef struct\r
+{\r
+    GU8   uchRsFirOrder;\r
+    GU8   uchRsI;\r
+    GU8   uchRsD;\r
+    GU8   uchRsFirCoefNum;\r
+    GU8   uchRsBufSize;\r
+    GU8   uchRsEnable;\r
+    GU32  ufStep;\r
+    GS32* rsFirCoef;\r
+               GU8   uchDownSampleType;\r
+} STGh3x2xDownSampleCalParamInfo;\r
+\r
+#define __SUPPORT_ECG_PPG_DOWNSAMP__  0\r
+  \r
+/* ecg sample event type */\r
+#define  ECG_SAMPLE_EVENT_TYPE_SAMPLE                     (0x01)     /**< sample evt type sample config */\r
+#define  ECG_SAMPLE_EVENT_TYPE_SLOT                       (0x02)     /**< sample evt type slot config */\r
+#define  ECG_SAMPLE_EVENT_TYPE_LEAD                       (0x04)     /**< sample evt type lead irq */\r
+#define  ECG_SAMPLE_EVENT_ALL                             (ECG_SAMPLE_EVENT_TYPE_SAMPLE | ECG_SAMPLE_EVENT_TYPE_SLOT | \\r
+                                                            ECG_SAMPLE_EVENT_TYPE_LEAD)     /**< sample evt all */\r
+\r
+#define   GH3X2X_ECG_CTRL_REG_ADDR                      (0x01EA)\r
+#define   GH3X2X_ECG_FAST_RECV_EN_LSB               (10)        /**< ecg fast recv en lsb @GH3X2X_ECG_CTRL_REG */\r
+#define   GH3X2X_ECG_FAST_RECV_EN_MSB               (10)        /**< ecg fast recv en msb @GH3X2X_ECG_CTRL_REG */\r
+/// ecg fast recover enable config\r
+#define  ECG_FAST_RECV_EN_CONFIG(en)        do {\\r
+                                                GH3X2X_AFE_WriteRegBitField(GH3X2X_ECG_CTRL_REG_ADDR, \\r
+                                                    GH3X2X_ECG_FAST_RECV_EN_LSB, GH3X2X_ECG_FAST_RECV_EN_MSB, (en)); \\r
+                                            } while (0)\r
+\r
+#define   GH3X2X_ADT_LEADON_CR_REG_ADDR                 (0x0400)\r
+#define   GH3X2X_ECG_LEAD_DET_EN_LSB                (0)         /**< ecg lead det en lsb @GH3X2X_ADT_LEADON_CR_REG */\r
+#define   GH3X2X_ECG_LEAD_DET_EN_MSB                (0)         /**< ecg lead det en msb @GH3X2X_ADT_LEADON_CR_REG */\r
+                                            \r
+  /// ecg lead detect enable config\r
+#define  ECG_LEAD_DET_EN_CONFIG(en)         do {\\r
+                                                GH3X2X_AFE_WriteRegBitField(GH3X2X_ADT_LEADON_CR_REG_ADDR, \\r
+                                                    GH3X2X_ECG_LEAD_DET_EN_LSB, GH3X2X_ECG_LEAD_DET_EN_MSB, (en)); \\r
+                                            } while (0)                                          \r
+                                            \r
+                                            \r
+#define GET_ECG_LEAD_DET_EN_VAL()              (GH3X2X_AFE_ReadRegBitField(GH3X2X_ADT_LEADON_CR_REG_ADDR, \\r
+                                                    GH3X2X_ECG_LEAD_DET_EN_LSB, GH3X2X_ECG_LEAD_DET_EN_MSB))\r
+ \r
+ \r
+\r
+GU8 GH3X2X_AFE_EcgRsHandle(GU8* puchFifoBuffer, GU16* pusFifoBufferLen, GU8 uchEcgSlotNum, GU16 usEcgSampleRate);\r
+GS32 GH3X2X_LeadOffDetectInit(void);\r
+void GH3X2X_ECGResampleConfig(GU16 usEcgSampleRate);\r
+void GH3X2X_PPGResampleConfig(GU16 usEcgSampleRate);                                                                                                                                                                   \r
+GU8 GH3X2X_LeadOffDetect(GU8* puchFifoBuffer, GU16* pusFifoBufferLen, GU8 uchEcgSlotNum);\r
+void GH3X2X_AFE_Leadon_hook(void);\r
+void GH3X2X_AFE_Leadoff_hook(void);\r
+void GH3x2xSetEcgOutputFs(GU16 usEcgOutputFs);\r
+\r
+#endif\r
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_user.h b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_user.h
new file mode 100644 (file)
index 0000000..4ccc448
--- /dev/null
@@ -0,0 +1,52 @@
+/*\r
+ * @Author: penglei 1624952103@qq.com\r
+ * @Date: 2025-01-13 10:11:20\r
+ * @LastEditors: penglei 1624952103@qq.com\r
+ * @LastEditTime: 2025-02-17 11:32:58\r
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/ppg/gh3x2x/inc/gh3x2x_afe_user.h\r
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE\r
+ */\r
+#ifndef __GH3X2X_AFE_USER_H__\r
+#define __GH3X2X_AFE_USER_H__\r
+#include "gh3x2x_afe_drv.h"\r
+\r
+\r
+#define   GH3X2X_CHIP_ID               GH3220_ID\r
+#define   GH3X2X_AFE_MP_MODE           GH3X2X_MP_ENABLE\r
+\r
+\r
+/******  communication type config **************************/\r
+#define GH3X2X_AFE_COM_INTERFACE_TYPE  GH3X2X_AFE_COM_INTERFACE_I2C\r
+#define GH3X2X_AFE_SPI_TYPE            GH3X2X_AFE_SPI_SOFTWARE_CS\r
+\r
+\r
+/****** I2C device id ***************************************/\r
+#define GH3X2X_AFE_I2C_DEVICE_CTRL_PIN_STATUS    GH3X2X_PIN_STATUS_CS_0_MISO_0\r
+\r
+\r
+\r
+/******  chip process type config ***************************/\r
+#define GH3X2X_AFE_PRO_TYPE            GH3X2X_AFE_PRO_BY_INT\r
+\r
+\r
+\r
+/******  chip reset type config ***************************/\r
+#define GH3X2X_AFE_RESET_TYPE          GH3X2X_AFE_RESET_SOFTWARE\r
+\r
+void hal_gh3x2x_afe_int_init(void);\r
+void hal_gh3x2x_afe_int_deinit(void);\r
+\r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_version.h b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_version.h
new file mode 100644 (file)
index 0000000..a5b7620
--- /dev/null
@@ -0,0 +1,45 @@
+\r
+/**\r
+ * @copyright (c) 2003 - 2022, Goodix Co., Ltd. All rights reserved.\r
+ *\r
+ * @file    gh3x2x_afe_version.h\r
+ *\r
+ * @brief   gh3x2x afe driver version and change log\r
+ *\r
+ * @par  history:\r
+ * @verbatim\r
+ * Date            Version     Notes\r
+ * 2021-11-04      v3.2.4.2    1.add calibration code\r
+ * 2021-11-05      v3.2.4.4    1.fix Efuse calibration bug\r
+ * 2021-11-05      v3.2.4.5    1.add Ffuse Crc Process\r
+ *                             2.add Check Chip Id process\r
+ *\r
+ * 2021-11-05      v3.2.4.6    1.update Head file\r
+ * 2021-11-05      v3.2.4.7    1.add ecg lead off det lib\r
+ * 2021-11-05      v3.2.4.8    1.add 5Hz adt\r
+ * 2023-12-06      v3.2.4.9    1.update ecg and agc\r
+ * @endverbatim  */\r
+\r
+#ifndef _GH3X2X_AFE_VERSION_H_\r
+#define _GH3X2X_AFE_VERSION_H_\r
+\r
+\r
+#define   GH3X2X_DRV_MAJOR_VERSION_NUMBER        3      /**< major version number */\r
+#define   GH3X2X_DRV_MINOR_VERSION_NUMBER        2      /**< minor version number */\r
+#define   GH3X2X_DRV_REVISION_VERSION_NUMBER     4      /**< revision version number */\r
+#define   GH3X2X_DRV_FIXED_VERSION_NUMBER        9      /**< fixed version number */\r
+\r
+#define   GH3X2X_TO_STRING(x)       #x                      /**< number to char */\r
+#define   GH3X2X_STR(x)             GH3X2X_TO_STRING(x)     /**< number to char */\r
+\r
+/// makeup version string\r
+#define   GH3X2X_VERSION_STRING     "v" GH3X2X_STR(GH3X2X_DRV_MAJOR_VERSION_NUMBER)\\r
+                                    "." GH3X2X_STR(GH3X2X_DRV_MINOR_VERSION_NUMBER)\\r
+                                    "." GH3X2X_STR(GH3X2X_DRV_REVISION_VERSION_NUMBER)\\r
+                                    "." GH3X2X_STR(GH3X2X_DRV_FIXED_VERSION_NUMBER)\\r
+                                    " (build:"__DATE__"_"__TIME__")"\r
+\r
+\r
+#endif /* _GH3X2X_AFE_VERSION_H_ */\r
+\r
+/********END OF FILE********* Copyright (c) 2003 - 2022, Goodix Co., Ltd. ********/\r
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_hal.h b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_hal.h
new file mode 100644 (file)
index 0000000..f9485fc
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-06-07 11:18:26
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-06-06 11:23:50
+ * @FilePath: /FD230/code/sdk/drivers/peripheral/ppg/hx3695/hx3695_hal.h
+ * @Description: 
+ * 
+ * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. 
+ */
+#ifndef GH_3X2X_HAL_H__
+#define GH_3X2X_HAL_H__
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#include "stdint.h"
+
+// typedef uint32_t PPG_CMD_TYPE_T ;
+
+void ppg_send_cmd_to_gh3x2x_driver(char* mode, uint8_t enable);
+
+uint32_t tyhx_poweron(void);
+uint32_t tyhx_poweroff(void);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_adt.c b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_adt.c
new file mode 100644 (file)
index 0000000..561922b
--- /dev/null
@@ -0,0 +1,156 @@
+/**\r
+ * @copyright (c) 2003 - 2022, Goodix Co., Ltd. All rights reserved.\r
+ *\r
+ * @file    gh3x2x_afe_adt.c\r
+ *\r
+ * @brief   gh3x2x led agc process functions\r
+ *\r
+ * @version \r
+ *\r
+ */\r
+\r
+\r
+#include <stdio.h>\r
+#include "gh3x2x_afe_adt.h"\r
+\r
+#define GH3X2X_MOVINF_AVA_WINDOW_SIZE  6\r
+\r
+\r
+\r
+EMWearDetectType g_uchWearDetectStatus = WEAR_DETECT_WEAR_ON;\r
+\r
+GU32 g_punGh3x2xMovingAvaFilterBuf[GH3X2X_MOVINF_AVA_WINDOW_SIZE];\r
+GU8  g_uchGh3x2xMovingAvaFilterPointCnt;\r
+GU8  g_Gh3x2xFilterHaveOutputFlag;\r
+\r
+\r
+\r
+void Gh3x2xMovingAvaFilterInit(void)\r
+{\r
+    g_uchGh3x2xMovingAvaFilterPointCnt = 0;\r
+    g_Gh3x2xFilterHaveOutputFlag = 0;\r
+}\r
+GU8 Gh3x2xMovingAvaFilter(GU32 *Rawdata, GU8 uchBypass)\r
+{\r
+    GU32 unSum = 0;\r
+\r
+    if(uchBypass)\r
+    {\r
+        return 1;\r
+    }\r
+    else\r
+    {\r
+        if(g_uchGh3x2xMovingAvaFilterPointCnt >= GH3X2X_MOVINF_AVA_WINDOW_SIZE)\r
+        {\r
+            for(GU8 uchCnt = 1; uchCnt < GH3X2X_MOVINF_AVA_WINDOW_SIZE; uchCnt ++)\r
+            {\r
+                g_punGh3x2xMovingAvaFilterBuf[uchCnt - 1] = g_punGh3x2xMovingAvaFilterBuf[uchCnt];\r
+            }\r
+            g_uchGh3x2xMovingAvaFilterPointCnt = GH3X2X_MOVINF_AVA_WINDOW_SIZE - 1;\r
+        }\r
+        g_punGh3x2xMovingAvaFilterBuf[g_uchGh3x2xMovingAvaFilterPointCnt] = Rawdata[0];\r
+        g_uchGh3x2xMovingAvaFilterPointCnt ++;\r
+            \r
+        if(g_uchGh3x2xMovingAvaFilterPointCnt > 1)\r
+        {\r
+            for(GU8 uchCnt = 0; uchCnt < g_uchGh3x2xMovingAvaFilterPointCnt - 1; uchCnt ++)\r
+            {\r
+                unSum += g_punGh3x2xMovingAvaFilterBuf[uchCnt];\r
+            }\r
+            Rawdata[0] = unSum/(g_uchGh3x2xMovingAvaFilterPointCnt - 1);\r
+        }\r
+        return 1;\r
+    }\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+GS8  GH3x2xAdtAlgoInit(void)\r
+{\r
+    Gh3x2xMovingAvaFilterInit();\r
+    g_uchWearDetectStatus = WEAR_DETECT_WEAR_ON;\r
+    return GH3X2X_AFE_RET_OK;\r
+}\r
+GS8 GH3x2xAdtAlgoDeinit(void)\r
+{\r
+    return GH3X2X_AFE_RET_OK;\r
+}\r
+\r
+void GH3x2xAdtAlgoExe(GU32* punRawdata,EMWearStatus* pemWearStatus)\r
+{\r
+    \r
+    GU32 unCurrentFrameRawdata;\r
+\r
+    GU32 unRawDataBeforeFilter;\r
+    unCurrentFrameRawdata = *punRawdata;\r
+    unRawDataBeforeFilter = *punRawdata;\r
+    GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe] punFrameRawdata = %d\r\n", unCurrentFrameRawdata);\r
+\r
+    Gh3x2xMovingAvaFilter(&unCurrentFrameRawdata, 0);\r
+    GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe] punFrameRawdata after filter = %d\r\n", unCurrentFrameRawdata);\r
+\r
+\r
+\r
+    GS32 snDiffRawdata;\r
+\r
+    GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe] start check...\r\n");\r
+\r
+    snDiffRawdata = (GS32)unRawDataBeforeFilter - (GS32)unCurrentFrameRawdata;\r
+\r
+    if(WEAR_DETECT_WEAR_ON == g_uchWearDetectStatus)\r
+    {\r
+        \r
+        *pemWearStatus = WEAR_STATUS_WEAR_OFF;\r
+        if((unRawDataBeforeFilter > __HARD_ADT_WAER_ON_THRD__)&&((snDiffRawdata > (GS32)__HARD_ADT_WAER_ON_DIFF_THRD__)))\r
+        {\r
+            *pemWearStatus = WEAR_STATUS_WEAR_ON;\r
+            g_uchWearDetectStatus = WEAR_DETECT_WEAR_OFF;\r
+            GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe] wear on !\r\n");\r
+        }\r
+        else\r
+        {\r
+            if(unRawDataBeforeFilter > __HARD_ADT_WAER_ON_THRD__)\r
+            {\r
+                GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe] wear on condition is not match ! r = %d, r_diff = %d\r\n",unCurrentFrameRawdata,snDiffRawdata);\r
+            }\r
+        }\r
+        if(snDiffRawdata > 30000)\r
+        {\r
+        GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe]ppg 5Hz diff big event, Rawdata = %d, unRawdataDiff = %d\r\n",*punRawdata,snDiffRawdata);\r
+        }\r
+    }\r
+    else if(WEAR_DETECT_WEAR_OFF == g_uchWearDetectStatus)\r
+    {\r
+        *pemWearStatus = WEAR_STATUS_WEAR_ON;\r
+        if(unRawDataBeforeFilter < __HARD_ADT_WAER_OFF_THRD__)\r
+        {\r
+            *pemWearStatus = WEAR_STATUS_WEAR_OFF;\r
+            g_uchWearDetectStatus = WEAR_DETECT_WEAR_ON;\r
+            GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe]ppg 5Hz wear off event, Rawdata = %d, unRawdataDiff = %d\r\n",*punRawdata,snDiffRawdata);\r
+            GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe] wear off !\r\n");\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_agc.c b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_agc.c
new file mode 100644 (file)
index 0000000..7cfbe6d
--- /dev/null
@@ -0,0 +1,1131 @@
+/**\r
+ * @copyright (c) 2003 - 2022, Goodix Co., Ltd. All rights reserved.\r
+ *\r
+ * @file    gh3x2x_afe_agc.c\r
+ *\r
+ * @brief   gh3x2x led agc process functions\r
+ *\r
+ * @version \r
+ *\r
+ */\r
+\r
+\r
+#include <stdio.h>\r
+#include "gh3x2x_afe_agc.h"\r
+#include "gh3x2x_afe_drv.h"\r
+\r
+#define __GH3X2X_AGC_GENERAL_TRIG_H_THD__  ((8388608 + 8388608*0.85f))\r
+#define __GH3X2X_AGC_GENERAL_TRIG_L_THD__  ((8388608 + 8388608*0.15f))\r
+#define __GH3X2X_AGC_GENERAL_IDEAL_VALUE__ ((8388608 + 8388608*0.56f))\r
+#define __GH3X2X_AGC_SPO2_TRIG_H_THD__  ((8388608 + 8388608*0.9f))\r
+#define __GH3X2X_AGC_SPO2_TRIG_L_THD__  ((8388608 + 8388608*0.5f))\r
+#define __GH3X2X_AGC_SPO2_IDEAL_VALUE__  ((8388608 + 8388608*0.7f))\r
+#define __GH3X2X_AGC_CONVERGENCE_LEVEL__  (16)  // The values that can be set are 8, 16 and 32, and the recommended value is 16. The larger the value, the smaller the convergence range of AGC. \r
+\r
+//sub channel\r
+\r
+#define GH3X2X_NEW_AGC_SUB_CHNNL_ANAYLSIS_TIME_SEC 1\r
+\r
+#define GH3X2X_AGC_REG_AGC_EN                     0\r
+#define GH3X2X_AGC_REG_LED_CURRENT_UP_LIMIT       1\r
+#define GH3X2X_AGC_REG_LED_CURRENT_DOWN_LIMIT     2\r
+#define GH3X2X_AGC_REG_LED_CURRENT_DRV0           3\r
+#define GH3X2X_AGC_REG_LED_CURRENT_DRV1           4\r
+#define GH3X2X_AGC_REG_TIA_GAIN_RX0               5\r
+#define GH3X2X_AGC_REG_TIA_GAIN_RX1               6\r
+#define GH3X2X_AGC_REG_TIA_GAIN_RX2               7\r
+#define GH3X2X_AGC_REG_TIA_GAIN_RX3               8\r
+#define GH3X2X_AGC_REG_AGC_SRC                    9\r
+#define GH3X2X_AGC_REG_BG_CANCEL_RX0              10\r
+#define GH3X2X_AGC_REG_BG_CANCEL_RX1              11\r
+#define GH3X2X_AGC_REG_BG_CANCEL_RX2              12\r
+#define GH3X2X_AGC_REG_BG_CANCEL_RX3              13\r
+#define GH3X2X_AGC_REG_SR_MULIPLIPER              14\r
+#define GH3X2X_AGC_ECG_PPG_RX_EN                  15\r
+\r
+\r
+#if __SUPPORT_SOFT_AGC_CONFIG__\r
+//main chnl\r
+STGh3x2xNewAgcMainChnlInfo  g_pstGh3x2xNewAgcMainChnlInfoEntity[GH3X2X_NEW_AGC_SLOT_NUM_LIMIT];\r
+STGh3x2xNewAgcMainChnlMeanInfo g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[GH3X2X_NEW_AGC_SLOT_NUM_LIMIT];\r
+STGh3x2xNewAgcMainChnlIdaelAdjInfo g_pstGh3x2xNewAgcMainChnlIdaelAdjInfoEntity[GH3X2X_NEW_AGC_SLOT_NUM_LIMIT];\r
+//sub chnl\r
+#if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0\r
+STGh3x2xNewAgcSubChnlRxInfo    g_pstGh3x2xNewAgcSubChnlRxInfoEntity[GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT];\r
+#endif\r
+\r
+\r
+STGh3x2xNewAgcMainChnlSat g_pstGh3x2xNewAgcMainChnlSat;\r
+const GU32 g_unNewAgcSpo2Trig_H_Thd = __GH3X2X_AGC_SPO2_TRIG_H_THD__;\r
+const GU32 g_unNewAgcSpo2Trig_L_Thd = __GH3X2X_AGC_SPO2_TRIG_L_THD__;\r
+const GU32 g_unNewAgcSpo2Ideal_value = __GH3X2X_AGC_SPO2_IDEAL_VALUE__;\r
+const GU32 g_unNewAgcGeneTrig_H_Thd = __GH3X2X_AGC_GENERAL_TRIG_H_THD__;\r
+const GU32 g_unNewAgcGeneTrig_L_Thd = __GH3X2X_AGC_GENERAL_TRIG_L_THD__;\r
+const GU32 g_unNewAgcGeneIdeal_value = __GH3X2X_AGC_GENERAL_IDEAL_VALUE__;\r
+const GU8  g_uchAgcConvergence_level = __GH3X2X_AGC_CONVERGENCE_LEVEL__;\r
+\r
+\r
+// soft agc parameter\r
+static STSoftAgcCfg g_stSoftAgcCfg;\r
+extern const GU16 g_usGH3x2xTiaGainR[];\r
+\r
+GU8 g_Gh3x2xNewAgcInitFlag = 0;\r
+\r
+void GH3X2X_LedAgcPramConfig(STSoftAgcCfg* stSoftAgcCfg)\r
+{\r
+    g_stSoftAgcCfg.uchSlotxSoftAgcAdjEn = stSoftAgcCfg->uchSlotxSoftAgcAdjEn;   //bit0: slot0\r
+       g_stSoftAgcCfg.uchSlotxSoftBgAdjEn = stSoftAgcCfg->uchSlotxSoftBgAdjEn;\r
+       g_stSoftAgcCfg.stAmbSlotCtrl.uchAmbSampleEn = stSoftAgcCfg->stAmbSlotCtrl.uchAmbSampleEn;\r
+    g_stSoftAgcCfg.uchSpo2RedSlotCfgEn = stSoftAgcCfg->uchSpo2RedSlotCfgEn;\r
+    g_stSoftAgcCfg.uchSpo2IrSlotCfgEn = stSoftAgcCfg->uchSpo2IrSlotCfgEn;\r
+       g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg32uA = stSoftAgcCfg->stSoftAgcGainLimit.uchGainLimitBg32uA;\r
+       g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg64uA = stSoftAgcCfg->stSoftAgcGainLimit.uchGainLimitBg64uA;\r
+       g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg128uA = stSoftAgcCfg->stSoftAgcGainLimit.uchGainLimitBg128uA;\r
+       g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg256uA = stSoftAgcCfg->stSoftAgcGainLimit.uchGainLimitBg256uA;\r
+       g_stSoftAgcCfg.unAgcTrigThd_H = stSoftAgcCfg->unAgcTrigThd_H;\r
+       g_stSoftAgcCfg.unAgcTrigThd_L = stSoftAgcCfg->unAgcTrigThd_L;\r
+       g_stSoftAgcCfg.unAgcRestrainThd_H = stSoftAgcCfg->unAgcRestrainThd_H;\r
+       g_stSoftAgcCfg.unAgcRestrainThd_L = stSoftAgcCfg->unAgcRestrainThd_L;\r
+    \r
+    GH3X2X_INFO_LOG("uchSlotxSoftAgcAdjEn = 0x%X, uchSlotxSoftBgAdjEn = 0x%X\r\n",(int)g_stSoftAgcCfg.uchSlotxSoftAgcAdjEn,(int)g_stSoftAgcCfg.uchSlotxSoftBgAdjEn);\r
+    GH3X2X_INFO_LOG("uchAmbSampleEn = 0x%X, uchAmbSlot = 0x%X\r\n",(int)g_stSoftAgcCfg.stAmbSlotCtrl.uchAmbSampleEn,(int)g_stSoftAgcCfg.stAmbSlotCtrl.uchAmbSlot);\r
+    GH3X2X_INFO_LOG("uchSpo2RedSlotCfgEn = 0x%X,uchSpo2IrSlotCfgEn = 0x%X\r\n",(int)g_stSoftAgcCfg.uchSpo2RedSlotCfgEn,(int)g_stSoftAgcCfg.uchSpo2IrSlotCfgEn);\r
+    GH3X2X_INFO_LOG("stSoftAgcGainLimit = 0x%X,0x%X,0x%X,0x%X\r\n",g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg32uA,g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg64uA,g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg128uA,g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg256uA);\r
+    GH3X2X_INFO_LOG("unAgcTrigThd_H = %d,unAgcTrigThd_L = %d\r\n",(int)g_stSoftAgcCfg.unAgcTrigThd_H,(int)g_stSoftAgcCfg.unAgcTrigThd_L);\r
+    GH3X2X_INFO_LOG("unAgcRestrainThd_H = %d,unAgcRestrainThd_L = %d\r\n",(int)g_stSoftAgcCfg.unAgcRestrainThd_H,(int)g_stSoftAgcCfg.unAgcRestrainThd_L);\r
+\r
+}\r
+\r
+void GH3X2X_StoreRxTiaGainAfterAgc(GU8 uchGain, GU8 uchSlotNo, GU8 uchAdcNo, GU8* puchGainRecord)\r
+{\r
+    puchGainRecord[uchSlotNo*4 + uchAdcNo] = uchGain;\r
+}\r
+\r
+void GH3X2X_StoreDrvCurrentAfterAgc(GU8 DrvCurrent, GU8 uchSlotNo, GU8 uchDrvIndex, GU16* puchDrvCurrentRecord)\r
+{\r
+       if(!uchDrvIndex)\r
+       {\r
+               puchDrvCurrentRecord[uchSlotNo] = (puchDrvCurrentRecord[uchSlotNo]&0xFF00)|DrvCurrent;\r
+       }\r
+       else\r
+       {\r
+         puchDrvCurrentRecord[uchSlotNo] = (puchDrvCurrentRecord[uchSlotNo]&0x00FF)|(DrvCurrent<<8);\r
+       }       \r
+}\r
+\r
+\r
+void GH3x2xNewAgcModuleReset(void)\r
+{\r
+    g_Gh3x2xNewAgcInitFlag = 0;\r
+    GH3X2X_Memset((GU8*)g_pstGh3x2xNewAgcMainChnlInfoEntity,0,(GU16)GH3X2X_NEW_AGC_SLOT_NUM_LIMIT*sizeof(STGh3x2xNewAgcMainChnlInfo));\r
+    GH3X2X_Memset( (GU8*)(&g_pstGh3x2xNewAgcMainChnlSat),0,sizeof(STGh3x2xNewAgcMainChnlSat)); // init  variable\r
+    GH3X2X_Memset((GU8*)g_pstGh3x2xNewAgcMainChnlMeanInfoEntity,0,(GU16)GH3X2X_NEW_AGC_SLOT_NUM_LIMIT*sizeof(STGh3x2xNewAgcMainChnlMeanInfo)); \r
+    GH3X2X_Memset((GU8*)g_pstGh3x2xNewAgcMainChnlIdaelAdjInfoEntity,0,(GU16)GH3X2X_NEW_AGC_SLOT_NUM_LIMIT*sizeof(STGh3x2xNewAgcMainChnlIdaelAdjInfo));                           \r
+               \r
+         #if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0\r
+    Gh3x2xNewAgcSubChnlModuleReset();   \r
+               #endif\r
+}\r
+ \r
+void GH3X2X_NewAgcRecoveryAgcRegToMainChnl(GU8 uchSlotIdx, STGh3x2xNewAgcMainChnlInfo *pstAgcMainChnlInfo)\r
+{\r
+    GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_UP_LIMIT, uchSlotIdx, pstAgcMainChnlInfo ->uchBakRegLedCurrentMax);\r
+    GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_DOWN_LIMIT, uchSlotIdx, pstAgcMainChnlInfo ->uchBakRegLedCurrentMin);\r
+    GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_AGC_SRC, uchSlotIdx, pstAgcMainChnlInfo ->uchBakRegAgcSrc);\r
+    GH3X2X_INFO_LOG("[NewAgc] recover agc src:agc_src = %d, SlotNo = %d\r\n",pstAgcMainChnlInfo ->uchBakRegAgcSrc,uchSlotIdx);\r
+}\r
+\r
+GU8 GH3X2X_NewAgcFindSubChnlSlotInfo(GU8 uchSlot)\r
+{\r
+    for(GU8 uchSlotCnt = 0; uchSlotCnt < GH3X2X_NEW_AGC_SLOT_NUM_LIMIT; uchSlotCnt ++)\r
+    {\r
+        STGh3x2xNewAgcMainChnlInfo *pstAgcMainChnlInfo = &g_pstGh3x2xNewAgcMainChnlInfoEntity[uchSlotCnt];\r
+        if(pstAgcMainChnlInfo ->uchEnable)\r
+        {\r
+            if(uchSlot == (pstAgcMainChnlInfo ->uchSlotAdc >> 2))\r
+            {\r
+                return uchSlotCnt;\r
+            }\r
+        }\r
+    }\r
+    return 0;\r
+}\r
+\r
+GU16 GH3x2xCalTrigerUpLimitForBiggerGain(GU8 uchCurrentGain ,GU8 uchSlotNo)\r
+{\r
+    GU32 unTempRawdata;\r
+    GU32 unTempTrigThd_H;\r
+\r
+    GU8 uchSlotCnt = GH3X2X_NewAgcFindSubChnlSlotInfo(uchSlotNo);\r
+    STGh3x2xNewAgcMainChnlInfo *pstAgcMainChnlInfo = &g_pstGh3x2xNewAgcMainChnlInfoEntity[uchSlotCnt];\r
+    if(pstAgcMainChnlInfo->uchSpo2ChnlIndex)\r
+    {\r
+        unTempTrigThd_H = g_unNewAgcSpo2Trig_H_Thd;\r
+    }else\r
+    {\r
+        unTempTrigThd_H = g_unNewAgcGeneTrig_H_Thd;\r
+    }\r
+        \r
+    if(12 <= uchCurrentGain)\r
+    {\r
+        return 0xFFFF;\r
+    }\r
+    else\r
+    {\r
+        unTempRawdata = unTempTrigThd_H - 8388608;\r
+        unTempRawdata = 8388608 + (GU32)(((float)unTempRawdata)/(float)1.3*(float)g_usGH3x2xTiaGainR[uchCurrentGain]/(float)g_usGH3x2xTiaGainR[uchCurrentGain + 1]);\r
+        return unTempRawdata>>8;\r
+    }\r
+}\r
+\r
+\r
+#if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0\r
+void GH3x2xNewAgcSubChnlClearAnalysisCntAndSetGain(GU8 uchSlotNo, GU8 uchRxEn ,GU8 uchNextGain)\r
+{\r
+    for(GU8 uchRxCnt = 0; uchRxCnt < 4; uchRxCnt ++)\r
+    {\r
+        if(uchRxEn&(1 << uchRxCnt))\r
+        {\r
+            for(GU8 uchChnlCnt = 0; uchChnlCnt < GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT; uchChnlCnt ++)\r
+            {\r
+                STGh3x2xNewAgcSubChnlRxInfo *pstSTGh3x2xNewAgcSubChnlRxInfo = &(g_pstGh3x2xNewAgcSubChnlRxInfoEntity[uchChnlCnt]);\r
+                if(pstSTGh3x2xNewAgcSubChnlRxInfo->uchEn)\r
+                {\r
+                    if(((uchSlotNo << 2) + uchRxCnt) == pstSTGh3x2xNewAgcSubChnlRxInfo ->uchSlotAdcNo)\r
+                    {\r
+                        pstSTGh3x2xNewAgcSubChnlRxInfo ->usAnalysisCnt = 0;\r
+                        if(0xFF != uchNextGain)\r
+                        {\r
+                            GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_TIA_GAIN_RX0 + uchRxCnt, uchSlotNo, 0);\r
+                            pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain = uchNextGain;\r
+                            pstSTGh3x2xNewAgcSubChnlRxInfo ->usTrigeUpLimitForBiggerGain = GH3x2xCalTrigerUpLimitForBiggerGain(uchNextGain,pstSTGh3x2xNewAgcSubChnlRxInfo->uchSlotAdcNo >> 2);\r
+                        }\r
+                    }    \r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
+#endif\r
+  \r
+  \r
+void GH3x2xNewAgcMeanInfoReset(GU8 uchSlotEnChange)\r
+{\r
+     for(GU8 uchSlotCnt = 0; uchSlotCnt < 8; uchSlotCnt++)\r
+     {\r
+        if( uchSlotEnChange & (1<<uchSlotCnt)) // SlotEn Change \r
+        {\r
+            for(GU8 uchAgcSlotCnt = 0; uchAgcSlotCnt < GH3X2X_NEW_AGC_SLOT_NUM_LIMIT; uchAgcSlotCnt ++) //// uchAgcSlotCnt'??????slot????\r
+            {\r
+                GU8  uchSlotIdx = ((g_pstGh3x2xNewAgcMainChnlInfoEntity[uchAgcSlotCnt].uchSlotAdc >> 2) & 0x0f);\r
+                GU8  uchEnable = g_pstGh3x2xNewAgcMainChnlInfoEntity[uchAgcSlotCnt].uchEnable;\r
+                if( uchEnable )  \r
+                { \r
+                   if( uchSlotIdx == uchSlotCnt)  \r
+                   {\r
+                       g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[uchAgcSlotCnt].usAnalysisCnt = 0;\r
+                       #if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0\r
+                       GH3x2xNewAgcSubChnlClearAnalysisCntAndSetGain(uchSlotIdx, 0x0F, 0xFF); //clear all rx analysis cnt in this slot\r
+                       #endif \r
+                   }\r
+                }\r
+            }\r
+        }\r
+     }\r
+}    \r
+\r
+GU8 GH3x2xGetDrvCurrent(GU8 uchSlotIdx ,GU8 uchAgcEn)\r
+{\r
+    GU8 uchTempDrv;\r
+    if(2 == uchAgcEn)\r
+    {    \r
+        uchTempDrv = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_DRV1, uchSlotIdx);\r
+    }\r
+    else\r
+    {\r
+        uchTempDrv = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_DRV0, uchSlotIdx);\r
+    }\r
+    return uchTempDrv;\r
+}\r
+\r
+void GH3x2xNewAgcChnlInfoInit(STGh3x2xAgcInfo *STGh3x2xAgcInfo)\r
+{\r
+    if(0 == GH3X2X_NEW_AGC_SLOT_NUM_LIMIT)\r
+    {\r
+        return;\r
+    }\r
+    if(0 == g_Gh3x2xNewAgcInitFlag)\r
+    {\r
+        GU8 uchNewAgcSlotCnt = 0;\r
+        for(GU8 uchSlotCnt = 0; uchSlotCnt < 8; uchSlotCnt ++)\r
+        {\r
+            if((g_stSoftAgcCfg.uchSlotxSoftAgcAdjEn & (1 << uchSlotCnt)))\r
+            {\r
+                if(uchNewAgcSlotCnt < GH3X2X_NEW_AGC_SLOT_NUM_LIMIT)\r
+                {\r
+                    g_pstGh3x2xNewAgcMainChnlInfoEntity[uchNewAgcSlotCnt].uchEnable = 1;\r
+                    g_pstGh3x2xNewAgcMainChnlInfoEntity[uchNewAgcSlotCnt].uchSlotAdc = (uchSlotCnt << 2); \r
+                                    \r
+                    /******* slot function Distinguish   START******************************************************/          \r
+                    if((g_stSoftAgcCfg.uchSpo2RedSlotCfgEn & (1 << uchSlotCnt))||(g_stSoftAgcCfg.uchSpo2IrSlotCfgEn & (1 << uchSlotCnt)))\r
+                    {\r
+                        g_pstGh3x2xNewAgcMainChnlInfoEntity[uchNewAgcSlotCnt].uchSpo2ChnlIndex =  1;\r
+                        GH3X2X_INFO_LOG("[NewAgc] uchNewAgcSpo2SlotCnt = %d\r\n",uchNewAgcSlotCnt);\r
+                    }\r
+                    /******* slot function Distinguish   END******************************************************/\r
+                    GH3X2X_INFO_LOG("[NewAgc] uchNewAgcSlotCnt = %d\r\n",uchNewAgcSlotCnt);\r
+                    uchNewAgcSlotCnt ++;\r
+                }\r
+                else\r
+                {\r
+                    GH3X2X_INFO_LOG("[NewAgc] error !!! main chnl info is no enough! \r\n");\r
+                    while(1);\r
+                }\r
+            }\r
+        }\r
+        g_Gh3x2xNewAgcInitFlag = 1;\r
+    }\r
+\r
+    for(GU8 uchSlotCnt = 0; uchSlotCnt < GH3X2X_NEW_AGC_SLOT_NUM_LIMIT; uchSlotCnt ++)\r
+    {    \r
+        STGh3x2xNewAgcMainChnlInfo *pstAgcMainChnlInfo = &g_pstGh3x2xNewAgcMainChnlInfoEntity[uchSlotCnt];\r
+        //GH3X2X_INFO_LOG_PARAM("AGC_InitValue %d: Enable = %d, AgcAdjEn = %d\r\n",uchSlotCnt, pstAgcMainChnlInfo->uchEnable,g_stSoftAgcCfg.uchSlotxSoftAgcAdjEn);\r
+        if(pstAgcMainChnlInfo->uchEnable)\r
+        {\r
+            GU8 uchSlotIdx;\r
+            uchSlotIdx = pstAgcMainChnlInfo ->uchSlotAdc >> 2;\r
+            //GH3X2X_INFO_LOG_PARAM("AGC_InitFlag%d: SlotCfgX=%d, Vaule = %d\r\n",uchSlotCnt, uchSlotIdx, pstAgcMainChnlInfo->uchHaveBakRegFlag);\r
+            if(0 == pstAgcMainChnlInfo ->uchHaveBakRegFlag)\r
+            {\r
+                GU8 uchBgCancel;\r
+                GU8 uchGainLimit;\r
+                GU16 usSampleRate;\r
+                GU16 usEcgPpgRxEn;\r
+\r
+                //bak reg\r
+                pstAgcMainChnlInfo ->uchBakRegAgcEn = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_AGC_EN, uchSlotIdx);\r
+                pstAgcMainChnlInfo ->uchBakRegAgcSrc = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_AGC_SRC, uchSlotIdx);\r
+                pstAgcMainChnlInfo ->uchSlotAdc = (uchSlotIdx << 2) + pstAgcMainChnlInfo ->uchBakRegAgcSrc;\r
+                pstAgcMainChnlInfo ->uchBakRegLedCurrentMax = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_UP_LIMIT, uchSlotIdx);                \r
+                pstAgcMainChnlInfo ->uchBakRegLedCurrentMin = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_DOWN_LIMIT, uchSlotIdx);    \r
+                pstAgcMainChnlInfo ->uchBakTiaGain = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_TIA_GAIN_RX0 + pstAgcMainChnlInfo ->uchBakRegAgcSrc, uchSlotIdx);\r
+                pstAgcMainChnlInfo ->uchCurrentTiaGain = pstAgcMainChnlInfo ->uchBakTiaGain;\r
+                pstAgcMainChnlInfo ->uchCurrentDrv =  GH3x2xGetDrvCurrent(uchSlotIdx, pstAgcMainChnlInfo->uchBakRegAgcEn); \r
+                //GH3X2X_StoreDrvCurrentAfterAgc(pstAgcMainChnlInfo ->uchCurrentDrv, uchSlotIdx,g_pstGh3x2xAgcInfo->uchDrvCurrentAfterSoftAgc);                                                        \r
+                uchBgCancel = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_BG_CANCEL_RX0 + pstAgcMainChnlInfo ->uchBakRegAgcSrc, uchSlotIdx);\r
+                GH3X2X_StoreRxTiaGainAfterAgc(pstAgcMainChnlInfo->uchBakTiaGain, uchSlotIdx, pstAgcMainChnlInfo->uchBakRegAgcSrc, STGh3x2xAgcInfo->uchTiaGainAfterSoftAgc);\r
+                if(0 == uchBgCancel)\r
+                {\r
+                    uchGainLimit = g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg32uA;\r
+                }\r
+                else if(1 == uchBgCancel)\r
+                {\r
+                    uchGainLimit = g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg64uA;\r
+                }\r
+                else if(2 == uchBgCancel)\r
+                {\r
+                    uchGainLimit = g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg128uA;\r
+                }\r
+                else\r
+                {\r
+                    uchGainLimit = g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg256uA;\r
+                }\r
+                GH3X2X_INFO_LOG("[NewAgc] uchGainLimit = %d, uchSlotIdx = %d\r\n",uchGainLimit, uchSlotIdx);\r
+                pstAgcMainChnlInfo ->uchTiaGainUpLimit = uchGainLimit;\r
+                usSampleRate = 1000/(GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_SR_MULIPLIPER, uchSlotIdx) + 1);\r
+                usEcgPpgRxEn = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_ECG_PPG_RX_EN, uchSlotIdx);\r
+                GH3X2X_INFO_LOG("[NewAgc] usEcgPpgRxEn = 0x%X\r\n",usEcgPpgRxEn);\r
+                if(usEcgPpgRxEn&0x0001)  // ecg is enable\r
+                {\r
+                    usEcgPpgRxEn = ((usEcgPpgRxEn>>1) & (~0x0008));  //clear RX3 enable bit\r
+                }\r
+                else\r
+                {\r
+                    usEcgPpgRxEn = (usEcgPpgRxEn>>1);\r
+                }\r
+                usEcgPpgRxEn &= (~(1 << pstAgcMainChnlInfo ->uchBakRegAgcSrc));   //clear main channel RX enable bit\r
+                \r
+                g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[uchSlotCnt].usSampleRate = usSampleRate;  //init\r
+                GH3X2X_INFO_LOG("[AgcInit] SlotCnt = %d, SampleRate = %d\r\n", uchSlotCnt, usSampleRate); \r
+                //sub channel slot\r
+#if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0\r
+                GH3x2xNewAgcSetNewSubChnl(uchSlotIdx,usEcgPpgRxEn,STGh3x2xAgcInfo);\r
+#endif\r
+                pstAgcMainChnlInfo ->uchHaveBakRegFlag = 1;                \r
+                GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_AGC_EN, uchSlotIdx, 0);   // disable hardware agc \r
+            }\r
+            else\r
+            {\r
+              pstAgcMainChnlInfo ->uchCurrentTiaGain = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_TIA_GAIN_RX0 + pstAgcMainChnlInfo ->uchBakRegAgcSrc, uchSlotIdx);\r
+              pstAgcMainChnlInfo ->uchCurrentDrv =  GH3x2xGetDrvCurrent(uchSlotIdx, pstAgcMainChnlInfo->uchBakRegAgcEn);\r
+              //GH3X2X_INFO_LOG_PARAM("Drv Gian inite read %d: IniteDrv = %d, IniteGain = %d\r\n",uchSlotIdx, pstAgcMainChnlInfo ->uchCurrentDrv, pstAgcMainChnlInfo ->uchCurrentTiaGain);\r
+              ////get initial DRV and current in case them change before StartSampling()\r
+//              GH3X2X_NewAgcRecoveryAgcRegToMainChnl(uchSlotIdx,pstAgcMainChnlInfo);\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+\r
+GU32 GH32x2xMedSel(GU32 unData0, GU32 unData1, GU32 unData2)\r
+{\r
+    if((unData0 >= unData1)&&(unData0 <= unData2))\r
+    {\r
+        return unData0;\r
+    }\r
+    if((unData0 >= unData2)&&(unData0 <= unData1))\r
+    {\r
+        return unData0;\r
+    }\r
+    if((unData1 >= unData0)&&(unData1 <= unData2))\r
+    {\r
+        return unData1;\r
+    }\r
+    if((unData1 >= unData2)&&(unData1 <= unData0))\r
+    {\r
+        return unData1;\r
+    }\r
+    return unData2;\r
+}\r
+\r
+float GH3X2X_CalcfRelativeVpp(GU32 unRawdata, GU8 uchDrv, GU8 uchGain)\r
+{\r
+    return ((float)unRawdata/(float)uchDrv/(float)g_usGH3x2xTiaGainR[uchGain]);\r
+}\r
+\r
+void GH3X2X_StoreTiaGainAfterAgc(GU16 usGainRegValue, GU8 uchSlotNo, GU8* puchGainRecord)\r
+{\r
+    for(GU8 uchAdcCnt = 0; uchAdcCnt < 4; uchAdcCnt ++)\r
+    {\r
+        puchGainRecord[uchSlotNo*4 + uchAdcCnt] = (usGainRegValue>>(uchAdcCnt*4))&0x000F;\r
+        GH3X2X_INFO_LOG("StoreTiaGainAfterAgc slot no = %d, adc no = %d, usGainRegValue = %d\r\n", uchSlotNo,uchAdcCnt,usGainRegValue);\r
+    }\r
+}\r
+\r
+void GH3X_AgcGetThreshold( GU8 uchSpo2ChnlIndex, GU32* punTemp_H_Thd, GU32* punTemp_L_Thd )\r
+{  \r
+   if(uchSpo2ChnlIndex) // is  spo2 slot\r
+   {\r
+      *punTemp_H_Thd = g_unNewAgcSpo2Trig_H_Thd; \r
+      *punTemp_L_Thd = g_unNewAgcSpo2Trig_L_Thd; \r
+   }else\r
+   { \r
+      *punTemp_H_Thd = g_unNewAgcGeneTrig_H_Thd;\r
+      *punTemp_L_Thd = g_unNewAgcGeneTrig_L_Thd;      \r
+   }\r
+}\r
+\r
+#if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0\r
+void Gh3x2xNewAgcSubChnlModuleReset(void)\r
+{\r
+    #if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0\r
+    GH3X2X_Memset((GU8*)g_pstGh3x2xNewAgcSubChnlRxInfoEntity,0,(GU16)GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT*sizeof(STGh3x2xNewAgcSubChnlRxInfo));\r
+    #endif\r
+}\r
+\r
+GU8 GH3x2xNewAgcSetNewSubChnl(GU8 uchSlotNo, GU8 uchRxEn, STGh3x2xAgcInfo *STGh3x2xAgcInfo)\r
+{\r
+    GU8 uchSetSuccess = 1;\r
+    for(GU8 uchRxCnt = 0; uchRxCnt < 4; uchRxCnt ++)\r
+    {\r
+        if(uchRxEn&(1 << uchRxCnt))\r
+        {\r
+            uchSetSuccess = 0;\r
+            for(GU8 uchChnlCnt = 0; uchChnlCnt < GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT; uchChnlCnt ++)\r
+            {\r
+                STGh3x2xNewAgcSubChnlRxInfo *pstSTGh3x2xNewAgcSubChnlRxInfo = &(g_pstGh3x2xNewAgcSubChnlRxInfoEntity[uchChnlCnt]);\r
+                if(0 ==  pstSTGh3x2xNewAgcSubChnlRxInfo->uchEn)\r
+                {\r
+                    pstSTGh3x2xNewAgcSubChnlRxInfo->uchEn = 1;\r
+                    pstSTGh3x2xNewAgcSubChnlRxInfo->uchSlotAdcNo = (uchSlotNo << 2) + uchRxCnt;\r
+                    //read current gain\r
+                    pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_TIA_GAIN_RX0 + uchRxCnt, uchSlotNo);\r
+                    GH3X2X_INFO_LOG("[NewAgc] Sub chnl current Gain = %d, Slot = %d, Rx = %d\r\n",pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain,uchSlotNo,uchRxCnt);\r
+                    pstSTGh3x2xNewAgcSubChnlRxInfo ->usTrigeUpLimitForBiggerGain = GH3x2xCalTrigerUpLimitForBiggerGain(pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain, uchSlotNo);\r
+                    GH3X2X_INFO_LOG("[NewAgc] usTrigeUpLimitForBiggerGain = %d, Slot = %d, Rx = %d\r\n",((GU32)pstSTGh3x2xNewAgcSubChnlRxInfo ->usTrigeUpLimitForBiggerGain)<<8,uchSlotNo,uchRxCnt);\r
+                    GH3X2X_StoreRxTiaGainAfterAgc(pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain, uchSlotNo, uchRxCnt, STGh3x2xAgcInfo->uchTiaGainAfterSoftAgc);\r
+                    uchSetSuccess = 1;\r
+                    break;\r
+                }\r
+            }\r
+            if(0 == uchSetSuccess)\r
+            {\r
+                GH3X2X_INFO_LOG("[NewAgc] Set new sub chnl fail !!! Slot = %d, Rx = %d\r\n",uchSlotNo,uchRxCnt);\r
+                while(1);\r
+            }\r
+        }\r
+    }\r
+    return uchSetSuccess;\r
+}\r
+#endif\r
+\r
+#if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0\r
+void GH3X2X_NewAgcSubChnlGainAdj(GU8* puchReadFifoBuffer, GU16 usFifoLen, STGh3x2xAgcInfo *STGh3x2xAgcInfo)\r
+{\r
+    for(GU8 uchChnlCnt = 0; uchChnlCnt < GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT; uchChnlCnt ++)\r
+    {    \r
+        GU16 usAnalysisDiscardLen;\r
+        GU16 usAnalysisEndLen;\r
+        GU8  uchSlotCnt;\r
+        GU8  uchSlotIdx;\r
+        GU8  uchAdcNo;\r
+        GU32 unTempTrigThd_L;\r
+        GU32 unTempTrigThd_H;\r
+        STGh3x2xNewAgcSubChnlRxInfo *pstSTGh3x2xNewAgcSubChnlRxInfo = &(g_pstGh3x2xNewAgcSubChnlRxInfoEntity[uchChnlCnt]);\r
+        uchSlotIdx = pstSTGh3x2xNewAgcSubChnlRxInfo ->uchSlotAdcNo >> 2;\r
+        uchAdcNo = pstSTGh3x2xNewAgcSubChnlRxInfo ->uchSlotAdcNo&0x03;\r
+        uchSlotCnt = GH3X2X_NewAgcFindSubChnlSlotInfo(uchSlotIdx);\r
+        GU16 usSampleRate = g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[uchSlotCnt].usSampleRate;\r
+        GU8 uchTiaGainLimit = g_pstGh3x2xNewAgcMainChnlInfoEntity[uchSlotCnt].uchTiaGainUpLimit;\r
+        usAnalysisDiscardLen = (usSampleRate<<1)/5;    //  2/5 Fs\r
+        usAnalysisEndLen = usAnalysisDiscardLen + usSampleRate * GH3X2X_NEW_AGC_SUB_CHNNL_ANAYLSIS_TIME_SEC;\r
+ \r
+        GH3X_AgcGetThreshold(g_pstGh3x2xNewAgcMainChnlInfoEntity[uchSlotCnt].uchSpo2ChnlIndex,&unTempTrigThd_H, &unTempTrigThd_L);    \r
+             \r
+        if(pstSTGh3x2xNewAgcSubChnlRxInfo ->uchEn)\r
+        {\r
+           // prevent unRawdataSum(GU32) overflow\r
+           if( (usAnalysisEndLen - usAnalysisDiscardLen) > 200 )  \r
+           {\r
+              usAnalysisDiscardLen = usAnalysisEndLen - 200;   // maximum number of accumulated rawdata is 200\r
+           }\r
+   \r
+            for (GU16 usIndex = 0; usIndex < usFifoLen; usIndex += GH3X2X_AFE_FIFO_RAWDATA_SIZE) \r
+            {\r
+                GU32 unFifoVal;\r
+                GU8  uchSlotAdcNo;\r
+                GU32 unDataRaw; \r
+                unFifoVal = GH3X2X_AFE_MAKEUP_DWORD(puchReadFifoBuffer[usIndex], puchReadFifoBuffer[usIndex + 1], \r
+                                                puchReadFifoBuffer[usIndex + 2], puchReadFifoBuffer[usIndex + 3]);\r
+                uchSlotAdcNo = ((unFifoVal >> 27)&0x0000001F);\r
+                unDataRaw = GH3X2X_RAWDATA_CLEAR_ALL_FLAG(unFifoVal);\r
+                if(uchSlotAdcNo == pstSTGh3x2xNewAgcSubChnlRxInfo ->uchSlotAdcNo)\r
+                {\r
+                    if(usAnalysisDiscardLen == pstSTGh3x2xNewAgcSubChnlRxInfo->usAnalysisCnt) //init\r
+                    {\r
+                        pstSTGh3x2xNewAgcSubChnlRxInfo ->unRawdataSum = 0;\r
+                        pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastLastRawdata = unDataRaw;\r
+                        pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastRawdata = unDataRaw;\r
+                        pstSTGh3x2xNewAgcSubChnlRxInfo ->usMoreThanUpLimitPointCnt = 0;\r
+                        pstSTGh3x2xNewAgcSubChnlRxInfo ->usMoreThanUpLimitPointCntForBiggerGain = 0;\r
+                    }\r
+                    if(pstSTGh3x2xNewAgcSubChnlRxInfo->usAnalysisCnt < usAnalysisEndLen)  //analysising\r
+                    {                \r
+                        GU32 unTempRawdata = GH32x2xMedSel(pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastLastRawdata, pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastRawdata, unDataRaw);\r
+                        if(usAnalysisDiscardLen == pstSTGh3x2xNewAgcSubChnlRxInfo->usAnalysisCnt)\r
+                        {\r
+                            GH3X2X_INFO_LOG("[NewAgc] sub chnl unTempRawdata  = %d, Slot = %d, rx = %d\r\n",unTempRawdata, uchSlotIdx, uchAdcNo);\r
+                        }\r
+                        pstSTGh3x2xNewAgcSubChnlRxInfo ->unRawdataSum += unTempRawdata;\r
+                        if(unTempRawdata > unTempTrigThd_H)\r
+                        {\r
+                            pstSTGh3x2xNewAgcSubChnlRxInfo->usMoreThanUpLimitPointCnt ++;\r
+                        }\r
+                        if((unTempRawdata >> 8) > pstSTGh3x2xNewAgcSubChnlRxInfo->usTrigeUpLimitForBiggerGain)\r
+                        {\r
+                            pstSTGh3x2xNewAgcSubChnlRxInfo->usMoreThanUpLimitPointCntForBiggerGain ++;\r
+                        }\r
+                        pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastLastRawdata = pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastRawdata;\r
+                        pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastRawdata = unDataRaw;\r
+                        pstSTGh3x2xNewAgcSubChnlRxInfo->usAnalysisCnt ++;                    \r
+                    }\r
+                    else //anlysis finished\r
+                    {\r
+                        GU32 unAvaRawdata;\r
+                        GU16 unRealAnaylsisNum = usAnalysisEndLen - usAnalysisDiscardLen;\r
+                        GU8  uchNextGain = 0xFF;\r
+                        GU8  uchCurrentGain = pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain;\r
+                        unAvaRawdata = pstSTGh3x2xNewAgcSubChnlRxInfo ->unRawdataSum/unRealAnaylsisNum;\r
+                        GH3X2X_INFO_LOG("[NewAgc] sub chnl rawdata ava  = %d,DownLimit = %d, Slot = %d, rx = %d\r\n",unAvaRawdata, unTempTrigThd_L,uchSlotIdx, uchAdcNo);\r
+                        GH3X2X_INFO_LOG("[NewAgc] usMoreThanUpLimitPointCnt  = %d,UpLimit = %d, Slot = %d, rx = %d\r\n",pstSTGh3x2xNewAgcSubChnlRxInfo ->usMoreThanUpLimitPointCnt, unTempTrigThd_H,uchSlotIdx, uchAdcNo);\r
+                        GH3X2X_INFO_LOG("[NewAgc] usMoreThanUpLimitPointCntForBiggerGain = %d,UpLimit = %d, Slot = %d, rx = %d\r\n",pstSTGh3x2xNewAgcSubChnlRxInfo ->usMoreThanUpLimitPointCntForBiggerGain, ((GU32)pstSTGh3x2xNewAgcSubChnlRxInfo->usTrigeUpLimitForBiggerGain)<<8, uchSlotIdx, uchAdcNo);\r
+                        if(pstSTGh3x2xNewAgcSubChnlRxInfo ->usMoreThanUpLimitPointCnt > (unRealAnaylsisNum >> 3))  // 1/8 points is bigger than trige up limit\r
+                        {\r
+                            if(uchCurrentGain > 0)\r
+                            {\r
+                                uchNextGain = uchCurrentGain - 1;\r
+                            }\r
+                        }\r
+                        if((pstSTGh3x2xNewAgcSubChnlRxInfo ->usMoreThanUpLimitPointCntForBiggerGain < (unRealAnaylsisNum >> 3))&&(unAvaRawdata < unTempTrigThd_L))\r
+                        {\r
+                            if(uchCurrentGain < uchTiaGainLimit)\r
+                            {\r
+                                uchNextGain = uchCurrentGain + 1;\r
+                            }\r
+                        }\r
+                        if(0xFF != uchNextGain)\r
+                        {                            \r
+                            GH3X2X_INFO_LOG("[NewAgc] sub chnl gain change: NewGain = %d, OldGain = %d, Slot = %d, rx = %d\r\n",uchNextGain,uchCurrentGain, uchSlotIdx, uchAdcNo);\r
+                            GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_TIA_GAIN_RX0 + uchAdcNo, uchSlotIdx, uchNextGain);\r
+                            pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain = uchNextGain;\r
+                            pstSTGh3x2xNewAgcSubChnlRxInfo ->usTrigeUpLimitForBiggerGain = GH3x2xCalTrigerUpLimitForBiggerGain(uchNextGain, uchSlotIdx);                                    \r
+                            GH3X2X_StoreRxTiaGainAfterAgc(uchNextGain, uchSlotIdx, uchAdcNo, STGh3x2xAgcInfo->uchTiaGainAfterSoftAgc);\r
+                        }\r
+                        pstSTGh3x2xNewAgcSubChnlRxInfo->usAnalysisCnt = 0;    \r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+#endif\r
+\r
+\r
+/*********************************************self-test function start*****************************************/\r
+#define GH3X2X_SPO2_SELF_TEST 0\r
+\r
+#if GH3X2X_SPO2_SELF_TEST\r
+const GU32 g_uchSpo2AgcSelftestSlotAdc = 0x01;  //slot0, adc1\r
+const GU32 g_usSpo2AgcFifoLen = 25*4;\r
+const GU32 g_unSpo2AgcRawdata[] = \r
+{\r
+    10111744,9818116,10074798,9832931,10038819,9812989,10067119,9791632,10220862,9843610,9888564,9974512,10041146,10117796,9858828,10260863,9900963,10159857,10259720,10054459,10247477,9957985,10078474,9916146,9821879\r
+};\r
+\r
+GU8 g_uchSpo2AgcFifoBuffer[4*100];\r
+\r
+void GH3X2X_Spo2AgcFifoDataGen(void)\r
+{\r
+    for (GU16 usIndex = 0; usIndex < g_usSpo2AgcFifoLen; usIndex += GH3X2X_AFE_FIFO_RAWDATA_SIZE) \r
+    {\r
+        if(usIndex >= sizeof(g_uchSpo2AgcFifoBuffer))\r
+        {\r
+            break;\r
+        }\r
+        g_uchSpo2AgcFifoBuffer[usIndex + 0] = (g_uchSpo2AgcSelftestSlotAdc<<3);\r
+        g_uchSpo2AgcFifoBuffer[usIndex + 1] = (0x000000FF&(g_unSpo2AgcRawdata[usIndex/4] >> 16));\r
+        g_uchSpo2AgcFifoBuffer[usIndex + 2] = (0x000000FF&(g_unSpo2AgcRawdata[usIndex/4] >> 8));\r
+        g_uchSpo2AgcFifoBuffer[usIndex + 3] = (0x000000FF&(g_unSpo2AgcRawdata[usIndex/4] >> 0));\r
+    }\r
+}\r
+#endif\r
+/*********************************************self-test function end*****************************************/\r
+\r
+\r
+/****************************************************************\r
+* Description: calculate mean value of main channel  \r
+* Input:  rawdata  \r
+* Return: none\r
+******************************************************************/\r
+static void GH3X2X_NewAgcMainChnlMeanValueCal(GU8* puchReadFifoBuffer, GU16 usFifoLen, GU32 *punRawdataMean, GU8 *pAdjFlag)\r
+{\r
+    for(GU8 uchSlotCnt = 0; uchSlotCnt < GH3X2X_NEW_AGC_SLOT_NUM_LIMIT; uchSlotCnt ++)\r
+    {\r
+        STGh3x2xNewAgcMainChnlInfo *pstAgcMainChnlInfo = &g_pstGh3x2xNewAgcMainChnlInfoEntity[uchSlotCnt];\r
+        GU8 uchMainChnlSlotAdcNo = pstAgcMainChnlInfo ->uchSlotAdc;\r
+        \r
+        if(pstAgcMainChnlInfo ->uchEnable)   // is  enabled  slot\r
+        {        \r
+            GU32 unTemp_Trig_H_Thd;    \r
+            GU32 unTemp_Trig_L_Thd;    \r
+            GU32 unTemp_Ideal_value;\r
+            GU16 usAnalysisEndLen; \r
+            GU16 usAnalysisDiscardLenAdjust = 0;\r
+            GU16 usAnalysisDiscardLenTrige;\r
+            GU32 TrigeMean  = 0; \r
+\r
+            if(pstAgcMainChnlInfo->uchSpo2ChnlIndex) // is  spo2 slot\r
+            {\r
+                unTemp_Ideal_value= g_unNewAgcSpo2Ideal_value;\r
+            }else\r
+            {                        \r
+                unTemp_Ideal_value= g_unNewAgcGeneIdeal_value;\r
+            }\r
+            GH3X_AgcGetThreshold( pstAgcMainChnlInfo->uchSpo2ChnlIndex, &unTemp_Trig_H_Thd, &unTemp_Trig_L_Thd);  \r
+                      \r
+            STGh3x2xNewAgcMainChnlMeanInfo *pstNewAgcMainChnlMeanInfo = &g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[uchSlotCnt];\r
+            STGh3x2xNewAgcMainChnlIdaelAdjInfo *pstNewAgcMainChnlIdaelAdjInfo = &g_pstGh3x2xNewAgcMainChnlIdaelAdjInfoEntity[uchSlotCnt];\r
+            GU16 usSampleRate =  pstNewAgcMainChnlMeanInfo->usSampleRate;\r
+            usAnalysisEndLen = (usSampleRate<<2)/5;            // 4/5 Fs  \r
+            usAnalysisDiscardLenTrige =  (usSampleRate<<1)/5;  // drop the first 2/5 data    \r
+            //have agc motion at last fifo read period or first init                        \r
+            if(pstNewAgcMainChnlMeanInfo->uchHaveAgcAtLastReadPrd)   \r
+            {\r
+                usAnalysisDiscardLenAdjust = (usSampleRate<<1)/5;  // drop the first 2/5 data\r
+                //// After AGC, the previous data is drop to calcluate precise mean\r
+                if(!pstNewAgcMainChnlMeanInfo->uchDropFlag)\r
+                {  // The frame count is only cleared for the first time to prevent data num cannot to be SampleRate\r
+                    pstNewAgcMainChnlMeanInfo->usAnalysisCnt = 0;  \r
+                    pstNewAgcMainChnlMeanInfo->uchDropFlag = 1;\r
+                }         \r
+            }\r
+            //The data fluctuates when initializing the early stage  \r
+            if(!pstNewAgcMainChnlIdaelAdjInfo->uchIniteFirst)  \r
+            {\r
+                usAnalysisDiscardLenAdjust =  (usSampleRate<<1)/5;  // drop the first 2/5 data\r
+            }\r
+\r
+           // prevent unSumAdjust(GU32) overflow\r
+           if( (usAnalysisEndLen - usAnalysisDiscardLenAdjust) > 200 )\r
+           {\r
+              usAnalysisDiscardLenAdjust = usAnalysisEndLen - 200; // maximum number of accumulated rawdata is 200\r
+           }\r
+           \r
+           if( (usAnalysisEndLen - usAnalysisDiscardLenTrige) > 200 )\r
+           {\r
+              usAnalysisDiscardLenTrige = usAnalysisEndLen - 200;\r
+           }\r
+\r
+            for (GU16 usIndex = 0; usIndex < usFifoLen; usIndex += GH3X2X_AFE_FIFO_RAWDATA_SIZE) \r
+            {\r
+                GU32 unFifoVal;\r
+                GU8  uchSlotAdcNo;\r
+                GU32 unDataRaw; \r
+                unFifoVal = GH3X2X_AFE_MAKEUP_DWORD(puchReadFifoBuffer[usIndex], puchReadFifoBuffer[usIndex + 1], \r
+                                                puchReadFifoBuffer[usIndex + 2], puchReadFifoBuffer[usIndex + 3]);\r
+                uchSlotAdcNo = ((unFifoVal >> 27)&0x0000001F);\r
+                unDataRaw = GH3X2X_RAWDATA_CLEAR_ALL_FLAG(unFifoVal); \r
+                //GH3X2X_INFO_LOG_SPO2("uchSlotAdcNo = %d\r\n",uchSlotAdcNo);\r
+                //GH3X2X_INFO_LOG_SPO2("uchMainChnlSlotAdcNo = %d\r\n",uchMainChnlSlotAdcNo);\r
+                if(uchSlotAdcNo == uchMainChnlSlotAdcNo)\r
+                {\r
+                    // begin Saturation judge   \r
+                    {  \r
+                        GU16 usSat_Check_Num_Max =   (usSampleRate<<2) + usSampleRate;   //// 5 seconds window\r
+                        g_pstGh3x2xNewAgcMainChnlSat.Sat_CheckCnt[uchSlotCnt]++;\r
+                        if( unDataRaw > unTemp_Trig_H_Thd)\r
+                        {\r
+                            g_pstGh3x2xNewAgcMainChnlSat.Sat_cnt[uchSlotCnt]++;\r
+                        }\r
+                        //// as soon as posible set the Saturation flag \r
+                        if( g_pstGh3x2xNewAgcMainChnlSat.Sat_cnt[uchSlotCnt] >= (usSat_Check_Num_Max>>4) ) // about 8% of all checked data\r
+                        {\r
+                            g_pstGh3x2xNewAgcMainChnlSat.Sat_flag |= (1<<uchSlotCnt);  \r
+                            g_pstGh3x2xNewAgcMainChnlSat.Sat_cnt[uchSlotCnt] = 0; \r
+                        }     \r
+\r
+                        if(g_pstGh3x2xNewAgcMainChnlSat.Sat_CheckCnt[uchSlotCnt] >= usSat_Check_Num_Max ) \r
+                        {                                      \r
+                            g_pstGh3x2xNewAgcMainChnlSat.Sat_cnt[uchSlotCnt] = 0;\r
+                            g_pstGh3x2xNewAgcMainChnlSat.Sat_CheckCnt[uchSlotCnt] = 0;  \r
+                        }                                 \r
+                    } \r
+                    // end Saturation judge   \r
+                    \r
+                    //// begin mean calculate    \r
+                    ////GH3X2X_INFO_LOG_PARAM("slot = %d, uchSlotAdcNo = %d\r\n",uchSlotCnt,uchSlotAdcNo);\r
+                                     \r
+                   if(usAnalysisDiscardLenAdjust == pstNewAgcMainChnlMeanInfo->usAnalysisCnt) //init\r
+                    {\r
+                        pstNewAgcMainChnlMeanInfo->unSumAdjust =  0;\r
+                        pstNewAgcMainChnlMeanInfo->unMaxRawdata =  0;      \r
+                        pstNewAgcMainChnlMeanInfo->unMinRawdata =  16777216;\r
+                    }\r
+                                        \r
+                    if(usAnalysisDiscardLenTrige == pstNewAgcMainChnlMeanInfo->usAnalysisCnt) //init\r
+                    {\r
+                        pstNewAgcMainChnlMeanInfo->unSumTrige  =  0;\r
+                    }    \r
+                                        \r
+                    if(pstNewAgcMainChnlMeanInfo->usAnalysisCnt  < usAnalysisEndLen)   //analysising\r
+                    {\r
+                    pstNewAgcMainChnlMeanInfo->unSumAdjust +=  unDataRaw;\r
+                    pstNewAgcMainChnlMeanInfo->unSumTrige +=  unDataRaw;\r
+                    pstNewAgcMainChnlMeanInfo->usAnalysisCnt++;   \r
+                    pstNewAgcMainChnlMeanInfo->unMaxRawdata = ((unDataRaw > pstNewAgcMainChnlMeanInfo->unMaxRawdata)? unDataRaw: pstNewAgcMainChnlMeanInfo->unMaxRawdata ); // Max of  rawdata\r
+                    pstNewAgcMainChnlMeanInfo->unMinRawdata = ((unDataRaw < pstNewAgcMainChnlMeanInfo->unMinRawdata)? unDataRaw: pstNewAgcMainChnlMeanInfo->unMinRawdata ); // Min of  rawdata\r
+                    }\r
+                    else //anlysis finished   calculate mean and judge whether AGC\r
+                    {    \r
+                        // mean value to calculate gain and current\r
+                        if(usAnalysisEndLen > usAnalysisDiscardLenAdjust)\r
+                        {\r
+                            punRawdataMean[uchSlotCnt] = pstNewAgcMainChnlMeanInfo->unSumAdjust/(usAnalysisEndLen - usAnalysisDiscardLenAdjust);    \r
+                            TrigeMean = pstNewAgcMainChnlMeanInfo->unSumTrige / (usAnalysisEndLen - usAnalysisDiscardLenTrige);\r
+                        }else //  The normal case will not be executed, in case the division by 0 in abnormal case\r
+                        {\r
+                            punRawdataMean[uchSlotCnt] =   unDataRaw; \r
+                            TrigeMean =   unDataRaw; \r
+                        }\r
+                        pstNewAgcMainChnlMeanInfo ->unRawdataMean = punRawdataMean[uchSlotCnt];\r
+                        pstNewAgcMainChnlMeanInfo->usAnalysisCnt=0;\r
+                        // The mean calculation key variable is cleared    (Prevent mean calculation from being too small:Accumulation lost some data, but numble of raw is all)    \r
+                        usAnalysisDiscardLenAdjust = 0; \r
+                        pstNewAgcMainChnlMeanInfo->uchHaveAgcAtLastReadPrd = 0; //  clear  after caculate mean!!!       \r
+                        //// end mean calculate\r
+\r
+                        ///////////////////// whether AGC  and adjust the mean value to calculate gain and current\r
+                        if( (TrigeMean < unTemp_Trig_L_Thd) || (TrigeMean > unTemp_Trig_H_Thd) )\r
+                        {\r
+                            *pAdjFlag |= (1<<uchSlotCnt);  //need adjust gain and current \r
+                        }\r
+                        \r
+                        if( g_pstGh3x2xNewAgcMainChnlSat.Sat_flag & (1<<uchSlotCnt)) //if the channel is saturation\r
+                        {\r
+                            GU32 unTempMean = 0;         //Pay attention to initialization of local variables\r
+                            if( pstNewAgcMainChnlMeanInfo->unMaxRawdata > unTemp_Trig_H_Thd)\r
+                            {\r
+                                /////////// Pay attention to data truncation, use 64-bi\r
+                                unTempMean =   (GS64)unTemp_Ideal_value*(GS64)(pstNewAgcMainChnlMeanInfo->unMaxRawdata)/15099494;  // to adjust the max data to (0.8*2^23 + 2^23)\r
+                                *pAdjFlag |= (1<<uchSlotCnt);  //need adjust gain and current \r
+                            }\r
+                            \r
+                            if( punRawdataMean[uchSlotCnt] > unTemp_Ideal_value)\r
+                            {\r
+                                // adjust the mean value to calculate gain and current (reduce the DC amount)\r
+                                punRawdataMean[uchSlotCnt] = ( (punRawdataMean[uchSlotCnt]>unTempMean)? punRawdataMean[uchSlotCnt]:unTempMean );\r
+                                *pAdjFlag |= (1<<uchSlotCnt);  //need adjust gain and current \r
+                            } \r
+                            else if( pstNewAgcMainChnlMeanInfo->unMaxRawdata > unTemp_Trig_H_Thd)\r
+                            {\r
+                                punRawdataMean[uchSlotCnt] = unTempMean; //  Increasing the mean value to reduce the DC amount\r
+                            } \r
+                        }\r
+                        ////////////////////////////////////////////////////\r
+                        //////////////begin ideal value adjust \r
+                        if( (!((*pAdjFlag) & (1<<uchSlotCnt))) && (!( g_pstGh3x2xNewAgcMainChnlSat.Sat_flag & (1<<uchSlotCnt))))//if the channel not adjust and satuartion\r
+                        {\r
+                            //// The deviation of the mean and the ideal target value is above 1/16  and   Data fluctuation is less than a certain value\r
+                            if(((pstNewAgcMainChnlMeanInfo->unRawdataMean< ((unTemp_Ideal_value*(g_uchAgcConvergence_level-1))/g_uchAgcConvergence_level) ) \\r
+                                || (pstNewAgcMainChnlMeanInfo->unRawdataMean > ((unTemp_Ideal_value*(g_uchAgcConvergence_level+1))/g_uchAgcConvergence_level))) \\r
+                                &&( 10*pstNewAgcMainChnlMeanInfo->unMaxRawdata< 12*pstNewAgcMainChnlMeanInfo->unMinRawdata) ) \r
+                            {\r
+                                if( !pstNewAgcMainChnlIdaelAdjInfo->uchIniteFirst ) //// Inite First time \r
+                                {\r
+                                    pstNewAgcMainChnlIdaelAdjInfo->uchIniteFirst = 1;\r
+                                    *pAdjFlag |= (1<<uchSlotCnt);  //need adjust gain and current \r
+                                }\r
+                                else\r
+                                {\r
+                                    pstNewAgcMainChnlIdaelAdjInfo->uchSeconsCnt++;\r
+                                    if(pstNewAgcMainChnlIdaelAdjInfo->uchSeconsCnt >= 19)\r
+                                    {\r
+                                        *pAdjFlag |= (1<<uchSlotCnt);  //need adjust gain and current \r
+                                        pstNewAgcMainChnlIdaelAdjInfo->uchSeconsCnt  = 0; \r
+                                    }    \r
+                                }             \r
+                            }\r
+                            else\r
+                            {\r
+                                 pstNewAgcMainChnlIdaelAdjInfo->uchSeconsCnt  = 0;\r
+                            }                    \r
+                        }\r
+                        else\r
+                        {\r
+                             pstNewAgcMainChnlIdaelAdjInfo->uchSeconsCnt  = 0;\r
+                        }\r
+                        pstNewAgcMainChnlIdaelAdjInfo->uchIniteFirst = 1;  //// Must be set to 1 after the first second!!!    \r
+                        ////end ideal value adjust \r
+                        //GH3X2X_INFO_LOG_PARAM("Mean cal: Slot_num = %d, Rawmean = %d, Adjmean = %d, TrigeMean = %d, AdjFlag= %d\r\n", uchSlotCnt,pstNewAgcMainChnlMeanInfo->unRawdataMean, punRawdataMean[uchSlotCnt]);\r
+                        //GH3X2X_INFO_LOG_PARAM("Sat flag: SatCnt = %d, SatCheck = %d, CheckMaxNum = %d, Satflag = %d\r\n", g_pstGh3x2xNewAgcMainChnlSat.Sat_cnt[uchSlotCnt], g_pstGh3x2xNewAgcMainChnlSat.Sat_CheckCnt[uchSlotCnt], g_pstGh3x2xNewAgcMainChnlSat.Sat_Check_Num_Max[uchSlotCnt], g_pstGh3x2xNewAgcMainChnlSat.Sat_flag);\r
+                        //GH3X2X_INFO_LOG_PARAM("Ideal adjust: SeconsCnt = %d\r\n", pstNewAgcMainChnlIdaelAdjInfo->uchSeconsCnt);\r
+                        //GH3X2X_INFO_LOG_PARAM("Adj flag: Slot_num = %d, Trigmean = %d, L_Thd = %d, H_Thd = %d, Adjflag = %d\r\n", uchSlotCnt,TrigeMean, unTemp_Trig_L_Thd, unTemp_Trig_H_Thd, *pAdjFlag);                                     \r
+                        g_pstGh3x2xNewAgcMainChnlSat.Sat_flag &= (~(1<<uchSlotCnt)) ; ////clear the Sat flag  \r
+\r
+                    }\r
+                }  \r
+             }\r
+        }\r
+        \r
+    }\r
+}\r
+\r
+/**\r
+ * @fn     GU8 GH3X2X_NewAgcCalDrvCurrentAndGain(GU32 CurRawdata, GU32 IdealRawdata, STGh3x2xNewAgcMainChnlInfo *pstAgcMainChnlInfo, GU8* puchIdealDrvCurrent, GU8* puchIdealGain)\r
+ *\r
+ * @brief  mark abnormal chnl\r
+ *\r
+ * @attention   \r
+ *\r
+ * @param[in]   CurRawdata, IdealRawdata, uchMainChnlInfoIndex\r
+ * @param[out]  puchIdealDrvCurrent, puchIdealGain\r
+ *\r
+ * @return  0:DrvCurrent or gain will NOT change  1: DrvCurrent or gain will  change\r
+ */\r
+GU8 GH3X2X_NewAgcCalDrvCurrentAndGain(GU32 CurRawdata, GU8 uchMainChnlInfoIndex,  GU8* puchIdealDrvCurrent, GU8* puchIdealGain)\r
+{\r
+    STGh3x2xNewAgcMainChnlInfo *pstAgcMainChnlInfo = &g_pstGh3x2xNewAgcMainChnlInfoEntity[uchMainChnlInfoIndex];\r
+    STGh3x2xNewAgcMainChnlMeanInfo *pstMainChnlExtralInfo = &g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[uchMainChnlInfoIndex];\r
+\r
+    GU8 uchDefaultGain = pstAgcMainChnlInfo->uchBakTiaGain;\r
+    GU8 uchGainUpLimit = pstAgcMainChnlInfo->uchTiaGainUpLimit;\r
+    GU8 uchLedCurrentMin = pstAgcMainChnlInfo->uchBakRegLedCurrentMin;\r
+    GU8 uchLedCurrentMax = pstAgcMainChnlInfo->uchBakRegLedCurrentMax;\r
+    GU8 uchCurrentDrv = pstAgcMainChnlInfo->uchCurrentDrv;\r
+    GU8 uchCurrentTiaGain = pstAgcMainChnlInfo->uchCurrentTiaGain;\r
+ \r
+    GU8 uchNewGain = uchDefaultGain;\r
+    GU32 unIdealRawdata_no;\r
+    GU32 unTempDrvCurrent;\r
+    GU8 uchChangeFlag = 0;  //bit0: drv current flag  bit1: gain flag\r
+    GU8 uchCalFinish = 0;\r
+    GU32 unTrigUpLimit;\r
+    GU8  unCalNum = 12;\r
+  \r
+    if(0 != pstAgcMainChnlInfo->uchSpo2ChnlIndex) // is  spo2 slot\r
+    {\r
+        unTrigUpLimit = g_unNewAgcSpo2Trig_H_Thd;\r
+        unIdealRawdata_no= g_unNewAgcSpo2Ideal_value - 8388608;\r
+    }else\r
+    {\r
+        unTrigUpLimit = g_unNewAgcGeneTrig_H_Thd;\r
+        unIdealRawdata_no = g_unNewAgcGeneIdeal_value - 8388608;\r
+    }\r
+    \r
+    //GH3X2X_INFO_LOG_PARAM("Drv cal: UpLimit = %d, Mean = %d, LastMean = %d\r\n",unTrigUpLimit, pstMainChnlExtralInfo->unRawdataMean, pstMainChnlExtralInfo->unLastRawdataMean);\r
+    // reduce rawdata as soon as posible\r
+    if((unTrigUpLimit < pstMainChnlExtralInfo->unRawdataMean)&&(unTrigUpLimit < pstMainChnlExtralInfo->unLastRawdataMean)&&(uchCurrentTiaGain > 0)) \r
+    {             \r
+       uchNewGain = 0;  \r
+       unTempDrvCurrent =  uchLedCurrentMin;\r
+       uchCalFinish = 1;\r
+    }\r
+    pstMainChnlExtralInfo ->unLastRawdataMean = pstMainChnlExtralInfo ->unRawdataMean;\r
+         \r
+    if(0 == uchCalFinish)\r
+    {\r
+        //remove offset\r
+        if(CurRawdata > (8388608 + 2048))  //// Can't open DC Cance !!!\r
+        {\r
+            CurRawdata -= 8388608;\r
+        }\r
+        else\r
+        {\r
+            //The value may be less than 2^23, preventing division by 0\r
+            CurRawdata = 2048;  // Take an appropriately large number to prevent calculated DRV current overflow 32bit\r
+        }\r
+        //Rawdata stretch  (The principle of magnification: the mean divided by the ideal target value is the data reduction factor )\r
+        if(CurRawdata < 8000000)\r
+        {\r
+        }\r
+        else if(CurRawdata < 8100000)\r
+        {\r
+            CurRawdata = 8000000 + (CurRawdata - 8000000)*6;\r
+        }\r
+        else if(CurRawdata < 8200000)\r
+        {\r
+            CurRawdata = 8000000 + ((CurRawdata - 8000000)<<3);\r
+        }\r
+        else\r
+        {\r
+            // The more saturated the data, the bigger the stretch, the key is that the data is really saturated\r
+            CurRawdata = 8000000 + (CurRawdata - 8000000)*14;   //  Blood oxygen drops 1 times, heart rate drops 2.5 times  \r
+        }\r
+\r
+        //find new drv current and gain\r
+        do\r
+        {   \r
+            unTempDrvCurrent = (GS64)(((GU32)uchCurrentDrv*(GU32)g_usGH3x2xTiaGainR[uchCurrentTiaGain]))* \\r
+            (GS64)unIdealRawdata_no/g_usGH3x2xTiaGainR[uchNewGain]/CurRawdata;\r
+\r
+#if 0\r
+           //GH3X2X_INFO_LOG_PARAM("Drv cal %d: CurrentDrv = %d, CurrentGain = %d, IdealRawdata_no = %d\r\n",uchMainChnlInfoIndex, uchCurrentDrv, uchCurrentTiaGain, unIdealRawdata_no);\r
+           //GH3X2X_INFO_LOG_PARAM("Drv cal %d: unTempDrvCurrent = %d, uchNewGain = %d, Meanraw = %d, CurRawdata = %d\r\n",uchMainChnlInfoIndex,unTempDrvCurrent, uchNewGain, pstMainChnlExtralInfo->unRawdataMean, CurRawdata);\r
+#endif\r
+          \r
+            if(unTempDrvCurrent > uchLedCurrentMax)  //drv is too big, need increase gain\r
+            {\r
+                if(uchNewGain < uchGainUpLimit)\r
+                {\r
+                    uchNewGain ++ ;\r
+                }\r
+                else\r
+                {\r
+                    unTempDrvCurrent = uchLedCurrentMax;\r
+                    break;\r
+                }\r
+            }\r
+            else if(unTempDrvCurrent < uchLedCurrentMin)  //drv is too small, need dncrease gain\r
+            {\r
+                if(uchNewGain > 0)\r
+                {\r
+                    uchNewGain -- ;\r
+                }\r
+                else\r
+                {\r
+                    unTempDrvCurrent = uchLedCurrentMin;\r
+                    break;\r
+                }\r
+            }\r
+            else   //got right drv\r
+            {\r
+                break;\r
+            }\r
+            unCalNum --;\r
+        }\r
+        while (unCalNum);\r
+    }\r
+\r
+    puchIdealDrvCurrent[0] = (GU8)unTempDrvCurrent;\r
+    puchIdealGain[0] = (GU8)uchNewGain;\r
+\r
+    if(puchIdealDrvCurrent[0] != uchCurrentDrv)\r
+    {\r
+        uchChangeFlag |= 0x01;\r
+        //GH3X2X_INFO_LOG_PARAM("Drv change %d: CurrentDrv = %d,  IdealDrv = %d\r\n",uchMainChnlInfoIndex, uchCurrentDrv, puchIdealDrvCurrent[0]);\r
+    }\r
+    if(puchIdealGain[0] != uchCurrentTiaGain)\r
+    {\r
+        uchChangeFlag |= 0x02;\r
+        //GH3X2X_INFO_LOG_PARAM("Gain change %d: CurrentGain = %d,  IdealGain = %d\r\n",uchMainChnlInfoIndex, uchCurrentTiaGain, puchIdealGain[0]);\r
+    }\r
+        \r
+    return uchChangeFlag;\r
+}\r
+\r
+GU8 NewAgcMainChelFlag = 0;\r
+\r
+void GH3X2X_NewAgcMainChnlPro(GU8* puchReadFifoBuffer, GU16 usFifoLen, STGh3x2xAgcInfo *STGh3x2xAgcInfo)\r
+{\r
+    GU32 unNewAgcRawdataMeanChnl[8] = {0};\r
+    GU8 uchAdjFlag = 0;     // Local variables used as judgments must be initialized to 0\r
+    GU8 uchNewDrvCurrent;\r
+    GU8 uchNewGain;    \r
+    GU8 uchChangeFlag = 0;  //bit0: drv current flag  bit1: gain flag\r
+    \r
+    if(0 == GH3X2X_NEW_AGC_SLOT_NUM_LIMIT)\r
+    {\r
+        return;\r
+    }\r
+\r
+#if GH3X2X_SPO2_SELF_TEST\r
+\r
+    GH3X2X_Spo2AgcFifoDataGen();\r
+    puchReadFifoBuffer = g_uchSpo2AgcFifoBuffer;\r
+    usFifoLen = g_usSpo2AgcFifoLen;\r
+#endif\r
+    \r
+            \r
+    GH3X2X_NewAgcMainChnlMeanValueCal( puchReadFifoBuffer,usFifoLen,unNewAgcRawdataMeanChnl,&uchAdjFlag); // caculate mean and whther adjust gain  current \r
+               \r
+    for(GU8 uchSlotCnt = 0; uchSlotCnt < GH3X2X_NEW_AGC_SLOT_NUM_LIMIT; uchSlotCnt ++)\r
+    {\r
+        if( uchAdjFlag & (1<<uchSlotCnt)) // need to AGC\r
+        {\r
+            STGh3x2xNewAgcMainChnlInfo *pstAgcMainChnlInfo = &g_pstGh3x2xNewAgcMainChnlInfoEntity[uchSlotCnt];\r
+            uchChangeFlag = GH3X2X_NewAgcCalDrvCurrentAndGain(unNewAgcRawdataMeanChnl[uchSlotCnt], uchSlotCnt, &uchNewDrvCurrent,&uchNewGain);\r
+            GU8  uchSlotIdx = ((pstAgcMainChnlInfo ->uchSlotAdc >> 2) & 0x0f);\r
+            if(uchChangeFlag&0x02)  //write tia gain to chip\r
+            {    \r
+                GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_TIA_GAIN_RX0 + pstAgcMainChnlInfo ->uchBakRegAgcSrc, uchSlotIdx, uchNewGain);    \r
+                pstAgcMainChnlInfo->uchCurrentTiaGain = uchNewGain;\r
+                GH3X2X_StoreRxTiaGainAfterAgc(uchNewGain, uchSlotIdx, pstAgcMainChnlInfo ->uchBakRegAgcSrc, STGh3x2xAgcInfo->uchTiaGainAfterSoftAgc);\r
+            }\r
+            if(uchChangeFlag&0x01)  //write drv current to chip\r
+            {\r
+                //change drv0/1\r
+                pstAgcMainChnlInfo ->uchCurrentDrv = uchNewDrvCurrent;\r
+                \r
+                if((pstAgcMainChnlInfo ->uchBakRegAgcEn)&0x01)\r
+                {\r
+                    GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_DRV0, uchSlotIdx, uchNewDrvCurrent);    \r
+                                                                               GH3X2X_StoreDrvCurrentAfterAgc(pstAgcMainChnlInfo ->uchCurrentDrv, uchSlotIdx,0,STGh3x2xAgcInfo->uchDrvCurrentAfterSoftAgc); \r
+                }\r
+                if((pstAgcMainChnlInfo ->uchBakRegAgcEn)&0x02)\r
+                {\r
+                    GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_DRV1, uchSlotIdx, uchNewDrvCurrent);    \r
+                                                                               GH3X2X_StoreDrvCurrentAfterAgc(pstAgcMainChnlInfo ->uchCurrentDrv, uchSlotIdx,1,STGh3x2xAgcInfo->uchDrvCurrentAfterSoftAgc);  \r
+                }\r
+                #if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0\r
+                GH3x2xNewAgcSubChnlClearAnalysisCntAndSetGain(uchSlotIdx, 0x0F, 0xFF); //clear all rx analysis cnt in this slot\r
+                #endif\r
+            }\r
+            if(uchChangeFlag)\r
+            {\r
+                g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[uchSlotCnt].uchHaveAgcAtLastReadPrd = 1; // current or  gain change at last time\r
+                g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[uchSlotCnt].uchDropFlag = 0;\r
+                NewAgcMainChelFlag |= (1<<uchSlotCnt); // ADjFlag write to CSV file\r
+            }                          \r
+        }                   \r
+    }     \r
+}\r
+\r
+#if  __SUPPORT_SOFT_AGC_CONFIG__\r
+/**\r
+ * @fn     static void GH3X2X_LedAgcInit(STGh3x2xAgcInfo *STGh3x2xAgcInfo)\r
+ * \r
+ * @brief  init led agc\r
+ *\r
+ * @attention   just use to show function support\r
+ *\r
+ * @param[in]   None\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_LedAgcInit(STGh3x2xAgcInfo *STGh3x2xAgcInfo)\r
+{\r
+               GH3X2X_RecordAgcInfo(); //record agc info\r
+    GH3x2xNewAgcChnlInfoInit(STGh3x2xAgcInfo);\r
+}\r
+/**\r
+ * @fn     void GH3X2X_LedAgcPramWrite(GU16 usRegVal, GU16 usRegPosi)\r
+ *\r
+ * @brief  write AGC parameter\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   usRegVal         reg value\r
+ * @param[in]   uchRegPosi         reg posi\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_LedAgcPramWrite(GU16 usRegVal, GU16 usRegPosi)\r
+{\r
+\r
+    GU16 usByteOffset;\r
+    GU8 uchByteVal;\r
+    GU8 uchByteCnt;\r
+    for(uchByteCnt = 0; uchByteCnt < 2; uchByteCnt ++)\r
+    {\r
+        uchByteVal = ((usRegVal >> (8*uchByteCnt))&0x00FF);\r
+        usByteOffset = (usRegPosi * 2) + uchByteCnt;\r
+        if(usByteOffset < sizeof(g_stSoftAgcCfg))\r
+        {\r
+            GH3X2X_Memcpy(((GU8 *)(&g_stSoftAgcCfg)) + usByteOffset, (GU8*)(&uchByteVal), 1);\r
+        }      \r
+    }\r
+}\r
+\r
+/**\r
+ * @fn  void GH3X2X_LedAgcReset(void)\r
+ *\r
+ * @brief   reset agc parameter\r
+ *\r
+ * @attention    None\r
+ *\r
+ * @param[in]    None\r
+ * @param[out]   None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_LedAgcReset(void)\r
+{\r
+    GH3X2X_Memset(&g_stSoftAgcCfg, 0, sizeof(STSoftAgcCfg));\r
+    GH3x2xNewAgcModuleReset();\r
+}\r
+\r
+/**\r
+ * @fn     void GH3X2X_LedAgcProcess(GU8* puchReadFifoBuffer, GU16 usFifoLen)\r
+ * \r
+ * @brief  led agc process function\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   puchReadFifoBuffer         pointer to read fifo data buffer\r
+ * @param[in]   usFifoLen           read fifo data buffer length\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+\r
+void GH3X2X_LedAgcProcess(GU8* puchReadFifoBuffer, GU16 usFifoLen, STGh3x2xAgcInfo *STGh3x2xAgcInfo)\r
+{\r
+               GH3X2X_UpdateAgcInfo();\r
+    if(usFifoLen==0)\r
+    {\r
+        return;\r
+    }\r
+    \r
+    GH3X2X_NewAgcMainChnlPro(puchReadFifoBuffer, usFifoLen,STGh3x2xAgcInfo);\r
+    \r
+#if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0\r
+    GH3X2X_NewAgcSubChnlGainAdj(puchReadFifoBuffer, usFifoLen,STGh3x2xAgcInfo);\r
+#endif\r
+               \r
+}\r
+#endif\r
+#endif\r
+/********END OF FILE********* Copyright (c) 2003 - 2022, Goodix Co., Ltd. ********/\r
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_demo.c b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_demo.c
new file mode 100644 (file)
index 0000000..211b1e0
--- /dev/null
@@ -0,0 +1,104 @@
+/*\r
+ * @Author: penglei 1624952103@qq.com\r
+ * @Date: 2025-01-13 11:45:20\r
+ * @LastEditors: penglei 1624952103@qq.com\r
+ * @LastEditTime: 2025-02-12 10:50:38\r
+ * @FilePath: /sdk615/code/sdk/zhihui/drivers/ppg/gh3x2x/src/gh3x2x_afe_demo.c\r
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE\r
+ */\r
+#include "gh3x2x_afe_ecg.h"\r
+#include "gh3x2x_afe_adt.h"\r
+#include "gh3x2x_afe_agc.h"\r
+#include "gh3x2x_afe_demo.h"\r
+\r
+\r
+\r
+GU32 g_unFuncMode = GH3X2X_NO_FUNCTION;\r
+\r
+\r
+\r
+void GH3X2X_AFE_StartFunction(GU32 unFuncMode)\r
+{\r
+    //红外佩戴检测\r
+    if(unFuncMode & (GH3X2X_FUNCTION_ADT))\r
+    {\r
+        GH3x2xAdtAlgoInit();\r
+        GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_SLOT_EN_ADDR,GH3X2X_ADT_SLOT_NUM,GH3X2X_ADT_SLOT_NUM,1);\r
+    }\r
+       \r
+    //心电图\r
+    if(unFuncMode & (GH3X2X_FUNCTION_ECG))\r
+    {\r
+        GH3X2X_LeadOffDetectInit();                    \r
+        GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_SLOT_EN_ADDR,GH3X2X_ECG_SLOT_NUM,GH3X2X_ECG_SLOT_NUM,1);\r
+        ECG_FAST_RECV_EN_CONFIG(1);\r
+    }\r
+                       \r
+    if(g_unFuncMode == GH3X2X_NO_FUNCTION)\r
+    {\r
+        GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_START_ADDR,GH3X2X_AFE_REG_START_LSB,GH3X2X_AFE_REG_START_MSB,1);\r
+    }\r
+    g_unFuncMode |= unFuncMode;\r
+\r
+}\r
+\r
+\r
+void GH3X2X_AFE_StopFunction(GU32 unFuncMode)\r
+{\r
+    if(unFuncMode & (GH3X2X_FUNCTION_ADT))\r
+    {\r
+        GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_SLOT_EN_ADDR,GH3X2X_ADT_SLOT_NUM,GH3X2X_ADT_SLOT_NUM,0);\r
+        GH3x2xAdtAlgoDeinit();\r
+    }\r
+    if(unFuncMode & (GH3X2X_FUNCTION_ECG))\r
+    {\r
+        GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_SLOT_EN_ADDR,GH3X2X_ECG_SLOT_NUM,GH3X2X_ECG_SLOT_NUM,0);\r
+        ECG_FAST_RECV_EN_CONFIG(0);\r
+\r
+    }\r
+    g_unFuncMode &= (~unFuncMode);\r
+    if(g_unFuncMode == GH3X2X_NO_FUNCTION)\r
+    {\r
+        GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_START_ADDR,GH3X2X_AFE_REG_START_LSB,GH3X2X_AFE_REG_START_MSB,0);\r
+    }\r
+    \r
+}\r
+\r
+\r
+void GH3X2X_AFE_Leadon_hook(void)\r
+{\r
+    GH3X2X_AFE_StartFunction(GH3X2X_FUNCTION_ECG);\r
+}\r
+\r
+void GH3X2X_AFE_Leadoff_hook(void)\r
+{\r
+    GH3X2X_AFE_StopFunction(GH3X2X_FUNCTION_ECG);\r
+    ECG_LEAD_DET_EN_CONFIG(0);// enable lead detect\r
+    ECG_LEAD_DET_EN_CONFIG(1);// enable lead detect\r
+    \r
+}\r
+\r
+\r
+void GH3X2X_DemoLedAgcPramConfig(void)\r
+{\r
+    static STSoftAgcCfg stSoftAgcCfg;\r
+\r
+         stSoftAgcCfg.uchSlotxSoftAgcAdjEn = 1;   //bit0-bit7: slot0 -slot7 \r
+         stSoftAgcCfg.uchSlotxSoftBgAdjEn = 0;\r
+         stSoftAgcCfg.stAmbSlotCtrl.uchAmbSampleEn = 0;\r
+         stSoftAgcCfg.uchSpo2RedSlotCfgEn =  2;  //bit0-bit7: slot0 -slot7 for spo2 red \r
+         stSoftAgcCfg.uchSpo2IrSlotCfgEn =  4;   //bit0-bit7: slot0 -slot7 for spo2 ir\r
+         stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg32uA = 8;\r
+         stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg64uA = 6;\r
+         stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg128uA = 5;\r
+         stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg256uA = 4;\r
+         stSoftAgcCfg.unAgcTrigThd_H = (GU32)(8388608 + 8388608*0.85f);\r
+         stSoftAgcCfg.unAgcTrigThd_L = (GU32)(8388608 + 8388608*0.15f);\r
+         stSoftAgcCfg.unAgcRestrainThd_H = 12868608;\r
+         stSoftAgcCfg.unAgcRestrainThd_L = 10692608;\r
+    \r
+    GH3X2X_LedAgcPramConfig(&stSoftAgcCfg);\r
+}\r
+\r
+\r
+\r
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_drv.c b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_drv.c
new file mode 100644 (file)
index 0000000..5fe8a90
--- /dev/null
@@ -0,0 +1,1541 @@
+/**\r
+ * @copyright (c) 2019 - 2024, Goodix Co., Ltd. All rights reserved.\r
+ * \r
+ * @file    gh3x2x_afe_drv.c\r
+ * \r
+ * @brief   gh3x2x driver example code\r
+ *\r
+ * @author  Gooidx Iot Team\r
+ * \r
+ * @attention\r
+ *  This file just show how to init and control gh3x2x sampling.\r
+ */\r
+#include "stdio.h"\r
+#include "gh3x2x_afe_drv.h"\r
+#include "gh3x2x_afe_user.h"\r
+#include "gh3x2x_afe_ecg.h"\r
+#include "gh3x2x_afe_agc.h"\r
+#include "gh3x2x_afe_adt.h"\r
+#include "gh3x2x_afe_demo.h"\r
+\r
+#include "custom_utils.h"\r
+\r
+ \r
+#define SWAP_SIZE_OF_GU16               (2)\r
+#define SWAP_INDEX_OF_NEXT_BYTE         (1)\r
+\r
+#define GH3X2X_I2C_BUS I2C_BUS_2\r
+\r
+//extern void GH3X2X_SoftLedADJAutoADJInt(void);\r
+//extern void GH3X2X_LedAgcProcess(GU8* puchReadFifoBuffer, GU16 usFifoLen);\r
+//extern void GH3X2X_LedAgcReset(void);\r
+//extern void GH3X2X_LedAgcPramWrite(void);\r
+//extern void GH3X2X_LedAgcInit(void);\r
+\r
+STGh3x2xAgcInfo g_stGh3x2xAgcInfo = {0};\r
+STGh3x2xAgcInfo *g_pstGh3x2xAgcInfo = &g_stGh3x2xAgcInfo;\r
+\r
+GU8 g_uchNeedWakeUpGh3x2xAfe = 1; // 0: do not need wake up gh3x2x  1: need wake up gh3x2x\r
+GU8 g_uchGh3x2xAfeIntCallBackIsCalled = 0;  //0: no new interrupt    1:  have new interrupt\r
+\r
+/*********************************************** reg cfg package *******************************************/\r
+STGH3X2X_AFEReg GH3X2X_AFE_reg_list[] =\r
+{\r
+//    {0x0000, 0x0610}, {0x0004, 0x001F}, {0x0006, 0x0001}, {0x000A, 0x0010}, {0x000E, 0x000D}, {0x0100, 0x0100},\r
+//    {0x010A, 0x27FC}, {0x0110, 0x0F65}, {0x0114, 0x00AA}, {0x011E, 0x021F}, {0x0120, 0x041F}, {0x0122, 0x137F},\r
+//    {0x0126, 0xC77C}, {0x012C, 0x0C10}, {0x012E, 0x2222}, {0x0130, 0x00AA}, {0x013A, 0x010C}, {0x013C, 0x0400},\r
+//    {0x01EC, 0x027C}, {0x01EE, 0x00AC}, {0x0200, 0x0120}, {0x0208, 0x0551}, {0x0280, 0x0A00}, {0x0282, 0xF530},\r
+//    {0x0284, 0x9388}, {0x0286, 0xC45C}, {0x0288, 0xA328}, {0x0408, 0x0001}, {0x0410, 0x49F0}, {0x0412, 0x0082},\r
+//    {0x0414, 0x49F0}, {0x0416, 0x0082}, {0x0422, 0x0011}, {0x0424, 0x0901}, {0x0426, 0x0108}, {0x0428, 0x0102},\r
+//    {0x0502, 0x4360}, {0x0504, 0x000A}, {0x0588, 0x0008}, {0x0692, 0x0233}, {0x0694, 0x0400}, {0x0698, 0x2310},\r
+//    {0x0700, 0x0000}, \r
+               \r
+//             {0x0000, 0x0602}, {0x0004, 0x0013}, {0x0006, 0x0201}, {0x000A, 0x005F}, {0x000E, 0x000D}, {0x0074, 0x0048},\r
+//    {0x0100, 0x0100}, {0x010A, 0x0462}, {0x010C, 0x0000}, {0x010E, 0x0000}, {0x0110, 0x0000}, {0x0120, 0x0400},\r
+//    {0x0126, 0xC73C}, {0x0128, 0x0404}, {0x012A, 0x0404}, {0x012C, 0x0C10}, {0x012E, 0x2222}, {0x0130, 0x00AA},\r
+//    {0x0136, 0x00FF}, {0x013A, 0x000C}, {0x013C, 0x0400}, {0x01EA, 0x0033}, {0x01EC, 0x0030}, {0x01EE, 0x0098},\r
+//    {0x0200, 0x1020}, {0x0402, 0x5555}, {0x0404, 0x4120}, {0x0406, 0x0041}, {0x0408, 0x0001}, {0x0410, 0x49F0},\r
+//    {0x0412, 0x0082}, {0x0414, 0x49F0}, {0x0416, 0x0082}, {0x0422, 0x0011}, {0x0424, 0x0901}, {0x0426, 0x0109},\r
+//    {0x0428, 0x0108}, {0x0480, 0x6550}, {0x0502, 0x4C66}, {0x0506, 0x0020}, {0x0588, 0x0008}, {0x0692, 0x0233},\r
+//    {0x0694, 0x0404}, {0x0698, 0x3310}, {0x069A, 0x1101}, {0x0700, 0x0000}, {0x0400, 0x5557}, {0x1000, 0x0000},\r
+//    {0x1002, 0x3197}, {0x1004, 0x0000}, {0x1006, 0x6C91}, {0x1008, 0x2CE1}, {0x100A, 0x0001}, {0x10E0, 0x0000},\r
+//    {0x10E2, 0xFFFF}, {0x10E4, 0xFFFF}, {0x10E6, 0xFFFF}, {0x10E8, 0x0202}, {0x10EA, 0x0202}, {0x10EC, 0x0202},\r
+//    {0x10EE, 0x0202}, {0x1120, 0x005F}, {0x1122, 0x0005}, {0x1124, 0x0000}, {0x2000, 0x0004}, {0x2002, 0x2A22},\r
+//    {0x2004, 0x3A32}, {0x20EE, 0x0001}, {0x20F0, 0x001C}, {0x2880, 0x0005}, {0x288E, 0x00FA}, {0x3000, 0x0101},\r
+//    {0x3002, 0x0000}, {0x3004, 0x49F0}, {0x3006, 0x0082}, {0x4500, 0x46C9}, {0x4502, 0x0F0F}, {0x4504, 0x0002},\r
+//    {0x4506, 0x0140}, {0xFFFF, 0x0001}\r
+\r
+               {0x0000, 0x0610}, {0x0004, 0x001F}, {0x0006, 0x0001}, {0x000A, 0x0050}, {0x000E, 0x000D}, {0x0100, 0x0100},\r
+    {0x010A, 0x277C}, {0x0110, 0x0D14}, {0x0112, 0x5555}, {0x0114, 0x00AA}, {0x011E, 0x0019}, {0x0120, 0x0400},\r
+    {0x0122, 0x0CFF}, {0x0126, 0xC704}, {0x0128, 0x0001}, {0x012A, 0x0000}, {0x012C, 0x0C10}, {0x012E, 0x4442},\r
+    {0x0130, 0x0002}, {0x0136, 0x0003}, {0x013A, 0x010C}, {0x013C, 0x0400}, {0x01EC, 0x0136}, {0x01EE, 0x00AC},\r
+    {0x0200, 0x0120}, {0x0208, 0x0551}, {0x0280, 0x0A00}, {0x0282, 0xF530}, {0x0284, 0x9388}, {0x0286, 0xC45C},\r
+    {0x0288, 0xA328}, {0x0408, 0x0001}, {0x0410, 0x49F0}, {0x0412, 0x0082}, {0x0414, 0x49F0}, {0x0416, 0x0082},\r
+    {0x0422, 0x0011}, {0x0424, 0x0901}, {0x0426, 0x0108}, {0x0428, 0x0102}, {0x0502, 0x4F60}, {0x0504, 0x000A},\r
+    {0x0588, 0x0008}, {0x0692, 0x0233}, {0x0694, 0x0400}, {0x0698, 0x2310}, {0x0700, 0x0000}, {0x1000, 0x0000},\r
+    {0x1002, 0x3197}, {0x1004, 0x0000}, {0x1006, 0x6904}, {0x1008, 0x2AF6}, {0x100A, 0x0001}, {0x10E0, 0x0000},\r
+    {0x10E2, 0xFFFF}, {0x10E4, 0xFFFF}, {0x10E6, 0xFFFF}, {0x10E8, 0x0202}, {0x10EA, 0x0202}, {0x10EC, 0x0202},\r
+    {0x10EE, 0x0202}, {0x1100, 0x0004}, {0x1102, 0x0000}, {0x1120, 0x0050}, {0x1122, 0x0005}, {0x1124, 0x0000},\r
+    {0x1140, 0x0000}, {0x1142, 0x00C8}, {0x1144, 0x0001}, {0x1160, 0x0001}, {0x1162, 0x0000}, {0x1164, 0x0000},\r
+    {0x1166, 0x4568}, {0x1168, 0xCCCC}, {0x116A, 0x00EC}, {0x116C, 0x3333}, {0x116E, 0x0093}, {0x1170, 0x5C00},\r
+    {0x1172, 0x00C4}, {0x1174, 0x2800}, {0x1176, 0x00A3}, {0x2000, 0x0001}, {0x2002, 0x0022}, {0x2022, 0x0004},\r
+    {0x2024, 0x0901}, {0x2026, 0x1911}, {0x2880, 0x0005}, {0x2882, 0x0019}, {0x3000, 0x0001}, {0x3002, 0x0000},\r
+    {0x3004, 0x49F0}, {0x3006, 0x0082}, {0xFFFF, 0x0001}\r
+};\r
+\r
+GU16 GH3X2X_AFE_reg_list_len = sizeof(GH3X2X_AFE_reg_list) / sizeof(GH3X2X_AFE_reg_list[0]);\r
+\r
+\r
+void GH3X2X_SwapLittleBigEndianData(GU8 *puchDataBuffer, GU16 usDataLength)\r
+{\r
+    GU16 usIndex = 0;\r
+\r
+    for (usIndex = 0; usIndex < (usDataLength / SWAP_SIZE_OF_GU16); usIndex++)\r
+    {\r
+        puchDataBuffer[usIndex * SWAP_SIZE_OF_GU16] ^= \\r
+                                                puchDataBuffer[usIndex * SWAP_SIZE_OF_GU16 + SWAP_INDEX_OF_NEXT_BYTE];\r
+        puchDataBuffer[usIndex * SWAP_SIZE_OF_GU16 + SWAP_INDEX_OF_NEXT_BYTE] ^= \\r
+                                                puchDataBuffer[usIndex * SWAP_SIZE_OF_GU16];\r
+        puchDataBuffer[usIndex * SWAP_SIZE_OF_GU16] ^= \\r
+                                                puchDataBuffer[usIndex * SWAP_SIZE_OF_GU16 + SWAP_INDEX_OF_NEXT_BYTE];\r
+    }\r
+}\r
+\r
+\r
+#if ( GH3X2X_AFE_COM_INTERFACE_TYPE == GH3X2X_AFE_COM_INTERFACE_SPI )\r
+\r
+\r
+/**\r
+ * @fn     static void GH3X2X_AFE_SpiSendCmd(GU8 uchCmd)\r
+ *\r
+ * @brief  Send cmd via spi\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   uchCmd      spi cmd\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS) \r
+void GH3X2X_AFE_SpiSendCmd(GU8 uchCmd)\r
+{\r
+    GU8 uchBuffArr[1];\r
+\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW);\r
+    uchBuffArr[0] = uchCmd;\r
+    hal_gh3x2x_afe_spi_write(uchBuffArr, 1);\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US);\r
+}\r
+#endif\r
+\r
+#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_HARDWEAR_CS) \r
+void GH3X2X_AFE_SpiSendCmdHardwareCs(GU8 uchCmd)\r
+{\r
+    GU8 uchBuffArr[1];\r
+    uchBuffArr[0] = uchCmd;\r
+    hal_gh3x2x_afe_spi_write(uchBuffArr, 1);\r
+}\r
+#endif\r
+\r
+\r
+/**\r
+ * @fn     static void GH3X2X_AFE_SpiWriteReg(GU16 usRegAddr, GU16 usRegValue)\r
+ *\r
+ * @brief  Write register via spi\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   usRegAddr       register addr\r
+ * @param[in]   usRegValue      register data\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS) \r
+void GH3X2X_AFE_SpiWriteReg(GU16 usRegAddr, GU16 usRegValue)\r
+{\r
+    GU8 uchBuffArr[7];\r
+\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW);\r
+    uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_WRITE;\r
+    uchBuffArr[1] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegAddr);\r
+    uchBuffArr[2] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegAddr);\r
+    uchBuffArr[3] = 0;\r
+    uchBuffArr[4] = 2;\r
+    uchBuffArr[5] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegValue);\r
+    uchBuffArr[6] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegValue);\r
+    hal_gh3x2x_afe_spi_write(uchBuffArr, 7);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US);\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US);\r
+}\r
+#endif\r
+\r
+#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_HARDWEAR_CS) \r
+void GH3X2X_AFE_SpiWriteRegHardwareCs(GU16 usRegAddr, GU16 usRegValue)\r
+{\r
+    GU8 puchWriteBuf[7];\r
+    puchWriteBuf[0] = 0xF0;\r
+    puchWriteBuf[1] = usRegAddr>>8;\r
+    puchWriteBuf[2] = usRegAddr&0x00FF;\r
+    puchWriteBuf[3] = 0;\r
+    puchWriteBuf[4] = 2;\r
+    puchWriteBuf[5] = usRegValue>>8;\r
+    puchWriteBuf[6] = usRegValue&0x00FF;\r
+    hal_gh3x2x_afe_spi_write(puchWriteBuf, 7);\r
+}\r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+/**\r
+ * @fn     static GU16 GH3X2X_AFE_SpiReadReg(GU16 usRegAddr)\r
+ *\r
+ * @brief  Read register via spi\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   usRegAddr      register addr\r
+ * @param[out]  None\r
+ *\r
+ * @return  register data\r
+ */\r
+ \r
+#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS) \r
+GU16 GH3X2X_AFE_SpiReadReg(GU16 usRegAddr)\r
+{\r
+    GU8 uchBuffArr[3] = {0};\r
+\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW);\r
+    uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_WRITE;\r
+    uchBuffArr[1] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegAddr);\r
+    uchBuffArr[2] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegAddr);\r
+    hal_gh3x2x_afe_spi_write(uchBuffArr, 3);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US);\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US);\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW);\r
+    uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_READ;\r
+    hal_gh3x2x_afe_spi_write(uchBuffArr, 1);\r
+    hal_gh3x2x_afe_spi_read(uchBuffArr, 2);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US);\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US);\r
+    return GH3X2X_AFE_MAKEUP_WORD(uchBuffArr[0], uchBuffArr[1]);\r
+}\r
+\r
+/**\r
+ * @fn      void GH3X2X_SpiReadRegs(GU16 usRegAddr, GU16 *pusRegValueBuffer, GU8 uchLen)\r
+ *\r
+ * @brief  Read multi register via spi\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   usRegAddr           register addr\r
+ * @param[in]   pusRegValueBuffer   pointer to register value buffer\r
+ * @param[in]   uchLen              registers len\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_SpiReadRegs(GU16 usRegAddr, GU16 *pusRegValueBuffer, GU8 uchLen)\r
+{\r
+    GU8 uchBuffArr[3] = {0};\r
+\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW);\r
+    uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_WRITE;\r
+    uchBuffArr[1] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegAddr);\r
+    uchBuffArr[2] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegAddr);\r
+    hal_gh3x2x_afe_spi_write(uchBuffArr, 3);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US);\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US);\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW);\r
+    uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_READ;\r
+    hal_gh3x2x_afe_spi_write(uchBuffArr, 1);\r
+    hal_gh3x2x_afe_spi_read((GU8 *)pusRegValueBuffer, uchLen * 2);\r
+    GH3X2X_SwapLittleBigEndianData((GU8 *)pusRegValueBuffer, (GU16)((GU16)uchLen * 2));\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US);\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US);\r
+}\r
+\r
+#endif\r
+\r
+#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_HARDWEAR_CS) \r
+GU16 GH3X2X_AFE_SpiReadRegHardwareCs(GU16 usRegAddr)\r
+{\r
+    GU8 puchWriteBuf[7];\r
+    GU8 puchReadBuf[2];\r
+    puchWriteBuf[0] = 0xF0;\r
+    puchWriteBuf[1] = usRegAddr>>8;\r
+    puchWriteBuf[2] = usRegAddr&0x00FF;\r
+    hal_gh3x2x_afe_spi_write(puchWriteBuf, 3);\r
+    hal_gh3x2x_afe_spi_write_F1_and_read(puchReadBuf, 2);\r
+    return ((((GU16)puchReadBuf[0])<<8) + puchReadBuf[1]);\r
+}\r
+\r
+\r
+\r
+void GH3X2X_AFE_SpiReadRegsHardwareCs(GU16 usRegAddr, GU16 *pusRegValueBuffer, GU8 uchLen)\r
+{\r
+    GU8 puchWriteBuf[3];\r
+    puchWriteBuf[0] = 0xF0;\r
+    puchWriteBuf[1] = usRegAddr>>8;\r
+    puchWriteBuf[2] = usRegAddr&0x00FF;\r
+    hal_gh3x2x_afe_spi_write(puchWriteBuf, 3);\r
+    hal_gh3x2x_afe_spi_write_F1_and_read((GU8 *)pusRegValueBuffer, uchLen * 2);\r
+    GH3X2X_SwapLittleBigEndianData((GU8 *)pusRegValueBuffer, (GU16)((GU16)uchLen * 2));\r
+}\r
+\r
+\r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+/**\r
+ * @fn     static void GH3X2X_AFE_SpiReadFifo(GU8 *puchDataBuffer, GU16 usLen)\r
+ *\r
+ * @brief  Read fifo via spi\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   puchDataBuffer      pointer to buffer for fifo rawdata\r
+ * @param[in]   usLen               fifo bytes len\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+ \r
+#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS) \r
+static void GH3X2X_AFE_SpiReadFifo(GU8 *puchDataBuffer, GU16 usLen)\r
+{\r
+    GU8 uchBuffArr[3] = {0};\r
+\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW);\r
+    uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_WRITE;\r
+    uchBuffArr[1] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(GH3X2X_AFE_FIFO_REG_ADDR);\r
+    uchBuffArr[2] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(GH3X2X_AFE_FIFO_REG_ADDR);\r
+    hal_gh3x2x_afe_spi_write(uchBuffArr, 3);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US);\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US);\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW);\r
+    uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_READ;\r
+    hal_gh3x2x_afe_spi_write(uchBuffArr, 1);\r
+    hal_gh3x2x_afe_spi_read(puchDataBuffer, usLen);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US);\r
+    hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US);\r
+}\r
+\r
+#endif\r
+\r
+\r
+#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_HARDWEAR_CS) \r
+void GH3X2X_AFE_SpiReadFifoHardwareCs(GU8 *puchDataBuffer, GU16 usLen)\r
+{\r
+    GU8 puchWriteBuf[3];\r
+    puchWriteBuf[0] = 0xF0;\r
+    puchWriteBuf[1] = 0xAAAA>>8;\r
+    puchWriteBuf[2] = 0xAAAA&0x00FF;\r
+    hal_gh3x2x_afe_spi_write(puchWriteBuf, 3);\r
+    hal_gh3x2x_afe_spi_write_F1_and_read(puchDataBuffer, usLen);\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
+#if ( GH3X2X_AFE_COM_INTERFACE_TYPE == GH3X2X_AFE_COM_INTERFACE_I2C )\r
+\r
+/**\r
+ * @fn     static void GH3X2X_AFE_I2cSendCmd(GU8 uchCmd)\r
+ *\r
+ * @brief  Send cmd via i2c\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   uchCmd      i2c cmd\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_I2cSendCmd(GU8 uchCmd)\r
+{\r
+    GU8 uchBuffArr[3] = {0};\r
+\r
+    uchBuffArr[0] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(GH3X2X_AFE_I2C_CMD_ADDR);\r
+    uchBuffArr[1] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(GH3X2X_AFE_I2C_CMD_ADDR);\r
+    uchBuffArr[2] = uchCmd;\r
+    hal_gh3x2x_afe_i2c_write(GH3X2X_AFE_I2C_DEVICE_BASE, uchBuffArr, 3);\r
+}\r
+\r
+/**\r
+ * @fn     static void GH3X2X_AFE_I2cWriteReg(GU16 usRegAddr, GU16 usRegValue)\r
+ *\r
+ * @brief  Write register via i2c\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   usRegAddr       register addr\r
+ * @param[in]   usRegValue      register data\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_I2cWriteReg(GU16 usRegAddr, GU16 usRegValue)\r
+{\r
+    GU8 uchBuffArr[4] = {0};\r
+\r
+    uchBuffArr[0] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegAddr);\r
+    uchBuffArr[1] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegAddr);\r
+    uchBuffArr[2] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegValue);\r
+    uchBuffArr[3] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegValue);\r
+    hal_gh3x2x_afe_i2c_write(GH3X2X_AFE_I2C_DEVICE_BASE, uchBuffArr, 4);\r
+}\r
+\r
+\r
+\r
+/**\r
+ * @fn     static GU16 GH3X2X_I2cReadReg(GU16 usRegAddr)\r
+ *\r
+ * @brief  Read register via i2c\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   usRegAddr      register addr\r
+ * @param[out]  None\r
+ *\r
+ * @return  register data\r
+ */\r
+GU16 GH3X2X_AFE_I2cReadReg(GU16 usRegAddr)\r
+{\r
+    GU8 uchCmdBuffArr[2] = {0};\r
+    GU8 uchReadBuffArr[2] = {0};\r
+\r
+    uchCmdBuffArr[0] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegAddr);\r
+    uchCmdBuffArr[1] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegAddr);\r
+    hal_gh3x2x_afe_i2c_read(GH3X2X_AFE_I2C_DEVICE_BASE, uchCmdBuffArr, 2, uchReadBuffArr, 2);\r
+\r
+    return GH3X2X_AFE_MAKEUP_WORD(uchReadBuffArr[0], uchReadBuffArr[1]);\r
+}\r
+\r
+/**\r
+ * @fn    void GH3X2X_I2cReadRegs(GU16 usRegAddr, GU16 *pusRegValueArr, GU8 uchLen)\r
+ *\r
+ * @brief  Read multi register via i2c\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   usRegAddr           register addr\r
+ * @param[in]   pusRegValueBuffer   pointer to register value buffer\r
+ * @param[in]   uchLen              registers len\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_I2cReadRegs(GU16 usRegAddr, GU16 *pusRegValueArr, GU8 uchLen)\r
+{\r
+    GU8 uchBuffArr[2] = {0};\r
+\r
+    uchBuffArr[0] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegAddr);\r
+    uchBuffArr[1] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegAddr);\r
+\r
+    hal_gh3x2x_afe_i2c_read(GH3X2X_AFE_I2C_DEVICE_BASE, uchBuffArr, 2, \\r
+                        (GU8 *)pusRegValueArr, uchLen * 2);\r
+    GH3X2X_SwapLittleBigEndianData((GU8 *)pusRegValueArr, (GU16)uchLen * 2);\r
+}\r
+\r
+\r
+\r
+\r
+/**\r
+ * @fn     static void GH3X2X_I2cReadFifo(GU8 *puchDataBuffer, GU16 usLen)\r
+ *\r
+ * @brief  Read fifo via i2c\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   puchDataBuffer      pointer to buffer for fifo rawdata\r
+ * @param[in]   usLen               fifo bytes len\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_I2cReadFifo(GU8 *puchDataBuffer, GU16 usLen)\r
+{\r
+    GU8 uchCmdBuffArr[2] = {0};\r
+\r
+    uchCmdBuffArr[0] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(GH3X2X_AFE_FIFO_REG_ADDR);\r
+    uchCmdBuffArr[1] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(GH3X2X_AFE_FIFO_REG_ADDR);\r
+    hal_gh3x2x_afe_i2c_read(GH3X2X_AFE_I2C_DEVICE_BASE, uchCmdBuffArr, 2, puchDataBuffer, usLen);\r
+}\r
+\r
+#endif\r
+\r
+/**\r
+ * @fn     void GH3X2X_WriteRegBitField(GU16 usRegAddr, GU8 uchLsb, GU8 uchMsb, GU16 usValue)\r
+ *\r
+ * @brief  write register bit field via i2c or spi\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   usRegAddr      register addr\r
+ * @param[in]   uchLsb         lsb of bit field\r
+ * @param[in]   uchMsb         msb of bit field\r
+ * @param[in]   usRegValue     register data\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_WriteRegBitField(GU16 usRegAddr, GU8 uchLsb, GU8 uchMsb, GU16 usValue)\r
+{\r
+    GU16 usMakData = ((((GU16)0x0001) << (uchMsb - uchLsb + 1)) - 1) << uchLsb;\r
+    GU16 usRegData = 0;\r
+    usRegData = GH3X2X_AFE_READ_REG(usRegAddr);\r
+    GH3X2X_VAL_CLEAR_BIT(usRegData, usMakData);\r
+    GH3X2X_VAL_SET_BIT(usRegData, (usValue << uchLsb) & usMakData);\r
+    GH3X2X_AFE_WRITE_REG(usRegAddr, usRegData);\r
+}\r
+\r
+/**\r
+ * @fn     GU16 GH3X2X_AFE_READ_REGBitField(GU16 usRegAddr, GU8 uchLsb, GU8 uchMsb)\r
+ *\r
+ * @brief  Read register bit field via i2c or spi\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   usRegAddr      register addr\r
+ * @param[in]   uchLsb         lsb of bit field\r
+ * @param[in]   uchMsb         msb of bit field\r
+ * @param[out]  None\r
+ *\r
+ * @return  register bit field data\r
+ */\r
+GU16 GH3X2X_AFE_ReadRegBitField(GU16 usRegAddr, GU8 uchLsb, GU8 uchMsb)\r
+{\r
+    GU16 usMakData = ((((GU16)0x0001) << (uchMsb - uchLsb + 1)) - 1) << uchLsb;\r
+    GU16 usRegData = 0;\r
+    usRegData = GH3X2X_AFE_READ_REG(usRegAddr);\r
+    GH3X2X_AFE_VAL_GET_BIT(usRegData, usMakData);\r
+    usRegData >>= uchLsb;\r
+    return usRegData;\r
+}\r
+\r
+\r
+void GH3X2X_AFE_SetNeedWakeUpGh3x2xFlag(GU8 uchFlag)\r
+{\r
+    g_uchNeedWakeUpGh3x2xAfe = uchFlag;\r
+}\r
+\r
+GU8 GH3X2X_AFE_GetNeedWakeUpGh3x2xFlag(void)\r
+{\r
+    return g_uchNeedWakeUpGh3x2xAfe;\r
+}\r
+\r
+\r
+\r
+void GH3X2X_AFE_ExitLowPowerMode(void)\r
+{\r
+    GH3X2X_AFE_SEND_CMD(GH3X2X_AFE_CMD_WAKEUP);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_WAKE_UP_CMD_DELAY_X_US);\r
+}\r
+\r
+void GH3X2X_AFE_EnterLowPowerMode(void)\r
+{\r
+    GH3X2X_AFE_SEND_CMD(GH3X2X_AFE_CMD_SLEEP);\r
+    GH3X2X_AFE_SetNeedWakeUpGh3x2xFlag(1);\r
+}\r
+\r
+\r
+void GH3X2X_AFE_ClearEvent(GU16 usEvent)\r
+{\r
+    GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_INT_EVENT_ADDR,usEvent);\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+/**\r
+ * @fn     void GH3X2X_AFE_SendRegPackage(STGH3X2X_AFEReg* GH3X2X_AFE_reg_list,  GU16 reg_list_len)\r
+ *\r
+ * @brief  send register package (for initialize GH3X2X_AFE chip)\r
+ *\r
+ * @attention   \r
+ *\r
+ * @param[in]  GH3X2X_AFE_reg_list      reg list that will be written to GH3X2X_AFE\r
+ * @param[in]  reg_list_len         reg count that contained in reg list\r
+ * @param[out] None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_SendRegPackage(STGH3X2X_AFEReg* GH3X2X_AFE_reg_list,  GU16 reg_list_len)\r
+{\r
+    GU16 luwIndex  = 0;\r
+\r
+    if ((GH3X2X_AFE_reg_list != NULL) && (reg_list_len > 0))\r
+    {\r
+        for (luwIndex = 0; luwIndex < reg_list_len; luwIndex++)\r
+        {\r
+            if (GH3X2X_AFE_REG_IS_VALID(GH3X2X_AFE_reg_list->usRegAddr))\r
+            {\r
+                GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_reg_list->usRegAddr, GH3X2X_AFE_reg_list->usRegData); \r
+            }            \r
+            GH3X2X_AFE_reg_list++;\r
+        }\r
+    }\r
+\r
+    if(GH3X2X_AFE_PRO_TYPE == GH3X2X_AFE_PRO_BY_POLLING)\r
+    {\r
+        //int pin should not action when poling mode\r
+        GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_INT_EVENT_EN_ADDR, 0); \r
+    }\r
+\r
+}\r
+\r
+\r
+\r
+/**\r
+ * @fn     GS8 GH3X2X_HardReset(void)\r
+ *\r
+ * @brief  Gh3x2x softreset via i2c/spi, can read&write reg with gh3x2x after reset\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   None\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ * @retval  #GH3X2X_RET_OK               return successfully\r
+ * @retval  #GH3X2X_RET_GENERIC_ERROR    reset pin control function not register\r
+ */\r
+void GH3X2X_AFE_Reset(void)\r
+{\r
+    GH3X2X_AFE_ClearEvent(0xFFFF);\r
+    #if(GH3X2X_AFE_RESET_TYPE == GH3X2X_AFE_RESET_HARDWARE)\r
+    hal_gh3x2x_afe_reset_pin_ctrl(0);\r
+    hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_HARD_RESET_DELAY_X_US); \r
+    hal_gh3x2x_afe_reset_pin_ctrl(1); \r
+    #else\r
+    GH3X2X_AFE_SEND_CMD(GH3X2X_AFE_CMD_RESET);\r
+    #endif\r
+    hal_gh3x2x_afe_DelayMs(10);\r
+}\r
+\r
+\r
+\r
+/**\r
+ * @fn     GS8 GH3X2X_CommunicateConfirm(void)\r
+ *\r
+ * @brief  Communication operation interface confirm\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   None\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_CommunicateConfirm(void)\r
+{\r
+    GU16 uchReadData;\r
+    GU16 uchWriteData;\r
+   \r
+    if (GH3X2X_AFE_READ_REG(GH3X2X_AFE_REG_CHIP_READY_CODE_REG_ADDR) == 0xAA55)\r
+    {\r
+        uchReadData = GH3X2X_AFE_READ_REG(GH3X2X_AFE_REG_SLOT_TMR0_REG_ADDR);\r
+        GH3X2X_INFO_LOG("slot_time0 reg = %d\r\n", (int)uchReadData);\r
+        uchWriteData = ~uchReadData;\r
+        GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_SLOT_TMR0_REG_ADDR, uchWriteData);\r
+        uchReadData = GH3X2X_AFE_READ_REG(GH3X2X_AFE_REG_SLOT_TMR0_REG_ADDR);\r
+        GH3X2X_INFO_LOG("slot_time0 reg = %d\r\n", (int)uchReadData);\r
+        if (uchWriteData == uchReadData)\r
+        {\r
+            uchWriteData = ~uchReadData;\r
+            GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_SLOT_TMR0_REG_ADDR, uchWriteData);\r
+        }\r
+        else\r
+        {\r
+            GH3X2X_INFO_LOG("[%s]read fail or write fail!!! \r\n", __FUNCTION__);\r
+            while(1);\r
+        }\r
+    }\r
+    else\r
+    {\r
+        GH3X2X_INFO_LOG("[%s]ready code reg is error !!! 0x%x\r\n", __FUNCTION__,GH3X2X_AFE_READ_REG(GH3X2X_AFE_REG_CHIP_READY_CODE_REG_ADDR));\r
+        while(1);\r
+    }\r
+\r
+    GH3X2X_INFO_LOG("[%s]Comunication confirm ok. \r\n", __FUNCTION__);\r
+        \r
+   \r
+    \r
+\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+/*********************************************** init function*******************************************/\r
+\r
+/**\r
+ * @fn     void GH3X2X_AFE_Init(void)\r
+ *\r
+ * @brief  init GH3X2X_AFE chip\r
+ *\r
+ * @attention   \r
+ *\r
+ * @param[in]  None\r
+ * @param[out] None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_Init(void)\r
+{\r
+    /* Step 1: init communicate interface. */\r
+    #if(GH3X2X_AFE_COM_INTERFACE_TYPE == GH3X2X_AFE_COM_INTERFACE_SPI)\r
+    hal_gh3x2x_afe_spi_init();\r
+    #else\r
+    hal_gh3x2x_afe_i2c_init();\r
+    #endif\r
+\r
+    /* Step 2: init interupt pin  */\r
+    #if(GH3X2X_AFE_PRO_TYPE == GH3X2X_AFE_PRO_BY_INT)\r
+    hal_gh3x2x_afe_int_init();\r
+    #endif\r
+    \r
+\r
+    /* Step 3: Reset GH3X2X_AFE chip */\r
+    #if(GH3X2X_AFE_RESET_TYPE == GH3X2X_AFE_RESET_HARDWARE)\r
+    hal_gh3x2x_afe_reset_pin_init();\r
+    #endif\r
+    GH3X2X_AFE_Reset();\r
+\r
+    /* Step 4: Check conmunication and chip id is ok or not */\r
+    GH3X2X_AFE_CommunicateConfirm();\r
+       GH3X2X_AFE_CheckChipId();\r
+       GH3X2X_AFE_CheckEfuseCrc();\r
+\r
+\r
+    /* Step 5: Init GH3X2X_AFE chip */\r
+    GH3X2X_AFE_SendRegPackage(GH3X2X_AFE_reg_list, GH3X2X_AFE_reg_list_len);\r
+\r
+    /* Step 6: agc module reset and set parm*/\r
+    GH3X2X_LedAgcReset();\r
+    GH3X2X_DemoLedAgcPramConfig();\r
+    //GH3X2X_LedAgcPramWrite();\r
+               \r
+    /* Step 7: enter low power mode */\r
+    GH3X2X_AFE_EnterLowPowerMode();\r
+\r
+}\r
+\r
+/*********************************************** sample control handle function*******************************************/\r
+\r
+/**\r
+ * @fn     void GH3X2X_AFE_StartSampling(GU8 SlotCfgEnable)\r
+ *\r
+ * @brief  start sample\r
+ *\r
+ * @attention   \r
+ *\r
+ * @param[in]  SlotCfgEnable slot enable bit  bit0 control slot0, bit1 control slot1, bit2 control slot2...\r
+ * @param[out] None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_StartSampling(GU8 SlotCfgEnable)\r
+{\r
+    GH3X2X_AFE_ExitLowPowerMode();\r
+\r
+    //agc init\r
+    GH3X2X_LedAgcInit(g_pstGh3x2xAgcInfo);\r
+    \r
+    //write slot enable\r
+    GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_SLOT_EN_ADDR, (GU16)SlotCfgEnable);\r
+    //start sample\r
+    GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_START_ADDR,GH3X2X_AFE_REG_START_LSB,GH3X2X_AFE_REG_START_MSB,1);\r
+    \r
+    GH3X2X_AFE_EnterLowPowerMode();\r
+}\r
+\r
+/**\r
+ * @fn     void GH3X2X_AFE_StopSampling(void)\r
+ *\r
+ * @brief  stop sample\r
+ *\r
+ * @attention   \r
+ *\r
+ * @param[in]  None\r
+ * @param[out] None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_StopSampling(void)\r
+{\r
+    GH3X2X_AFE_ExitLowPowerMode();\r
+\r
+    //stop sample\r
+    GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_START_ADDR,GH3X2X_AFE_REG_START_LSB,GH3X2X_AFE_REG_START_MSB,0);\r
+\r
+    GH3X2X_AFE_EnterLowPowerMode();\r
+}\r
+\r
+/**\r
+ * @fn     void GH3X2X_AFE_SwitchSlot(GU8 SlotCfgEnable)\r
+ *\r
+ * @brief  switch sample slot.\r
+ *\r
+ * @attention   this function can only be used during sampling, after call GH3X2X_AFE_StartSampling\r
+ *\r
+ * @param[in]  SlotCfgEnable slot enable bit  bit0 control slot0, bit1 control slot1, bit2 control slot2...\r
+ * @param[out] None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_SwitchSlot(GU8 SlotCfgEnable)\r
+{\r
+    GH3X2X_AFE_ExitLowPowerMode();\r
+            \r
+    //write slot enable\r
+    GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_SLOT_EN_ADDR, (GU16)SlotCfgEnable);\r
+    \r
+    GH3X2X_AFE_EnterLowPowerMode();\r
+}\r
+\r
+/********************************* interrupt handle:fifo read and analysis ***************************/\r
+#define GH3X2X_AFE_READ_FIFO_BUF_LEN (800)\r
+GU32 GH3X2X_AFE_ReadFifoBuffer[(GU16)GH3X2X_AFE_READ_FIFO_BUF_LEN];\r
+\r
+/*\r
+    FIFO rawdata decode\r
+*/\r
+typedef struct\r
+{\r
+    GU32 uiAdcCode;                      //sampling rawdata of ADC\r
+    GU8  ubSlotNo;                       //slot number\r
+    GU8  ubAdcNo;                        //adc number\r
+    GU8  ubFlagLedAdjIsAgc_EcgRecover;   //adj flag of ppg data or fast recover flag of ecg data\r
+    GU8  ubFlagLedAdjAgcUp;            //adj up flag of ppg data\r
+}StFifoDataInformation;\r
+\r
+/**\r
+ * @fn     GU32 EndienRev32(GU32 luiTempData)\r
+ *\r
+ * @brief  reverse data endien\r
+ *\r
+ * @attention   \r
+ *\r
+ * @param[in]  luiTempData input data\r
+ * @param[out] None\r
+ *\r
+ * @return  output data\r
+ */\r
+static GU32 EndienRev32(GU32 luiTempData)\r
+{\r
+    GU8 *lpubIn;\r
+    GU8 *lpubOut;\r
+    \r
+    GU32 luiOutData;\r
+    \r
+    lpubIn = (GU8 *)(&luiTempData);\r
+    lpubOut = (GU8 *)(&luiOutData);\r
+    \r
+    for(GU8 i = 0; i < 4; i ++)\r
+    {\r
+        lpubOut[i] = lpubIn[3 - i];\r
+    }\r
+    \r
+    return luiOutData;\r
+}\r
+\r
+void GH3X2X_UpdateAgcInfo(void)\r
+{\r
+    GH3X2X_Memcpy(g_pstGh3x2xAgcInfo->uchTiaGainRecord, g_pstGh3x2xAgcInfo->uchTiaGainAfterSoftAgc, sizeof(g_pstGh3x2xAgcInfo->uchTiaGainRecord));\r
+               GH3X2X_Memcpy(g_pstGh3x2xAgcInfo->uchDrvCurrentRecord, g_pstGh3x2xAgcInfo->uchDrvCurrentAfterSoftAgc, sizeof(g_pstGh3x2xAgcInfo->uchDrvCurrentRecord));\r
+       \r
+       \r
+}\r
+\r
+void GH3X2X_RecordAgcInfo(void)\r
+{\r
+    GU16 usDrv0CurRegData = 0;\r
+    GU16 usDrv0CurRegAddr = 0;    \r
+    GU16 usDrv1CurRegData = 0;\r
+    GU16 usDrv1CurRegAddr = 0;\r
+               GU16 uchTIAData = 0;\r
+\r
+               // record TIA\r
+               for (GU8 uchSlotIndex = 0; uchSlotIndex < 8; uchSlotIndex++)\r
+               {\r
+        uchTIAData = GH3X2X_AFE_READ_REG(0x0112 + (uchSlotIndex * 0x001C));\r
+                       \r
+                               for (GU8 nAdcCnt = 0; nAdcCnt < 4; nAdcCnt++)\r
+                               {\r
+                                               uchTIAData = (GU8)(((uchTIAData) >> (4 * nAdcCnt)) & 0x000F);\r
+                                               g_pstGh3x2xAgcInfo->uchTiaGainAfterSoftAgc[uchSlotIndex*4 + nAdcCnt] = uchTIAData;\r
+                               }       \r
+               }\r
+               \r
+                               //Record Drv            \r
+        usDrv0CurRegAddr = 0x011E;\r
+        usDrv1CurRegAddr = 0x0120;\r
+        for (GU8 uchSlotIndexCnt = 0; uchSlotIndexCnt < 8; uchSlotIndexCnt++)\r
+        {\r
+                                       usDrv0CurRegData = (GH3X2X_AFE_READ_REG(usDrv0CurRegAddr + (uchSlotIndexCnt * 0x001C)) & 0xFF);\r
+                                       usDrv1CurRegData = (GH3X2X_AFE_READ_REG(usDrv1CurRegAddr + (uchSlotIndexCnt * 0x001C)) & 0xFF);\r
+                                       g_pstGh3x2xAgcInfo->uchDrvCurrentAfterSoftAgc[uchSlotIndexCnt] =  (GU16)(usDrv0CurRegData << 0x0);\r
+                                       g_pstGh3x2xAgcInfo->uchDrvCurrentAfterSoftAgc[uchSlotIndexCnt] |= (GU16)(usDrv1CurRegData << 0x0);\r
+        }\r
+}\r
+\r
+/**\r
+ * @fn     void GH3X2X_AFE_FifoDataAnalysis(GU16 luwFifoDataCnt)\r
+ *\r
+ * @brief  analysis fifo data\r
+ *\r
+ * @attention   \r
+ *\r
+ * @param[in]  luwFifoDataCnt    the number of rawdata \r
+ * @param[out] None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_FifoDataAnalysis(GU16 luwFifoDataCnt)\r
+{\r
+    StFifoDataInformation stTempFifoInfo = {0};\r
+    GU16 luwFifoCnt = 0;\r
+    \r
+    GU32 luiTempFifoData = 0;\r
+\r
+    GH3X2X_INFO_LOG("Received rawdata sample num = %d \r\n", (int)luwFifoDataCnt);\r
+    \r
+    for(luwFifoCnt = 0; luwFifoCnt < luwFifoDataCnt; luwFifoCnt++)\r
+    {\r
+        luiTempFifoData = EndienRev32(GH3X2X_AFE_ReadFifoBuffer[luwFifoCnt]);  //big endien -> little endien\r
+        \r
+        stTempFifoInfo.uiAdcCode = ((luiTempFifoData >> 0) & 0x00FFFFFF);\r
+        stTempFifoInfo.ubSlotNo =  ((luiTempFifoData >> 29) & 0x00000007);\r
+        stTempFifoInfo.ubAdcNo = ((luiTempFifoData >> 27) & 0x00000003);\r
+        stTempFifoInfo.ubFlagLedAdjIsAgc_EcgRecover = ((luiTempFifoData >> 26) & 0x00000001);\r
+        stTempFifoInfo.ubFlagLedAdjAgcUp = ((luiTempFifoData >> 25) & 0x00000001);\r
+        #if GH3X2X_ADT_FUNC_ENABLE\r
+        if(stTempFifoInfo.ubSlotNo == GH3X2X_ADT_SLOT_NUM && stTempFifoInfo.ubAdcNo == GH3X2X_ADT_ADC_NUM)\r
+        {\r
+            EMWearStatus emWearStatus;\r
+            GH3x2xAdtAlgoExe(&stTempFifoInfo.uiAdcCode,&emWearStatus);\r
+        }\r
+        #endif\r
+        GH3X2X_INFO_LOG("Received rawdata:slot:%d,adc:%d,data:%d\r\n", stTempFifoInfo.ubSlotNo, stTempFifoInfo.ubAdcNo,stTempFifoInfo.uiAdcCode);\r
+                               //GH3X2X_INFO_LOG("drv = %d, g0 = %d,g1 = %d,g2 = %d,g0 = %d\r\n",(int)g_pstGh3x2xAgcInfo->uchDrvCurrentRecord[0],(int)g_pstGh3x2xAgcInfo->uchTiaGainRecord[0],(int)g_pstGh3x2xAgcInfo->uchTiaGainRecord[1],g_pstGh3x2xAgcInfo->uchTiaGainRecord[2],g_pstGh3x2xAgcInfo->uchTiaGainRecord[3]);\r
+               \r
+\r
+        \r
+        /******************************** add your fifo date process code******************************/\r
+        //you can combine frame rawdata according to stTempFifoInfo\r
+        //and then excute algorithm calculate\r
+        \r
+        \r
+    }\r
+}\r
+\r
+\r
+/**\r
+ * @fn     void GH3X2X_AFE_ChipPro(void)\r
+ *\r
+ * @brief  interrupt handle function\r
+ *\r
+ * @attention   \r
+ *\r
+ * @param[in]  None\r
+ * @param[out] None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_ChipPro(void)\r
+{\r
+    GU16 luwGH3X2X_AFEFifoLen = 0;\r
+        GU16 luwGotEvent = 0;\r
+\r
+\r
+#if (GH3X2X_AFE_PRO_TYPE == GH3X2X_AFE_PRO_BY_INT)\r
+    if(0 == g_uchGh3x2xAfeIntCallBackIsCalled)\r
+    {\r
+        GH3X2X_INFO_LOG("InterruptProcess:invalid call, do not process.\r\n");\r
+        return;\r
+    }\r
+    g_uchGh3x2xAfeIntCallBackIsCalled = 0;  \r
+        \r
+#endif\r
+\r
+     if (GH3X2X_AFE_GetNeedWakeUpGh3x2xFlag())\r
+    {\r
+        GH3X2X_AFE_ExitLowPowerMode();\r
+    }\r
+\r
+\r
+    luwGH3X2X_AFEFifoLen = 0;\r
+\r
+    //read event\r
+    luwGotEvent = GH3X2X_AFE_READ_REG(GH3X2X_AFE_REG_INT_EVENT_ADDR);  \r
+    GH3X2X_INFO_LOG("Received irq = %d \r\n", (int)luwGotEvent);\r
+    //clear event\r
+    GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_INT_EVENT_ADDR,luwGotEvent);  //clear event\r
+\r
+    //read fifo use\r
+    luwGH3X2X_AFEFifoLen = GH3X2X_AFE_READ_REG(GH3X2X_AFE_REG_FIFO_USE_ADDR);\r
+    if(luwGH3X2X_AFEFifoLen > GH3X2X_AFE_READ_FIFO_BUF_LEN)\r
+    {\r
+        luwGH3X2X_AFEFifoLen = GH3X2X_AFE_READ_FIFO_BUF_LEN;\r
+    }\r
+\r
+    // read fifo data\r
+    if(0 != luwGH3X2X_AFEFifoLen)\r
+    {\r
+        GH3X2X_AFE_READ_FIFO((GU8 *)GH3X2X_AFE_ReadFifoBuffer,luwGH3X2X_AFEFifoLen * 4);\r
+    } \r
+    \r
+    \r
+    //ECG_LEAD OFF DET & resample\r
+    #if GH3X2X_ECG_FUNC_ENABLE\r
+\r
+    GU16 luwGH3X2X_AFEFifoByteLen = luwGH3X2X_AFEFifoLen * 4;\r
+    luwGotEvent &= (~GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_LEAD_OFF));\r
+    \r
+    GU8 lubRet = GH3X2X_LeadOffDetect((GU8 *)GH3X2X_AFE_ReadFifoBuffer, &luwGH3X2X_AFEFifoByteLen, 0);\r
+     if(lubRet != 0)\r
+    {\r
+        luwGotEvent |= (GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_LEAD_OFF));\r
+    }\r
+    \r
+    GH3X2X_INFO_LOG("before Rs luwGH3X2X_AFEFifoLen = %d\r\n",luwGH3X2X_AFEFifoLen);\r
+    GH3X2X_AFE_EcgRsHandle((GU8 *)GH3X2X_AFE_ReadFifoBuffer, &luwGH3X2X_AFEFifoByteLen,0,GH3X2X_ECG_DOWN_FS);\r
+    luwGH3X2X_AFEFifoLen = luwGH3X2X_AFEFifoByteLen/4;\r
+    GH3X2X_INFO_LOG("after Rs luwGH3X2X_AFEFifoLen = %d\r\n",luwGH3X2X_AFEFifoLen);\r
+    #endif\r
+    \r
+    if(0 != (luwGotEvent & GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_WEAR_ON)))\r
+    {\r
+        GH3X2X_INFO_LOG("Received wear on event\r\n");\r
+    }\r
+\r
+    if(0 != (luwGotEvent & GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_WEAR_OFF)))\r
+    {\r
+        GH3X2X_INFO_LOG("Received wear off event\r\n");\r
+    }\r
+\r
+    if(0 != (luwGotEvent & GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_LEAD_ON)))\r
+    {\r
+        GH3X2X_INFO_LOG("Received lead on event\r\n");\r
+        GH3X2X_AFE_Leadon_hook();\r
+    }\r
+\r
+    if(0 != (luwGotEvent & GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_LEAD_OFF)))\r
+    {\r
+        GH3X2X_INFO_LOG("Received lead off event\r\n");\r
+        GH3X2X_AFE_Leadoff_hook();\r
+\r
+    }\r
+\r
+    if(0 != (luwGotEvent & GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_LED_TUNE_FAIL)))\r
+    {\r
+        GH3X2X_INFO_LOG("Received tune fail event\r\n");\r
+    }\r
+\r
+    if(0 != (luwGotEvent & GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_LED_TUNE_DONE)))\r
+    {\r
+        GH3X2X_INFO_LOG("Received tune done event\r\n");\r
+    }\r
+\r
+\r
+    //you can add some code to adjust ppg sample parameter, such as led drv current    GU16 usTempDrvCurrent;\r
+    \r
+    //GH3x2xSetPpgCtrlReg(GH3X2X_AFE_PPG_CTRL_REG_AGC_EN,1,0);\r
+    //GH3x2xSetPpgCtrlReg(GH3X2X_AFE_PPG_CTRL_REG_LED_CURRENT_DRV0,1,60);\r
+    //GH3X2X_INFO_LOG("change slot0 drv0 current.\r\n");\r
+    //GH3X2X_INFO_LOG("Get slot0 drv0 current = %d.\r\n",(int)GH3x2xGetPpgCtrlReg(GH3X2X_AFE_PPG_CTRL_REG_LED_CURRENT_DRV0,0));\r
+\r
+               GH3X2X_LedAgcProcess((GU8 *)GH3X2X_AFE_ReadFifoBuffer, luwGH3X2X_AFEFifoLen * 4, g_pstGh3x2xAgcInfo);\r
+    \r
+    GH3X2X_AFE_EnterLowPowerMode();\r
+    \r
+\r
+    if(0 != luwGH3X2X_AFEFifoLen)\r
+    {\r
+        GH3X2X_AFE_FifoDataAnalysis(luwGH3X2X_AFEFifoLen);\r
+    }                \r
+}\r
+\r
+const GU16 g_usGH3x2xTiaGainR[] = \r
+{\r
+    10,\r
+    25,\r
+    50,\r
+    75,\r
+    100,\r
+    250,\r
+    500,\r
+    750,\r
+    1000,\r
+    1250,\r
+    1500,\r
+    1750,\r
+    2000,\r
+};\r
+\r
+const GU16 g_usGH3x2xSlotRegBase[8] = \r
+{\r
+    0x0100,\r
+    0x011C,\r
+    0x0138,\r
+    0x0154,\r
+    0x0170,\r
+    0x018C,\r
+    0x01A8,\r
+    0x01C4,\r
+};\r
+\r
+\r
+const STGh3x2xAgcReg g_pstGH3x2xAgcReg[] = \r
+{\r
+    {0x10, 9, 8},              //0: agc en\r
+    {0x22, 7, 0},              //1: led current up limit\r
+    {0x22, 15, 8},               //2: led current down limit\r
+    {0x1E, 7, 0},               //3: led current drv0\r
+    {0x20, 7, 0},               //4: led current drv1\r
+    {0x12, 3, 0},               //5: rx0 tia gain\r
+    {0x12, 7, 4},               //6: rx1 tia gain\r
+    {0x12, 11, 8},               //7: rx2 tia gain\r
+    {0x12, 15, 12},               //8: rx3 tia gain\r
+    {0x10, 7,6},               //9: agc src\r
+    {0x1A, 1,0},               //10: rx0 bg cancel\r
+    {0x1A, 3,2},               //11: rx1 bg cancel    \r
+    {0x1A, 5,4},               //12: rx2 bg cancel\r
+    {0x1A, 7,6},               //13: rx2 bg cancel\r
+    {0x0A, 15,8},               //14: sr mulipliper\r
+    {0x0A, 5,1},               //15: ecg en& rx0~rx1 en\r
+};\r
+\r
+void GH3x2x_AFESetAgcReg(GU8 uchAgcReg,  GU8 uchSlot, GU16 usValue)\r
+{\r
+    GH3X2X_AFE_WriteRegBitField(g_usGH3x2xSlotRegBase[uchSlot] + g_pstGH3x2xAgcReg[uchAgcReg].uchAddrOffset, g_pstGH3x2xAgcReg[uchAgcReg].uchLsb, g_pstGH3x2xAgcReg[uchAgcReg].uchMsb, usValue);\r
+}\r
+\r
+GU16 GH3x2x_AFEGetAgcReg(GU8 uchAgcReg,  GU8 uchSlot)\r
+{\r
+    return GH3X2X_AFE_ReadRegBitField(g_usGH3x2xSlotRegBase[uchSlot] + g_pstGH3x2xAgcReg[uchAgcReg].uchAddrOffset, g_pstGH3x2xAgcReg[uchAgcReg].uchLsb, g_pstGH3x2xAgcReg[uchAgcReg].uchMsb);\r
+}\r
+\r
+/**\r
+ * @fn  void GH3X2X_AFE_GetEfuseCode(GS8* pchLedDrvEcode,GS8* pchTiaEcode,GS8* pchEcgEcode)\r
+ *\r
+ * @brief: Get Efuse Code\r
+ *\r
+ * @attention   \r
+ *\r
+ * @param[in]    \r
+ * @param[out]  pchLedDrvEcode\r
+ *              pchTiaEcode\r
+ *              pchEcgEcode\r
+ * @return  :  none\r
+ */\r
+void GH3X2X_AFE_GetEfuseCode(GS8* pchLedDrvEcode,GS8* pchTiaEcode,GS8* pchEcgEcode)\r
+{\r
+    GU16 usRegVal;\r
+    GH3X2X_AFE_WRITE_REG(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,0x0020);\r
+    GH3X2X_AFE_WRITE_REG(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,0x0030);\r
+\r
+    while(0 == GH3X2X_AFE_ReadRegBitField(GH3X2X_EFUSE_CTRL_STATUS_REG_ADDR,0,0));\r
+    usRegVal = GH3X2X_AFE_READ_REG(GH3X2X_EFUSE_CTRL_RDATA_1_REG_ADDR);\r
+    *pchLedDrvEcode = (GS8)GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegVal);\r
+    *pchTiaEcode    = (GS8)GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegVal);\r
+    *pchEcgEcode    = (GS8)GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(GH3X2X_AFE_READ_REG(GH3X2X_EFUSE_CTRL_RDATA_2_REG_ADDR));\r
+}\r
+\r
+\r
+/**\r
+ * @fn  GU16 GH3X2X_AFE_SetLedDrvCurrent(GU8 uchCurrent_mA,GU8 uchDrvNum, GS8 chECODE)\r
+ *\r
+ * @brief: led drv calibration\r
+ *\r
+ * @attention   \r
+ *\r
+ * @param[in]   GU8 uchCurrent_mA:led drv current, unit: mA\r
+                GU8 uchDrvNum    :led Drv num,0 or 1\r
+                GS8 chECODE      :Led Drv Ecode from efuse\r
+ * @param[out] None\r
+ *\r
+ * @return  :  Drv code\r
+ */\r
+GU16 GH3X2X_AFE_SetLedDrvCurrent(GU8 uchCurrent_mA, GU8 uchDrvNum, GS8 chECODE)\r
+{\r
+    GF32 fEr;\r
+    GF32 fY;\r
+    GU8  uchN;\r
+    GU16 usDrvCode;\r
+    GU16 usDrvScale;\r
+    \r
+    if(uchDrvNum == 0)\r
+    {\r
+        fY = 0.1;\r
+        usDrvScale = GH3X2X_AFE_ReadRegBitField(GH3X2X_LED_DRV_AD_REG_REG_ADDR,GH3X2X_DRV0_FULL_SCAL_CURRENT_LSB,GH3X2X_DRV0_FULL_SCAL_CURRENT_MSB);\r
+    }\r
+    else\r
+    {\r
+        fY = 0.01;\r
+        usDrvScale = GH3X2X_AFE_ReadRegBitField(GH3X2X_LED_DRV_AD_REG_REG_ADDR,GH3X2X_DRV1_FULL_SCAL_CURRENT_LSB,GH3X2X_DRV1_FULL_SCAL_CURRENT_MSB);\r
+        \r
+    }\r
+    uchN = 1 << (3 - usDrvScale);    \r
+    \r
+    fEr = (GF32)((GF32)chECODE/256) + 1.0f;\r
+    usDrvCode = (GU16)(0.5f+((GF32)fEr*255*(GF32)uchN)/(0.225f/((GF32)uchCurrent_mA/1000) - fY));\r
+    \r
+    return usDrvCode;\r
+}\r
+\r
+\r
+/**\r
+ * @fn  GF32 GH3X2X_AFE_GetLedDrvCurrent(GU16 usDrvCode, GU8 uchDrvNum, GS8 chECODE)\r
+ *\r
+ * @brief: get led drv calibration current\r
+ *\r
+ * @attention   \r
+ *\r
+ * @param[in]  GU16 usDrvCode   :led drv code\r
+                GU8 uchDrvNum    :led Drv num,0 or 1\r
+                GS8 chECODE      :Led Drv Ecode from efuse\r
+ * @param[out] None\r
+ *\r
+ * @return  :  calibration current\r
+ */\r
+\r
+GF32 GH3X2X_AFE_GetLedDrvCurrent(GU16 usDrvCode, GU8 uchDrvNum, GS8 chECODE)\r
+{\r
+    GF32 fEr;\r
+    GF32 fY;\r
+    GU8  uchN;\r
+    GF32 fDrvCurrent;\r
+    GU16 usDrvScale;\r
+       \r
+    if(uchDrvNum == 0)\r
+    {\r
+        fY = 0.1;\r
+        usDrvScale = GH3X2X_AFE_ReadRegBitField(GH3X2X_LED_DRV_AD_REG_REG_ADDR,GH3X2X_DRV0_FULL_SCAL_CURRENT_LSB,GH3X2X_DRV0_FULL_SCAL_CURRENT_MSB);\r
+    }\r
+    else\r
+    {\r
+        fY = 0.01;\r
+        usDrvScale = GH3X2X_AFE_ReadRegBitField(GH3X2X_LED_DRV_AD_REG_REG_ADDR,GH3X2X_DRV1_FULL_SCAL_CURRENT_LSB,GH3X2X_DRV1_FULL_SCAL_CURRENT_MSB);\r
+    }\r
+    uchN = 1 << (3 - usDrvScale);    \r
+    fEr = (GF32)((GF32)chECODE/256) + 1;\r
+    fDrvCurrent = 0.225f/(fEr*255*(GF32)uchN/(GF32)usDrvCode + fY);\r
+    return fDrvCurrent*1000;\r
+\r
+}\r
+\r
+/**\r
+ * @fn   GF32 GH3X2X_AFE_GetTiaCalCode(GS8 chECODE)\r
+ \r
+ *\r
+ * @brief:  Get Tia Calibration Code\r
+ *\r
+ * @attention   \r
+ *\r
+ * @param[in]  GS8 chECODE      :Tia Ecode from efuse\r
+ * @param[out] None\r
+ *\r
+ * @return  :  calibration Code\r
+ */\r
+GF32 GH3X2X_AFE_GetTiaCalCode(GS8 chECODE)\r
+{\r
+    GF32 fEr;\r
+    fEr = (GF32)((GF32)chECODE/512) + 1;\r
+    return fEr;\r
+}\r
+\r
+/**\r
+ * @fn   GF32 GH3X2X_AFE_GetEcgCalCode(GS8 chECODE)\r
+ \r
+ *\r
+ * @brief:  Get ECG Calibration Code\r
+ *\r
+ * @attention   \r
+ *\r
+ * @param[in]  GS8 chECODE      :ECG Ecode from efuse\r
+ * @param[out] None\r
+ *\r
+ * @return  :  calibration Code\r
+ */\r
+GF32 GH3X2X_AFE_GetEcgCalCode(GS8 chECODE)\r
+{\r
+    GF32 fEr;\r
+    fEr = (GF32)((GF32)chECODE/1024) + 1;\r
+    return fEr;\r
+}\r
+\r
+\r
+/**\r
+ * @fn     GCHAR *GH3X2X_GetAfeLibVersion(void)\r
+ *\r
+ * @brief  Get afe driver version\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   None\r
+ * @param[out]  None\r
+ *\r
+ * @return  library version string\r
+ */\r
+GCHAR *GH3X2X_GetAfeLibVersion(void)\r
+{\r
+    return (GCHAR *)GH3X2X_VERSION_STRING;\r
+}\r
+\r
+\r
+GU8 GH3X2X_AFE_GetChipId(void)\r
+{\r
+       return (GU8)GH3X2X_AFE_ReadRegBitField(GH3X2X_WHO_AM_I_REG_ADDR,GH3X2X_WHO_AM_I_LSB,GH3X2X_WHO_AM_I_MSB);\r
+}\r
+\r
+GS8 GH3X2X_AFE_CheckChipId(void)\r
+{\r
+    GS8 chRet = GH3X2X_AFE_RET_OK;\r
+    GS8 chipd_id = GH3X2X_AFE_GetChipId();\r
+       if(GH3X2X_CHIP_ID != chipd_id)\r
+       {\r
+               GH3X2X_INFO_LOG("wrong chip id!! 0x%x\r\n",chipd_id);\r
+               chRet = GH3X2X_AFE_RET_GENERIC_ERROR;\r
+       }\r
+    else\r
+    {\r
+        GH3X2X_INFO_LOG("check chip id success!!  0x%x\r\n",chipd_id);\r
+    }\r
+    return chRet;\r
+}\r
+\r
+/**\r
+ * @fn     void *GH3X2X_Memcpy(void *pDest, const void *pSrc, GU32 unByteSize)\r
+ *\r
+ * @brief  memcpy() Re-implementation\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   pSrc        pointer to source buffer\r
+ * @param[in]   unByteSize  source buffer byte size\r
+ * @param[out]  pDest       pointer to destination buffer\r
+ *\r
+ * @return  pointer to destination buffer\r
+ */\r
+void *GH3X2X_Memcpy(void *pDest, const void *pSrc, GU32 unByteSize)\r
+{\r
+    GU8 *puchSrc = (GU8 *)pSrc;\r
+    GU8 *puchDest = (GU8 *)pDest;\r
+    GU32 unAlign = ((GU32)puchDest | (GU32)puchSrc) << 30;\r
+\r
+    if ((pDest == GH3X2X_PTR_NULL) || (pSrc == GH3X2X_PTR_NULL) || (0 == unByteSize))\r
+    {\r
+        return GH3X2X_PTR_NULL;\r
+    }\r
+    if (unAlign == 0) // if align 4\r
+    {\r
+        while (unByteSize >= 4)\r
+        {\r
+            *(GU32 *)puchDest = *(GU32 *)puchSrc;\r
+            puchSrc += 4;\r
+            puchDest += 4;\r
+            unByteSize -= 4;\r
+        }\r
+    }\r
+    while (unByteSize) // bytes\r
+    {\r
+        *(GU8 *)puchDest = *(GU8 *)puchSrc;\r
+        puchSrc++;\r
+        puchDest++;\r
+        unByteSize--;\r
+    }\r
+    return pDest;\r
+}\r
+\r
+/**\r
+ * @fn     void *GH3X2X_Memset(void* pDest, GCHAR chVal, GU32 unByteSize)\r
+ *\r
+ * @brief  memset() Re-implementation\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   chVal       char val for set\r
+ * @param[in]   unByteSize       source buffer len\r
+ * @param[out]  pDest       pointer to destination buffer\r
+ *\r
+ * @return  pointer to destination buffer\r
+ */\r
+void *GH3X2X_Memset(void* pDest, GCHAR chVal, GU32 unByteSize)\r
+{\r
+    GU8 *puchDest = (GU8 *)pDest;\r
+    GU32 unAlign = ((GU32)puchDest) << 30;\r
+    GU32 unWordVal = GH3X2X_AFE_MAKEUP_DWORD(chVal, chVal, chVal, chVal);\r
+\r
+    if (pDest == GH3X2X_PTR_NULL)\r
+    {\r
+        return GH3X2X_PTR_NULL;\r
+    }\r
+    if (unAlign == 0) // if align 4\r
+    {\r
+        while (unByteSize >= 4)\r
+        {\r
+            *(GU32 *)puchDest = unWordVal;\r
+            puchDest += 4;\r
+            unByteSize -= 4;\r
+        }\r
+    }\r
+    while (unByteSize) // bytes\r
+    {\r
+        *(GU8 *)puchDest = (GU8)chVal;\r
+        puchDest++;\r
+        unByteSize--;\r
+    }\r
+    return pDest;\r
+}\r
+\r
+GU8 _crc8(GU8 *ptr,GS32 len)\r
+{\r
+  GS32 i;\r
+  GU8 crc = 0x00;\r
+  while(len--)\r
+  {\r
+    crc ^= *ptr++;\r
+    for(i=8;i>0;--i)\r
+    {\r
+      if(crc&0x80)\r
+      {\r
+        crc = (crc<<1)^0x31;\r
+      }\r
+      else\r
+      {\r
+        crc = (crc<<1);\r
+      }\r
+      crc = crc & 0xff;\r
+    }\r
+  }\r
+  return (GU8)(crc);\r
+}\r
+\r
+void GH3X2X_AFE_LoadEfuse(GU8* puchEfuseBuffer,GU16 EfuseByteLen)\r
+{\r
+       if(EfuseByteLen < 24)\r
+       {\r
+               GH3X2X_INFO_LOG("EfuseByteLen is too short!!\r\n");\r
+               return;\r
+       }\r
+       \r
+    GU16 usRegVal;\r
+       GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_MODE_LSB,GH3X2X_EFUSE_MODE_MSB,0);\r
+       GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_CHOOSE_LSB,GH3X2X_EFUSE_CHOOSE_MSB,0);\r
+       GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_CLK_EN_LSB,GH3X2X_EFUSE_CLK_EN_MSB,1);\r
+       GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_START_LSB,GH3X2X_EFUSE_START_MSB,1);\r
+       while(0 == GH3X2X_AFE_ReadRegBitField(GH3X2X_EFUSE_CTRL_STATUS_REG_ADDR,0,0));\r
+       for(GU8 i = 0; i < 4; i++)\r
+       {\r
+          usRegVal = GH3X2X_AFE_READ_REG(GH3X2X_EFUSE_CTRL_RDATA_0_REG_ADDR + 2 * i);\r
+          puchEfuseBuffer[2*i]         = (GU8)GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegVal);\r
+          puchEfuseBuffer[2*i + 1] = (GU8)GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegVal);\r
+       }\r
+\r
+       GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_CHOOSE_LSB,GH3X2X_EFUSE_CHOOSE_MSB,1);\r
+       GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_START_LSB,GH3X2X_EFUSE_START_MSB,1);\r
+       while(0 == GH3X2X_AFE_ReadRegBitField(GH3X2X_EFUSE_CTRL_STATUS_REG_ADDR,0,0));\r
+       for(GU8 i = 0; i < 4; i++)\r
+       {\r
+          usRegVal = GH3X2X_AFE_READ_REG(GH3X2X_EFUSE_CTRL_RDATA_0_REG_ADDR + 2 * i);\r
+          puchEfuseBuffer[8 + 2*i]     = (GU8)GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegVal);\r
+          puchEfuseBuffer[8 + 2*i + 1] = (GU8)GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegVal);\r
+       }\r
+\r
+       GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_CHOOSE_LSB,GH3X2X_EFUSE_CHOOSE_MSB,2);\r
+       GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_START_LSB,GH3X2X_EFUSE_START_MSB,1);\r
+       while(0 == GH3X2X_AFE_ReadRegBitField(GH3X2X_EFUSE_CTRL_STATUS_REG_ADDR,0,0));\r
+       for(GU8 i = 0; i < 4; i++)\r
+       {\r
+          usRegVal = GH3X2X_AFE_READ_REG(GH3X2X_EFUSE_CTRL_RDATA_0_REG_ADDR + 2 * i);\r
+          puchEfuseBuffer[16 + 2*i]     = (GU8)GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegVal);\r
+          puchEfuseBuffer[16 + 2*i + 1] = (GU8)GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegVal);\r
+       }\r
+\r
+       \r
+}\r
+\r
+GS8 GH3X2X_AFE_CheckEfuseCrc(void)\r
+{\r
+    GS8 chRet = GH3X2X_AFE_RET_OK;\r
+       GU8  uchEfuseBuffArr[24];\r
+    GH3X2X_AFE_LoadEfuse(uchEfuseBuffArr,24);\r
+       GU8 uchCrcArr[3];\r
+       uchCrcArr[0] = _crc8(uchEfuseBuffArr,7);\r
+       uchCrcArr[1] = _crc8((uchEfuseBuffArr + 8),3);\r
+       uchCrcArr[2] = _crc8((uchEfuseBuffArr + 12),10);\r
+       if(uchCrcArr[0] != uchEfuseBuffArr[7] || uchCrcArr[1] != uchEfuseBuffArr[11] ||uchCrcArr[2] != uchEfuseBuffArr[22])\r
+       {\r
+               GH3X2X_INFO_LOG("Efuse crc error!!\r\n");\r
+               chRet = GH3X2X_AFE_RET_GENERIC_ERROR;\r
+       }\r
+    return chRet;\r
+}\r
+\r
+void gh3x2x_control(char* mode, uint8_t enable)\r
+{\r
+\r
+    uint32_t md = 1;\r
+    if (strcmp(mode, "hrs") == 0) {\r
+        md = 0;\r
+    } else if (strcmp(mode, "hrv") == 0) {\r
+        md = 1;\r
+    } else if (strcmp(mode, "spo2") == 0) {\r
+        md = 2;\r
+    } else if (strcmp(mode, "leaklight") == 0) {\r
+        md = 4;\r
+    } else if (strcmp(mode, "graycard") == 0) {\r
+        md = 8;\r
+    } else if (strcmp(mode, "ledoff") == 0) {\r
+        md = 16;\r
+    } else if (strcmp(mode, "wear") == 0) {\r
+        md = 32;\r
+    } else if (strcmp(mode, "single") == 0) {\r
+        md = 64;\r
+    }else if (strcmp(mode, "factory") == 0) {\r
+        md = 128;\r
+    }else if (strcmp(mode, "fpc") == 0) {\r
+        // md = WORK_MODE_UNDEFINED;\r
+    }else if (strcmp(mode, "int") == 0) {\r
+    } \r
+\r
+    if (enable == 1)\r
+    {\r
+        // ppg_service_running_stat = true;\r
+        // uapi_pm_control(PM_APP_WAKE_NEEDED);\r
+        // GH3X2X_AFE_StartFunction(mode);\r
+        GH3X2X_AFE_Init();\r
+        GH3X2X_AFE_StartSampling(1);\r
+\r
+    } else {\r
+        \r
+        // uapi_pm_control(PM_APP_WAKE_NONEED);\r
+        GH3X2X_AFE_StopSampling();\r
+    } \r
+}
\ No newline at end of file
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_lead_off.c b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_lead_off.c
new file mode 100644 (file)
index 0000000..b1e628a
--- /dev/null
@@ -0,0 +1,748 @@
+#include "gh3x2x_afe_ecg.h"\r
+#include "gh3x2x_afe_demo.h"\r
+\r
+#define RESAMPLE_800HZ_TO_500HZ 0\r
+#define RESAMPLE_800HZ_TO_250HZ 0\r
+#define RESAMPLE_320HZ_TO_250HZ 1 \r
+#define RESAMPLE_256HZ_TO_250HZ 0 \r
+\r
+\r
+#if __SUPPORT_ECG_PPG_DOWNSAMP__\r
+#define RESAMPLE_400HZ_TO_250HZ 1 \r
+#else\r
+#define RESAMPLE_400HZ_TO_250HZ 0 \r
+#endif\r
+\r
+#define GH3X2X_PPG_START_SLOT    1\r
+#define GH3X2X_ECG_START_SLOT    0\r
+\r
+#define   GH3X2X_AFE_GET_ECG_CHANNEL_MAP(slotNum)                     (((slotNum << 5) | (3 <<3)) &0xF8)\r
+#define   GH3X2X_AFE_GET_PPG_CHANNEL_MAP(slotNum)                     (((slotNum << 5) | (0 <<3)) &0xF8)\r
+\r
+STGh3x2xSoftLeadOffDetInfo  g_pstGh3x2xSoftLeadOffDetInfoEntity[1];\r
+STGh3x2xRsInfo  g_pstGh3x2xEcgRsInfoEntity[1];\r
+const GU8 g_uchGh3x2xEcgChnlNumLimit = 1;\r
+STGh3x2xSoftLeadOffDetInfo * const g_pstGh3x2xSoftLeadOffDetInfo = g_pstGh3x2xSoftLeadOffDetInfoEntity;\r
+STGh3x2xRsInfo * const g_pstGh3x2xEcgRsInfo = g_pstGh3x2xEcgRsInfoEntity;\r
+\r
+\r
+#if __SUPPORT_ECG_PPG_DOWNSAMP__\r
+#define GH3X2X_PPG_DOWNSAMP_CHNL_NUM 1\r
+const GU32 g_uchPPGDownSampleChnlNumLimit = GH3X2X_PPG_DOWNSAMP_CHNL_NUM;\r
+STGh3x2xRsInfo  g_pstGh3x2xPPGRsInfoEntity[GH3X2X_PPG_DOWNSAMP_CHNL_NUM];\r
+STGh3x2xRsInfo * const g_pstGh3x2xPPGRsInfo = g_pstGh3x2xPPGRsInfoEntity;\r
+#endif\r
+\r
+//Ecg sample rate from hardware\r
+static GU16 g_usEcgInputFs = GH3X2X_ECG_FS; // ecg sample rate 800/320/256\r
+static GU16 g_usEcgOutputFs = GH3X2X_ECG_DOWN_FS; // ecg down sample rate 500/250\r
+\r
+/// down sample lead module(ECG PPG)\r
+static GU8 g_uchDownSampleModule = DOWNSAMPLE_ECG;\r
+\r
+#define ADCREF 1800   \r
+#define ADC_OFFSET (1<<23)\r
+#define PI 3.14159265\r
+#define  ABS(x) ( (x)>0?(x):(-(x)) ) \r
+#define AMP_NUM 5  \r
+#define IQ_NUM 48  \r
+\r
+const int winCoef[IQ_NUM / 2] = { 0, 9580474, 38150933, 85201535, 149892663, 231069901, 327284639, 436819923, 557721094, 687830666, 824826833, 966264894, 1109620882, 1252336609, 1391865307, 1525717084, 1651503351, 1766979451, 1870084709, 1958979209, 2032076627, 2088072537, 2125967693, 2145085852};\r
+#define winAmpCoef  4082 \r
+//unsigned char gscFlagFrPrev = 0; \r
+GU32 g_nLeadOffDetIqAmpThr = 1500;//unit: uv\r
+long long g_lLeadOffDetIqAmp;\r
+long long  g_lLeadOffDetIqAmpThrRaw;\r
+long long  g_lLeadOffDetIqAmpFrThrRaw;\r
+\r
+GU32 g_nLeadOffDetIqAmpDiffThr = 1000;//unit: uv\r
+long long g_lLeadOffDetIqAmpDiff;\r
+long long g_lLeadOffDetIqAmpDiffThrRaw;\r
+long long g_lLeadOffDetIqAmpDiffFrThrRaw;\r
+\r
+int COND_VAL_VALID_TIME = 1; \r
+GU32 g_nLeadOffDetValThr = 80;//unit: mv\r
+int g_LeadOffDetValThrRaw;\r
+\r
+#define SHIFTBITS 30\r
+\r
+#if RESAMPLE_800HZ_TO_500HZ\r
+       const int rsFirCoef_800_500hz[] = { 58200, 102435, 156130, 215460, 274735, 326585, 362380, 372790, 348645, 281870, 166550, 0, -216285, -475850, -766815, -1071825, -1368460, -1630170, -1827760, -1931325, -1912605,\r
+                                -1747635, -1419445, -920670, -255820, 557070, 1485515, 2482735, 3488860, 4433375, 5238695, 5824850, 6114965, 6041350, 5551740, 4615280, 3227790, 1415785, -761100, -3209770, -5805610, -8396875, -10811545, -12866385,\r
+                                -14377925, -15174745, -15110485, -14076620, -12014295, -8924190, -4873605, 0, 5489625, 11323885, 17176845, 22682405, 27452740, 31100030, 33260510, 33619540, 31936265, 28066360, 21981325, 13782945, 3711580, -7852615,\r
+                                -20396185, -33286830, -45795550, -57125820, -66448630, -72941905, -75832375, -74437800, -68207360, -56757870, -39903755, -17678885, 9651270, 41588185, 77410100, 116192965, 156841955, 198132190, 238757000, 277381455, 312698655, 343486005, 368658785, 387318230, 398791740, 402663190 };\r
+#endif\r
+#if RESAMPLE_800HZ_TO_250HZ    \r
+       const int rsFirCoef_800_250hz[] = { -74905, -95385, -116975, -138740, -159540, -178080, -192900, -202440, -205060, -199120, -183040, -155365, -114830, -60455, 8370, 91845, 189655, 300920, 424150, 557225, 697345, 841065, 984315, 1122440, 1250290, 1362325,\r
+                                1452720, 1515555, 1544935, 1535220, 1481220, 1378385, 1223050, 1012615, 745780, 422705, 45175, -383265, -857210, -1369370, -1910565, -2469770, -3034240, -3589685, -4120510, -4610090, -5041145, -5396125, -5657660, -5809045, -5834740, -5720895, -5455890,\r
+                                -5030825, -4440010, -3681420, -2757070, -1673325, -441140, 923805, 2401100, 3965690, 5588100, 7234765, 8868540, 10449275, 11934545, 13280495, 14442770, 15377525, 16042520, 16398240, 16409055, 16044325, 15279560, 14097430, 12488725, 10453225, 8000385,\r
+                                5149865, 1931900, -1612575, -5431990, -9464450, -13638290, -17872830, -22079425, -26162660, -30021820, -33552510, -36648435, -39203325, -41112955, -42277200, -42602135, -42002095, -40401670, -37737600, -33960495, -29036370, -22947970, -15695790,\r
+                                -7298825, 2204995, 12758710, 24286615, 36694830, 49872305, 63692080, 78012930, 92681285, 107533410, 122397830, 137097950, 151454790, 165289835, 178427925, 190700125, 201946505, 212018845, 220783110, 228121755, 233935695, 238146055, 240695490, 241549195 };\r
+#endif\r
+\r
+#if RESAMPLE_400HZ_TO_250HZ    \r
+//const int rsFirCoef_250hz1[] = { 0,-24495,-56710,-95045,-136775,-178125,-214440,-240490,-250920,-240760,-205965,-144050,-54555,60475,196250,345190,497105,639650,759070,841160,872410,841285,739500,563245,314150,0,-365010,-760510,-1160685,-1535620,-1853070,-2080745,-2188790,-2152475,-1954770,-1588670,-1058960,-383360,407260,1269625,2149850,2986210,3712890,4264415,4580525,4611280,4321835,3696680,2742865,1491895,0,-1653335,-3368750,-5032125,-6521320,-7714135,-8497040,-8774130,-8475685,-7565610,-6047220,-3966715,-1413955,1479820,4547350,7593800,10407850,12774895,14491705,15381495,15308470,14190830,12011055,8822720,4752940,0,-5174080,-10455925,-15497715,-19937805,-23423930,-25637735,-26318950,-25287690,-22463185,-17877445,-11682610,-4150955,4332910,13287805,22159230,30349170,37251070,42288110,44952645,44844420,41705155,35447110,26173540,14189250,0,-15699840,-32051440,-48066690,-62673020,-74765800,-83265770,-87178475,-85652480,-78033065,-63908265,-43144325,-15908305,17323970,55775495,98391360,143876925,190749335,237400000,282164985,323399855,359555130,389248460,411329760,424935830,429531605};\r
+const int rsFirCoef_250hz2[] = {-20165,29190,117750,248970,420650,623445,839855,1044105,1203060,1278285,1229350,1018175,614220,0,-823490,-1832200,-2975865,-4177020,-5332555,-6318335,-6996880,-7227970,-6881615,-5852620,-4075600,-1539030,1703020,5523035,9717440,14010255,18063685,21495860,23905235,24900525,24134595,21339975,16363405,9196555,0,-10882185,-22919440,-35404830,-47478995,-58167535,-66430495,-71221570,-71553685,-66566985,-55594615,-38221750,-14333265,15853795,51776230,92531020,136902815,183411755,230379530,276010140,318480795,356037520,387089565,410296710,424643805,429497860,};\r
+#endif\r
+               \r
+#if RESAMPLE_320HZ_TO_250HZ    \r
+       const int rsFirCoef_320_250hz[] = {79095,936340,341760,-2712470,-2547785,4817105,8099190,-5170865,-17933790,0,30974265,15517780,-42765395,-45670380,44706790,92106715,-24021395,-152053275,-36768905,217784250,166596045,-277901355,-451953470,320248390,1667310365,2147483647,};\r
+#endif\r
+#if RESAMPLE_256HZ_TO_250HZ            \r
+       const int rsFirCoef_256_250hz[]={194000,77770,-331070,-632290,-254280,769680,1439880,622640,-1454740,-2779600,-1303600,2436730,4847325,2461115,-3753755,-7872475,-4310105,5424840,12120690,7126740,-7444180,-17902495,-11265025,9777230,25594875,17187555,-12359260,-35689230,-25526795,15096890,48893725,37213545,-17872685,-66356185,-53763065,20552645,90184745,77974330,-22995885,-124828195,-115908245,25065740,181561700,183974820,-26641130,-299102515,-347934030,27626950,749679370,1463910805,1761638120,};\r
+#endif\r
+\r
+GS32* rsFirCoef;\r
+GS32* rsFirCoef1;\r
+               \r
+STGh3x2xDownSampleCalParamInfo pstECGDownSampCalParamInfo[1];\r
+#if __SUPPORT_ECG_PPG_DOWNSAMP__\r
+STGh3x2xDownSampleCalParamInfo pstPPGDownSampCalParamInfo[1];\r
+#endif\r
+\r
+void GH3X2X_DownSampleMarcoIni(GU16 usEcgSampleRate)\r
+{\r
+       switch (g_usEcgInputFs)\r
+       {\r
+       case 800:\r
+        if( usEcgSampleRate == 500)\r
+        {\r
+            pstECGDownSampCalParamInfo->uchDownSampleType = DOWNSAMPLE_800HZ_TO_500HZ;\r
+        }\r
+        else\r
+        {\r
+            pstECGDownSampCalParamInfo->uchDownSampleType = DOWNSAMPLE_800HZ_TO_250HZ;\r
+        }\r
+        break;\r
+       case 320:\r
+        if( usEcgSampleRate == 250)\r
+        {\r
+            pstECGDownSampCalParamInfo->uchDownSampleType = DOWNSAMPLE_320HZ_TO_250HZ;\r
+        }\r
+        break;\r
+       case 256:\r
+        if( usEcgSampleRate == 250)\r
+        {\r
+            pstECGDownSampCalParamInfo->uchDownSampleType = DOWNSAMPLE_256HZ_TO_250HZ;\r
+        }\r
+        break;\r
+       default: // do nothing\r
+        break;\r
+       }\r
+\r
+       // ppg downsample ini\r
+       #if __SUPPORT_ECG_PPG_DOWNSAMP__\r
+               pstPPGDownSampCalParamInfo->uchDownSampleType = DOWNSAMPLE_400HZ_TO_250HZ;\r
+       #endif\r
+}\r
+\r
+void RsFirResetSingle(GU8 uchChipIndex, GU8 uchMode)\r
+{\r
+    STGh3x2xRsInfo * pstRsInfo;\r
+    GU8 uchChnNum = 0;\r
+    #if __SUPPORT_ECG_PPG_DOWNSAMP__\r
+    if(DOWNSAMPLE_PPG == uchMode)\r
+    {\r
+        pstRsInfo = g_pstGh3x2xPPGRsInfo;\r
+        uchChnNum = g_uchPPGDownSampleChnlNumLimit;\r
+    }\r
+    #endif\r
+\r
+    if(DOWNSAMPLE_ECG == uchMode)\r
+    {\r
+        pstRsInfo = g_pstGh3x2xEcgRsInfo;\r
+        uchChnNum = uchChipIndex+1;\r
+    }\r
+\r
+    for( GU8 i=0; i<uchChnNum;i++)\r
+    {\r
+        pstRsInfo[i].snBufHead = -1;\r
+        pstRsInfo[i].snRsFirState = 0;\r
+        pstRsInfo[i].nRsIcounter = 0;\r
+        pstRsInfo[i].nRrsDcounter = 0;\r
+        pstRsInfo[i].uchFlagFrPrev = 1;\r
+        pstRsInfo[i].nRsLastRaw = 0;\r
+        pstRsInfo[i].fDownStep = 0;\r
+        pstRsInfo[i].uchLinearInterState = 0;\r
+        pstRsInfo[i].uchLinearDataUpdate = 0;\r
+    }\r
+}\r
+\r
+void RsFirReset(GU8 uchMode)\r
+{\r
+    RsFirResetSingle(0,uchMode);\r
+}\r
+\r
+void GH3X2X_ECGResampleConfig(GU16 usEcgSampleRate)\r
+{\r
+    RsFirReset(DOWNSAMPLE_ECG);\r
+    GH3X2X_DownSampleMarcoIni(usEcgSampleRate);\r
+    if(usEcgSampleRate == 500)\r
+    {\r
+        #if RESAMPLE_800HZ_TO_500HZ\r
+        if(DOWNSAMPLE_800HZ_TO_500HZ == pstECGDownSampCalParamInfo->uchDownSampleType)\r
+        {\r
+            pstECGDownSampCalParamInfo->rsFirCoef= (GS32*)rsFirCoef_800_500hz;\r
+            pstECGDownSampCalParamInfo->uchRsFirOrder = 182;\r
+            pstECGDownSampCalParamInfo->uchRsI = 5;\r
+            pstECGDownSampCalParamInfo->uchRsD = 8;\r
+            pstECGDownSampCalParamInfo->uchRsEnable = 1;\r
+        }\r
+        #endif\r
+    }\r
+    else if(usEcgSampleRate == 250)\r
+    {\r
+        #if RESAMPLE_800HZ_TO_250HZ\r
+        if(DOWNSAMPLE_800HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType)\r
+        {\r
+            pstECGDownSampCalParamInfo->rsFirCoef= (GS32*)rsFirCoef_800_250hz;\r
+            pstECGDownSampCalParamInfo->uchRsFirOrder = 250;\r
+            pstECGDownSampCalParamInfo->uchRsI = 5;\r
+            pstECGDownSampCalParamInfo->uchRsD = 16;\r
+            pstECGDownSampCalParamInfo->uchRsEnable = 1;\r
+        }\r
+        #endif\r
+\r
+        #if RESAMPLE_320HZ_TO_250HZ\r
+        if(DOWNSAMPLE_320HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType)\r
+        {\r
+            pstECGDownSampCalParamInfo->rsFirCoef= (GS32*)rsFirCoef_320_250hz;\r
+            pstECGDownSampCalParamInfo->uchRsFirOrder = 50;\r
+            pstECGDownSampCalParamInfo->uchRsI = 1;\r
+            pstECGDownSampCalParamInfo->uchRsD = 1;\r
+            pstECGDownSampCalParamInfo->uchRsEnable = 1;\r
+            pstECGDownSampCalParamInfo->ufStep = 128;\r
+        }\r
+        #endif\r
+\r
+        #if RESAMPLE_256HZ_TO_250HZ\r
+        if(DOWNSAMPLE_256HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType)\r
+        {\r
+            pstECGDownSampCalParamInfo->rsFirCoef= (GS32*)rsFirCoef_256_250hz;\r
+            pstECGDownSampCalParamInfo->uchRsFirOrder = 100;\r
+            pstECGDownSampCalParamInfo->uchRsI = 1;\r
+            pstECGDownSampCalParamInfo->uchRsD = 1;\r
+            pstECGDownSampCalParamInfo->uchRsEnable = 1;\r
+            pstECGDownSampCalParamInfo->ufStep = 1024;\r
+        }\r
+        #endif\r
+    }\r
+    else\r
+    {\r
+        pstECGDownSampCalParamInfo->uchRsEnable = 0;\r
+        return;\r
+    }\r
+\r
+    if(pstECGDownSampCalParamInfo->uchRsFirOrder % 2)\r
+    {\r
+        pstECGDownSampCalParamInfo->uchRsFirCoefNum = ((pstECGDownSampCalParamInfo->uchRsFirOrder+1)/2) ;\r
+    }\r
+    else\r
+    {\r
+        pstECGDownSampCalParamInfo->uchRsFirCoefNum = ((pstECGDownSampCalParamInfo->uchRsFirOrder+2)/2);\r
+    }\r
+    pstECGDownSampCalParamInfo->uchRsBufSize = (pstECGDownSampCalParamInfo->uchRsFirOrder / pstECGDownSampCalParamInfo->uchRsI + 1);\r
+}\r
+\r
+#if __SUPPORT_ECG_PPG_DOWNSAMP__\r
+void GH3X2X_PPGResampleConfig(GU16 usPPGSampleRate)\r
+{\r
+    RsFirReset(DOWNSAMPLE_PPG);\r
+               GH3X2X_DownSampleMarcoIni(usPPGSampleRate);\r
+    if(usPPGSampleRate == 250)\r
+    {\r
+        #if RESAMPLE_400HZ_TO_250HZ\r
+        pstPPGDownSampCalParamInfo->rsFirCoef = (GS32*)rsFirCoef_250hz2;\r
+        pstPPGDownSampCalParamInfo->uchRsFirOrder = 126;\r
+        pstPPGDownSampCalParamInfo->uchRsI = 5;\r
+        pstPPGDownSampCalParamInfo->uchRsD = 8;\r
+        pstPPGDownSampCalParamInfo->uchRsEnable = 1;\r
+        #else\r
+        pstPPGDownSampCalParamInfo->uchRsEnable = 0;\r
+        #endif\r
+    }\r
+    else\r
+    {\r
+        pstPPGDownSampCalParamInfo->uchRsEnable = 0;\r
+        return;\r
+    }\r
+\r
+    if(pstPPGDownSampCalParamInfo->uchRsFirOrder % 2)\r
+    {\r
+        pstPPGDownSampCalParamInfo->uchRsFirCoefNum = ((pstPPGDownSampCalParamInfo->uchRsFirOrder+1)/2) ;\r
+    }\r
+    else\r
+    {\r
+        pstPPGDownSampCalParamInfo->uchRsFirCoefNum = ((pstPPGDownSampCalParamInfo->uchRsFirOrder+2)/2);\r
+    }\r
+    pstPPGDownSampCalParamInfo->uchRsBufSize = (pstPPGDownSampCalParamInfo->uchRsFirOrder / pstPPGDownSampCalParamInfo->uchRsI + 1);\r
+}\r
+#else\r
+void GH3X2X_PPGResampleConfig(GU16 usPPGSampleRate)\r
+{\r
+    return;\r
+}\r
+#endif\r
+\r
+void GH3X2X_LeadOffDetectResetSingleChip(GU8 uchChipIndex)\r
+{\r
+    int i;\r
+    STGh3x2xSoftLeadOffDetInfo * pstSoftLeadOffDetInfo = g_pstGh3x2xSoftLeadOffDetInfo + uchChipIndex;\r
+    pstSoftLeadOffDetInfo -> snCounter = 0;\r
+    pstSoftLeadOffDetInfo -> sniqCounter = 0;\r
+    pstSoftLeadOffDetInfo -> snniVal = 0;\r
+    pstSoftLeadOffDetInfo -> snnqVal = 0;\r
+    pstSoftLeadOffDetInfo -> uchFastRecoryHistory = 0;\r
+    for (i = 0; i < AMP_NUM; i++)\r
+        pstSoftLeadOffDetInfo -> snniqAmp[i] = 0;\r
+}\r
+\r
+void GH3X2X_LeadOffDetectReset(void)\r
+{\r
+    GH3X2X_LeadOffDetectResetSingleChip(0);\r
+}\r
+\r
+void GH3X2X_ConfigLeadOffThr(GU32 uIQAmpThr, GU32 uIQAmpDiffThr,GU32 uValThr)\r
+{\r
+    g_nLeadOffDetIqAmpThr = uIQAmpThr;\r
+    g_lLeadOffDetIqAmp = ((long long)g_nLeadOffDetIqAmpThr * 20 * ADC_OFFSET / ADCREF/1000*IQ_NUM*1000/winAmpCoef);\r
+    g_lLeadOffDetIqAmpThrRaw = (g_lLeadOffDetIqAmp*g_lLeadOffDetIqAmp);\r
+    g_lLeadOffDetIqAmpFrThrRaw = (g_lLeadOffDetIqAmp*g_lLeadOffDetIqAmp / 20 / 20); \r
+\r
+    g_nLeadOffDetIqAmpDiffThr = uIQAmpDiffThr;\r
+    g_lLeadOffDetIqAmpDiff = ((long long)g_nLeadOffDetIqAmpDiffThr * 20 * ADC_OFFSET / ADCREF/1000*IQ_NUM*1000/winAmpCoef);\r
+    g_lLeadOffDetIqAmpDiffThrRaw = (g_lLeadOffDetIqAmpDiff*g_lLeadOffDetIqAmpDiff);\r
+    g_lLeadOffDetIqAmpDiffFrThrRaw = (g_lLeadOffDetIqAmpDiff*g_lLeadOffDetIqAmpDiff / 20 / 20); \r
+\r
+    g_nLeadOffDetValThr = uValThr;\r
+    g_LeadOffDetValThrRaw = (g_nLeadOffDetValThr * (20 * ADC_OFFSET / ADCREF)); \r
+}\r
+\r
+GS32 GH3X2X_LeadOffDetectInit(void)\r
+{\r
+    GH3X2X_ECGResampleConfig(g_usEcgOutputFs);\r
+       \r
+               #if __SUPPORT_ECG_PPG_DOWNSAMP__\r
+    GH3X2X_PPGResampleConfig(GH3X2X_PPG_DOWN_FS);        \r
+               #endif\r
+       \r
+    GH3X2X_ConfigLeadOffThr(g_nLeadOffDetIqAmpThr,  g_nLeadOffDetIqAmpDiffThr, g_nLeadOffDetValThr);\r
+    GH3X2X_LeadOffDetectReset();\r
+    return 0;\r
+}\r
+\r
+/**\r
+ * @fn     GU8 GH3X2X_LeadOffDetect(GU8* puchFifoBuffer, GU16 usFifoBufferLen)\r
+ *\r
+ * @brief  Lead off Detection, suppose the increment of  normal ECG value in LEADOFF_DET_POINT_NUM+1 samples point \r
+ *         not exceed   LEADOFF_DET_THR_mV\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   puchFifoBuffer           pointer to read fifo data buffer\r
+ * @param[in]   usFifoBufferLen          read fifo buffer len\r
+ * @param[out]  None\r
+ *\r
+ * @return  lead off status output \r
+ * @retval  #0          not detect lead off\r
+ * @retval  bit0=1      AdcValue larger than thresh\r
+ * @retval  bit1=1      IQ Value larger than thresh\r
+ */\r
+\r
+GU8 GH3X2X_LeadOffDetectSingleChip(GU8* puchFifoBuffer, GU16* pusFifoBufferLen, GU8 unChipIndex, GU8 uchEcgSlotNum)\r
+{\r
+    GU16 usByteIndexTmp = 0;\r
+    GS32 j;\r
+    GU8 uchRet = 0;\r
+    GU32 fifoVal;\r
+    GS32 adcVal;\r
+    GU8  flagFastRecovery;\r
+    GS32 absAdcVal; //ABS of adcVal\r
+    GS64 temp;\r
+\r
+    STGh3x2xSoftLeadOffDetInfo * pstSoftLeadOffDetInfo = g_pstGh3x2xSoftLeadOffDetInfo + unChipIndex;\r
+\r
+    for (usByteIndexTmp = 0; usByteIndexTmp < *pusFifoBufferLen; usByteIndexTmp += GH3X2X_AFE_FIFO_RAWDATA_SIZE)\r
+    {\r
+        if (GH3X2X_AFE_CHANNEL_MAP_GET(puchFifoBuffer[usByteIndexTmp]) == GH3X2X_AFE_GET_ECG_CHANNEL_MAP(uchEcgSlotNum))\r
+        {\r
+            fifoVal = GH3X2X_AFE_MAKEUP_DWORD(puchFifoBuffer[usByteIndexTmp], puchFifoBuffer[usByteIndexTmp + 1],puchFifoBuffer[usByteIndexTmp + 2], puchFifoBuffer[usByteIndexTmp + 3]);\r
+            adcVal = (GS32)((fifoVal & 0x00FFFFFF)) - ADC_OFFSET; \r
+            flagFastRecovery = (fifoVal >> 26) & 0x01;\r
+            if(flagFastRecovery)\r
+            {\r
+                pstSoftLeadOffDetInfo->uchFastRecoryHistory = 1;\r
+                                       //GH3X2X_INFO_LOG("has fast recovery!!!!\r\n");\r
+            }\r
+            if(0 == pstSoftLeadOffDetInfo->uchFastRecoryHistory)\r
+            {\r
+                                       //GH3X2X_INFO_LOG("Warning: No fast recovery!!!!\r\n");\r
+                continue;\r
+            }\r
+            if (pstSoftLeadOffDetInfo-> uchFlagFrPrev != flagFastRecovery)\r
+            {\r
+                GH3X2X_LeadOffDetectReset();\r
+                pstSoftLeadOffDetInfo->uchFastRecoryHistory = 1;\r
+            }\r
+            pstSoftLeadOffDetInfo-> uchFlagFrPrev = flagFastRecovery;\r
+\r
+            //sample counter\r
+            if (pstSoftLeadOffDetInfo -> snCounter < 20000)\r
+                pstSoftLeadOffDetInfo -> snCounter++;\r
+            \r
+            if (flagFastRecovery == 0 && pstSoftLeadOffDetInfo -> snCounter>COND_VAL_VALID_TIME)\r
+            {\r
+                absAdcVal = ABS(adcVal);\r
+                if (absAdcVal > g_LeadOffDetValThrRaw)\r
+                    uchRet |= 0x01;\r
+            }\r
+            if (pstSoftLeadOffDetInfo -> sniqCounter < IQ_NUM / 2)\r
+            {\r
+                temp = (GS64)adcVal*winCoef[pstSoftLeadOffDetInfo -> sniqCounter];\r
+            }\r
+            else\r
+            {\r
+                temp = (GS64)adcVal*winCoef[IQ_NUM-1 - pstSoftLeadOffDetInfo -> sniqCounter];\r
+            }\r
+            switch (pstSoftLeadOffDetInfo -> sniqCounter%4)\r
+            {\r
+            case 0:\r
+                pstSoftLeadOffDetInfo -> snniVal += temp;\r
+                break;\r
+            case 1:\r
+                pstSoftLeadOffDetInfo -> snnqVal += temp;\r
+                break;\r
+            case 2:\r
+                pstSoftLeadOffDetInfo -> snniVal -= temp;\r
+                break;\r
+            case 3:\r
+                pstSoftLeadOffDetInfo -> snnqVal -= temp;\r
+                break;\r
+            default:\r
+                break;\r
+            }\r
+            if (pstSoftLeadOffDetInfo -> sniqCounter == (IQ_NUM - 1))\r
+            {\r
+                for (j = AMP_NUM-1; j >0; j--)\r
+                {\r
+                    pstSoftLeadOffDetInfo -> snniqAmp[j] = pstSoftLeadOffDetInfo -> snniqAmp[j - 1];\r
+                }\r
+                pstSoftLeadOffDetInfo -> snniVal = pstSoftLeadOffDetInfo -> snniVal >> 31;\r
+                pstSoftLeadOffDetInfo -> snnqVal = pstSoftLeadOffDetInfo -> snnqVal >> 31;\r
+                pstSoftLeadOffDetInfo -> snniqAmp[0] = pstSoftLeadOffDetInfo -> snniVal*(int)pstSoftLeadOffDetInfo -> snniVal + pstSoftLeadOffDetInfo -> snnqVal*(int)pstSoftLeadOffDetInfo -> snnqVal;\r
+                pstSoftLeadOffDetInfo -> snniVal = 0;\r
+                pstSoftLeadOffDetInfo -> snnqVal = 0;\r
+    \r
+                if (flagFastRecovery == 0)\r
+                {\r
+                    if (pstSoftLeadOffDetInfo -> snniqAmp[0] > g_lLeadOffDetIqAmpThrRaw && pstSoftLeadOffDetInfo -> snniqAmp[1] > g_lLeadOffDetIqAmpThrRaw)\r
+                        uchRet |= 0x02;\r
+\r
+                    if ((pstSoftLeadOffDetInfo -> snniqAmp[0] - pstSoftLeadOffDetInfo -> snniqAmp[2]) > g_lLeadOffDetIqAmpDiffThrRaw && (pstSoftLeadOffDetInfo -> snniqAmp[1] - pstSoftLeadOffDetInfo -> snniqAmp[2]) > g_lLeadOffDetIqAmpDiffThrRaw)\r
+                    {\r
+                        if(pstSoftLeadOffDetInfo ->snCounter > 2 * IQ_NUM)\r
+                        {\r
+                            uchRet |= 0x04;\r
+                        }\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    if (pstSoftLeadOffDetInfo -> snniqAmp[0] > g_lLeadOffDetIqAmpFrThrRaw && pstSoftLeadOffDetInfo -> snniqAmp[1] > g_lLeadOffDetIqAmpFrThrRaw)\r
+                        uchRet |= 0x08;\r
+                }\r
+            }\r
+            pstSoftLeadOffDetInfo -> sniqCounter++;\r
+            pstSoftLeadOffDetInfo -> sniqCounter = pstSoftLeadOffDetInfo -> sniqCounter%(IQ_NUM);\r
+        } // end of if (GH3X2X_AFE_CHANNEL_MAP_GET(puchFifoBuffer[usByteIndexTmp]) == g_uchEcgLeadChannelMap)\r
+    } // end of for (usByteIndexTmp = 0; usByteIndexTmp < usFifoBufferLen; usByteIndexTmp += GH3X2X_AFE_FIFO_RAWDATA_SIZE)\r
+\r
+    return uchRet;\r
+}\r
+\r
+\r
+\r
+void GH3x2xSetEcgOutputFs(GU16 usEcgOutputFs)\r
+{\r
+    g_usEcgOutputFs = usEcgOutputFs;\r
+}\r
+\r
+GU8 GH3X2X_LeadOffDetect(GU8* puchFifoBuffer, GU16* pusFifoBufferLen, GU8 uchEcgSlotNum)\r
+{\r
+    GU8 uchRet = 0;\r
+    uchRet |= GH3X2X_LeadOffDetectSingleChip(puchFifoBuffer, pusFifoBufferLen, 0, uchEcgSlotNum);\r
+    if(g_uchGh3x2xEcgChnlNumLimit > 1)\r
+    {\r
+        uchRet |= GH3X2X_LeadOffDetectSingleChip(puchFifoBuffer, pusFifoBufferLen, 1, uchEcgSlotNum);\r
+    }\r
+        return uchRet;\r
+}\r
+\r
+void GH3X2X_DownSampleCal( GU8 *puchFifoBuffer, GU16 usByteIndexTmp, GU16 *usRawdataBufIdx, GU16 usSampleRate, STGh3x2xRsInfo * pstRsInfo ,STGh3x2xDownSampleCalParamInfo * pstDownSampCalParamInfo)\r
+{\r
+    GU32 fifoVal;\r
+    GS32 adcVal;\r
+    GU8 chNo;\r
+    GU8  flagFastRecovery;\r
+    GS32 j;\r
+\r
+    fifoVal = GH3X2X_AFE_MAKEUP_DWORD(puchFifoBuffer[usByteIndexTmp], puchFifoBuffer[usByteIndexTmp + 1], puchFifoBuffer[usByteIndexTmp + 2], puchFifoBuffer[usByteIndexTmp + 3]);\r
+    chNo = (fifoVal >> 27); \r
+    adcVal = (GS32)((fifoVal & 0x00FFFFFF)) - ADC_OFFSET; \r
+       \r
+    if(g_uchDownSampleModule == DOWNSAMPLE_ECG)\r
+    {\r
+        flagFastRecovery = (fifoVal >> 26) & 0x01;\r
+        if (pstRsInfo ->uchFlagFrPrev != flagFastRecovery)\r
+        {\r
+            GH3X2X_ECGResampleConfig(usSampleRate);\r
+        }\r
+        pstRsInfo ->uchFlagFrPrev = flagFastRecovery;\r
+    }\r
+\r
+    #if __SUPPORT_ECG_PPG_DOWNSAMP__\r
+    else if(g_uchDownSampleModule == DOWNSAMPLE_PPG)\r
+    {\r
+        flagFastRecovery = (fifoVal >> 26) & 0x01;\r
+        if (pstRsInfo ->uchFlagFrPrev != 1)\r
+        {\r
+            if(usSampleRate)\r
+            {\r
+                GH3X2X_PPGResampleConfig(usSampleRate);\r
+            }\r
+        }\r
+        pstRsInfo ->uchFlagFrPrev = 1;\r
+    }\r
+    #endif\r
+               \r
+    // ECG downsample\r
+    #if RESAMPLE_320HZ_TO_250HZ || RESAMPLE_256HZ_TO_250HZ\r
+    if((DOWNSAMPLE_320HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType) || (DOWNSAMPLE_256HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType))\r
+    {  \r
+        GS32 LinerAdcVal;\r
+        if(pstDownSampCalParamInfo->uchRsEnable)\r
+        {\r
+            GS32 k;\r
+            GS64 y;\r
+\r
+            //??\r
+            if (pstRsInfo ->snRsFirState > 0)\r
+            {\r
+                pstRsInfo ->snBufHead = pstRsInfo ->snBufHead - 1;\r
+                pstRsInfo ->snBufHead = pstRsInfo ->snBufHead < 0 ? (pstDownSampCalParamInfo->uchRsBufSize - 1) : pstRsInfo ->snBufHead;\r
+                pstRsInfo ->snRsXbuf[pstRsInfo ->snBufHead] = adcVal;\r
+            }\r
+            else\r
+            {\r
+                for (j = 0; j < pstDownSampCalParamInfo->uchRsFirOrder / pstDownSampCalParamInfo->uchRsI + 1; j++)\r
+                        pstRsInfo ->snRsXbuf[j] = adcVal;\r
+                pstRsInfo ->snBufHead = pstDownSampCalParamInfo->uchRsBufSize - 1;\r
+            }\r
+                              \r
+            k = pstRsInfo ->snBufHead;\r
+            y = 0;\r
+            for (j = 1; j < pstDownSampCalParamInfo->uchRsFirCoefNum; j = j + 1) //\r
+            {\r
+                y += ((GS64)pstRsInfo ->snRsXbuf[k] * pstDownSampCalParamInfo->rsFirCoef[j]);\r
+                k = (k + 1) % pstDownSampCalParamInfo->uchRsBufSize;\r
+            }\r
+            for (; j <(pstDownSampCalParamInfo->uchRsFirOrder+1); j = j + 1) //\r
+            {\r
+                y += ((GS64)pstRsInfo ->snRsXbuf[k] * pstDownSampCalParamInfo->rsFirCoef[pstDownSampCalParamInfo->uchRsFirOrder - j]);\r
+                k = (k + 1) % pstDownSampCalParamInfo->uchRsBufSize;\r
+            }\r
+\r
+            y = y >> SHIFTBITS;\r
+            k = (GS32)y + ADC_OFFSET; //\r
+            if (k < 0)\r
+                k = 0;\r
+            else if (k>=(ADC_OFFSET * 2))\r
+                k = (ADC_OFFSET * 2-1);\r
+\r
+            // ???????\r
+            if(pstRsInfo->uchLinearInterState >0)\r
+            {\r
+                #if RESAMPLE_320HZ_TO_250HZ\r
+                if(DOWNSAMPLE_320HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType)\r
+                {\r
+                    if(pstRsInfo->fDownStep <=100)\r
+                    {\r
+                        LinerAdcVal = ((GU32)k*pstRsInfo->fDownStep + (100-pstRsInfo->fDownStep)*pstRsInfo->nRsLastRaw)/100;\r
+                        pstRsInfo->nRsLastRaw = (GU32)k;\r
+                        pstRsInfo->fDownStep = pstRsInfo->fDownStep + pstDownSampCalParamInfo->ufStep - 100;\r
+                        pstRsInfo->uchLinearDataUpdate = 1;\r
+                    }\r
+                    else\r
+                    {\r
+                        pstRsInfo->nRsLastRaw = (GU32)k;\r
+                        pstRsInfo->fDownStep = pstRsInfo->fDownStep - 100;\r
+                        pstRsInfo->uchLinearDataUpdate = 0;\r
+                    }\r
+                }\r
+                #endif\r
+\r
+                #if RESAMPLE_256HZ_TO_250HZ\r
+                if(DOWNSAMPLE_256HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType)\r
+                {\r
+                    if(pstRsInfo->fDownStep <=1000)\r
+                    {\r
+                        LinerAdcVal = (GU32)(((GS64)(k)*(GS64)(pstRsInfo->fDownStep) + (GS64)((1000-pstRsInfo->fDownStep)*(GS64)(pstRsInfo->nRsLastRaw)))/1000);\r
+                        pstRsInfo->nRsLastRaw = (GU32)k;\r
+                        pstRsInfo->fDownStep = pstRsInfo->fDownStep + pstDownSampCalParamInfo->ufStep - 1000;\r
+                        pstRsInfo->uchLinearDataUpdate = 1;\r
+                    }\r
+                    else\r
+                    {\r
+                        pstRsInfo->nRsLastRaw = (GU32)k;\r
+                        pstRsInfo->fDownStep = pstRsInfo->fDownStep - 1000;\r
+                        pstRsInfo->uchLinearDataUpdate = 0;\r
+                    }\r
+                }\r
+                #endif\r
+            }\r
+            else\r
+            {\r
+                LinerAdcVal = (GU32)k;\r
+                pstRsInfo->nRsLastRaw = (GU32)k;\r
+                pstRsInfo->fDownStep = pstRsInfo->fDownStep + pstDownSampCalParamInfo->ufStep;\r
+                pstRsInfo->uchLinearInterState =1;\r
+                pstRsInfo->uchLinearDataUpdate = 1;\r
+            }\r
+\r
+            if(pstRsInfo->uchLinearDataUpdate == 1)\r
+            {\r
+                fifoVal = (((GU8)chNo)<<27) + (((GU8)flagFastRecovery)<<26) + ((GU32)LinerAdcVal/5);\r
+                puchFifoBuffer[*usRawdataBufIdx]     = GH3X2X_AFE_GET_BYTE3_FROM_DWORD(fifoVal);\r
+                puchFifoBuffer[*usRawdataBufIdx + 1] = GH3X2X_AFE_GET_BYTE2_FROM_DWORD(fifoVal);\r
+                puchFifoBuffer[*usRawdataBufIdx + 2] = GH3X2X_AFE_GET_BYTE1_FROM_DWORD(fifoVal);\r
+                puchFifoBuffer[*usRawdataBufIdx + 3] = GH3X2X_AFE_GET_BYTE0_FROM_DWORD(fifoVal);\r
+\r
+                *usRawdataBufIdx += GH3X2X_AFE_FIFO_RAWDATA_SIZE;\r
+            }\r
+        }\r
+    }\r
+    #endif\r
+\r
+    #if  RESAMPLE_800HZ_TO_500HZ ||RESAMPLE_800HZ_TO_250HZ || (RESAMPLE_400HZ_TO_250HZ & (__SUPPORT_ECG_PPG_DOWNSAMP__))\r
+    if((DOWNSAMPLE_800HZ_TO_500HZ == pstECGDownSampCalParamInfo->uchDownSampleType)||(DOWNSAMPLE_800HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType)||(DOWNSAMPLE_400HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType))\r
+    {\r
+        if(pstDownSampCalParamInfo->uchRsEnable)\r
+        {\r
+            GS32 k;\r
+            GS64 y;\r
+            GS32 delta;\r
+            if (pstRsInfo ->snRsFirState > 0)\r
+            {\r
+                pstRsInfo ->snBufHead = pstRsInfo ->snBufHead - 1;\r
+                pstRsInfo ->snBufHead = pstRsInfo ->snBufHead < 0 ? (pstDownSampCalParamInfo->uchRsBufSize - 1) : pstRsInfo ->snBufHead;\r
+                pstRsInfo ->snRsXbuf[pstRsInfo ->snBufHead] = adcVal;\r
+                pstRsInfo ->nRsIcounter += pstDownSampCalParamInfo->uchRsI;\r
+            }\r
+            else\r
+            {\r
+                for (j = 0; j < pstDownSampCalParamInfo->uchRsFirOrder / pstDownSampCalParamInfo->uchRsI + 1; j++)\r
+                        pstRsInfo ->snRsXbuf[j] = adcVal;\r
+                pstRsInfo ->nRsIcounter = 0;\r
+                pstRsInfo ->snRsFirState = 1;\r
+                pstRsInfo ->snBufHead = pstDownSampCalParamInfo->uchRsBufSize - 1;\r
+            }\r
+\r
+            if (pstRsInfo ->nRrsDcounter >= pstRsInfo ->nRsIcounter && pstRsInfo ->nRrsDcounter < (pstRsInfo ->nRsIcounter + pstDownSampCalParamInfo->uchRsI))\r
+            {\r
+                delta = pstRsInfo ->nRrsDcounter - pstRsInfo ->nRsIcounter;\r
+                k = pstRsInfo ->snBufHead;\r
+                y = 0;\r
+                for (j = delta; j < pstDownSampCalParamInfo->uchRsFirCoefNum; j = j + pstDownSampCalParamInfo->uchRsI)\r
+                {\r
+                        y += ((GS64)pstRsInfo ->snRsXbuf[k] * pstDownSampCalParamInfo->rsFirCoef[j]);\r
+                        k = (k + 1) % pstDownSampCalParamInfo->uchRsBufSize;\r
+                }\r
+                for (j = j; j <(pstDownSampCalParamInfo->uchRsFirOrder+1); j = j + pstDownSampCalParamInfo->uchRsI)\r
+                {\r
+                        y += ((GS64)pstRsInfo ->snRsXbuf[k] * pstDownSampCalParamInfo->rsFirCoef[pstDownSampCalParamInfo->uchRsFirOrder - j]);\r
+                        k = (k + 1) % pstDownSampCalParamInfo->uchRsBufSize;\r
+                }\r
+                pstRsInfo ->nRrsDcounter += pstDownSampCalParamInfo->uchRsD;\r
+\r
+                y = y >> SHIFTBITS;\r
+                k = (GS32)y + ADC_OFFSET;\r
+                if (k < 0)\r
+                        k = 0;\r
+                else if (k>=(ADC_OFFSET * 2))\r
+                        k = (ADC_OFFSET * 2-1); \r
+                fifoVal = (((GU8)chNo)<<27) + (((GU8)flagFastRecovery)<<26) + ((GU32)k);\r
+                puchFifoBuffer[*usRawdataBufIdx]     = GH3X2X_AFE_GET_BYTE3_FROM_DWORD(fifoVal);\r
+                puchFifoBuffer[*usRawdataBufIdx + 1] = GH3X2X_AFE_GET_BYTE2_FROM_DWORD(fifoVal);\r
+                puchFifoBuffer[*usRawdataBufIdx + 2] = GH3X2X_AFE_GET_BYTE1_FROM_DWORD(fifoVal);\r
+                puchFifoBuffer[*usRawdataBufIdx + 3] = GH3X2X_AFE_GET_BYTE0_FROM_DWORD(fifoVal);\r
+                *usRawdataBufIdx += GH3X2X_AFE_FIFO_RAWDATA_SIZE;\r
+            }\r
+        }\r
+    }\r
+#endif\r
+}\r
+\r
+void GH3X2X_EcgPPGRsHandleSingleChip(GU8 *puchFifoBuffer, GU16 *pusFifoBufferLen, GU8 uchChipIndex, GU8 uchEcgSlotNum ,GU16 usSampleRate)\r
+{\r
+    GU16 usByteIndexTmp = 0;\r
+    GU16 usRawdataBufIdx = 0;\r
+    GU8  usCheckDataType = 0; // 1:ECG 2:PPG 0:other\r
+\r
+    for (usByteIndexTmp = 0; usByteIndexTmp < *pusFifoBufferLen; usByteIndexTmp += GH3X2X_AFE_FIFO_RAWDATA_SIZE)\r
+    {  \r
+        if (GH3X2X_AFE_CHANNEL_MAP_GET(puchFifoBuffer[usByteIndexTmp]) == GH3X2X_AFE_GET_ECG_CHANNEL_MAP((GU8)(GH3X2X_ECG_START_SLOT + uchEcgSlotNum)))\r
+        {\r
+            STGh3x2xRsInfo * pstRsInfo_ECG = g_pstGh3x2xEcgRsInfo + uchChipIndex;\r
+            g_uchDownSampleModule = DOWNSAMPLE_ECG;\r
+            GH3X2X_DownSampleCal( puchFifoBuffer, usByteIndexTmp, &usRawdataBufIdx, usSampleRate,pstRsInfo_ECG,pstECGDownSampCalParamInfo);\r
+            usCheckDataType =1;\r
+        }\r
+                                       \r
+        #if __SUPPORT_ECG_PPG_DOWNSAMP__\r
+        if(g_uchPPGDownSampleChnlNumLimit && pstPPGDownSampCalParamInfo->uchRsEnable==1)\r
+        {\r
+            for(GU8 uchPPGSlotNumTmp = 0; uchPPGSlotNumTmp < g_uchPPGDownSampleChnlNumLimit; uchPPGSlotNumTmp++)\r
+            {\r
+                if (GH3X2X_AFE_CHANNEL_MAP_GET(puchFifoBuffer[usByteIndexTmp]) == GH3X2X_AFE_GET_PPG_CHANNEL_MAP((GU8)(GH3X2X_PPG_START_SLOT + uchPPGSlotNumTmp)))\r
+                {\r
+                    STGh3x2xRsInfo * pstRsInfo_PPG = g_pstGh3x2xPPGRsInfo + uchPPGSlotNumTmp;\r
+                    g_uchDownSampleModule = DOWNSAMPLE_PPG;\r
+                    GH3X2X_DownSampleCal(puchFifoBuffer, usByteIndexTmp, &usRawdataBufIdx, usSampleRate,pstRsInfo_PPG,pstPPGDownSampCalParamInfo);\r
+                    usCheckDataType =2;\r
+                }\r
+            }\r
+        }\r
+        #endif\r
+        if(!usCheckDataType)\r
+        {\r
+            if(pstECGDownSampCalParamInfo->uchRsEnable)\r
+            {\r
+                //this rawdata is not ECG data\r
+                puchFifoBuffer[usRawdataBufIdx]     = puchFifoBuffer[usByteIndexTmp];\r
+                puchFifoBuffer[usRawdataBufIdx + 1] = puchFifoBuffer[usByteIndexTmp + 1];\r
+                puchFifoBuffer[usRawdataBufIdx + 2] = puchFifoBuffer[usByteIndexTmp + 2];\r
+                puchFifoBuffer[usRawdataBufIdx + 3] = puchFifoBuffer[usByteIndexTmp + 3];\r
+                usRawdataBufIdx += GH3X2X_AFE_FIFO_RAWDATA_SIZE;\r
+            }\r
+        }\r
+        usCheckDataType = 0;\r
+    } // end of for (usByteIndexTmp = 0; usByteIndexTmp < usFifoBufferLen; usByteIndexTmp += GH3X2X_AFE_FIFO_RAWDATA_SIZE)\r
+    *pusFifoBufferLen = usRawdataBufIdx;\r
+}\r
+\r
+GU8 GH3X2X_AFE_EcgRsHandle(GU8* puchFifoBuffer, GU16* pusFifoBufferLen, GU8 uchEcgSlotNum, GU16 usEcgSampleRate)\r
+{\r
+    if(pstECGDownSampCalParamInfo->uchRsEnable == 1)\r
+    {\r
+        GH3X2X_EcgPPGRsHandleSingleChip(puchFifoBuffer, pusFifoBufferLen, 0,uchEcgSlotNum,usEcgSampleRate);\r
+        return 1;\r
+    }\r
+    else\r
+    {\r
+        return 0;\r
+    }\r
+}\r
+\r
+/********END OF FILE********* Copyright (c) 2003 - 2022, Goodix Co., Ltd. ********/\r
+\r
+\r
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_user.c b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_user.c
new file mode 100644 (file)
index 0000000..c067d1a
--- /dev/null
@@ -0,0 +1,468 @@
+#include "gh3x2x_afe_user.h"\r
+#include "gh3x2x_afe_drv.h"\r
+#include "pinctrl_porting.h"\r
+#include "hal_gpio.h"\r
+#include "i2c.h"\r
+#include "pm_definition.h"\r
+#if GH3X2X_AFE_MP_MODE\r
+// #include "gh3x2x_mp_common.h"\r
+#endif\r
+\r
+#include "los_tick.h"\r
+#include "debug_print.h"\r
+\r
+#ifdef GOODIX_DEMO_PLATFORM\r
+#include "gh3x2x_demo_goodix_PLATFORM.h"\r
+#else\r
+\r
+\r
+#include "spi.h"\r
+\r
+#include "custom_utils.h"\r
+\r
+#define GOODIX_PLATFORM_SPI_WRITE_ENTITY(write_buffer, length)\r
+#define GOODIX_PLATFORM_SPI_READ_ENTITY()\r
+#define GOODIX_PLATFORM_SPI_CS_CTRL_ENTITY()\r
+#define GOODIX_PLATFORM_SPI_RESET_PIN_ENTITY()\r
+#define GOODIX_PLATFORM_INT_HANDLER_CALL_BACK_ENTITY()\r
+#define GOODIX_PLATFORM_LOG_ENTITY()      \r
+#define GOODIX_PLATFORM_DELAY_US_ENTITY()\r
+#define GOODIX_PLATFORM_DELAY_MS_ENTITY()\r
+#define GOODIX_PLATFORM_DELAY_MS_ENTITY()\r
+#define GOODIX_PLATFORM_INT_INIT_ENTITY()\r
+#define GOODIX_PLATFORM_RESET_PIN_INIT_ENTITY()\r
+#define GOODIX_PLATFORM_SPI_INIT_ENTITY()\r
+#define GOODIX_PLATFORM_I2C_WRITE_ENTITY(device_id, write_buffer,length)\r
+#define GOODIX_PLATFORM_I2C_INIT_ENTITY()\r
+#define GOODIX_PLATFORM_I2C_READ_ENTITY(device_id, write_buffer, write_length, read_buffer, read_length)\r
+#endif\r
+\r
+#define GH3X2X_CS   S_MGPIO3\r
+#define GH3X2X_CLK  S_MGPIO2\r
+#define GH3X2X_MOSI S_MGPIO1\r
+#define GH3X2X_MISO S_MGPIO0\r
+\r
+#define H_INT S_AGPIO_R6\r
+\r
+#define GH3X2X_SPI_BUS SPI_BUS_0\r
+#define GH3X2X_I2C_BUS I2C_BUS_2\r
+\r
+/**\r
+ * @fn     void hal_gh3x2x_afe_DelayUs(GU16 usUsec)\r
+ * \r
+ * @brief  Delay in us,user should register this function into driver lib\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   None\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+\r
+void hal_gh3x2x_afe_DelayUs(GU16 usUsec)\r
+{\r
+    // GH3X2X_AFE_UNUSED_VAR(usUsec);\r
+    // GOODIX_PLATFORM_DELAY_US_ENTITY();\r
+    LOS_Udelay(usUsec);\r
+\r
+}\r
+\r
+/**\r
+ * @fn     void hal_gh3x2x_afe_BspDelayMs(GU16 usMsec)\r
+ * \r
+ * @brief  Delay in ms\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   None\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+void hal_gh3x2x_afe_DelayMs(GU16 usMsec)\r
+{\r
+    // GH3X2X_AFE_UNUSED_VAR(usMsec);\r
+    // GOODIX_PLATFORM_DELAY_MS_ENTITY();\r
+    LOS_Mdelay(usMsec);\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+#if ( GH3X2X_AFE_COM_INTERFACE_TYPE == GH3X2X_AFE_COM_INTERFACE_I2C )\r
+\r
+/* i2c interface */\r
+/**\r
+ * @fn     void hal_gh3x2x_afe_i2c_init(void)\r
+ * \r
+ * @brief  hal i2c init for gh3x2x_afe\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   None\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+void hal_gh3x2x_afe_i2c_init(void)\r
+{\r
+\r
+    /* code implement by user */\r
+    GOODIX_PLATFORM_I2C_INIT_ENTITY();\r
+\r
+}\r
+\r
+/**\r
+ * @fn     uint8_t hal_gh3x2x_afe_i2c_write(uint8_t device_id, const uint8_t write_buffer[], uint16_t length)\r
+ * \r
+ * @brief  hal i2c write for gh3x2x_afe\r
+ *\r
+ * @attention   device_id is 8bits, if platform i2c use 7bits addr, should use (device_id >> 1)\r
+ *\r
+ * @param[in]   device_id       device addr\r
+ * @param[in]   write_buffer    write data buffer\r
+ * @param[in]   length          write data len\r
+ * @param[out]  None\r
+ *\r
+ * @return  status\r
+ * @retval  #1      return successfully\r
+ * @retval  #0      return error\r
+ */\r
+GU8 hal_gh3x2x_afe_i2c_write(GU8 device_id, const GU8 write_buffer[], GU16 length)\r
+{\r
+    // custom_i2c_transfer(0x14,write_buffer, length, NULL, 0, GH3X2X_I2C_BUS);\r
+    custom_i2c_write_reg(0x14, 0, 0, write_buffer, length, GH3X2X_I2C_BUS);\r
+    return 1;\r
+}\r
+\r
+/**\r
+ * @fn     uint8_t hal_gh3x2x_afe_i2c_read(uint8_t device_id, const uint8_t write_buffer[], uint16_t write_length,\r
+ *                            uint8_t read_buffer[], uint16_t read_length)\r
+ * \r
+ * @brief  hal i2c read for gh3x2x_afe\r
+ *\r
+ * @attention   device_id is 8bits, if platform i2c use 7bits addr, should use (device_id >> 1)\r
+ *\r
+ * @param[in]   device_id       device addr\r
+ * @param[in]   write_buffer    write data buffer\r
+ * @param[in]   write_length    write data len\r
+ * @param[in]   read_length     read data len\r
+ * @param[out]  read_buffer     pointer to read buffer\r
+ *\r
+ * @return  status\r
+ * @retval  #1      return successfully\r
+ * @retval  #0      return error\r
+ */\r
+GU8 hal_gh3x2x_afe_i2c_read(GU8 device_id, const GU8 write_buffer[], GU16 write_length, GU8 read_buffer[], GU16 read_length)\r
+{\r
+    // custom_i2c_transfer(0x14,write_buffer, write_length, read_buffer, read_length, GH3X2X_I2C_BUS);\r
+    // custom_i2c_write_reg(0x14, 0, 0, write_buffer, length, GH3X2X_I2C_BUS);\r
+    custom_i2c_read_regs(0x14, write_buffer, write_length, read_buffer,read_length, GH3X2X_I2C_BUS);\r
+    return 1;\r
+}\r
+\r
+#else \r
+\r
+/* spi interface */\r
+/**\r
+ * @fn     void hal_gh3x2x_afe_spi_init(void)\r
+ * \r
+ * @brief  hal spi init for gh3x2x_afe\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   None\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+\r
+void hal_gh3x2x_afe_spi_init(void)\r
+{\r
+    /* init spi and cs pin */\r
+    GOODIX_PLATFORM_SPI_INIT_ENTITY();\r
+}\r
+\r
+/**\r
+ * @fn     GU8 hal_gh3x2x_afe_spi_write(GU8 write_buffer[], GU16 length)\r
+ * \r
+ * @brief  hal spi write for gh3x2x_afe\r
+ *\r
+ * @attention   if __gh3x2x_afe_SPI_TYPE__ == __gh3x2x_afe_SPI_TYPE_SOFTWARE_CS__  , user need generate timming: write_buf[0](W) + write_buf[1](W) + ...\r
+ * @attention   if __gh3x2x_afe_SPI_TYPE__ == __gh3x2x_afe_SPI_TYPE_HARDWARE_CS__  , user need generate timming: CS LOW  + write_buf[0](W) + write_buf[1](W) + ... + CS HIGH\r
+ *\r
+ * @param[in]   write_buffer    write data buffer\r
+ * @param[in]   length          write data len\r
+ * @param[out]  None\r
+ *\r
+ * @return  status\r
+ * @retval  #1      return successfully\r
+ * @retval  #0      return error\r
+ */\r
+GU8 hal_gh3x2x_afe_spi_write(GU8 write_buffer[], GU16 length)\r
+{\r
+    uint8_t cnt = pm_veto_get_id_cnt(PM_ID_HEART);\r
+    if (cnt == 0) \r
+    {\r
+        uapi_pm_add_sleep_veto(PM_ID_HEART);\r
+    }\r
+\r
+    errcode_t ret;\r
+\r
+    //   GOODIX_PLATFORM_SPI_WRITE_ENTITY(write_buffer, length);\r
+    spi_xfer_data_t sdata ={0} ;\r
+       sdata.tx_buff = write_buffer;\r
+       sdata.tx_bytes = length;\r
+       sdata.rx_buff = NULL;\r
+       sdata.rx_bytes = 0;\r
+\r
+    ret = uapi_spi_master_write(GH3X2X_SPI_BUS, &sdata, 0XFF);\r
+    if (ret != ERRCODE_SUCC) \r
+        printf("spi write data fail! ret=0x%x\n", ret);\r
+\r
+    cnt = pm_veto_get_id_cnt(PM_ID_HEART);\r
+    if (cnt == 1) \r
+    {\r
+        uapi_pm_remove_sleep_veto(PM_ID_HEART);\r
+    }\r
+\r
+    return 1;\r
+}\r
+\r
+\r
+#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS) \r
+/**\r
+ * @fn     GU8 hal_gh3x2x_afe_spi_read(GU8 read_buffer[], GU16 length)\r
+ * \r
+ * @brief  hal spi read for gh3x2x_afe\r
+ *\r
+ * @attention   user need generate timming: read_buf[0](R) + write_buf[1](R) + ... \r
+ *\r
+ * @param[in]   read_length     read data len\r
+ * @param[out]  read_buffer     pointer to read buffer\r
+ *\r
+ * @return  status\r
+ * @retval  #1      return successfully\r
+ * @retval  #0      return error\r
+ */\r
+GU8 hal_gh3x2x_afe_spi_read(GU8 read_buffer[], GU16 length)\r
+{\r
+    uint8_t cnt = pm_veto_get_id_cnt(PM_ID_HEART);\r
+    if (cnt == 0) \r
+    {\r
+        uapi_pm_add_sleep_veto(PM_ID_HEART);\r
+    }\r
+\r
+    errcode_t ret;\r
+    // GH3X2X_AFE_UNUSED_VAR(read_buffer);\r
+    // GH3X2X_AFE_UNUSED_VAR(length);\r
+    // GOODIX_PLATFORM_SPI_READ_ENTITY();\r
+\r
+    spi_xfer_data_t sdata ={0} ;\r
+       sdata.tx_buff = NULL;\r
+       sdata.tx_bytes = 0;\r
+       sdata.rx_buff = read_buffer;\r
+       sdata.rx_bytes = length;\r
+\r
+    ret = uapi_spi_master_read(GH3X2X_SPI_BUS, &sdata, 0XFF);\r
+\r
+    cnt = pm_veto_get_id_cnt(PM_ID_HEART);\r
+    if (cnt == 1) \r
+    {\r
+        uapi_pm_remove_sleep_veto(PM_ID_HEART);\r
+    }\r
+\r
+    return 1;\r
+}\r
+#elif (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_HARDWEAR_CS)\r
+/**\r
+ * @fn     GU8 hal_gh3x2x_afe_spi_write_F1_and_read(GU8 read_buffer[], GU16 length)\r
+ * \r
+ * @brief  hal spi write F1 and read for gh3x2x_afe\r
+ *\r
+ * @attention    user need generate timming: CS LOW + F1(W) + read_buf[0](R) + read_buf[1](R) + ... + CS HIGH\r
+ *\r
+ * @param[in]   write_buf     write data\r
+ * @param[in]   length     write data len\r
+ *\r
+ * @return  status\r
+ * @retval  #1      return successfully\r
+ * @retval  #0      return error\r
+ */\r
+GU8 hal_gh3x2x_afe_spi_write_F1_and_read(GU8 read_buffer[], GU16 length)\r
+{\r
+    // GU8 ret = 1;\r
+    // GH3X2X_AFE_UNUSED_VAR(read_buffer);\r
+    // GH3X2X_AFE_UNUSED_VAR(length);\r
+    // GOODIX_PLATFORM_SPI_READ_ENTITY();\r
+    \r
+    // return ret;\r
+\r
+    errcode_t ret = 1;\r
+    // GH3X2X_AFE_UNUSED_VAR(read_buffer);\r
+    // GH3X2X_AFE_UNUSED_VAR(length);\r
+    // GOODIX_PLATFORM_SPI_READ_ENTITY();\r
+\r
+    spi_xfer_data_t sdata ={0} ;\r
+       sdata.tx_buff = NULL;\r
+       sdata.tx_bytes = 0;\r
+       sdata.rx_buff = read_buffer;\r
+       sdata.rx_bytes = length;\r
+\r
+    ret = uapi_spi_master_read(GH3X2X_SPI_BUS, &sdata, 0XFF);\r
+    if (ret != ERRCODE_SUCC) \r
+        printf("spi read data fail! ret=0x%x\n", ret);\r
+    return 1;\r
+}\r
+#endif\r
+\r
+/**\r
+ * @fn     void hal_gh3x2x_afe_spi_cs_ctrl(GU8 cs_pin_level)\r
+ * \r
+ * @brief  hal spi cs pin ctrl for gh3x2x_afe\r
+ *\r
+ * @attention   pin level set 1 [high level] or 0 [low level]\r
+ *\r
+ * @param[in]   cs_pin_level     spi cs pin level\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+\r
+\r
+\r
+#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS) \r
+void hal_gh3x2x_afe_spi_cs_ctrl(GU8 cs_pin_level)\r
+{\r
+    // GH3X2X_AFE_UNUSED_VAR(cs_pin_level);\r
+    // GOODIX_PLATFORM_SPI_CS_CTRL_ENTITY();\r
+\r
+    uapi_pin_set_mode(GH3X2X_CS, (pin_mode_t)HAL_PIO_FUNC_SPI0);\r
+    uapi_gpio_set_dir(GH3X2X_CS, GPIO_DIRECTION_OUTPUT);\r
+    uapi_gpio_set_val(GH3X2X_CS, cs_pin_level);\r
+\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
+#if (GH3X2X_AFE_RESET_TYPE == GH3X2X_AFE_RESET_HARDWARE)\r
+/**\r
+ * @fn     void hal_gh3x2x_afe_int_init(void)\r
+ * \r
+ * @brief  gh3x2x_afe int init\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   None\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+\r
+\r
+\r
+void hal_gh3x2x_afe_reset_pin_init(void)\r
+{\r
+    GOODIX_PLATFORM_RESET_PIN_INIT_ENTITY();\r
+}\r
+\r
+/**\r
+ * @fn     void hal_gh3x2x_afe_reset_pin_ctrl(GU8 pin_level)\r
+ * \r
+ * @brief  hal reset pin ctrl for gh3x2x_afe\r
+ *\r
+ * @attention   pin level set 1 [high level] or 0 [low level]\r
+ *\r
+ * @param[in]   pin_level     reset pin level\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+\r
+void hal_gh3x2x_afe_reset_pin_ctrl(GU8 pin_level)\r
+{\r
+    GH3X2X_AFE_UNUSED_VAR(pin_level);\r
+    GOODIX_PLATFORM_SPI_RESET_PIN_ENTITY();\r
+}\r
+\r
+#endif\r
+\r
+/**\r
+ * @fn     void hal_gh3x2x_afe_int_init(void)\r
+ * \r
+ * @brief  gh3x2x_afe int init\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   None\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+\r
+\r
+void hal_gh3x2x_afe_int_init(void)\r
+{\r
+    // GOODIX_PLATFORM_INT_INIT_ENTITY();\r
+    uapi_pin_set_ie(H_INT,HAL_PIO_IE_ENBALE);\r
+}\r
+\r
+void hal_gh3x2x_afe_int_deinit(void)\r
+{\r
+    // GOODIX_PLATFORM_INT_INIT_ENTITY();\r
+    uapi_pin_set_ie(H_INT,HAL_PIO_IE_DISABLE);\r
+}\r
+\r
+#if (GH3X2X_AFE_PRO_BY_INT == GH3X2X_AFE_PRO_TYPE)\r
+/**\r
+ * @fn     void hal_gh3x2x_afe_int_handler_call_back(void)\r
+ * \r
+ * @brief  call back of gh3x2x_afe int handler\r
+ *\r
+ * @attention   None\r
+ *\r
+ * @param[in]   None\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+void hal_gh3x2x_afe_int_handler_call_back(void)\r
+{\r
+/****************** DO NOT MODITY ****************************************************************/\r
+       GH3X2X_AFE_SetNeedWakeUpGh3x2xFlag(0);  //not need wake up gh3x2x_afe when process int event\r
+       g_uchGh3x2xAfeIntCallBackIsCalled = 1;\r
+#if GH3X2X_AFE_MP_MODE\r
+       // GH3X2X_MP_SET_INT_FLAG();  //gh3x2x mp test must call it\r
+#endif\r
+/****************** DO NOT MODITY ****************************************************************/\r
+    \r
+    \r
+    \r
+    GOODIX_PLATFORM_INT_HANDLER_CALL_BACK_ENTITY();\r
+}\r
+\r
+#endif\r
+\r
+/**\r
+ * @fn     void GH3X2X_AFE_Log(char *log_string)\r
+ * \r
+ * @brief  for debug version, log\r
+ *\r
+ * @attention   this function must define that use debug version lib\r
+ *\r
+ * @param[in]   log_string      pointer to log string\r
+ * @param[out]  None\r
+ *\r
+ * @return  None\r
+ */\r
+void GH3X2X_AFE_Log(GCHAR *log_string)\r
+{\r
+    // GH3X2X_AFE_UNUSED_VAR(log_string);\r
+    // GOODIX_PLATFORM_LOG_ENTITY();\r
+    PRINT("%s", log_string);\r
+}\r
+\r
diff --git a/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_hal.c b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_hal.c
new file mode 100644 (file)
index 0000000..385077b
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * @Author: penglei 1624952103@qq.com
+ * @Date: 2024-03-13 15:08:38
+ * @LastEditors: penglei 1624952103@qq.com
+ * @LastEditTime: 2025-05-28 14:13:17
+ * @FilePath: /FD230/code/sdk/drivers/peripheral/ppg/hx3695/hx3695_hal.c
+ * @Description: 
+ * 
+ * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. 
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+#include "pm_control.h"
+#include "pinctrl_porting.h"
+#include "hal_gpio.h"
+#include "gh3x2x_afe_user.h"
+#include "gh3x2x_afe_demo.h"
+
+// S_AGPIO_L26 心率复位 PPG reset
+#define GPIO_PIN_PRG_RESET S_AGPIO_L26
+// S_AGPIO_R0 PRG_LED_POWER ON  心率等电源控制脚
+#define GPIO_PIN_PRG_LED_ON S_AGPIO_R0
+
+uint32_t tyhx_poweron(void)
+{
+    uapi_pin_set_mode(GPIO_PIN_PRG_LED_ON, (pin_mode_t)HAL_PIO_FUNC_GPIO);
+    uapi_gpio_set_dir(GPIO_PIN_PRG_LED_ON, GPIO_DIRECTION_OUTPUT);
+    uapi_gpio_set_val(GPIO_PIN_PRG_LED_ON, GPIO_LEVEL_HIGH);
+    
+    uapi_pin_set_mode(GPIO_PIN_PRG_RESET, (pin_mode_t)HAL_PIO_FUNC_GPIO);
+    uapi_gpio_set_dir(GPIO_PIN_PRG_RESET, GPIO_DIRECTION_OUTPUT);
+    uapi_gpio_set_val(GPIO_PIN_PRG_RESET, GPIO_LEVEL_HIGH);
+    LOS_Mdelay(10);
+    return 0;
+}
+uint32_t tyhx_poweroff(void)
+{
+    hal_gh3x2x_afe_int_deinit();
+    
+    uapi_pin_set_mode(GPIO_PIN_PRG_RESET, (pin_mode_t)HAL_PIO_FUNC_GPIO);
+    uapi_gpio_set_dir(GPIO_PIN_PRG_RESET, GPIO_DIRECTION_OUTPUT);
+    uapi_gpio_set_val(GPIO_PIN_PRG_RESET, GPIO_LEVEL_LOW);
+   
+    uapi_pin_set_mode(GPIO_PIN_PRG_LED_ON, (pin_mode_t)HAL_PIO_FUNC_GPIO);
+    uapi_gpio_set_dir(GPIO_PIN_PRG_LED_ON, GPIO_DIRECTION_OUTPUT);
+    uapi_gpio_set_val(GPIO_PIN_PRG_LED_ON, GPIO_LEVEL_LOW);
+    LOS_Mdelay(10);
+    return 0;
+}
+
+void ppg_send_cmd_to_gh3x2x_driver(char* mode, uint8_t enable)
+{
+
+    uint32_t md = 1;
+    if (strcmp(mode, "hrs") == 0) {
+        md = 0;
+    } else if (strcmp(mode, "hrv") == 0) {
+        md = 1;
+    } else if (strcmp(mode, "spo2") == 0) {
+        md = 2;
+    } else if (strcmp(mode, "leaklight") == 0) {
+        md = 4;
+    } else if (strcmp(mode, "graycard") == 0) {
+        md = 8;
+    } else if (strcmp(mode, "ledoff") == 0) {
+        md = 16;
+    } else if (strcmp(mode, "wear") == 0) {
+        md = 32;
+    } else if (strcmp(mode, "single") == 0) {
+        md = 64;
+    }else if (strcmp(mode, "factory") == 0) {
+        md = 128;
+    }else if (strcmp(mode, "fpc") == 0) {
+        // md = WORK_MODE_UNDEFINED;
+    }else if (strcmp(mode, "int") == 0) {
+    } 
+
+    if (enable == 1)
+    {
+        // ppg_service_running_stat = true;
+        // uapi_pm_control(PM_APP_WAKE_NEEDED);
+        tyhx_poweron();
+        // GH3X2X_AFE_StartFunction(mode);
+        GH3X2X_AFE_Init();
+        GH3X2X_AFE_StartSampling(1);
+
+    } else {
+        
+        // uapi_pm_control(PM_APP_WAKE_NONEED);
+        GH3X2X_AFE_StopSampling();
+        tyhx_poweroff();
+    } 
+}
\ No newline at end of file
index 4c48871..a38e2d0 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: penglei 1624952103@qq.com
  * @Date: 2024-03-13 15:08:38
  * @LastEditors: penglei 1624952103@qq.com
- * @LastEditTime: 2025-06-05 15:25:30
+ * @LastEditTime: 2025-06-09 11:37:07
  * @FilePath: /FD230/code/sdk/drivers/peripheral/ppg/hx3695/hx3695_hal.c
  * @Description: 
  * 
 #include "pah800x_main.h"
 #endif
 
+#ifdef PPG_GH3X2X
+#include "gh3x2x_afe_drv.h"
+#endif
+
+
 #ifdef SUPPORT_CYWEE_SERVICE
 #include "cywee_service.h"
 #endif
@@ -105,6 +110,8 @@ uint16_t ppg_get_chip_id(void)
     chip_id = hx3695_chip_check();
 #elif defined PPG_PAH8009
     chip_id = pah8009_get_chip_id();
+#elif defined PPG_GH3X2X
+    chip_id = GH3X2X_AFE_GetChipId();
 #endif
         ppg_power_off();
     return chip_id;
@@ -130,6 +137,9 @@ void ppg_int_handler(void)
 {
 #ifdef PPG_PAH8009
     pah8009_int_handler();
+#elif defined PPG_PAH8009
+    hal_gh3x2x_afe_int_handler_call_back();
+    GH3X2X_AFE_ChipPro();
 #endif
 }
 
@@ -142,6 +152,8 @@ void ppg_send_cmd_to_driver(char* mode, uint8_t enable)
     hx3695_control(mode,enable);
 #elif defined PPG_PAH8009
     pah8009_control(mode,enable);
+#elif defined PPG_GH3X2X
+    gh3x2x_control(mode,enable);
 #endif
     if(!enable)
         ppg_power_off();
index d878a71..8cda8ad 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: penglei 1624952103@qq.com
  * @Date: 2024-06-07 11:18:26
  * @LastEditors: penglei 1624952103@qq.com
- * @LastEditTime: 2025-06-05 14:46:32
+ * @LastEditTime: 2025-06-09 11:26:55
  * @FilePath: /FD230/code/sdk/drivers/peripheral/ppg/ppg/ppg_hal.h
  * @Description: 
  * 
@@ -27,6 +27,8 @@ extern "C" {
 #define PPG_CHIP_ID 0x65
 #elif defined PPG_PAH8009
 #define PPG_CHIP_ID 0x8008
+#elif defined PPG_GH3X2X
+#define PPG_CHIP_ID GH3X2X_CHIP_ID
 #else
 #define PPG_CHIP_ID 0
 #endif
index a208d81..f6b2a8e 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: penglei 1624952103@qq.com\r
  * @Date: 2025-05-27 11:09:04\r
  * @LastEditors: penglei 1624952103@qq.com\r
- * @LastEditTime: 2025-06-04 15:38:48\r
+ * @LastEditTime: 2025-06-09 14:27:54\r
  * @FilePath: /sdk615/code/sdk/zhihui/drivers/ppg/pah8009/sensor/pah800x_bsp.c\r
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE\r
  */\r
 #include "custom_utils.h"\r
 #include "systick.h"\r
 \r
+#ifdef SUPPORT_CYWEE_SERVICE\r
+#include "cywee_hal.h"\r
+#endif\r
+\r
 //============================================================================\r
 // Definition\r
 //============================================================================\r
@@ -81,5 +85,11 @@ void pah_print(
 \r
 void ReadGSensor(float *x, float *y, float *z)\r
 {\r
-    \r
+#ifdef SUPPORT_CYWEE_SERVICE\r
+    gsenson_t data = {0};\r
+    gsensor_get_n_data(1,&data);\r
+    *x = data.x;\r
+    *y = data.y;\r
+    *z = data.z;\r
+#endif\r
 }\r
index 6cb58fa..f824d63 100644 (file)
@@ -507,6 +507,7 @@ void hr_alg_task(void)
                     // data = cywee_wear_status;\r
                     // func(PPG_MSG_TYPE_WEARSTAT_UPDATE, &data, 1);\r
                     time_cnt = 0;\r
+                    hr = 0;\r
                 }\r
 #endif\r
                 report_hr_data(&ppg_mems_data_alg, ret, hr, hr_grader);\r
@@ -1380,9 +1381,12 @@ static void process(uint64_t timestamp)
             //MEMS_SensorZ() absolute data must be largest when let hand horizontal on the table at static state.\r
             /***********************G sensor explanation end***********************************/\r
 \r
-            ppg_mems_data.MEMS_Data[0] = mems_data[0];//ReadGSensorX();\r
-            ppg_mems_data.MEMS_Data[1] = mems_data[1];//ReadGSensorY();\r
-            ppg_mems_data.MEMS_Data[2] = mems_data[2];//ReadGSensorZ();\r
+            ReadGSensor(&mems_data[0],&mems_data[1],&mems_data[2]);\r
+\r
+            ppg_mems_data.MEMS_Data[0] = mems_data[0] * 2048 / 10;//ReadGSensorX();\r
+            ppg_mems_data.MEMS_Data[1] = mems_data[1] * 2048 / 10;//ReadGSensorY();\r
+            ppg_mems_data.MEMS_Data[2] = mems_data[2] * 2048 / 10;//ReadGSensorZ();\r
+            // printf("x:%f y:%f z:%f\n",ppg_mems_data.MEMS_Data[0],ppg_mems_data.MEMS_Data[1],ppg_mems_data.MEMS_Data[2]);\r
             ppg_mems_data.duration = duration;\r
             \r
             ppg_mems_data.ppg_data = ppg_data ;\r
index abf28f2..a05c1c1 100644 (file)
@@ -84,6 +84,13 @@ static const uint8_t PAH8009_REG_DIW_4MM_G_IR_PPG[][2] = {
     { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
     { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0]\r
     { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0]\r
+// #ifdef TOUCH_DETECT_TRH_1\r
+//     { 0x4C,0x20 },//R_TouchDetection_Th_Low[7:0]\r
+//     { 0x4D,0x03 },//R_TouchDetection_Th_Low[13:8]  //1800 ir阈值\r
+//     #else\r
+//     { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0]  //1280 ir阈值\r
+//     { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8]\r
+//     #endif\r
     { 0xEB,0x80 },//update_flag\r
 };\r
 \r
index 0e3d853..f02f9dc 100644 (file)
@@ -9,7 +9,7 @@
  * Select LED Supplier\r
  * If Use new Supplier LED , Need to define LED_SUPPLIER_NEW\r
 */\r
-//#define LED_SUPPLIER_NEW\r
+#define LED_SUPPLIER_NEW\r
 \r
 \r
 /*\r
index 314b0b2..f9225ce 100644 (file)
@@ -118,7 +118,7 @@ void create_mixo_queue(void)
     }
 }
 
-#define MIXO_BOARD_TASK_SIZE   0x1000
+#define MIXO_BOARD_TASK_SIZE   0x500
 errcode_t uapi_mixo_service_init(void)
 {
     PRINT("uapi_mixo_service_init !\r\n");
index 60ded83..eb4170a 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: penglei 1624952103@qq.com
  * @Date: 2024-12-23 15:12:01
  * @LastEditors: penglei 1624952103@qq.com
- * @LastEditTime: 2025-05-14 16:29:38
+ * @LastEditTime: 2025-06-11 17:33:01
  * @FilePath: /sdk615/code/sdk/zhihui/drivers/mixo/service/mixo_service.h
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
index a087994..26dfa8a 100644 (file)
@@ -30,10 +30,7 @@ extern "C" {
 #include "pm_veto.h"
 uint32_t uapi_cat1_bat_on(uint32_t pwron)
 {
-
-#if defined(BOARD_L22)
-    pin_t bat_en_pin =  S_AGPIO_L14;
-#elif defined(BOARD_W9)
+#if defined(BOARD_W9) || defined(BOARD_N9)
     pin_t bat_en_pin =  S_AGPIO_L17;
 
     if( pwron == 0)
@@ -89,9 +86,7 @@ bool uapi_cat1_get_power_stat(void)
 {
 #if defined(BOARD_FD230)
    return (  GPIO_LEVEL_HIGH == uapi_gpio_get_output_val(S_AGPIO_L23));
-#elif defined(BOARD_L22)
-   return (  GPIO_LEVEL_HIGH == uapi_gpio_get_output_val(S_AGPIO_L14));
-#elif defined(BOARD_W9)
+#elif defined(BOARD_W9) || defined(BOARD_N9)
    return (  GPIO_LEVEL_HIGH == uapi_gpio_get_output_val(S_AGPIO_L17));
 #endif
 
index a7e3f5e..2d4ff83 100644 (file)
 #include "custom_save_runtime.h"
 #include "ppg_hal.h"
 
+#ifdef ENABLE_BN02
+#include "bp_service.h"
+#endif
+
 errcode_t uapi_create_osThread_custom(app_task_definition_t *task_cfg)
 {
     if (task_cfg==NULL)
@@ -1426,7 +1430,7 @@ int uapi_callVolumeGet(void)
 
 void power_on_cat1(void)
 {
-    #if defined(FD230) && !defined(BOARD_W9)
+    #if defined(FD230) && !(defined(BOARD_W9) || defined(BOARD_N9))
     uapi_cat1_power_on(1);    
     uapi_cat1_reset(0);
     #else
@@ -1441,7 +1445,7 @@ void power_on_cat1(void)
 
 void power_off_cat1(void)
 {
-    #if defined(FD230) && !defined(BOARD_W9)
+    #if defined(FD230) && !(defined(BOARD_W9) || defined(BOARD_N9))
     uapi_cat1_reset(1);
     uapi_cat1_power_on(0); 
     #else
@@ -2471,9 +2475,10 @@ void custom_i2c_reset(uint8_t i2cbus, uint16_t i2c_clock)
     PRINT(" custom_iic_reset done! i2cbus %d clock %d\n",i2cbus,i2c_clock);
 }
 
-errcode_t custom_iic_init(void)
+errcode_t custom_i2c_init(uint8_t bus_index)
 {
-    errcode_t result;
+    // if(i2c_installed == 1)
+        // return ERRCODE_SUCC;
 
 // #ifdef CONFIG_I2C_SUPPORT_DMA
 // #if CONFIG_I2C_SUPPORT_DMA
@@ -2482,20 +2487,19 @@ errcode_t custom_iic_init(void)
 // #warning CONFIG_I2C_SUPPORT_DMA = 0
 // #endif
 // #endif
-    if(i2c_installed == 0)
-    {
-        result = uapi_i2c_master_init(I2C_BUS_2, 400000, I2C_SPEED_MODE_FS); /* 400000: 400KHz */
 
-        if (result != ERRCODE_SUCC) {
-            PRINT("cywee i2c init fail! ret=0x%x\n", result);
-            return ERRCODE_FAIL;
-        }
+    errcode_t result = uapi_i2c_master_init(bus_index, 400000, I2C_SPEED_MODE_FS); /* 400000: 400KHz */
 
-        i2c_installed = 1;
-        return ERRCODE_SUCC;
-    }
-    else
+    if (result != ERRCODE_SUCC) {
+        PRINT("cywee i2c init fail! ret=0x%x\n", result);
         return ERRCODE_FAIL;
+    }
+
+    // i2c_installed = 1;
+    return ERRCODE_SUCC;
+    
+    // else
+    //     return ERRCODE_FAIL;
 }
 
 errcode_t custom_i2c_read_regs(uint16_t slaveAddr, uint16_t reg, int regLength, uint8_t *readData, int readDataSize, int busIndex)
@@ -2633,7 +2637,7 @@ errcode_t custom_i2c_transfer(uint16_t slaveAddr, uint16_t reg, int regLength, u
     uint8_t *write_data = NULL;
     int16_t write_len = 0;
 
-    //custom_iic_init();
+    //custom_i2c_init();
     write_len = regLength + writeDataSize;
     write_data = (uint8_t *)osal_kmalloc(write_len, OSAL_GFP_KERNEL);
     if (write_data == NULL) {
index 15be90f..b4eb919 100755 (executable)
@@ -51,6 +51,9 @@ typedef enum {
     PM_ID_P_TEST,//产测
     PM_ID_BUTTON_GPIO,//gpio按键
     PM_ID_4G_AI,//4g AI
+#ifdef ENABLE_BN02
+    PM_ID_BP,//血压
+#endif
     PM_ID_MAX,
 } pm_id_t;
 
index 6c66f12..4fb1675 100755 (executable)
@@ -240,6 +240,9 @@ const char* pm_id_name_arr[] ={
     "PM_ID_P_TEST",
     "PM_ID_BUTTON_GPIO",//GPIO按键
     "PM_ID_4G_AI",//AI投票
+#ifdef ENABLE_BN02
+    "PM_ID_BP",//血压
+#endif
     "PM_ID_MAX"
 };
 
diff --git a/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-n9-r/libgfx_rm.a b/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-n9-r/libgfx_rm.a
new file mode 100644 (file)
index 0000000..aa0af42
Binary files /dev/null and b/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-n9-r/libgfx_rm.a differ
diff --git a/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-n9/libgfx_rm.a b/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-n9/libgfx_rm.a
new file mode 100644 (file)
index 0000000..12f9d8b
Binary files /dev/null and b/code/sdk/middleware/services/gpu/api/rm/brandy-native-js-n9/libgfx_rm.a differ
diff --git a/code/sdk/middleware/services/gui/hal/display/brandy-native-js-n9/libdisplay_gfx.a b/code/sdk/middleware/services/gui/hal/display/brandy-native-js-n9/libdisplay_gfx.a
new file mode 100644 (file)
index 0000000..40adc6f
Binary files /dev/null and b/code/sdk/middleware/services/gui/hal/display/brandy-native-js-n9/libdisplay_gfx.a differ
diff --git a/code/sdk/middleware/services/gui/uikit/brandy-native-js-n9/libuikit_ext.a b/code/sdk/middleware/services/gui/uikit/brandy-native-js-n9/libuikit_ext.a
new file mode 100644 (file)
index 0000000..6f04c26
Binary files /dev/null and b/code/sdk/middleware/services/gui/uikit/brandy-native-js-n9/libuikit_ext.a differ
index 8024e63..eb63012 100755 (executable)
@@ -58,7 +58,7 @@ static OHOS::UIImageAnimatorView* ReBootImageAnimatorView=nullptr;
 #ifdef CUSTOM_Z1
 static constexpr char *ReBootPaths = "/user/res/RebootAndShutDown/ReBoot/"; //开机图片路径
 static constexpr int16_t REBOOT_IMAGE_ANIMATOR_VIEW_NUM_FRAMES = 30; // 图片帧数
-#elif BOARD_W9
+#elif defined(BOARD_W9) || defined(BOARD_N9)
 static constexpr char *ReBootPaths = "/user/res/RebootAndShutDown/ReBoot/"; //开机图片路径
 static constexpr int16_t REBOOT_IMAGE_ANIMATOR_VIEW_NUM_FRAMES = 30; // 图片帧数
 #else
@@ -99,7 +99,7 @@ static app_task_definition_t taskcfg={0};
 #endif
 #endif
 
-#ifdef BOARD_W9
+#if defined(BOARD_W9) || defined(BOARD_N9)
 #ifdef IMAGE_OPEN_LOGO_PATH
 #undef IMAGE_OPEN_LOGO_PATH
 #endif
@@ -198,7 +198,7 @@ bool ShowReBootAnimatorView()
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new ReBootImageAnimatorView fail");
             return false;
         }
-#ifdef BOARD_W9
+#if defined(BOARD_W9) || defined(BOARD_N9)
         for (int j = 0, i = REBOOT_IMAGE_ANIMATOR_VIEW_NUM_FRAMES - 1; 
             i > 0 && j < REBOOT_IMAGE_ANIMATOR_VIEW_NUM_FRAMES; 
             i--, j++) 
diff --git a/code/sdk/middleware/utils/fs/vfs/brandy-native-js-n9-r/libx_vfs_private.a b/code/sdk/middleware/utils/fs/vfs/brandy-native-js-n9-r/libx_vfs_private.a
new file mode 100644 (file)
index 0000000..cddab45
Binary files /dev/null and b/code/sdk/middleware/utils/fs/vfs/brandy-native-js-n9-r/libx_vfs_private.a differ
diff --git a/code/sdk/middleware/utils/fs/vfs/brandy-native-js-n9/libx_vfs_private.a b/code/sdk/middleware/utils/fs/vfs/brandy-native-js-n9/libx_vfs_private.a
new file mode 100644 (file)
index 0000000..6feed1e
Binary files /dev/null and b/code/sdk/middleware/utils/fs/vfs/brandy-native-js-n9/libx_vfs_private.a differ
diff --git a/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-n9-r/libfs_yaffs2.a b/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-n9-r/libfs_yaffs2.a
new file mode 100644 (file)
index 0000000..d8a248b
Binary files /dev/null and b/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-n9-r/libfs_yaffs2.a differ
diff --git a/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-n9/libfs_yaffs2.a b/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-n9/libfs_yaffs2.a
new file mode 100644 (file)
index 0000000..aaa672c
Binary files /dev/null and b/code/sdk/middleware/utils/fs/yaffs2/brandy-native-js-n9/libfs_yaffs2.a differ
diff --git a/code/sdk/open_source/openharmony/foundation/aafwk/aafwk_lite/brandy-native-js-n9/libams.a b/code/sdk/open_source/openharmony/foundation/aafwk/aafwk_lite/brandy-native-js-n9/libams.a
new file mode 100644 (file)
index 0000000..eae8d08
Binary files /dev/null and b/code/sdk/open_source/openharmony/foundation/aafwk/aafwk_lite/brandy-native-js-n9/libams.a differ
diff --git a/code/sdk/open_source/openharmony/foundation/ace/ace_engine_lite/brandy-native-js-n9/libace.a b/code/sdk/open_source/openharmony/foundation/ace/ace_engine_lite/brandy-native-js-n9/libace.a
new file mode 100644 (file)
index 0000000..d4c567f
Binary files /dev/null and b/code/sdk/open_source/openharmony/foundation/ace/ace_engine_lite/brandy-native-js-n9/libace.a differ
diff --git a/code/sdk/open_source/openharmony/foundation/appexecfwk/appexecfwk_lite/brandy-native-js-n9/libbms.a b/code/sdk/open_source/openharmony/foundation/appexecfwk/appexecfwk_lite/brandy-native-js-n9/libbms.a
new file mode 100644 (file)
index 0000000..265db3d
Binary files /dev/null and b/code/sdk/open_source/openharmony/foundation/appexecfwk/appexecfwk_lite/brandy-native-js-n9/libbms.a differ
diff --git a/code/sdk/open_source/openharmony/third_party/jerryscript/brandy-native-js-n9/libjerryscript.a b/code/sdk/open_source/openharmony/third_party/jerryscript/brandy-native-js-n9/libjerryscript.a
new file mode 100644 (file)
index 0000000..c395070
Binary files /dev/null and b/code/sdk/open_source/openharmony/third_party/jerryscript/brandy-native-js-n9/libjerryscript.a differ