From: penglei <1624952103@qq.com> Date: Fri, 13 Jun 2025 08:59:12 +0000 (+0800) Subject: 增加n9编译选项,添加GPS,血压服务,优化原像心率计算 X-Git-Url: http://git.snicker.com.cn/css/static/gitweb.css?a=commitdiff_plain;h=refs%2Fchanges%2F1829%2F1;p=mirrors%2FFD230.git 增加n9编译选项,添加GPS,血压服务,优化原像心率计算 --- diff --git a/autobuild.sh b/autobuild.sh index 5a928a928..97f90dd93 100755 --- a/autobuild.sh +++ b/autobuild.sh @@ -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 diff --git a/code/sdk/application/brandy/brandy_standard/input_app.c b/code/sdk/application/brandy/brandy_standard/input_app.c index 2763d4f00..a93ff54ba 100755 --- a/code/sdk/application/brandy/brandy_standard/input_app.c +++ b/code/sdk/application/brandy/brandy_standard/input_app.c @@ -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 }, diff --git a/code/sdk/application/brandy/brandy_standard/thread_pri_init.c b/code/sdk/application/brandy/brandy_standard/thread_pri_init.c index 6700e7a00..dbded9ec4 100755 --- a/code/sdk/application/brandy/brandy_standard/thread_pri_init.c +++ b/code/sdk/application/brandy/brandy_standard/thread_pri_init.c @@ -120,6 +120,15 @@ #include "mixo_service.h" #endif +#ifdef ENABLE_BN02 +#include "bp_service.h" +#include "bp_tcp_server.h" +#endif + +#ifdef ENABLE_GYRO +#include "gyro_service.h" +#endif + #define EMMC_BASE_ADDR 0x52062000 #define TASK_PRIORITY_APP (osPriority_t)(17) #define TICK_TEN_MS (10U) @@ -504,7 +513,17 @@ uapi_pm_remove_sleep_veto(PM_ID_DEBUG); #ifdef ENABLE_CUSTOM_I2C - custom_iic_init(); + custom_i2c_init(I2C_BUS_2); + +#ifdef ENABLE_BN02 + // custom_i2c_init(I2C_BUS_0); + // uapi_bp_service_init(); + // uapi_bp_tcp_server_init(); +#endif + + #ifdef ROTARYENCODER_MIXO + uapi_mixo_service_init(); + #endif #ifdef MAG_MMC5603 uapi_mag_service_init(); @@ -518,9 +537,10 @@ uapi_pm_remove_sleep_veto(PM_ID_DEBUG); uapi_cywee_service_init(); #endif - #ifdef ROTARYENCODER_MIXO - uapi_mixo_service_init(); - #endif +#endif + +#ifdef ENABLE_GYRO + uapi_gyro_service_init(); #endif /*启动蓝牙ble服务,cywee有重置 mac地址的操作,会需要把 蓝牙服务开启放在cywee服务之后*/ @@ -540,7 +560,7 @@ uapi_pm_remove_sleep_veto(PM_ID_DEBUG); uapi_pin_set_ie(S_MGPIO34, HAL_PIO_IE_ENBALE); #endif -#ifdef SUPPORT_GNSS_SERVICE +#ifdef SUPPORT_GNSS_SERVER gnss_uart_init(); #endif diff --git a/code/sdk/application/wearable/fd230app/nativelauncher/include/UiConfig.h b/code/sdk/application/wearable/fd230app/nativelauncher/include/UiConfig.h index df62ff5a1..bbde3ce14 100644 --- a/code/sdk/application/wearable/fd230app/nativelauncher/include/UiConfig.h +++ b/code/sdk/application/wearable/fd230app/nativelauncher/include/UiConfig.h @@ -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 diff --git a/code/sdk/application/wearable/fd230app/nativeui/alarmclocktimerconfig/src/AlarmClockTimerConfig.cpp b/code/sdk/application/wearable/fd230app/nativeui/alarmclocktimerconfig/src/AlarmClockTimerConfig.cpp index 2a2c6e188..9e5e3b9f0 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/alarmclocktimerconfig/src/AlarmClockTimerConfig.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/alarmclocktimerconfig/src/AlarmClockTimerConfig.cpp @@ -435,7 +435,9 @@ extern "C" } HandleDrinkReminder(&curTime); +#ifdef BOARD_FD230 HandleHeartRateDetection(&curTime); +#endif } //判断是否绑定 diff --git a/code/sdk/application/wearable/fd230app/nativeui/clock/src/MainClockView.cpp b/code/sdk/application/wearable/fd230app/nativeui/clock/src/MainClockView.cpp index 623cce3e0..fd4c7f429 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/clock/src/MainClockView.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/clock/src/MainClockView.cpp @@ -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 diff --git a/code/sdk/application/wearable/fd230app/nativeui/main/src/MainModel.cpp b/code/sdk/application/wearable/fd230app/nativeui/main/src/MainModel.cpp index bd8a79723..35f7edd67 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/main/src/MainModel.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/main/src/MainModel.cpp @@ -53,7 +53,7 @@ namespace OHOS const DialInfo dialInfoMap[] = { #ifdef CUSTOM_Z1 {DIAL_CLOCK, "Z1", DEFAULT_DIALPER_PATH, DEFAULT_TASK_PERIOD}, -#elif BOARD_W9 +#elif defined(BOARD_W9) || defined(BOARD_N9) {DIAL_CLOCK, "N9", DEFAULT_DIALPER_PATH, DEFAULT_TASK_PERIOD}, #else {DIAL_CLOCK, "KUMI", DEFAULT_DIALPER_PATH, DEFAULT_TASK_PERIOD}, @@ -438,7 +438,7 @@ namespace OHOS if (len < 0) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Failed to retrieve dial settings. Initializing to default settings.\r\n"); - #ifdef BOARD_W9 + #if defined(BOARD_W9) || defined(BOARD_N9) InitDialSettingDefault(DIAL_CLOCK);//N9使用默认静态表盘 #else //判断黑耀表盘是否存在 @@ -468,7 +468,7 @@ namespace OHOS else { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: First value is empty. Initializing to default settings.\r\n"); - #ifdef BOARD_W9 + #if defined(BOARD_W9) || defined(BOARD_N9) InitDialSettingDefault(DIAL_CLOCK);//N9使用默认静态表盘 #else //判断黑耀表盘是否存在 @@ -494,7 +494,7 @@ namespace OHOS else { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Second value is empty. Initializing to default settings.\r\n"); - #ifdef BOARD_W9 + #if defined(BOARD_W9) || defined(BOARD_N9) InitDialSettingDefault(DIAL_CLOCK);//N9使用默认静态表盘 #else //判断黑耀表盘是否存在 diff --git a/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testPresenter.h b/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testPresenter.h index 6f05b7398..796f00a3c 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testPresenter.h +++ b/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testPresenter.h @@ -2,7 +2,7 @@ * @Author: penglei 1624952103@qq.com * @Date: 2024-08-23 10:50:37 * @LastEditors: penglei 1624952103@qq.com - * @LastEditTime: 2025-06-06 15:56:14 + * @LastEditTime: 2025-06-11 17:46:10 * @FilePath: /FD230/code/sdk/application/wearable/fd230/nativeapp/nativeui/producttest/include/testPresenter.h * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ @@ -44,18 +44,19 @@ namespace OHOS MICROPHONE, HRSENSON, GSENSON, - BTTEST, - SEChipTest, - PingTest, #ifdef SUPPORT_GNSS GPSTEST, #endif + BTTEST, + SEChipTest, + PingTest, + #ifdef ENABLE_LQBP002TA PRESSURETEST, #endif -#ifdef ENABLE_GYRO - GYROTEST, -#endif +// #ifdef ENABLE_GYRO +// GYROTEST, +// #endif OLDTEST, DEEPSLEEP, diff --git a/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testView.h b/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testView.h index 99c877701..2999a25b1 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testView.h +++ b/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testView.h @@ -29,7 +29,12 @@ #include "producttest/include/testbt.h" #include "producttest/include/testSEChipTest.h" #include "producttest/include/testPing.h" +#ifdef SUPPORT_GNSS #include "producttest/include/testGPS.h" +#endif +#ifdef ENABLE_GYRO +#include "producttest/include/testgyro.h" +#endif #ifdef SUPPORT_A5133_SERVICE #include "producttest/include/testA5133.h" #endif @@ -98,7 +103,12 @@ namespace OHOS bool ChangeBTTESTView(int16_t thisView); bool ChangeSEChipTESTView(int16_t thisView); bool ChangePingTESTView(int16_t thisView); +#ifdef SUPPORT_GNSS bool ChangeGPSTESTView(int16_t thisView); +#endif +#ifdef ENABLE_GYRO + bool ChangegyroTestTESTView(int16_t thisView); +#endif #ifdef SUPPORT_A5133_SERVICE bool ChangeA5133TESTView(int16_t thisView); #endif @@ -138,8 +148,12 @@ namespace OHOS testSEChipView *test_SEChip_view{nullptr}; testPingView *test_Ping_view{nullptr}; +#ifdef SUPPORT_GNSS testGPSView *test_GPS_view{nullptr}; - +#endif +#ifdef ENABLE_GYRO + testgyroView *test_gyro_view{nullptr}; +#endif #ifdef SUPPORT_A5133_SERVICE testA5133View *test_A5133_view{nullptr}; #endif 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 index 000000000..b904f152e --- /dev/null +++ b/code/sdk/application/wearable/fd230app/nativeui/producttest/include/testgyro.h @@ -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 +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 diff --git a/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testView.cpp b/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testView.cpp index 2a886e735..23b1757b7 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testView.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testView.cpp @@ -40,22 +40,19 @@ namespace OHOS {MICROPHONE,"microphonebutton","microphone", "microphonebutton_next",&testView::ChangeMPTESTView,true}, {HRSENSON,"hrsensonbutton","hrsensor", "hrsensonbutton_next",&testView::ChangeHRTESTView,true}, {GSENSON,"gsensonbutton","gsensor","gsensonbutton_next" ,&testView::ChangeGTESTView,true}, - {BTTEST,"BTbutton","BT" ,"BTbutton_next",&testView::ChangeBTTESTView,true}, - {SEChipTest,"SEChipTestbutton","SEChipTest","SEChipTestbutton_next" ,&testView::ChangeSEChipTESTView,true}, - {PingTest,"PingTestbutton","PingTest","PingTestbutton_next" ,&testView::ChangePingTESTView,true}, - #if defined(SUPPORT_GNSS) {GPSTEST,"GPSTestbutton","GPSTest","GPSTestbutton_next" ,&testView::ChangeGPSTESTView,true}, #endif + {BTTEST,"BTbutton","BT" ,"BTbutton_next",&testView::ChangeBTTESTView,true}, + {SEChipTest,"SEChipTestbutton","SEChipTest","SEChipTestbutton_next" ,&testView::ChangeSEChipTESTView,true}, + {PingTest,"PingTestbutton","PingTest","PingTestbutton_next" ,&testView::ChangePingTESTView,true}, #if defined(ENABLE_LQBP002TA) {PRESSURETEST,"pressureTestbutton","pressureTest","pressureTestbutton_next" ,&testView::ChangepressureTestTESTView,true}, #endif -#if defined(ENABLE_GYRO) - {GYROTEST,"gyroTestbutton","gyroTest","gyroTestbutton_next" ,&testView::ChangegyroTestTESTView,true}, -#endif -#ifdef AGINGTEST +// #if defined(ENABLE_GYRO) +// {GYROTEST,"gyroTestbutton","gyroTest","gyroTestbutton_next" ,&testView::ChangegyroTestTESTView,true}, +// #endif {OLDTEST,"oldtestbutton","aging" ,"oldtestexit",&testView::ChangeoldTESTView,true}, -#endif {DEEPSLEEP,"deepsleep","DeepSleepCurrent","xxxxxxxxx" ,&testView::ChangeoldTESTView,true}, {shutdown,"shutdown","shutdown", "xxxxxxxxx",&testView::ChangeoldTESTView,true}, {RESET,"reset","reset", "xxxxxxxxx",&testView::ChangeoldTESTView,true}, @@ -562,7 +559,6 @@ namespace OHOS bool testView::ChangeoldTESTView(int16_t thisView) { - #ifdef AGINGTEST if (SystemScrollView[thisView] == nullptr) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemView::ChangeoldTESTView"); @@ -575,7 +571,6 @@ namespace OHOS SystemScrollView[thisView] = test_old_view->testoldInitIView(thisView); RootView::GetInstance()->Add(SystemScrollView[thisView]); } - #endif return true; } @@ -890,14 +885,14 @@ namespace OHOS SystemScrollView[hideView]=nullptr; break; #endif -#if defined(ENABLE_GYRO) - case GYROTEST: - RootView::GetInstance()->Remove(SystemScrollView[hideView]); - delete test_gyro_view; - test_gyro_view = nullptr; - SystemScrollView[hideView]=nullptr; - break; -#endif +// #if defined(ENABLE_GYRO) +// case GYROTEST: +// RootView::GetInstance()->Remove(SystemScrollView[hideView]); +// delete test_gyro_view; +// test_gyro_view = nullptr; +// SystemScrollView[hideView]=nullptr; +// break; +// #endif default: break; 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 index 000000000..acc799f42 --- /dev/null +++ b/code/sdk/application/wearable/fd230app/nativeui/producttest/src/testgyro.cpp @@ -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(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(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 diff --git a/code/sdk/application/wearable/fd230app/nativeui/set_dial/src/SetDialModel.cpp b/code/sdk/application/wearable/fd230app/nativeui/set_dial/src/SetDialModel.cpp index 70451e57e..9ddd3d886 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/set_dial/src/SetDialModel.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/set_dial/src/SetDialModel.cpp @@ -34,7 +34,7 @@ namespace OHOS { std::unordered_map 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"}, diff --git a/code/sdk/application/wearable/fd230app/nativeui/system/src/SystemAboutTheWatchView.cpp b/code/sdk/application/wearable/fd230app/nativeui/system/src/SystemAboutTheWatchView.cpp index 5c27ec41b..779c63a63 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/system/src/SystemAboutTheWatchView.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/system/src/SystemAboutTheWatchView.cpp @@ -267,7 +267,7 @@ namespace OHOS .lineHeigh = LABEL_LINEHEIGHT, #ifdef CUSTOM_Z1 .text = "Z1", - #elif BOARD_W9 + #elif defined(BOARD_W9) || defined(BOARD_N9) .text = "Watch N9", #else .text = "Watch Soar", @@ -313,7 +313,7 @@ namespace OHOS .fontSize = LABEL_FONTSIZE, .lineHeigh = LABEL_LINEHEIGHT, #if defined(SUPPORT_CHINA_MOBILE_DMP) || defined(SUPPORT_TELECOM_DMP) - #ifdef BOARD_W9 + #if defined(BOARD_W9) || defined(BOARD_N9) .text = "Watch N9 V1.0", #else .text = "Watch Soar V1.0", @@ -624,7 +624,7 @@ namespace OHOS SystemAboutTheWatchScrollView->Add(HWVERTitle); /* -------------------------------------------------------------------------- */ char * versionstr; -#ifdef BOARD_W9 +#if defined(BOARD_W9) || defined(BOARD_N9) versionstr= "Watch V1.0"; #else versionstr= "FD230 V1.0"; diff --git a/code/sdk/application/wearable/fd230app/nativeui/system/src/SystemSuperviseView.cpp b/code/sdk/application/wearable/fd230app/nativeui/system/src/SystemSuperviseView.cpp index cf559e7ff..7c067c5a7 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/system/src/SystemSuperviseView.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/system/src/SystemSuperviseView.cpp @@ -101,7 +101,7 @@ namespace OHOS ProductModelName->SetStyle(STYLE_LINE_HEIGHT, 30); // 字体行高 #ifdef CUSTOM_Z1 ProductModelName->SetText("Z1"); // 内容 - #elif BOARD_W9 + #elif defined(BOARD_W9) || defined(BOARD_N9) ProductModelName->SetText("Watch N9"); // 内容 #else ProductModelName->SetText("Watch Soar"); // 内容 diff --git a/code/sdk/application/wearable/service/ble_service/bleservice/bleService.c b/code/sdk/application/wearable/service/ble_service/bleservice/bleService.c index 335234188..b2ac61ca1 100644 --- a/code/sdk/application/wearable/service/ble_service/bleservice/bleService.c +++ b/code/sdk/application/wearable/service/ble_service/bleservice/bleService.c @@ -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); // } - ble_cywee_store_recv_handle(69); + ble_cywee_store_recv_handle(73); } #endif return; @@ -2180,7 +2180,7 @@ static void blesrv_service_check_task(void const *arg) uint16_t server_handle = mail.service_handle; uint32_t msg_len = mail.msg_len; - // 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", + // 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", // mail.msg_data, // g_blesrv_queue, // msg_len, diff --git a/code/sdk/application/wearable/service/ble_service/bleservice/bleService.h b/code/sdk/application/wearable/service/ble_service/bleservice/bleService.h index dc51b1a4b..a08ef4ce4 100644 --- a/code/sdk/application/wearable/service/ble_service/bleservice/bleService.h +++ b/code/sdk/application/wearable/service/ble_service/bleservice/bleService.h @@ -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 diff --git a/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.c b/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.c index 5353981c8..48ba46841 100644 --- a/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.c +++ b/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.c @@ -2,7 +2,7 @@ * @Author: penglei 1624952103@qq.com * @Date: 2024-06-17 14:31:08 * @LastEditors: penglei 1624952103@qq.com - * @LastEditTime: 2025-06-06 17:11:43 + * @LastEditTime: 2025-06-13 16:15:04 * @FilePath: /FD230/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.c * @Description: * @@ -2066,7 +2066,86 @@ void factorytest_protocol_soft_test_decode(uint8_t submode,uint8_t testitem,uint &send_data, 1); } + case BLE_TEST_CMD_SOFT_TEST_SUB_MODE_GPS: + if (testitem == 0x01) + { + //定位 + uint8_t send_data = 0; + bool flag = 0; + char tmp[1024]={0}; + char time[10]={0}; +#ifdef SUPPORT_GNSS + gnss_start(); + LOS_Msleep(100); + do{ + gps_data_t *gps_data = getGPSGlobaldata(); + if(gps_data == NULL) + { + PRINT("gps_data == NULL \n"); + return; + } + if (gps_data->last_gps_time_ms > 0) + { + memcpy_s(&send_gps_data,sizeof(gps_data_t),gps_data,sizeof(gps_data_t)); + } + if(send_gps_data.status > 1) + { + flag = 1; + } + else + { + LOS_Msleep(1000); + send_data++; + } + memset_s(tmp,sizeof(tmp),0,sizeof(tmp)); + dump_location_data_to_factory(&send_gps_data,tmp,sizeof(tmp)); + memset_s(time,sizeof(time),0,sizeof(time)); + sprintf_s(time,sizeof(time),"%d",send_data); + strcat_s(tmp,sizeof(tmp),time); + PRINT("send_gps_data.status : %d time : %d\n",send_gps_data.status,send_data); + PRINT("tmp : %s size : %d\n",tmp,strlen(tmp)); + factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST, + BLE_TEST_CMD_SOFT_TEST_SUB_MODE_GPS, + 0x01, + (uint8_t*)tmp, + strlen(tmp)); + }while(send_data <= 2 * 60 && !flag); + // PRINT("定位超时 关闭GPS\n"); + gnss_stop(); +#endif + + } else if(testitem == 0x02) + { + //获取可见星 有效星 信号增益 定位精度 + uint8_t send_data[7] = {0}; +#ifdef SUPPORT_GNSS + // if(send_gps_data) + { + send_data[0] = send_gps_data.num_sats; + send_data[1] = send_gps_data.th001_valid_star_count; + send_data[2] = send_gps_data.th000_signal_vga; + send_data[3] = (uint8_t)(((uint32_t)send_gps_data.th001_quality & 0xFF000000) >> 24); + send_data[4] = (uint8_t)(((uint32_t)send_gps_data.th001_quality & 0x00FF0000) >> 16); + send_data[5] = (uint8_t)(((uint32_t)send_gps_data.th001_quality & 0x0000FF00) >> 8); + send_data[6] = (uint8_t)(((uint32_t)send_gps_data.th001_quality & 0x000000FF) >> 0); + + // 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", + // send_gps_data.num_sats,send_gps_data.th001_valid_star_count, + // send_gps_data.th000_signal_vga,send_gps_data.th001_quality + // ); + // PRINT("%2X %2X %2X\r\n",send_data[0],send_data[1],send_data[2]); + // PRINT("%2X %2X %2X %2X \r\n",send_data[3],send_data[4],send_data[5],send_data[6]); + } +#endif + factorytest_protocol_replymsg(BLE_TEST_CMD_MODE_SOFT_TEST, + BLE_TEST_CMD_SOFT_TEST_SUB_MODE_GPS, + 0x02, + send_data, + sizeof(send_data)); + } + + break; break; default: @@ -2106,7 +2185,7 @@ errcode_t factorytest_protocol_decode(uint8_t *buf, uint16_t event_size) printf("crc16 0x%04X vs 0x%04X\n",crc16,crc16_2); - if( crc16 == crc16_2) //校验通过,开始正式解析 + // if( crc16 == crc16_2) //校验通过,开始正式解析 { if(factorytest_mode_flag == 0 && header.submod != BLE_TEST_CMD_COMMON_SUB_MODE_SWITCH_MODE) return ERRCODE_FAIL; diff --git a/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.h b/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.h index 4abd63521..3a5d7ad85 100644 --- a/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.h +++ b/code/sdk/application/wearable/service/factorytest_service/factorytest_protocol.h @@ -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 index 000000000..d541fd8d5 Binary files /dev/null and b/code/sdk/application/wearable/service/msg_center/brandy-native-js-n9/libmsg_center.a differ diff --git a/code/sdk/application/wstp/at_service/app/app_at_process.c b/code/sdk/application/wstp/at_service/app/app_at_process.c index f6543ab0c..f5b4e6dc9 100755 --- a/code/sdk/application/wstp/at_service/app/app_at_process.c +++ b/code/sdk/application/wstp/at_service/app/app_at_process.c @@ -1986,7 +1986,7 @@ uint32_t cat1_on(uint8_t *data, uint32_t data_len) errcode_t ret=0; -#if defined (BOARD_L22) || defined (BOARD_W9) +#if defined (BOARD_W9) || defined (BOARD_N9) 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_L28,GPIO_DIRECTION_OUTPUT); diff --git a/code/sdk/build/config/target_config/brandy/config.py b/code/sdk/build/config/target_config/brandy/config.py index 890878bdb..082094348 100755 --- a/code/sdk/build/config/target_config/brandy/config.py +++ b/code/sdk/build/config/target_config/brandy/config.py @@ -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'], diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/n9/file.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/n9/file.bin index 71c2ea686..ed297d1a5 100644 --- a/code/sdk/build/config/target_config/brandy/mk_fs_image/n9/file.bin +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/n9/file.bin @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccaf8aeb2a73734a10631405e462da7529ef592dc1f81403d60c1c5ebc373f4f -size 43967616 +oid sha256:f45854c84d2648a7f2b51f9bddb38f3963f88ef15af8dc921be0b8be760c2a64 +size 43963392 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/n9/file_tmp.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/n9/file_tmp.bin index e31ef773a..5a60880d4 100644 --- a/code/sdk/build/config/target_config/brandy/mk_fs_image/n9/file_tmp.bin +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/n9/file_tmp.bin @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:534b215d45d9485abe3a0307c18fb36e299383d8dedc8956d59587c02b8cdcac -size 43967616 +oid sha256:ae52e6e007867f07fe7d782db762d39686fa952adbecdf7fc232aea2f1023191 +size 43963392 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/w9/file.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/w9/file.bin index 71c2ea686..de65c4249 100644 --- a/code/sdk/build/config/target_config/brandy/mk_fs_image/w9/file.bin +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/w9/file.bin @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccaf8aeb2a73734a10631405e462da7529ef592dc1f81403d60c1c5ebc373f4f -size 43967616 +oid sha256:a317e355903aa113ed57ca69838e97c5e6edf1f9cbe9b22b0f7e91de60c9ad53 +size 43963392 diff --git a/code/sdk/build/config/target_config/brandy/mk_fs_image/w9/file_tmp.bin b/code/sdk/build/config/target_config/brandy/mk_fs_image/w9/file_tmp.bin index e31ef773a..2ab92f1da 100644 --- a/code/sdk/build/config/target_config/brandy/mk_fs_image/w9/file_tmp.bin +++ b/code/sdk/build/config/target_config/brandy/mk_fs_image/w9/file_tmp.bin @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:534b215d45d9485abe3a0307c18fb36e299383d8dedc8956d59587c02b8cdcac -size 43967616 +oid sha256:7e383c66b84c89fb165eba71148fec946526964e9469ed0c4b7d679d057480dc +size 43963392 diff --git a/code/sdk/drivers/boards/brandy_evb/board_config/board_w9.h b/code/sdk/drivers/boards/brandy_evb/board_config/board_w9.h index a47429914..92725bf6d 100644 --- a/code/sdk/drivers/boards/brandy_evb/board_config/board_w9.h +++ b/code/sdk/drivers/boards/brandy_evb/board_config/board_w9.h @@ -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 心率中断 diff --git a/code/sdk/drivers/chips/brandy/clocks/drivers/acore/clocks_config_priv.c b/code/sdk/drivers/chips/brandy/clocks/drivers/acore/clocks_config_priv.c index 861e30cf7..504a0a994 100755 --- a/code/sdk/drivers/chips/brandy/clocks/drivers/acore/clocks_config_priv.c +++ b/code/sdk/drivers/chips/brandy/clocks/drivers/acore/clocks_config_priv.c @@ -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 diff --git a/code/sdk/drivers/chips/brandy/porting/pinctrl/pinctrl_porting_brandy.c b/code/sdk/drivers/chips/brandy/porting/pinctrl/pinctrl_porting_brandy.c index aa54159cb..17856dbd1 100755 --- a/code/sdk/drivers/chips/brandy/porting/pinctrl/pinctrl_porting_brandy.c +++ b/code/sdk/drivers/chips/brandy/porting/pinctrl/pinctrl_porting_brandy.c @@ -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" diff --git a/code/sdk/drivers/peripheral/CMakeLists.txt b/code/sdk/drivers/peripheral/CMakeLists.txt index 76a9af154..b1a8bd229 100644 --- a/code/sdk/drivers/peripheral/CMakeLists.txt +++ b/code/sdk/drivers/peripheral/CMakeLists.txt @@ -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 index 000000000..7ae07b332 --- /dev/null +++ b/code/sdk/drivers/peripheral/bp/CMakeLists.txt @@ -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 index 000000000..11a95eff1 --- /dev/null +++ b/code/sdk/drivers/peripheral/bp/bn02/bn02.c @@ -0,0 +1,260 @@ +/* + * @Author: penglei 1624952103@qq.com + * @Date: 2025-01-16 12:35:15 + * @LastEditors: penglei 1624952103@qq.com + * @LastEditTime: 2025-06-12 16:37:28 + * @FilePath: /sdk615/code/sdk/zhihui/drivers/bp/bn02/bn02.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 "pinctrl_porting.h" +#include "hal_gpio.h" +#include "i2c.h" +#include "pm_definition.h" +#include "bp_ble_service.h" +#include "bp_tcp_server.h" + + +#define BN02_I2C_ADDR 0x05 +#define BN02_I2C_BUS I2C_BUS_0 +#define I2C_ADDR_BN02_W 0x0a +#define I2C_ADDR_BN02_R 0x0b +#define P_EN S_AGPIO_L24 +#define P_INT S_AGPIO_R3 + +#define POWER_EN S_AGPIO_R0 + +#define BN02_FILE "user/userdata/bn02.bin" + +static int DATA_HANDLE = 1 << 24; + +static FILE *fp = NULL; + +static int data_cnt = 0; +// static int data[16 * 5 * 60] = {0}; + +// int data = ((rxByte[i] & 0xff) << 16) +// + ((rxByte[i + 1] & 0xff) << 8) +// + (rxByte[i + 2] & 0xff); +// if (data >= DATA_HANDLE / 2) { +// data -= DATA_HANDLE; +// } +// 其中:DATA_HANDLE = 2^24 + + +bool Bn02_write_reg(uint8_t data) +{ + uint8_t cnt = pm_veto_get_id_cnt(PM_ID_BP); + if (cnt == 0) + { + uapi_pm_add_sleep_veto(PM_ID_BP); + } + + i2c_data_t i2c_data; + i2c_data.send_buf = &data; + i2c_data.send_len = sizeof(data); + i2c_data.receive_buf = NULL; + i2c_data.receive_len = 0; + // custom_i2c_write_reg(BN02_I2C_ADDR, 0x00, 1, &data, 1, BN02_I2C_BUS); + errcode_t ret = uapi_i2c_master_write(BN02_I2C_BUS, BN02_I2C_ADDR, &i2c_data); + if (ret != ERRCODE_SUCC) + printf("i2c Write data write fail! ret=0x%x\n", ret); + + cnt = pm_veto_get_id_cnt(PM_ID_BP); + if (cnt == 1) + { + uapi_pm_remove_sleep_veto(PM_ID_BP); + } + + return 1; +} + +bool Bn02_reads(uint8_t *data,int len) +{ + + uint8_t cnt = pm_veto_get_id_cnt(PM_ID_BP); + if (cnt == 0) + { + uapi_pm_add_sleep_veto(PM_ID_BP); + } + + i2c_data_t i2c_data; + i2c_data.send_buf = NULL; + i2c_data.send_len = 0; + i2c_data.receive_buf = data; + i2c_data.receive_len = len; + // custom_i2c_write_reg(BN02_I2C_ADDR, 0x00, 1, &data, 1, BN02_I2C_BUS); + errcode_t ret = uapi_i2c_master_read(BN02_I2C_BUS, BN02_I2C_ADDR, &i2c_data); + if (ret != ERRCODE_SUCC) + printf("i2c read data fail! ret=0x%x\n", ret); + + cnt = pm_veto_get_id_cnt(PM_ID_BP); + if (cnt == 1) + { + uapi_pm_remove_sleep_veto(PM_ID_BP); + } + + return 1; +} + +static void delay_ms(int cnt) +{ + LOS_Mdelay(cnt); +} + +void Bn02_Power_Ctrl(int onoff) +{ + if(onoff == 1) + { + uapi_pin_set_mode(POWER_EN, (pin_mode_t)HAL_PIO_FUNC_GPIO); + uapi_gpio_set_dir(POWER_EN, GPIO_DIRECTION_OUTPUT); + uapi_gpio_set_val(POWER_EN, GPIO_LEVEL_HIGH); + LOS_Mdelay(1); + uapi_pin_set_mode(P_EN, (pin_mode_t)HAL_PIO_FUNC_GPIO); + uapi_gpio_set_dir(P_EN, GPIO_DIRECTION_OUTPUT); + uapi_gpio_set_val(P_EN, GPIO_LEVEL_HIGH); + // delay_ms(20); + LOS_Mdelay(50); + } + else + { + uapi_pin_set_mode(P_EN, (pin_mode_t)HAL_PIO_FUNC_GPIO); + uapi_gpio_set_dir(P_EN, GPIO_DIRECTION_OUTPUT); + uapi_gpio_set_val(P_EN, GPIO_LEVEL_LOW); + + uapi_pin_set_mode(POWER_EN, (pin_mode_t)HAL_PIO_FUNC_GPIO); + uapi_gpio_set_dir(POWER_EN, GPIO_DIRECTION_OUTPUT); + uapi_gpio_set_val(POWER_EN, GPIO_LEVEL_LOW); + } +} + +void bn02_int_init(void) +{ + uapi_pin_set_ie(P_INT,HAL_PIO_IE_ENBALE); +} + +void bn02_int_deinit(void) +{ + uapi_pin_set_ie(P_INT,HAL_PIO_IE_DISABLE); +} + +void bn02_int_handle(void) +{ + uint8_t bn02_buf[48] = {0}; + int i; + memset(bn02_buf,0,sizeof(bn02_buf)); + Bn02_reads(bn02_buf,48); + int reply_data[16] = {0}; + int cnt = 0; + for(i = 0;i<48;i+=3,cnt++) + { + reply_data[cnt] = ((bn02_buf[i] & 0xff) << 16) + + ((bn02_buf[i + 1] & 0xff) << 8) + + (bn02_buf[i + 2] & 0xff); + + if (reply_data[cnt] >= DATA_HANDLE / 2) + reply_data[cnt] -= DATA_HANDLE; + + printf("111data[%d]:%d\n",cnt,reply_data[cnt]); + // 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]); + } + + // if(bn02_get_ble_status()) + // { + // bn02_replymsg(reply_data,cnt,1); + // } + + // if(fp) + // { + // data_cnt += cnt; + // if(fwrite(bn02_buf,sizeof(int),cnt,fp) != cnt) + // printf("bn02 fwrite failed\n"); + // else + // printf("bn02 fwrite succed data_cnt:%d\n",cnt); + // } + + + // printf("data_cnt:%d\n",data_cnt); + + + do_bp_tcp_server_send_data((void *)reply_data,cnt); + + // if(data_cnt >= 16 * 5 * 60 && fp) + // { + // int *data_array = (int *)malloc(data_cnt * sizeof(int)); + + // if (!data_array) + // { + // printf("内存分配失败\n"); + // } + // else + // { + // int read_count = 0; + + // fseek(fp, 0, SEEK_SET); + + // while (read_count < data_cnt && fread(&data_array[read_count], sizeof(int), 1, fp) == 1) + // { + // printf("%d ", data_array[read_count]); + // read_count++; + + // if (read_count % 10 == 0) + // printf("\n"); + // } + + // printf("\n实际读取数据: %d 个\n", read_count); + + // if (feof(fp)) + // printf("已读取所有数据\n"); + // else if (ferror(fp)) + // { + // printf("读取数据时发生错误\n"); + // free(data_array); + // data_array = NULL; + // } + + + // free(data_array); + // data_array = NULL; + + // // 清空文件内容(将文件指针移到文件开头并截断文件) + // fclose(fp); // 关闭文件 + // if(remove(BN02_FILE) != 0) + // printf("remove %s failed\n",BN02_FILE); + // else + // printf("remove %s succed\n",BN02_FILE); + + // bn02_stop(); + // } + // } + +} + +void bn02_start(void) +{ + Bn02_Power_Ctrl(1); + bn02_int_init(); + Bn02_write_reg(BN02_START_CMD); + // data_cnt = 0; + // fp = fopen(BN02_FILE, "ab+"); + // if(fp == NULL) + // printf("open %s failed\n",BN02_FILE); + // else + // printf("open %s succed\n",BN02_FILE); +} + +void bn02_stop(void) +{ + bn02_int_deinit(); + Bn02_write_reg(BN02_STOP_CMD); + Bn02_Power_Ctrl(0); + + bp_tcp_data_clean(); + // if(fp) + // { + // fclose(fp); + // fp = NULL; + // } +} diff --git a/code/sdk/drivers/peripheral/bp/bn02/bn02.h b/code/sdk/drivers/peripheral/bp/bn02/bn02.h new file mode 100644 index 000000000..c4216a982 --- /dev/null +++ b/code/sdk/drivers/peripheral/bp/bn02/bn02.h @@ -0,0 +1,32 @@ +/* + * @Author: penglei 1624952103@qq.com + * @Date: 2025-01-16 12:35:15 + * @LastEditors: penglei 1624952103@qq.com + * @LastEditTime: 2025-01-16 14:55:48 + * @FilePath: /sdk615/code/sdk/zhihui/drivers/bp/bn02/bn02.h + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +#ifndef _BN02_H_ +#define _BN02_H_ + +enum +{ + + BN02_INT_HANDLE, + BN02_INIT_ENABLE, + BN02_START, + BN02_POWER_DISABLE, + BN02_STOP, +}; + +#define BN02_START_CMD 0x04 +#define BN02_STOP_CMD 0x08 + +void bn02_int_handle(void); + +void bn02_start(void); + +void bn02_stop(void); + +#endif // _HRS3300_H_ + 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 index 000000000..f470a88b3 --- /dev/null +++ b/code/sdk/drivers/peripheral/bp/lib/lib_hr.h @@ -0,0 +1,150 @@ +#ifndef __LIB_EMOTION_H__ +#define __LIB_EMOTION_H__ + +#ifdef __cplusplus +extern "C"{ +#endif +#include +#include +#include + + +#define SAMPLERATE 81 // sampling rate +//#define SAMPLERATE 100 +#define SAMPLETIME 5 // sampling time (seconds) data of which will be processed every time +#define EMOTIONTIME 60 +#define HRVTIME 300 +#define BPTIME 30 +#define DDTIME 20 // measure duration of drinking degree +#define SINGLETIME 5 +#define MAX_SLEEP_STATE 50 + + +/* Integer data types */ +#if ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) && \ + (!defined(__ICC8051__) || (__ICC8051__ == 0))) +#include +#else + typedef signed char int8_t; + typedef unsigned char uint8_t; + typedef signed short int16_t; + typedef unsigned short uint16_t; + typedef signed long int32_t; + typedef unsigned long uint32_t; + typedef unsigned long long uint64_t; +#endif + +typedef struct +{ + short int x; + short int y; + short int z; +} gsensor_data_t; + +typedef enum +{ + LS_STATE = 11, // light sleep + DS_STATE = 12, // deep sleep + REM_STATE = 2, // rapid eye movement +} SLEEP_STATE_E; + +typedef struct +{ + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; +} sleep_time_t; + +typedef struct +{ + uint32_t duration; // the duration of corresponding state + SLEEP_STATE_E state; // state +} sleep_detail_data_t; + +typedef struct +{ + uint32_t total_sleep_time; // minutes + sleep_time_t begin_sleep_time; // sleep_time_t + sleep_time_t end_sleep_time; + uint16_t state_count; // number of some sleep state + sleep_detail_data_t data[MAX_SLEEP_STATE]; +} sleep_data_t; + +typedef struct +{ + uint16_t hr; + uint32_t timestamp; // timestamp in measuretime (s) +} sleep_hr_t; + + +typedef struct +{ + uint16_t sbp; + uint16_t dbp; + int32_t timestamp; // timestamp in measuretime +} bps_t; + + + +// base api (include callback function) +typedef void (*extern_printf_cb_t)(const char* format, ...); +unsigned int extern_printf_cb_reg(extern_printf_cb_t fun); +int init_algorithm(unsigned char* buf, unsigned int len); + + +// heart rate variability algorithm api (include callback function) +typedef void (*extern_get_hr_run_time_cb_t)(int* type, int* sec); +unsigned int extern_get_hr_run_time_cb_reg(extern_get_hr_run_time_cb_t fun); +int get_hr(int data[], int datalen, int fs, int* hr); + + +// emotion algorithm api +int ppg_midvalue(int data[], int datalen, int fs, float Fm[25][8], int* fmlen); +int get_emotion_pi(int data[], int datalen, int fs, int* emo, int* pi); +int get_dd_index(int data[], int datalen, int fs, int* dd, int* hr); + + +// blood pressure algorithm api +int load_bp_model(unsigned char str_model[], const unsigned int str_model_len); +int get_bp(int data[], int datalen, int fs, int* sbp, int* dbp); +int load_gen_info(int height, int weight, int age, int gender); +int get_bp_general(int data[], int datalen, int fs, int* sbp, int* dbp); + + +// temperature algorithm api +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); + + +// sleep algorithm api (include callback function) +typedef void (*extern_get_wear_state_cb_t)(uint8_t* worn); +unsigned int extern_get_wear_state_cb_reg(extern_get_wear_state_cb_t fun); +typedef void (*extern_get_inst_hr_cb_t)(uint8_t* hr, sleep_time_t* hr_time); +unsigned int extern_get_inst_hr_cb_reg(extern_get_inst_hr_cb_t fun); +void init_sleep_algo_ex(sleep_data_t* sdata, int gfs, int pfs); +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); + + +// authentication api +void request_validation( + const unsigned char fact[], const unsigned int fact_len, + const unsigned char imei[], const unsigned int imei_len, + unsigned char req_code[], unsigned int* req_code_len); + +int activate_algorithm( + const unsigned char req_code[], const unsigned int req_code_len, + const unsigned char key_code[], const unsigned int key_code_len); + + +// version api +void version_get_string(char* string, unsigned int* str_len); + + + +#ifdef __cplusplus +} +#endif + + +#endif 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 index 000000000..65ce39c6e 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 index 000000000..220ddea50 --- /dev/null +++ b/code/sdk/drivers/peripheral/bp/lib/yyl_pfev01.h @@ -0,0 +1,74 @@ +// +// Created on 2021/12/22. +// + +#ifndef YYLPFEV01_H +#define YYLPFEV01_H + +#include +#include +#include +#include +#include + +//#include "algo.h" + +#define OUTPUTDATALEN 120U +#define LIMITEDPPGLEN 3000U +#define LIMITOFMOTIONCAL 3 + + + typedef struct + { + int32_t x; + int32_t y; + int32_t z; + }yylPFE_AxesData_t; + + typedef struct + { + yylPFE_AxesData_t axes; + int32_t ppgSample; + }yylPFE_InputData_t; + + +#if 0 +typedef struct { + uint32_t timestamp; + uint16_t RRI; + uint32_t areaUP; + uint16_t areaUPBase; + uint16_t areaUPHeight; + uint32_t areaDOWN; + uint16_t areaDOWNBase; + uint16_t areaDOWNHeight; + uint16_t motion; +}yylPFE_OutputData; + +#else + +typedef struct { + uint32_t timestamp; + uint32_t areaUP; + uint16_t areaUPBase; + uint16_t areaUPHeight; + uint32_t areaDOWN; + uint16_t areaDOWNBase; + uint16_t areaDOWNHeight; + uint16_t RRI; + uint16_t motion; +}yylPFE_OutputData; + +#endif +// len >= 6870 +void YYL_Init_PFE(unsigned char* buf, unsigned int len); + +void YYL_Input_PFE(yylPFE_InputData_t *pInputData, int32_t hr); + +yylPFE_OutputData * YYL_Output_PFE(int32_t *outputLen); + +void YYL_Output_PFE_Array_Clear(void); + +char * YYL_PFE_Get_Current_Version(void); + +#endif //YYLPFEV01_H 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 index 000000000..f9771b400 --- /dev/null +++ b/code/sdk/drivers/peripheral/bp/service/bp_at_cmd.c @@ -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 index 000000000..3409d1d3f --- /dev/null +++ b/code/sdk/drivers/peripheral/bp/service/bp_at_cmd.h @@ -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 +#include +#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 index 000000000..995dd8b5b --- /dev/null +++ b/code/sdk/drivers/peripheral/bp/service/bp_ble_service.c @@ -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 index 000000000..ace1004f6 --- /dev/null +++ b/code/sdk/drivers/peripheral/bp/service/bp_ble_service.h @@ -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 index 000000000..e8bf0864a --- /dev/null +++ b/code/sdk/drivers/peripheral/bp/service/bp_service.c @@ -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 index 000000000..ba02c9a9d --- /dev/null +++ b/code/sdk/drivers/peripheral/bp/service/bp_service.h @@ -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 index 000000000..fc8fd9437 --- /dev/null +++ b/code/sdk/drivers/peripheral/bp/service/bp_tcp_server.c @@ -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 index 000000000..b20a90adc --- /dev/null +++ b/code/sdk/drivers/peripheral/bp/service/bp_tcp_server.h @@ -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 diff --git a/code/sdk/drivers/peripheral/cywee/service/cywee_ble_Service.c b/code/sdk/drivers/peripheral/cywee/service/cywee_ble_Service.c index f489d7c8f..e5e2e36b0 100644 --- a/code/sdk/drivers/peripheral/cywee/service/cywee_ble_Service.c +++ b/code/sdk/drivers/peripheral/cywee/service/cywee_ble_Service.c @@ -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); /*****参考结束****/ } diff --git a/code/sdk/drivers/peripheral/cywee/src/main_dml.c b/code/sdk/drivers/peripheral/cywee/src/main_dml.c index ac9ac6ad6..66e3109d7 100644 --- a/code/sdk/drivers/peripheral/cywee/src/main_dml.c +++ b/code/sdk/drivers/peripheral/cywee/src/main_dml.c @@ -20,6 +20,10 @@ #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: diff --git a/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_pin_port.h b/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_pin_port.h index 1a3570652..51810a89a 100644 --- a/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_pin_port.h +++ b/code/sdk/drivers/peripheral/gnss/driver/common/interface/board_interface/board_porting/tiot_board_pin_port.h @@ -29,19 +29,7 @@ extern "C" { */ #define TIOT_PIN_NONE 0xFFFFFFFFU -#ifdef BOARD_U8 -#define TIOT_UART_PORT UART_BUS_0 -#define TIOT_PIN_WAKEUP_HOST_NUM S_AGPIO_L31 /* 用于唤醒HOST. */ -#define TIOT_PIN_WAKEUP_GNSS_NUM TIOT_PIN_NONE /* 用于 唤醒GNSS. */ -#define TIOT_PIN_POWER S_AGPIO_L30 /* 用于开启GNSS. */ - -#define TIOT_PIN_UART_TX S_MGPIO19 -#define TIOT_PIN_UART_RX S_MGPIO20 -#define TIOT_PIN_UART_CTS S_MGPIO22 -#define TIOT_PIN_UART_RTS S_MGPIO21 -#define TIOT_PINMUX HAL_PIO_FUNC_UART1 - -#elif defined(BOARD_L22) || defined(BOARD_W9) +#if defined(BOARD_W9) || defined(BOARD_N9) #define TIOT_UART_PORT UART_BUS_1 #define TIOT_PIN_WAKEUP_HOST_NUM S_AGPIO_L15 /* 用于唤醒HOST. */ #define TIOT_PIN_WAKEUP_GNSS_NUM S_HGPIO0 /* 用于 唤醒GNSS. */ diff --git a/code/sdk/drivers/peripheral/gnss/sample/gnss_sample/gnss_sample.c b/code/sdk/drivers/peripheral/gnss/sample/gnss_sample/gnss_sample.c index e59debb8d..799aa7741 100644 --- a/code/sdk/drivers/peripheral/gnss/sample/gnss_sample/gnss_sample.c +++ b/code/sdk/drivers/peripheral/gnss/sample/gnss_sample/gnss_sample.c @@ -10,6 +10,7 @@ #include "tiot_service_interface.h" #include "pm_definition.h" #include "gnss_ctl.h" +#include "cywee_hal.h" #define COLDSTART_FIXMODEGPS_NMEAALL_SAMPLE 0 #define AUTOSTART_FIXMODEALL_NMEADEF_SAMPLE 1 @@ -115,39 +116,39 @@ int32_t CfgColdStartFixModeGpsNmeaAll(tiot_handle handle) // 配置启动模式:冷启动模式。 int32_t ret = tiot_service_write(handle, cfgColdStartCmd, sizeof(cfgColdStartCmd)); if (ret < 0) { - printf("\nerror: cfgColdStartCmd error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: cfgColdStartCmd error: %d\n", ret); return 0; } // 配置使能的GNSS星座:GPS。 ret = tiot_service_write(handle, cfgFixModeAllCmd, sizeof(cfgFixModeAllCmd)); if (ret < 0) { - printf("\nerror: cfgFixModeAllCmd error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: cfgFixModeAllCmd error: %d\n", ret); return 0; } // 配置上报NMEA类型:PNT/ZDA/VTG/RMC/GSV/GSA/GLL/GGA。 ret = tiot_service_write(handle, cfgNmeaAllCmd, sizeof(cfgNmeaAllCmd)); if (ret < 0) { - printf("\nerror: cfgNmeaAllCmd error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: cfgNmeaAllCmd error: %d\n", ret); return 0; } ret = tiot_service_write(handle, CFG_TRK_LPW_DISABLE, sizeof(CFG_TRK_LPW_DISABLE)); if (ret < 0) { - printf("\nerror: CFG_TRK_LPW_DISABLE error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: CFG_TRK_LPW_DISABLE error: %d\n", ret); return 0; } ret = tiot_service_write(handle, CFG_ACQ_LPW_DISABLE, sizeof(CFG_ACQ_LPW_DISABLE)); if (ret < 0) { - printf("\nerror: CFG_ACQ_LPW_DISABLE error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: CFG_ACQ_LPW_DISABLE error: %d\n", ret); return 0; } ret = tiot_service_write(handle, CFG_ANTIJAM_ENABLE, sizeof(CFG_ANTIJAM_ENABLE)); if (ret < 0) { - printf("\nerror: CFG_ANTIJAM_ENABLE error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: CFG_ANTIJAM_ENABLE error: %d\n", ret); return 0; } return 1; @@ -161,33 +162,33 @@ int32_t CfgAutoStartFixModeAllNmeaDefault(tiot_handle handle) // 配置启动模式:自动模式。 int32_t ret = tiot_service_write(handle, cfgAutoStartCmd, sizeof(cfgAutoStartCmd)); if (ret < 0) { - printf("\nerror: cfgAutoStartCmd error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: cfgAutoStartCmd error: %d\n", ret); return 0; } // 配置使能的GNSS星座:QZSS/GAL/BDS/GLO/GPS。 ret = tiot_service_write(handle, cfgFixModeAllCmd, sizeof(cfgFixModeAllCmd)); if (ret < 0) { - printf("\nerror: cfgFixModeAllCmd error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: cfgFixModeAllCmd error: %d\n", ret); return 0; } // 配置上报NMEA类型:RMC/GGA。 ret = tiot_service_write(handle, cfgNmeaDefaultCmd, sizeof(cfgNmeaDefaultCmd)); if (ret < 0) { - printf("\nerror: cfgNmeaDefaultCmd error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: cfgNmeaDefaultCmd error: %d\n", ret); return 0; } ret = tiot_service_write(handle, CFG_TRK_LPW_DISABLE, sizeof(CFG_TRK_LPW_DISABLE)); if (ret < 0) { - printf("\nerror: CFG_TRK_LPW_DISABLE error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: CFG_TRK_LPW_DISABLE error: %d\n", ret); return 0; } ret = tiot_service_write(handle, CFG_ACQ_LPW_DISABLE, sizeof(CFG_ACQ_LPW_DISABLE)); if (ret < 0) { - printf("\nerror: CFG_ACQ_LPW_DISABLE error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: CFG_ACQ_LPW_DISABLE error: %d\n", ret); return 0; } return 1; @@ -199,7 +200,7 @@ static int32_t QryVersion(tiot_handle handle) // 查询版本号 int32_t ret = tiot_service_write(handle, qryVersion, sizeof(qryVersion)); if (ret < 0) { - printf("\nerror: QryVersion error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: QryVersion error: %d\n", ret); return 0; } return 1; @@ -216,10 +217,10 @@ static int32_t StartGnss(tiot_handle handle) // 启动GNSS int32_t ret = tiot_service_write(handle, startCmd, sizeof(startCmd)); if (ret < 0) { - printf("\nerror: start gnss error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: start gnss error: %d\n", ret); return 0; } - printf("\nstart gnss\n"); + CWM_OS_dbgPrintf("\nstart gnss\n"); return 1; } @@ -228,10 +229,10 @@ static int32_t StopGnss(tiot_handle handle) // 停止GNSS int32_t ret = tiot_service_write(handle, stopCmd, sizeof(stopCmd)); if (ret < 0) { - printf("\nerror: stop gnss error: %d\n", ret); + CWM_OS_dbgPrintf("\nerror: stop gnss error: %d\n", ret); return 0; } - printf("\nstop gnss\n"); + CWM_OS_dbgPrintf("\nstop gnss\n"); return 1; } @@ -242,7 +243,7 @@ static void ListenGnssData(tiot_handle handle) for (;;) { // 写日志条件 if (i >= LISTEN_DATA_MAX_LINES) { - printf("\ncnt enough\n"); + CWM_OS_dbgPrintf("\ncnt enough\n"); break; } if (g_gnss_stopflag == 1) @@ -256,7 +257,7 @@ static void ListenGnssData(tiot_handle handle) if (type[0] == MSG_TYPE_ASCII) { g_gnssServiceBuff[ret] = '\0'; char* pbuf=(char *)&g_gnssServiceBuff[MSG_CONTENT_IDX]; - printf("%s\n", pbuf); + CWM_OS_dbgPrintf("%s\n", pbuf); if (g_is_gnss_logon) fprintf(g_gnssLogFp, "%s\n", pbuf); for (int index=0;index < ret ;index++) @@ -264,7 +265,7 @@ static void ListenGnssData(tiot_handle handle) if (decode_nmea(pbuf[index])==1) { // dump_location_data(&g_global_gpsData); - printf("decode_nmea done\r\n"); + CWM_OS_dbgPrintf("decode_nmea done\r\n"); } } } @@ -300,10 +301,10 @@ int GnssLogEnable(bool enable) void GnssServerStart(void) { - printf("\nenter gnss samples\n"); + CWM_OS_dbgPrintf("\nenter gnss samples\n"); if(g_is_gnss_poweron == 1) { - printf("gnss already on\r\n"); + CWM_OS_dbgPrintf("gnss already on\r\n"); return ; } uapi_pm_add_sleep_veto(PM_ID_SYS); @@ -316,7 +317,7 @@ void GnssServerStart(void) // Step1: init int32_t ret = tiot_service_init(); if (ret != 0) { - printf("\ntiot service init fail\n"); + CWM_OS_dbgPrintf("\ntiot service init fail\n"); g_is_gnss_poweron = 0; g_gnss_stopflag = 1; } @@ -326,21 +327,21 @@ void GnssServerStart(void) { g_gnssLogFp = fopen("/user/log/gnss.log", "w"); if (g_gnssLogFp == NULL) { - printf("\nerror: open log file error\n"); + CWM_OS_dbgPrintf("\nerror: open log file error\n"); return; } } - printf("\nbefore open tiot service\n"); + CWM_OS_dbgPrintf("\nbefore open tiot service\n"); // Step2: power on gnss tiot_handle handle = tiot_service_open("gn71", NULL); if (handle == 0) { - printf("\nopen tiot service fail\n"); + CWM_OS_dbgPrintf("\nopen tiot service fail\n"); g_is_gnss_poweron = 0; g_gnss_stopflag = 1; return; } - printf("\nopen tiot service success\n"); + CWM_OS_dbgPrintf("\nopen tiot service success\n"); int32_t cfgRet; // ---- loop ---------- @@ -354,7 +355,7 @@ void GnssServerStart(void) if (cfgRet == 0) { continue; } - printf("\ncfg sample id:%u\n", g_gnssSamplesCfg[i].sampleId); + CWM_OS_dbgPrintf("\ncfg sample id:%u\n", g_gnssSamplesCfg[i].sampleId); QryVersion(handle); // Step4: start gnss @@ -386,5 +387,5 @@ void GnssServerStart(void) #endif uapi_pm_remove_sleep_veto(PM_ID_SYS); g_is_gnss_poweron=0; - printf("\nfinish gnss samples\n"); + CWM_OS_dbgPrintf("\nfinish gnss samples\n"); } \ No newline at end of file diff --git a/code/sdk/drivers/peripheral/gnss/src/gnss_ctl.c b/code/sdk/drivers/peripheral/gnss/src/gnss_ctl.c index ce8914b57..ed33383ef 100644 --- a/code/sdk/drivers/peripheral/gnss/src/gnss_ctl.c +++ b/code/sdk/drivers/peripheral/gnss/src/gnss_ctl.c @@ -31,70 +31,45 @@ #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 diff --git a/code/sdk/drivers/peripheral/gnss/src/uart_gnss.c b/code/sdk/drivers/peripheral/gnss/src/uart_gnss.c index 63d4b91f3..024893b5a 100644 --- a/code/sdk/drivers/peripheral/gnss/src/uart_gnss.c +++ b/code/sdk/drivers/peripheral/gnss/src/uart_gnss.c @@ -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 index 000000000..68110308c --- /dev/null +++ b/code/sdk/drivers/peripheral/gyro/CMakeLists.txt @@ -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 index 000000000..ef0237f5d --- /dev/null +++ b/code/sdk/drivers/peripheral/gyro/service/gyro_at_cmd.c @@ -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 index 000000000..e6bd34caa --- /dev/null +++ b/code/sdk/drivers/peripheral/gyro/service/gyro_at_cmd.h @@ -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 +#include +#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 index 000000000..9e0f083f1 --- /dev/null +++ b/code/sdk/drivers/peripheral/gyro/service/gyro_hal.c @@ -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 +#include +#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 index 000000000..2e732483f --- /dev/null +++ b/code/sdk/drivers/peripheral/gyro/service/gyro_hal.h @@ -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 + +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 index 000000000..51e46eef4 --- /dev/null +++ b/code/sdk/drivers/peripheral/gyro/service/gyro_service.c @@ -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 index 000000000..3dd128822 --- /dev/null +++ b/code/sdk/drivers/peripheral/gyro/service/gyro_service.h @@ -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 index 000000000..27035beb4 --- /dev/null +++ b/code/sdk/drivers/peripheral/gyro/sh5001/sh5001.c @@ -0,0 +1,3086 @@ +/****************************************************************** +* Senodia 6D IMU(Gyroscope+Accelerometer) SH5001 driver, By Senodia AE@20220505; +* +* +* 1. SH5001_init() : SH5001 initialize function +* 2. SH5001_GetImuData( ... ): SH5001 read gyro and accel data function +* 3. SH5001_GetTempData(): SH5001 read termperature function +* 4. delay_ms(x): delay x millisecond. +* 5. SH5001_initFIFO(): initialize FIFO function +* 6. SH5001_ReadFIFO(): read FIFO data +* +******************************************************************/ + +#include "sh5001.h" +#include "custom_utils.h" +#include "los_base.h" + +// 32-bit version number represented as major[31:16].minor[15:0] +#define SH5001_MAJOR 1 +#define SH5001_MINOR 01 +#define SH5001_REV 31 +#define MCU_VERSION_SH5001 ((SH5001_MAJOR<<16) | (SH5001_MINOR<<8) | SH5001_REV) + +#define SH5001_I2C_BUS I2C_BUS_2 + +static gyro_data_t gyro_data = {0}; + +/****************************************************************** +* Description: I2C or SPI bus interface functions and delay time function +* +* Parameters: +* devAddr: I2C device address, modify the macro(SH5001_ADDRESS @SH5001.h) based on your I2C function. +* If SPI interface, please ingnore the parameter. +* regAddr: register address +* readLen: data length to read +* *readBuf: data buffer to read; If using FIFO function, the max buffer size is 1024; +* writeLen: data length to write +* *writeBuf: data buffer to write +* +* Note: I2C interface, define USER_INTERFACE_I2C (1) +* SPI interface, define USER_INTERFACE_I2C (0) +* SPI 3 Wire interface, define SH5001_SPI_3WIRE_MODE (1) +* SPI 4 Wire interface, define SH5001_SPI_3WIRE_MODE (0) +* +******************************************************************/ +#define USER_INTERFACE_I2C (1) + +#if USER_INTERFACE_I2C + +unsigned char I2C_ReadNBytes( unsigned char devAddr, + unsigned char regAddr, + unsigned short readLen, + unsigned char *readBuf) +{ + //your I2C interface code: + //...... + custom_i2c_read_regs(devAddr, regAddr, 1, readBuf, readLen,SH5001_I2C_BUS); + return (SH5001_TRUE); +} + +unsigned char I2C_WriteNBytes( unsigned char devAddr, + unsigned char regAddr, + unsigned short writeLen, + unsigned char *writeBuf) +{ + //your I2C interface code: + //...... + custom_i2c_write_reg(devAddr, regAddr, 1, writeBuf, writeLen,SH5001_I2C_BUS); + return (SH5001_TRUE); +} + +IMU_read SH5001_read = I2C_ReadNBytes; +IMU_write SH5001_write = I2C_WriteNBytes; + +#else + +#define SH5001_SPI_3WIRE_MODE (0) + +unsigned char SPI_readNBytes ( unsigned char devAddr, + unsigned char regAddr, + unsigned short readLen, + unsigned char *readBuf) +{ + //your SPI interface code: + + //For example: + //unsigned char u8Data; + //devAddr = devAddr; + //u8Data = (regAddr > 0x7F) ? 0x01 : 0x00; + //SPIWrite(SH5001_SPI_REG_ACCESS, &u8Data, 1); + + //SPIRead((regAddr | 0x80), readBuf, readLen); + return (SH5001_TRUE); +} + +unsigned char SPI_writeNBytes( unsigned char devAddr, + unsigned char regAddr, + unsigned short writeLen, + unsigned char *writeBuf) +{ + //your SPI interface code: + + //For example: + //unsigned char u8Data; + //devAddr = devAddr; + //u8Data = (regAddr > 0x7F) ? 0x01 : 0x00; + //SPIWrite(SH5001_SPI_REG_ACCESS, &u8Data, 1); + + //SPIWrite((regAddr & 0x7F), writeBuf, writeLen); + return (SH5001_TRUE); +} + +IMU_read SH5001_read = SPI_readNBytes; +IMU_write SH5001_write = SPI_writeNBytes; + +#endif + + +static void delay_ms(unsigned short mSecond) +{ + //your delay code(mSecond: millisecond): + //...... + LOS_Mdelay(mSecond); + // HAL_Delay(mSecond); +} + + +#if SH5001_OIS_ENABLE +unsigned char SH5001_OIS_read( unsigned char devAddr, + unsigned char regAddr, + unsigned short readLen, + unsigned char *readBuf) +{ + //your SPI interface code: + + + //SPIRead((regAddr | 0x80), readBuf, readLen); + return (SH5001_TRUE); +} + +#endif + + +/****************************************************************** +* Description: Local Variable +******************************************************************/ + + +/****************************************************************** +* Description: Local Function Prototypes +******************************************************************/ +static void SH5001_ModuleReset(void); +static void SH5001_Acc_Config(unsigned char accODR, + unsigned char accRange, + unsigned char accCutOffFreq, + unsigned char accFilter, + unsigned char accByPass); + +static void SH5001_Gyro_Config( unsigned char gyroODR, + unsigned char gyroRange, + unsigned char gyroCutOffFreq, + unsigned char gyroFilter, + unsigned char gyroByPass); + +static void SH5001_TimeStamp_Config(unsigned char timeStampODR, + unsigned char timeStampEnable); + +static void SH5001_Temp_Config( unsigned char tempODR, + unsigned char tempEnable); + + + +static void SH5001_SoftReset(void) +{ + unsigned char regData = 0; + + regData = 0x01; + SH5001_write(SH5001_ADDRESS, 0x2B, 1, ®Data); + regData = 0x73; + SH5001_write(SH5001_ADDRESS, 0x00, 1, ®Data); + + delay_ms(50); +} + +static void SH5001_DriveStart(void) +{ + unsigned char regData = 0; + //Driver start + regData = 0x01; + SH5001_write(SH5001_ADDRESS, 0x2B, 1, ®Data); + + delay_ms(2); + + regData = 0x00; + SH5001_write(SH5001_ADDRESS, 0x2B, 1, ®Data); + + delay_ms(1); + +} + +static void SH5001_ADCReset(void) +{ + unsigned char regData = 0; + + regData = 0x08; + SH5001_write(SH5001_ADDRESS, 0x30, 1, ®Data); + + regData = 0x00; + SH5001_write(SH5001_ADDRESS, 0xD2, 1, ®Data); + + regData = 0x6B; + SH5001_write(SH5001_ADDRESS, 0xD1, 1, ®Data); + + regData = 0x02; + SH5001_write(SH5001_ADDRESS, 0xD5, 1, ®Data); + delay_ms(5); + + regData = 0x68; + SH5001_write(SH5001_ADDRESS, 0xD1, 1, ®Data); + delay_ms(2); + + regData = 0x00; + SH5001_write(SH5001_ADDRESS, 0xD5, 1, ®Data); + + regData = 0x00; + SH5001_write(SH5001_ADDRESS, 0x30, 1, ®Data); + + regData = 0x08; + SH5001_write(SH5001_ADDRESS, 0x30, 1, ®Data); + + regData = 0xE0; + SH5001_write(SH5001_ADDRESS, 0xD8, 1, ®Data); + + delay_ms(5); + + regData = 0x00; + SH5001_write(SH5001_ADDRESS, 0xD8, 1, ®Data); + + regData = 0x00; + SH5001_write(SH5001_ADDRESS, 0x30, 1, ®Data); +} + +static void SH5001_CVAReset(void) +{ + unsigned char regData = 0; + + regData = 0x12; + SH5001_write(SH5001_ADDRESS, 0xCD, 1, ®Data); + regData = 0x12; + SH5001_write(SH5001_ADDRESS, 0xCE, 1, ®Data); + regData = 0x12; + SH5001_write(SH5001_ADDRESS, 0xCF, 1, ®Data); + + delay_ms(1); + + regData = 0x2; + SH5001_write(SH5001_ADDRESS, 0xCD, 1, ®Data); + regData = 0x2; + SH5001_write(SH5001_ADDRESS, 0xCE, 1, ®Data); + regData = 0x2; + SH5001_write(SH5001_ADDRESS, 0xCF, 1, ®Data); + +} + + +/****************************************************************** +* Description: reset some internal modules; +* +* Parameters: void +* +* return: void +* +******************************************************************/ +static void SH5001_ModuleReset(void) +{ + unsigned char regData = 0; + + // soft reset + SH5001_SoftReset(); + +#if SH5001_SPI_3WIRE_MODE + SH5001_SPI_Config(SH5001_SPI_3_WIRE); +#endif + + //Driver start + SH5001_DriveStart(); + + + // ADC reset + SH5001_ADCReset(); + + //CVA Reset + SH5001_CVAReset(); + + delay_ms(250); +} + + +/****************************************************************** +* Description: 1.set accelerometer parameters; +* 2.accCutOffRreq = accODR * 0.40 or accODR * 0.25 or accODR * 0.11 or accODR * 0.04 or accODR * 0.02; +* +* Parameters: accODR accRange accCutOffFreq accFilter accByPass +* SH5001_ACC_ODR_1000HZ SH5001_ACC_RANGE_16G SH5001_ACC_ODRX040 SH5001_ACC_FILTER_EN SH5001_ACC_BYPASS_EN +* SH5001_ACC_ODR_500HZ SH5001_ACC_RANGE_8G SH5001_ACC_ODRX025 SH5001_ACC_FILTER_DIS SH5001_ACC_BYPASS_DIS +* SH5001_ACC_ODR_250HZ SH5001_ACC_RANGE_4G SH5001_ACC_ODRX011 +* SH5001_ACC_ODR_125HZ SH5001_ACC_RANGE_2G SH5001_ACC_ODRX004 +* SH5001_ACC_ODR_63HZ SH5001_ACC_ODRX002 +* SH5001_ACC_ODR_31HZ +* SH5001_ACC_ODR_16HZ +* SH5001_ACC_ODR_2000HZ +* SH5001_ACC_ODR_4000HZ +* SH5001_ACC_ODR_8000HZ +* +* return: void +* +******************************************************************/ +unsigned char storeAccODR; +static void SH5001_Acc_Config(unsigned char accODR, + unsigned char accRange, + unsigned char accCutOffFreq, + unsigned char accFilter, + unsigned char accByPass) +{ + unsigned char regData = 0; + + // enable acc digital filter and bypass or not + SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF0, 1, ®Data); + regData = (regData & 0xFCU) | accFilter | accByPass; + SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF0, 1, ®Data); + + // set acc ODR range + SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF1, 1, ®Data); + regData = (regData & 0x80U) | accODR | accRange; + storeAccODR = regData; + //regData = (regData & 0x80U)| accRange | accODR; + //regData = (regData & 0x80U)| 0x38; + SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF1, 1, ®Data); + + // set acc low pass filter cut-off frequency + SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, ®Data); + regData = (regData & 0xF0U) | accCutOffFreq; + SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, ®Data); + +} + + + + +/****************************************************************** +* Description: 1.set accelerometer parameters; +* 2.accCutOffRreq = accODR * 0.40 or accODR * 0.25 or accODR * 0.11 or accODR * 0.04 or accODR * 0.02; +* +* Parameters: accODR accRange accCutOffFreq accOisEnable + +* return: void +* +******************************************************************/ +static void SH5001_Acc_OIS_Config(unsigned char accODR, + unsigned char accRange, + unsigned char accCutOffFreq, + unsigned char accOisEnable) +{ + unsigned char regData = 0; + + regData = accODR | accRange | accCutOffFreq | accOisEnable; + SH5001_write(SH5001_ADDRESS, SH5001_OIS_ACC_CONF, 1, ®Data); + +} + +/****************************************************************** +* Description: 1.set gyroscope parameters; +* 2.gyroCutOffRreq is at Page 33 of SH5001 datasheet. +* +* Parameters: gyroODR gyroRangeX,Y,Z gyroCutOffFreq gyroFilter gyroByPass +* SH5001_GYRO_ODR_800HZ SH5001_GYRO_RANGE_125 SH5001_GYRO_ODRX00 SH5001_GYRO_FILTER_EN SH5001_GYRO_BYPASS_EN +* SH5001_GYRO_ODR_400HZ SH5001_GYRO_RANGE_250 SH5001_GYRO_ODRX01 SH5001_GYRO_FILTER_DIS SH5001_GYRO_BYPASS_DIS +* SH5001_GYRO_ODR_200HZ SH5001_GYRO_RANGE_500 SH5001_GYRO_ODRX02 +* SH5001_GYRO_ODR_100HZ SH5001_GYRO_RANGE_1000 SH5001_GYRO_ODRX03 +* SH5001_GYRO_ODR_50HZ SH5001_GYRO_RANGE_2000 +* SH5001_GYRO_ODR_25HZ +* SH5001_GYRO_ODR_1600HZ +* SH5001_GYRO_ODR_3200HZ +* SH5001_GYRO_ODR_6400HZ +* SH5001_GYRO_ODR_12800HZ +* SH5001_GYRO_ODR_25600HZ +* +* gyroOnOff +* SH5001_GYRO_OFF_INACT +* SH5001_GYRO_ON_INACT +* return: void +* +******************************************************************/ +/* +static void SH5001_Gyro_Config( unsigned char gyroODR, + unsigned char gyroRange, + unsigned char gyroCutOffFreq, + unsigned char gyroFilter, + unsigned char gyroByPass, + unsigned char gyroOnOff) +{ + unsigned char regData = 0; + + // enable gyro digital filter + SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, ®Data); + regData = (regData & 0x7CU) | gyroFilter | gyroByPass | gyroOnOff; + SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, ®Data); + + // set gyro ODR + SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF1, 1, ®Data); + regData = (regData & 0xF0U) | gyroODR; + SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF1, 1, ®Data); + + // set gyro low pass filter cut-off frequency + SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF2, 1, ®Data); + regData = (regData & 0xFCU) | gyroCutOffFreq; + SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF2, 1, ®Data); + + + // set gyro range + SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF3, 1, ®Data); + regData = (regData & 0xF8U) | gyroRange; + SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF3, 1, ®Data); + +} + +*/ +static void SH5001_Gyro_Config( unsigned char gyroODR, + unsigned char gyroRange, + unsigned char gyroCutOffFreq, + unsigned char gyroFilter, + unsigned char gyroByPass) +{ + unsigned char regData = 0; + + // enable gyro digital filter + SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, ®Data); + regData = (regData & 0x7CU) | gyroFilter | gyroByPass; + SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, ®Data); + + // set gyro ODR Range + SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF1, 1, ®Data); + regData = (regData & 0x80U) | gyroODR | gyroRange; + SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF1, 1, ®Data); + + // set gyro low pass filter cut-off frequency + SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF2, 1, ®Data); + regData = (regData & 0xF0U) | gyroCutOffFreq; + SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF2, 1, ®Data); + +} + +//Jin: Modify +/* */ + + +static void SH5001_Gyro_OIS_Config( unsigned char gyroODR, + unsigned char gyroRange, + unsigned char gyroCutOffFreq, + unsigned char gyroOisEnable) +{ + unsigned char regData = 0; + + regData = gyroODR | gyroRange | gyroCutOffFreq | gyroOisEnable; + SH5001_write(SH5001_ADDRESS, SH5001_OIS_GYRO_CONF, 1, ®Data); + +} + + +/****************************************************************** +* Description: set time stamp parameters; +* +* Parameters: timeStampODR timeStampEnable +* SH5001_TS_ODR_25KHZ SH5001_TS_EN +* SH5001_TS_ODR_1KHZ SH5001_TS_DIS +* +* return: void +* +******************************************************************/ +static void SH5001_TimeStamp_Config(unsigned char timeStampODR, + unsigned char timeStampEnable) +{ + unsigned char regData = 0; + + // config time stamp + SH5001_read(SH5001_ADDRESS, SH5001_TIMESTAMP_CONF, 1, ®Data); + regData = (regData & 0x9FU) | timeStampODR | timeStampEnable; + SH5001_write(SH5001_ADDRESS, SH5001_TIMESTAMP_CONF, 1, ®Data); +} + + +/****************************************************************** +* Description: set temperature parameters; +* +* Parameters: tempODR tempEnable +* SH5001_TEMP_ODR_500HZ SH5001_TEMP_EN +* SH5001_TEMP_ODR_250HZ SH5001_TEMP_DIS +* SH5001_TEMP_ODR_125HZ +* SH5001_TEMP_ODR_63HZ +* +* return: void +* +******************************************************************/ +static void SH5001_Temp_Config( unsigned char tempODR, + unsigned char tempEnable) +{ + unsigned char regData = 0; + + // enable temperature, set ODR + SH5001_read(SH5001_ADDRESS, SH5001_TEMP_CONF0, 1, ®Data); + regData = (regData & 0xF8U) | tempODR | tempEnable; + SH5001_write(SH5001_ADDRESS, SH5001_TEMP_CONF0, 1, ®Data); +} + + +/****************************************************************** +* Description: read temperature parameters; +* +* Parameters: void +* +* return: temperature data(deg); +* +******************************************************************/ +float SH5001_GetTempData(void) +{ + unsigned char regData[2] = {0}; + unsigned short int tempref[2] = {0}; + + // read temperature data, unsigned 12bits; SH5001_TEMP_CONF2..SH5001_TEMP_CONF1 + SH5001_read(SH5001_ADDRESS, SH5001_TEMP_CONF1, 2, ®Data[0]); + tempref[0] = ((unsigned short int)(regData[1] & 0x0FU) << 8U) | regData[0]; + + SH5001_read(SH5001_ADDRESS, SH5001_TEMP_ZL, 2, ®Data[0]); + tempref[1] = ((unsigned short int)(regData[1] & 0x0FU) << 8U) | regData[0]; + + return ( (((float)(tempref[1] - tempref[0]))/14.0f) + 25.0f ); +} + + + +/****************************************************************** +* Description: enable or disable INT, mapping interrupt to INT pin or INT1 pin +* +* Parameters: intType intEnable intPinSel +* SH5001_INT_LOWG SH5001_INT_EN SH5001_INT_MAP_INT0 +* SH5001_INT_HIGHG SH5001_INT_DIS SH5001_INT_MAP_INT1 +* SH5001_INT_INACT +* SH5001_INT_ACT +* SH5001_INT_DOUBLE_TAP +* SH5001_INT_SINGLE_TAP +* SH5001_INT_FLAT +* SH5001_INT_ORIENTATION +* SH5001_INT_TAP (Only INT/INT1 Map) +* SH5001_INT_SMD +* SH5001_INT_FIFO_WATERMARK +* SH5001_INT_GYRO_READY +* SH5001_INT_ACC_READY +* SH5001_INT_FREE_FALL +* SH5001_INT_UP_DOWN_Z +* return: void +* +******************************************************************/ +void SH5001_INT_Enable( unsigned short intType, + unsigned char intEnable, + unsigned char intPinSel) +{ + unsigned char regData[2] = {0}; + unsigned short int u16IntVal = 0; + + // Z axis change between UP to DOWN + if((intType & 0x0040U) == SH5001_INT_UP_DOWN_Z) + { + SH5001_read(SH5001_ADDRESS, SH5001_ORIEN_INTCONF0, 1, ®Data[0]); + regData[0] = (intEnable == SH5001_INT_EN) \ + ? (regData[0] & 0xBFU) : (regData[0] | 0x40U); + SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INTCONF0, 1, ®Data[0]); + } + + if(intType & 0xFF3FU) + { + // enable or disable INT + SH5001_read(SH5001_ADDRESS, SH5001_INT_ENABLE0, 2, ®Data[0]); + + u16IntVal = ((unsigned short int)regData[0] << 8U) | regData[1]; + + u16IntVal = u16IntVal & 0xFF1FU; + u16IntVal = (intEnable == SH5001_INT_EN) \ + ? (u16IntVal | intType) : (u16IntVal & ~intType); + + regData[0] = (unsigned char)(u16IntVal >> 8U); + regData[1] = (unsigned char)(u16IntVal); + //SH5001_write(SH5001_ADDRESS, SH5001_INT_ENABLE0, 2, ®Data[0]); + SH5001_write(SH5001_ADDRESS, SH5001_INT_ENABLE0, 1, ®Data[0]); + SH5001_write(SH5001_ADDRESS, SH5001_INT_ENABLE1, 1, ®Data[1]); + + // mapping interrupt to INT0 pin or INT1 pin + SH5001_read(SH5001_ADDRESS, SH5001_INT_PIN_MAP0, 2, ®Data[0]); + u16IntVal = ((unsigned short int)regData[0] << 8U) | regData[1]; + + u16IntVal = u16IntVal & 0xFF3FU; + u16IntVal = (intPinSel == SH5001_INT_MAP_INT1) \ + ? (u16IntVal | intType) : (u16IntVal & ~intType); + + regData[0] = (unsigned char)(u16IntVal >> 8U); + regData[1] = (unsigned char)(u16IntVal); + SH5001_write(SH5001_ADDRESS, SH5001_INT_PIN_MAP0, 1, ®Data[0]); + SH5001_write(SH5001_ADDRESS, SH5001_INT_PIN_MAP1, 1, ®Data[1]); + } +} + + +/****************************************************************** +* Description: 1.config INT function +* 2.intCount is valid only when intLatch is equal to SH5001_INT_NO_LATCH; +* +* Parameters: intLevel intLatch intClear +* SH5001_INT_LEVEL_HIGH SH5001_INT_NO_LATCH SH5001_INT_CLEAR_ANY +* SH5001_INT_LEVEL_LOW SH5001_INT_LATCH SH5001_INT_CLEAR_STATUS +* +* intTime +* Unit: 2mS +* +* int1Mode int0Mode +* SH5001_INT1_NORMAL SH5001_INT0_NORMAL +* SH5001_INT1_OD SH5001_INT0_OD +* +* int1OE int0OE +* SH5001_INT1_OUTPUT SH5001_INT0_OUTPUT +* SH5001_INT1_INPUT SH5001_INT1_INPUT +* +* return: void +* +******************************************************************/ + + +void SH5001_INT_Config( unsigned char intLevel, + unsigned char intLatch, + unsigned char intClear, + unsigned char intTime, + unsigned char int1Mode, + unsigned char int0Mode, + unsigned char int1OE, + unsigned char int0OE) +{ + unsigned char regData = 0; + + //SH5001_read(SH5001_ADDRESS, SH5001_INT_CONF, 1, ®Data); + + regData = (intLevel == SH5001_INT0_LEVEL_LOW) \ + ? (regData | SH5001_INT0_LEVEL_LOW) : (regData & SH5001_INT0_LEVEL_HIGH); + + regData = (intLatch == SH5001_INT_NO_LATCH) \ + ? (regData | SH5001_INT_NO_LATCH) : (regData & SH5001_INT_LATCH); + + regData = (intClear == SH5001_INT_CLEAR_ANY) \ + ? (regData | SH5001_INT_CLEAR_ANY) : (regData & SH5001_INT_CLEAR_STATUS); + + regData = (int1Mode == SH5001_INT1_OD) \ + ? (regData | SH5001_INT1_OD) : (regData & SH5001_INT1_NORMAL); + + regData = (int1OE == SH5001_INT1_OUTPUT) \ + ? (regData | SH5001_INT1_OUTPUT) : (regData & SH5001_INT1_INPUT); + + regData = (int0Mode == SH5001_INT0_OD) \ + ? (regData | SH5001_INT0_OD) : (regData & SH5001_INT0_NORMAL); + + regData = (int0OE == SH5001_INT0_OUTPUT) \ + ? (regData | SH5001_INT0_OUTPUT) : (regData & SH5001_INT0_INPUT); + + SH5001_write(SH5001_ADDRESS, SH5001_INT_CONF, 1, ®Data); + + if(intLatch == SH5001_INT_NO_LATCH) + { + regData = intTime; + SH5001_write(SH5001_ADDRESS, SH5001_INT_LIMIT, 1, ®Data); + } +} + + + + +/****************************************************************** +* Description: 1.config INT0 & INT1 function +* +* Parameters: int1Mode int0Mode +* SH5001_INT1_NORMAL SH5001_INT0_NORMAL +* SH5001_INT1_OD SH5001_INT0_OD +* +* int1OE int0OE +* SH5001_INT1_OUTPUT SH5001_INT0_OUTPUT +* SH5001_INT1_INPUT SH5001_INT1_INPUT +* +* return: void +* +******************************************************************/ +void SH5001_INT_Output_Config( unsigned char int1Mode, + unsigned char int0Mode, + unsigned char int1OE, + unsigned char int0OE) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_INT_CONF, 1, ®Data); + + regData = (int1Mode == SH5001_INT1_OD) \ + ? (regData | SH5001_INT1_OD) : (regData & SH5001_INT1_NORMAL); + + regData = (int1OE == SH5001_INT1_OUTPUT) \ + ? (regData | SH5001_INT1_OUTPUT) : (regData & SH5001_INT1_INPUT); + + regData = (int0Mode == SH5001_INT0_OD) \ + ? (regData | SH5001_INT0_OD) : (regData & SH5001_INT0_NORMAL); + + regData = (int0OE == SH5001_INT0_OUTPUT) \ + ? (regData | SH5001_INT0_OUTPUT) : (regData & SH5001_INT1_INPUT); + + SH5001_write(SH5001_ADDRESS, SH5001_INT_CONF, 1, ®Data); +} + + +/****************************************************************** +* Description: orientation config; +* +* Parameters: orientBlockMode orientMode orientTheta +* SH5001_ORIENT_BLOCK_MODE0 SH5001_ORIENT_SYMM (1 Byte) +* SH5001_ORIENT_BLOCK_MODE1 SH5001_ORIENT_HIGH_ASYMM +* SH5001_ORIENT_BLOCK_MODE2 SH5001_ORIENT_LOW_ASYMM +* SH5001_ORIENT_BLOCK_MODE3 +* +* orientG1point5 orientSlope orientHyst +* (2 Bytes) (2 Bytes) (2 Bytes) +* +* return: void +* +******************************************************************/ +void SH5001_INT_Orient_Config( unsigned char orientBlockMode, + unsigned char orientMode, + unsigned char orientTheta, + unsigned short orientG1point5, + unsigned short orientSlope, + unsigned short orientHyst) +{ + unsigned char regData[2] = {0}; + + SH5001_read(SH5001_ADDRESS, SH5001_ORIEN_INTCONF0, 1, ®Data[0]); + regData[0] |= (regData[0] & 0xC0U) | (orientTheta & 0x3FU); + SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INTCONF0, 1, ®Data[0]); + + SH5001_read(SH5001_ADDRESS, SH5001_ORIEN_INTCONF1, 1, ®Data[0]); + regData[0] |= (regData[0] & 0xF0U) | (orientBlockMode & 0x0CU) | (orientMode & 0x03U); + SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INTCONF1, 1, ®Data[0]); + + regData[0] = (unsigned char)orientG1point5; + regData[1] = (unsigned char)(orientG1point5 >> 8U); + SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INT_1G5_LOW, 2, ®Data[0]); + + regData[0] = (unsigned char)orientSlope; + regData[1] = (unsigned char)(orientSlope >> 8U); + SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INT_SLOPE_LOW, 2, ®Data[0]); + + regData[0] = (unsigned char)orientHyst; + regData[1] = (unsigned char)(orientHyst >> 8U); + SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INT_HYST_LOW, 2, ®Data[0]); +} + + + +// Jin: flatTimeTH 200,400,800,000, sure? + +/****************************************************************** +* Description: flat INT time threshold, unit: mS; +* +* Parameters: flatTimeTH flatTanHeta2 +* SH5001_FLAT_TIME_200MS 0 ~ 63 +* SH5001_FLAT_TIME_400MS +* SH5001_FLAT_TIME_800MS +* SH5001_FLAT_TIME_000MS +* +* return: void +* +******************************************************************/ +void SH5001_INT_Flat_Config(unsigned char flatTimeTH, + unsigned char flatTanHeta2) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_ORIEN_INTCONF1, 1, ®Data); + regData = (regData & 0xF3U) | SH5001_ORIENT_BLOCK_MODE1; + SH5001_write(SH5001_ADDRESS, SH5001_ORIEN_INTCONF1, 1, ®Data); + + SH5001_read(SH5001_ADDRESS, SH5001_FLAT_INT_CONF, 1, ®Data); + regData = (flatTimeTH & 0xC0U) | (flatTanHeta2 & 0x3FU); + SH5001_write(SH5001_ADDRESS, SH5001_FLAT_INT_CONF, 1, ®Data); +} + +// Jin: Act and inAct function --- actIntClear ? + +/****************************************************************** +* Description: activity INT config; +* actIntThres: 1 LSB is 0.24mg@+/-2G, 0.48mg@+/-4G, 0.97mg@+/-8G, 1.95mg@+/-16G +* +* Parameters: actEnDisIntX actEnDisIntY actEnDisIntZ +* SH5001_ACT_X_INT_EN SH5001_ACT_Y_INT_EN SH5001_ACT_Z_INT_EN +* SH5001_ACT_X_INT_DIS SH5001_ACT_Y_INT_DIS SH5001_ACT_Z_INT_DIS +* +* +* actTimeNum actIntThres actLinkStatus actIntClear +* (1 Byte) (2 Byte2) SH5001_LINK_PRE_STA SH5001_ACT_INACT_CLR_STATUS1 +* SH5001_LINK_PRE_STA_NO SH5001_ACT_INACT_CLR_STATUS3 +* +* return: void +* +******************************************************************/ +void SH5001_INT_Act_Config( unsigned char actEnDisIntX, + unsigned char actEnDisIntY, + unsigned char actEnDisIntZ, + unsigned char actTimeNum, + unsigned short actIntThres, + unsigned char actLinkStatus, + unsigned char actIntClear) +{ + unsigned char regData[2] = {0}; + + SH5001_read(SH5001_ADDRESS, SH5001_ACT_INACT_INT_CONF, 1, ®Data[0]); + regData[0] |= (regData[0] & 0x8FU) | actEnDisIntX | actEnDisIntY | actEnDisIntZ; + SH5001_write(SH5001_ADDRESS, SH5001_ACT_INACT_INT_CONF, 1, ®Data[0]); + + regData[0] = (unsigned char)actIntThres; + regData[1] = (unsigned char)(actIntThres >> 8U); + //SH5001_write(SH5001_ADDRESS, SH5001_ACT_INT_THRESHOLDL, 2, ®Data[0]); + SH5001_write(SH5001_ADDRESS, SH5001_ACT_INT_THRESHOLDL, 1, ®Data[0]); + SH5001_write(SH5001_ADDRESS, SH5001_ACT_INT_THRESHOLDH, 1, ®Data[1]); + + regData[0] = actTimeNum; + SH5001_write(SH5001_ADDRESS, SH5001_ACT_INT_TIME, 1, ®Data[0]); + + SH5001_read(SH5001_ADDRESS, SH5001_ACT_INACT_INT_LINK, 1, ®Data[0]); + regData[0] |= (regData[0] & 0x7EU) | actLinkStatus | actIntClear; + SH5001_write(SH5001_ADDRESS, SH5001_ACT_INACT_INT_LINK, 1, ®Data[0]); +} + + +/****************************************************************** +* Description: inactivity INT config; +* +* Parameters: inactEnDisIntX inactEnDisIntY inactEnDisIntZ +* SH5001_INACT_X_INT_EN SH5001_INACT_Y_INT_EN SH5001_INACT_Z_INT_EN +* SH5001_INACT_X_INT_DIS SH5001_INACT_Y_INT_DIS SH5001_INACT_Z_INT_DIS +* +* inactLinkStatus inactTimeMs inactIntThres +* SH5001_LINK_PRE_STA Unit: mS (2 Bytes) +* SH5001_LINK_PRE_STA_NO +* +* inactG1 inactIntClear +* (2 Bytes) SH5001_ACT_INACT_CLR_STATUS1 +* SH5001_ACT_INACT_CLR_STATUS3 +* +* return: void +* +******************************************************************/ +void SH5001_INT_Inact_Config( unsigned char inactEnDisIntX, + unsigned char inactEnDisIntY, + unsigned char inactEnDisIntZ, + unsigned char inactLinkStatus, + unsigned char inactTimeMs, + unsigned short inactIntThres, + unsigned short inactG1, + unsigned char inactIntClear) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_ACT_INACT_INT_CONF, 1, ®Data); + regData |= (regData & 0xF8U) | inactEnDisIntX | inactEnDisIntY | inactEnDisIntZ; + SH5001_write(SH5001_ADDRESS, SH5001_ACT_INACT_INT_CONF, 1, ®Data); + + regData = (unsigned char)inactIntThres; + SH5001_write(SH5001_ADDRESS, SH5001_INACT_INT_THRESHOLDL, 1, ®Data); + regData = (unsigned char)(inactIntThres >> 8U); + SH5001_write(SH5001_ADDRESS, SH5001_INACT_INT_THRESHOLDH, 1, ®Data); + + regData = inactTimeMs; + SH5001_write(SH5001_ADDRESS, SH5001_INACT_INT_TIME, 1, ®Data); + + /* + regData = (unsigned char)inactG1; + SH5001_write(SH5001_ADDRESS, SH5001_INACT_INT_1G_REFL, 1, ®Data); + regData = (unsigned char)(inactG1 >> 8U); + SH5001_write(SH5001_ADDRESS, SH5001_INACT_INT_1G_REFH, 1, ®Data); + + SH5001_read(SH5001_ADDRESS, SH5001_ACT_INACT_INT_LINK, 1, ®Data); + regData |= (regData & 0x7EU) | inactLinkStatus | inactIntClear; + SH5001_write(SH5001_ADDRESS, SH5001_ACT_INACT_INT_LINK, 1, ®Data); + */ +} + + +/****************************************************************** +* Description: 1.tap INT config; +* 2.tapIntThres is between 0 and 8191; +* 3.tapWaitTimeWindowMs is more than tapWaitTimeMs; +* +* Parameters: tapEnDisIntX tapEnDisIntY tapEnDisIntZ +* SH5001_TAP_X_INT_EN SH5001_TAP_Y_INT_EN SH5001_TAP_Z_INT_EN +* SH5001_TAP_X_INT_DIS SH5001_TAP_Y_INT_DIS SH5001_TAP_Z_INT_DIS +* +* tapIntThres tapTimeMs tapWaitTimeMs tapWaitTimeWindowMs +* (13 bits) Unit: mS Unit: mS Unit: 2mS +* +* return: void +* +******************************************************************/ +void SH5001_INT_Tap_Config( unsigned char tapEnDisIntX, + unsigned char tapEnDisIntY, + unsigned char tapEnDisIntZ, + unsigned char tapIntThres, + unsigned char tapTimeMs, + unsigned char tapWaitTimeMs, + unsigned char tapWaitTimeWindowMs) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_ACT_INACT_INT_LINK, 1, ®Data); + regData |= (regData & 0xF1U) | tapEnDisIntX | tapEnDisIntY | tapEnDisIntZ; + SH5001_write(SH5001_ADDRESS, SH5001_ACT_INACT_INT_LINK, 1, ®Data); + + regData = (unsigned char)tapIntThres; + SH5001_write(SH5001_ADDRESS, SH5001_TAP_INT_THRESHOLDL, 1, ®Data); + SH5001_read(SH5001_ADDRESS, SH5001_TAP_INT_THRESHOLDH, 1, ®Data); + regData = ((unsigned char)(tapIntThres >> 8U) & 0x1FU) | (regData & 0xE0U); + SH5001_write(SH5001_ADDRESS, SH5001_TAP_INT_THRESHOLDH, 1, ®Data); + + regData = tapTimeMs; + SH5001_write(SH5001_ADDRESS, SH5001_TAP_INT_DURATION, 1, ®Data); + + regData = tapWaitTimeMs; + SH5001_write(SH5001_ADDRESS, SH5001_TAP_INT_LATENCY, 1, ®Data); + + regData = tapWaitTimeWindowMs; + SH5001_write(SH5001_ADDRESS, SH5001_DTAP_INT_WINDOW, 1, ®Data); +} + + +/****************************************************************** +* Description: 1.SMD INT config; +* 2.smdBlockTimeS:0-0.5S; 1-1.0S; 2-1.5S; 3-2.0S; +* 4-3.0S; 5-4.0S; 6-5.0S; 7-6.0S; +* 8-7.0S; 9-8.0S; A-9.0S; B-10S; +* C-12S; D-14S; E-15S; F-16S; +* +* 3.smdProofTimeS:0-0.2S; 1-0.25S; 2-0.3S; 3-0.4S; +* 4-0.5S; 5-0.6S; 6-0.7S; 7-0.8S; +* 8-0.9S; 9-1.0S; A-1.2S; B-1.5S; +* C-1.8S; D-2.1S; E-2.4S; F-2.8S; +* +* Parameters: smdThres smdBlockTimeS smdProofTimeS +* 2 Bytes Unit: S Unit: S +* +* return: void +* +******************************************************************/ +void SH5001_INT_SMD_Config( unsigned short smdThres, + unsigned char smdBlockTimeS, + unsigned char smdProofTimeS) +{ + unsigned char regData[2] = {0}; + + regData[0] = (unsigned char)smdThres; + regData[1] = (unsigned char)(smdThres >> 8U); + SH5001_write(SH5001_ADDRESS, SH5001_SMD_INT_THRESHOLDL, 2, ®Data[0]); + + regData[0] |= (unsigned char)((smdBlockTimeS & 0xF0U) << 4U) | (smdProofTimeS & 0xF0U); + SH5001_write(SH5001_ADDRESS, SH5001_HIGHG_INT_CONF, 1, ®Data[0]); +} + + +/****************************************************************** +* Description: 1.highG INT config; +* 2.highGThres is between 0 and 8191; +* 3.highGThres: x=0.5mG@2G, x=1mG@4G, x=2mG@8G, x=4mG@16G +* +* Parameters: highGEnDisIntX highGEnDisIntY highGEnDisIntZ +* SH5001_HIGHG_X_INT_EN SH5001_HIGHG_Y_INT_EN SH5001_HIGHG_Z_INT_EN +* SH5001_HIGHG_X_INT_DIS SH5001_HIGHG_Y_INT_DIS SH5001_HIGHG_Z_INT_DIS +* +* highGEnDisIntAll highGThres highGTimeMs +* SH5001_HIGHG_ALL_INT_EN Unit: x*8mG Unit: 2mS +* SH5001_HIGHG_ALL_INT_DIS (13 bits) +* +* return: void +* +******************************************************************/ +void SH5001_INT_HighG_Config( unsigned char highGEnDisIntX, + unsigned char highGEnDisIntY, + unsigned char highGEnDisIntZ, + unsigned char highGEnDisIntAll, + unsigned short highGThres, + unsigned char highGTimeMs) +{ + unsigned char regData[2] = {0}; + + SH5001_read(SH5001_ADDRESS, SH5001_HIGHG_INT_CONF, 1, ®Data[0]); + regData[0] |= (regData[0] & 0x0FU) | highGEnDisIntX | highGEnDisIntY | highGEnDisIntZ | highGEnDisIntAll; + SH5001_write(SH5001_ADDRESS, SH5001_HIGHG_INT_CONF, 1, ®Data[0]); + + SH5001_read(SH5001_ADDRESS, SH5001_HIGHG_INT_THRESHOLDL, 2, ®Data[0]); + regData[0] = (unsigned char)highGThres; + regData[1] = (regData[1] & 0xE0U) | ((unsigned char)(highGThres >> 8U) & 0x1FU); + SH5001_write(SH5001_ADDRESS, SH5001_HIGHG_INT_THRESHOLDL, 2, ®Data[0]); + + regData[0] = highGTimeMs; + SH5001_write(SH5001_ADDRESS, SH5001_HIGHG_INT_TIME, 1, ®Data[0]); +} + + +/****************************************************************** +* Description: 1.lowG INT config; +* 2.lowGThres is between 0 and 8191; +* 3.lowGThres: x=0.5mG@2G or x=1mG@4G or x=2mG@8G or x=4mG@16G +* +* Parameters: lowGEnDisIntAll lowGThres lowGTimeMs +* SH5001_LOWG_ALL_INT_EN Unit: x*8mG Unit: 2mS +* SH5001_LOWG_ALL_INT_DIS (13 bits) +* +* return: void +* +******************************************************************/ +void SH5001_INT_LowG_Config( unsigned char lowGEnDisIntAll, + unsigned short lowGThres, + unsigned char lowGTimeMs) +{ + unsigned char regData[2] = {0}; + + SH5001_read(SH5001_ADDRESS, SH5001_HIGHG_INT_CONF, 1, ®Data[0]); + regData[0] |= (regData[0] & 0xFEU) | lowGEnDisIntAll; + SH5001_write(SH5001_ADDRESS, SH5001_HIGHG_INT_CONF, 1, ®Data[0]); + + SH5001_read(SH5001_ADDRESS, SH5001_LOWG_INT_THRESHOLDL, 2, ®Data[0]); + regData[0] = (unsigned char)lowGThres; + regData[1] = (regData[1] & 0xE0U) | ((unsigned char)(lowGThres >> 8U) & 0x1FU); + SH5001_write(SH5001_ADDRESS, SH5001_LOWG_INT_THRESHOLDL, 2, ®Data[0]); + + regData[0] = lowGTimeMs; + SH5001_write(SH5001_ADDRESS, SH5001_LOWG_INT_TIME, 1, ®Data[0]); +} + + +/****************************************************************** +* Description: 1.freeFall INT config; +* 2.freeFallThres: x=0.5mG@2G or x=1mG@4G or x=2mG@8G or x=4mG@16G +* +* Parameters: freeFallThres freeFallTimeMs +* Unit: x*8mG Unit: 2mS +* +* return: void +* +******************************************************************/ +void SH5001_INT_FreeFall_Config( unsigned char freeFallThres, + unsigned char freeFallTimeMs) +{ + unsigned char regData = 0; + + regData = freeFallThres; + SH5001_write(SH5001_ADDRESS, SH5001_FREEFALL_INT_THRES, 1, ®Data); + + regData = freeFallTimeMs; + SH5001_write(SH5001_ADDRESS, SH5001_FREEFALL_INT_TIME, 1, ®Data); +} + + + +/****************************************************************** +* Description: 1.read INT status0 +* +* Parameters: void +* +* return: unsigned short +* bit 13: Tap, Single or Double Tap Interrupt status +* bit 12: SMD Interrupt status +* bit 11: FIFO Watermark Interrupt status +* bit 10: Gyro Data Ready Interrupt status +* bit 9: Acc Data Ready Interrupt status +* bit 8: Free-fall Interrupt status +* bit 7: Low-G Interrupt status +* bit 6: High-G Interrupt status +* bit 5: Inactivity Interrupt status +* bit 4: Activity Interrupt status +* bit 3: Double Tap Interrupt status +* bit 2: Single Tap Interrupt status +* bit 1: Flat Interrupt status +* bit 0: Orientation Interrupt status +* 0: Not Active +* 1: Active +* +******************************************************************/ +unsigned short SH5001_INT_Read_Status01(void) +{ + unsigned char regData[3] = {0}; + + SH5001_read(SH5001_ADDRESS, SH5001_INT_STA0, 3, ®Data[0]); + + return( ((unsigned short)(regData[1] & 0x3FU) << 8U) | regData[0] ); +} + + +/****************************************************************** +* Description: 1.read INT status2 +* +* Parameters: void +* +* return: unsigned char +* bit 7: High-G Sign +* 0: Positive +* 1: Negative +* bit 6: High-G X-axis Interrupt status +* bit 5: High-G Y-axis Interrupt status +* bit 4: High-G Z-axis Interrupt status +* 0: No Active +* 1: Active +* bit 3: Reserved +* bit 2: Reserved +* bit 1: Reserved +* bit 0: Low-G Interrupt status +* 0: Not Active +* 1: Active +* +******************************************************************/ +unsigned char SH5001_INT_Read_Status2(void) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_INT_STA2, 1, ®Data); + + return( (regData & 0xF1U)); +} + + +/****************************************************************** +* Description: 1.read INT status3 +* +* Parameters: void +* +* return: unsigned char +* bit 7: Activity-Inactivity Sign +* 0: Positive +* 1: Negative +* bit 6: Activity-Inactivity X-axis Interrupt Status +* bit 5: Activity-Inactivity Y-axis Interrupt Status +* bit 4: Activity-Inactivity Z-axis Interrupt Status +* 0: No Active +* 1: Active +* bit 3: Sign of acceleration that trigger Single or Double Tap Interrup +* 0: Positive +* 1: Negative +* bit 2: Whether Single or Double Tap Interrupt is triggered by X axis +* bit 1: Whether Single or Double Tap Interrupt is triggered by Y axis +* bit 0: Whether Single or Double Tap Interrupt is triggered by Z axis +* 0: No +* 1: Yes +******************************************************************/ +unsigned char SH5001_INT_Read_Status3(void) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_INT_STA3, 1, ®Data); + + return(regData); +} + + +/****************************************************************** +* Description: 1.read INT status4 +* +* Parameters: void +* +* return: unsigned char +* bit 7: Reserved +* bit 6: Reserved +* bit 5: Reserved +* bit 4: Reserved +* bit 3: Reserved +* bit 2: Orientation Interrupt Value of Z-axis +* 0: Upward +* 1: Downward +* bit 1..0: Orientation Interrupt Value of X and Y-axis +* 00: Landscape left +* 01: Landscape right +* 10: Portrait upside down +* 11: Portrait upright +* +******************************************************************/ +unsigned char SH5001_INT_Read_Status4(void) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_INT_STA4, 1, ®Data); + + return(regData & 0x07U); +} + + + +/****************************************************************** +* Description: reset FIFO controller; +* +* Parameters: fifoMode +* SH5001_FIFO_MODE_DIS +* SH5001_FIFO_MODE_FIFO +* SH5001_FIFO_MODE_STREAM +* SH5001_FIFO_MODE_TRIGGER +* +* return: void +* +******************************************************************/ +void SH5001_FIFO_Mode_Set(unsigned char fifoMode) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_FIFO_CONF0, 1, ®Data); + regData &= 0x7F; + SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF0, 1, ®Data); + + regData = fifoMode & 0x03; + SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF0, 1, ®Data); +} + +void SH5001_FIFO_Reset(void) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_FIFO_CONF0, 1, ®Data); + regData |= 0x80; + SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF0, 1, ®Data); +} + + + +/****************************************************************** +* Description: 1.FIFO down sample frequency config; +* 2.fifoAccFreq: accODR*1/2, *1/4, *1/8, *1/16, *1/32, *1/64, *1/128, *1/256 +* 3.fifoGyroFreq: gyroODR*1/2, *1/4, *1/8, *1/16, *1/32, *1/64, *1/128, *1/256 +* +* Parameters: fifoAccDownSampleEnDis fifoAccFreq/fifoGyroFreq fifoGyroDownSampleEnDis +* SH5001_FIFO_ACC_DOWNS_EN SH5001_FIFO_FREQ_X1_2 SH5001_FIFO_GYRO_DOWNS_EN +* SH5001_FIFO_ACC_DOWNS_DIS SH5001_FIFO_FREQ_X1_4 SH5001_FIFO_GYRO_DOWNS_DIS +* SH5001_FIFO_FREQ_X1_8 +* SH5001_FIFO_FREQ_X1_16 +* SH5001_FIFO_FREQ_X1_32 +* SH5001_FIFO_FREQ_X1_64 +* SH5001_FIFO_FREQ_X1_128 +* SH5001_FIFO_FREQ_X1_256 +* return: void +* +******************************************************************/ +void SH5001_FIFO_Freq_Config( unsigned char fifoAccDownSampleEnDis, + unsigned char fifoAccFreq, + unsigned char fifoGyroDownSampleEnDis, + unsigned char fifoGyroFreq) +{ + unsigned char regData = 0; + + regData |= fifoAccDownSampleEnDis | fifoGyroDownSampleEnDis; + regData |= (fifoAccFreq << 4) | fifoGyroFreq; + SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF4, 1, ®Data); +} + + +// Jin: fifoWaterMarkLevel??? +/****************************************************************** +* Description: 1.config data type in FIFO; +* 2.fifoWaterMarkLevel <= channelNum*2*(INT(1024/(channelNum*2))-1) +* eg. fifomode = SH5001_FIFO_ACC_X_EN | SH5001_FIFO_ACC_Y_EN | SH5001_FIFO_ACC_Z_EN +* then fifoWaterMarkLevel maximum is 1014 +* +* Parameters: fifoMode fifoWaterMarkLevel + SH5001_FIFO_TIMESTAMP_EN <=1024 +* SH5001_FIFO_EXT_Z_EN +* SH5001_FIFO_EXT_Y_EN +* SH5001_FIFO_EXT_X_EN +* SH5001_FIFO_TEMPERATURE_EN +* SH5001_FIFO_GYRO_Z_EN +* SH5001_FIFO_GYRO_Y_EN +* SH5001_FIFO_GYRO_X_EN +* SH5001_FIFO_ACC_Z_EN +* SH5001_FIFO_ACC_Y_EN +* SH5001_FIFO_ACC_X_EN +* SH5001_FIFO_ALL_DIS +* +* return: void +* +******************************************************************/ +void SH5001_FIFO_Data_Config( unsigned short fifoMode, + unsigned short fifoWaterMarkLevel) +{ + unsigned char regData = 0; + + if(fifoWaterMarkLevel > 1024U) + { + fifoWaterMarkLevel = 1024U; + } + + SH5001_read(SH5001_ADDRESS, SH5001_FIFO_CONF2, 1, ®Data); + regData = (regData & 0x88U) \ + | ((unsigned char)(fifoMode >> 8U) & 0x70U) \ + | (((unsigned char)(fifoWaterMarkLevel >> 8U)) & 0x07U); + SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF2, 1, ®Data); + + regData = (unsigned char)fifoMode; + SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF3, 1, ®Data); + + regData = (unsigned char)fifoWaterMarkLevel; + SH5001_write(SH5001_ADDRESS, SH5001_FIFO_CONF1, 1, ®Data); +} + + + +/****************************************************************** +* Description: 1. read Fifo status and fifo entries count +* +* Parameters: *fifoEntriesCount, store fifo entries count, less than or equal to 1024; +* +* +* return: unsigned char +* bit 7: 0 +* bit 6: 0 +* bit 5: Whether FIFO Watermark has been reached +* bit 4: Whether FIFO is full +* bit 3: Whether FIFO is empty +* 0: No +* 1: Yes +* bit 2: 0 +* bit 1: 0 +* bit 0: 0 +* +* +******************************************************************/ +unsigned char SH5001_FIFO_Read_Status(unsigned short int *fifoEntriesCount) +{ + unsigned char regData[2] = {0}; + + SH5001_read(SH5001_ADDRESS, SH5001_FIFO_STA0, 2, ®Data[0]); + + *fifoEntriesCount = ((unsigned short int)(regData[1] & 0x0FU) << 8U) | regData[0]; + + + return (regData[1] & 0x70U); +} + + +/****************************************************************** +* Description: 1. read Fifo data +* +* Parameters: *fifoReadData fifoDataLength +* data data length +* +* return: void +* +* +******************************************************************/ +void SH5001_FIFO_Read_Data(unsigned char *fifoReadData, unsigned short int fifoDataLength) +{ + if(fifoDataLength == 0) + { + return; + } + + if(fifoDataLength > 1024U) + { + fifoDataLength = 1024U; + } + + SH5001_read(SH5001_ADDRESS, SH5001_FIFO_DATA, fifoDataLength, fifoReadData); + /* + while(fifoDataLength--) + { + SH5001_read(SH5001_ADDRESS, SH5001_FIFO_DATA, 1, fifoReadData); + fifoReadData++; + } + */ +} + + +/****************************************************************** +* Description: reset Mater I2C; +* +* Parameters: void +* +* return: void +* +******************************************************************/ +void SH5001_MI2C_Reset(void) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); + regData |= 0x80U; + SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); + regData &= 0x7FU; + SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); + +} + + +/****************************************************************** +* Description: 1.master I2C config; +* 2.master I2C clock frequency is (1MHz/(6+3*mi2cFreq)); +* 3.mi2cSlaveAddr: slave device address, 7 bits; +* +* +* Parameters: mi2cReadMode mi2cODR mi2cFreq +* SH5001_MI2C_READ_MODE_AUTO SH5001_MI2C_READ_ODR_200HZ <=15 +* SH5001_MI2C_READ_MODE_MANUAL SH5001_MI2C_READ_ODR_100HZ +* SH5001_MI2C_READ_ODR_50HZ +* SH5001_MI2C_READ_ODR_25HZ +* return: void +* +******************************************************************/ +void SH5001_MI2C_Bus_Config( unsigned char mi2cReadMode, + unsigned char mi2cODR, + unsigned char mi2cFreq) +{ + unsigned char regData = 0; + + if(mi2cFreq > 15U) + { + mi2cFreq = 15U; + } + + SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF1, 1, ®Data); + regData = (regData & 0xC0U) | (mi2cODR & 0x30U) | mi2cFreq; + SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF1, 1, ®Data); + + SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); + regData = (regData & 0xBFU) | mi2cReadMode; + SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); +} + + +/****************************************************************** +* Description: 1.master I2C address and command config; +* 2.mi2cSlaveAddr: slave device address, 7 bits; +* +* Parameters: mi2cSlaveAddr mi2cSlaveCmd mi2cReadMode +* (1 Byte) (1 Byte) SH5001_MI2C_READ_MODE_AUTO +* SH5001_MI2C_READ_MODE_MANUAL +* +* return: void +* +******************************************************************/ +void SH5001_MI2C_Cmd_Config( unsigned char mi2cSlaveAddr, + unsigned char mi2cSlaveCmd, + unsigned char mi2cReadMode) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); + regData = (regData & 0xBFU) | mi2cReadMode; + SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); + + SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CMD0, 1, ®Data); + regData |= (mi2cSlaveAddr << 1U); + SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CMD0, 1, ®Data); + SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CMD1, 1, &mi2cSlaveCmd); +} + + +/****************************************************************** +* Description: 1.master I2C write data fucntion; +* 2.mi2cWriteData: write data; +* +* Parameters: mi2cWriteData +* +* return: SH5001_TRUE or SH5001_FALSE +* +******************************************************************/ +unsigned char SH5001_MI2C_Write(unsigned char mi2cWriteData) +{ + unsigned char regData = 0; + unsigned char i = 0; + + SH5001_write(SH5001_ADDRESS, SH5001_MI2C_WR, 1, &mi2cWriteData); + + //Master I2C enable, write-operation + SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); + regData = (regData & 0xFCU) | 0x02U; + SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); + + // wait write-operation to end + while(i++ < 20U) + { + SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); + if(regData & 0x30U) + break; + } + + if((regData & 0x30U) == SH5001_MI2C_SUCCESS) + { + return (SH5001_TRUE); + } + else + { + return (SH5001_FALSE); + } +} + + +/****************************************************************** +* Description: 1.master I2C read data fucntion; +* 2.*mi2cReadData: read data; +* +* Parameters: *mi2cReadData +* +* return: SH5001_TRUE or SH5001_FALSE +* +******************************************************************/ +unsigned char SH5001_MI2C_Read(unsigned char *mi2cReadData) +{ + unsigned char regData = 0; + unsigned char i = 0; + + + SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); + if((regData & 0x40U) == 0) + { + //Master I2C enable, read-operation + regData |= 0x03U; + SH5001_write(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); + } + + // wait read-operation to end + while(i++ < 20U) + { + SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); + if(regData & 0x30U) + break; + } + + SH5001_read(SH5001_ADDRESS, SH5001_MI2C_CONF0, 1, ®Data); + if((regData & 0x30U) == SH5001_MI2C_SUCCESS) + { + SH5001_read(SH5001_ADDRESS, SH5001_MI2C_RD, 1, ®Data); + *mi2cReadData = regData; + + return (SH5001_TRUE); + } + else + { + return (SH5001_FALSE); + } +} + + +/****************************************************************** +* Description: 1.SPI interface config; Default: SH5001_SPI_4_WIRE +* +* Parameters: spiInterfaceMode +* SH5001_SPI_3_WIRE +* SH5001_SPI_4_WIRE +* +* return: void +* +******************************************************************/ +void SH5001_SPI_Config( unsigned char spiInterfaceMode) +{ + #if 0 + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_SPI_CONF, 1, ®Data); + regData = (regData & 0xDFU) | spiInterfaceMode; + #endif + unsigned char regData = spiInterfaceMode; + + SH5001_write(SH5001_ADDRESS, SH5001_SPI_CONF, 1, ®Data); +} + + +/****************************************************************** +* Description: 1.I2C interface config; Default: SH5001_I2C_EN +* +* Parameters: i2cInterfaceEnDis +* SH5001_I2C_EN +* SH5001_I2C_DIS +* +* return: void +* +******************************************************************/ +void SH5001_I2C_Config(unsigned char i2cInterfaceEnDis) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_I2C_CONF, 1, ®Data); + regData = (regData & 0x7FU) | i2cInterfaceEnDis; + SH5001_write(SH5001_ADDRESS, SH5001_I2C_CONF, 1, ®Data); +} + + + +// Jin +/****************************************************************** +* Description: 1.I2C loop mode config; +* 2.SH5001_I2C_LP_06BYTE: ACC_X ACC_Y ACC_Z +* 3.SH5001_I2C_LP_12BYTE: ACC_X ACC_Y ACC_Z GYRO_X GYRO_Y GYRO_Z +* 4.SH5001_I2C_LP_14BYTE: ACC_X ACC_Y ACC_Z GYRO_X GYRO_Y GYRO_Z TEMPERATURE +* +* Parameters: i2cReadLoopMode +* SH5001_I2C_LP_06BYTE +* SH5001_I2C_LP_12BYTE +* SH5001_I2C_LP_14BYTE +* SH5001_I2C_LP_DISABLE +* +* return: void +* +******************************************************************/ +void SH5001_I2C_LP_Config(unsigned char i2cReadLoopMode) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_I2C_CONF, 1, ®Data); + regData = (regData & 0xF8U) | i2cReadLoopMode; + SH5001_write(SH5001_ADDRESS, SH5001_I2C_CONF, 1, ®Data); +} + + +/****************************************************************** +* Description: 1.OIS SPI interface config; Default: SH5001_OIS_SPI_DIS +* +* Parameters: oisSpiInterfaceMode oisSpiInterfaceEnDis +* SH5001_OIS_SPI_3WIRE SH5001_OIS_SPI_EN +* SH5001_OIS_SPI_4WIRE SH5001_OIS_SPI_DIS +* +* return: void +* +******************************************************************/ + +void SH5001_OIS_SPI_Config(unsigned char oisSpiInterfaceEnDis) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, SH5001_OIS_SPI_CONF, 1, ®Data); + regData = (regData & 0xEFU) | oisSpiInterfaceEnDis; + SH5001_write(SH5001_ADDRESS, SH5001_OIS_SPI_CONF, 1, ®Data); +} + + +/****************************************************************** +* Description: 1.Switch SH5001 power mode; +* 2.SH5001_NORMAL_MODE +* 3.SH5001_ACC_HP_MODE +* 4.SH5001_ACC_LP_MODE +* 5.SH5001_POWERDOWN_MODE +* +* Parameters: powerMode +* SH5001_NORMAL_MODE +* SH5001_ACC_HP_MODE +* SH5001_ACC_LP_MODE +* SH5001_POWERDOWN_MODE +* +* return: SH5001_FALSE or SH5001_TRUE +* +******************************************************************/ +unsigned char SH5001_SwitchPowerMode(unsigned char powerMode) +{ + + int i = 0; + unsigned char reg_addr[SH5001_POWMODE_REG_NUM] = { 0x30, 0x20, 0x2B, 0xBD, 0xD9, 0xD1, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8}; + unsigned char reg_data_normal[SH5001_POWMODE_REG_NUM] = { 0x08, 0x23, 0x00, 0x0C, 0x99, 0x68, 0x00, 0x00, 0x01, 0x50, 0x00}; + unsigned char reg_data_acc_hp[SH5001_POWMODE_REG_NUM] = { 0x08, 0x23, 0x01, 0x0C, 0x98, 0x6B, 0x00, 0x7A, 0xFF, 0xFC, 0x00}; + unsigned char reg_data_acc_lp[SH5001_POWMODE_REG_NUM] = { 0x08, 0xA1, 0x01, 0x0E, 0x98, 0x6B, 0x90, 0xFA, 0xFF, 0xFC, 0x00}; + unsigned char reg_data_powerdown[SH5001_POWMODE_REG_NUM] = { 0x08, 0xA1, 0x01, 0x0E, 0x98, 0x6B, 0xF1, 0xFE, 0xFF, 0xFC, 0xE2}; + unsigned char accODR = SH5001_ACC_ODR_2000HZ; + unsigned char regData = 0; + + if(powerMode > 0x03) + { + return (SH5001_FALSE); + } + + switch(powerMode) + { + case SH5001_NORMAL_MODE: + + SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, ®Data); + regData = regData & 0x7F; + SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, ®Data); + + SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF1, 1, &storeAccODR); + for(i = 0; i < SH5001_POWMODE_REG_NUM; i++) + { + SH5001_write(SH5001_ADDRESS, reg_addr[i], 1, ®_data_normal[i]); + } + + SH5001_DriveStart(); + SH5001_ADCReset(); + SH5001_CVAReset(); + delay_ms(100);// or discard 10 + + return (SH5001_TRUE); + + case SH5001_ACC_HP_MODE: + + SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, ®Data); + regData = regData | 0x80; + SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, ®Data); + + SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF1, 1, &storeAccODR); + for(i = 0; i < SH5001_POWMODE_REG_NUM; i++) + { + SH5001_write(SH5001_ADDRESS, reg_addr[i], 1, ®_data_acc_hp[i]); + } + + delay_ms(30); // or discard 2 + + return (SH5001_TRUE); + + case SH5001_ACC_LP_MODE: + + SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, ®Data); + regData = regData & 0x7F; + SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, ®Data); + + regData = (storeAccODR & 0xF0) | accODR; + SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF1, 1, ®Data); + for(i = 0; i < SH5001_POWMODE_REG_NUM; i++) + { + SH5001_write(SH5001_ADDRESS, reg_addr[i], 1, ®_data_acc_lp[i]); + } + + delay_ms(30); // or discard 2 + return (SH5001_TRUE); + + case SH5001_POWERDOWN_MODE: + + for(i = 0; i < SH5001_POWMODE_REG_NUM; i++) + { + SH5001_write(SH5001_ADDRESS, reg_addr[i], 1, ®_data_powerdown[i]); + } + + return (SH5001_TRUE); + + default: + return (SH5001_FALSE); + } +} + +/****************************************************************** +* Description: 1. fast compensate offset +* +* Parameters: SH5001Positon +* SH5001_X_UP +* SH5001_X_DOWN +* SH5001_Y_UP +* SH5001_Y_DOWN +* SH5001_Z_UP +* SH5001_Z_DOWN +* +* return: SH5001_FALSE or SH5001_TRUE +* +******************************************************************/ +void SH5001_FastOffsetComp(unsigned char SH5001Positon) +{ + unsigned char regData = 0; + + switch(SH5001Positon) + { + case SH5001_X_UP: + regData = 0x90U; + break; + case SH5001_X_DOWN: + regData = 0x91U; + break; + case SH5001_Y_UP: + regData = 0x92U; + break; + case SH5001_Y_DOWN: + regData = 0x93U; + break; + case SH5001_Z_UP: + regData = 0x94U; + break; + case SH5001_Z_DOWN: + regData = 0x95U; + break; + default: + regData = 0x94U; + break; + } + +// SH5001_write(SH5001_ADDRESS, SH5001_FAST_COMP, 1, ®Data); +} + + +#ifdef SH5001_ACTIVITY_INT + +void SH5001_Init_Activity_Int(void) +{ + + unsigned char regData = 0; + + SH5001_INT_Config(SH5001_INT0_LEVEL_HIGH, + SH5001_INT_LATCH, //SH5001_INT_NO_LATCH, SH5001_INT_LATCH + SH5001_INT_CLEAR_STATUS, //SH5001_INT_CLEAR_ANY, SH5001_INT_CLEAR_STATUS + 1, + SH5001_INT1_NORMAL, + SH5001_INT0_NORMAL, + SH5001_INT1_OUTPUT, + SH5001_INT0_OUTPUT); + + SH5001_INT_Act_Config(SH5001_ACT_X_INT_EN, + SH5001_ACT_Y_INT_EN, + SH5001_ACT_Z_INT_EN, + 2, + 20, + SH5001_LINK_PRE_STA_NO, + SH5001_ACT_INACT_CLR_STATUS1); + + SH5001_INT_Enable(SH5001_INT_ACT, + SH5001_INT_EN, + SH5001_INT_MAP_INT0); + //TODO + SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, ®Data); + regData = regData & 0x7F; + SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF2, 1, ®Data); + + SH5001_read(SH5001_ADDRESS, 0xBD, 1, ®Data); + regData = (regData & 0x7F); + SH5001_write(SH5001_ADDRESS, 0xBD, 1, ®Data); +} + +#endif + +#ifdef SH5001_DATA_READY_INT +void SH5001_Init_Data_Ready_Int(void) +{ + + unsigned char regData = 0; + + SH5001_INT_Config(SH5001_INT0_LEVEL_HIGH, + SH5001_INT_LATCH, //SH5001_INT_NO_LATCH, SH5001_INT_LATCH + SH5001_INT_CLEAR_STATUS, //SH5001_INT_CLEAR_ANY, SH5001_INT_CLEAR_STATUS + 1, + SH5001_INT1_NORMAL, + SH5001_INT0_NORMAL, + SH5001_INT1_OUTPUT, + SH5001_INT0_OUTPUT); + + SH5001_INT_Enable(SH5001_INT_ACC_READY, //SH5001_INT_GYRO_READY SH5001_INT_ACC_READY + SH5001_INT_EN, + SH5001_INT_MAP_INT0); + +} + +#endif + +/****************************************************************** +* Description: 1. SH5001 initialization FIFO +* 2. INT mode +* 3. Enable ACC_X, ACC_Y, ACC_Z, GYRO_X, GYRO_Y, GYRO_Z +* +* Parameters: void +* +* return: void +* +******************************************************************/ +void SH5001_InitFIFO(void) +{ + + SH5001_INT_Config(SH5001_INT0_LEVEL_HIGH, + SH5001_INT_LATCH, //SH5001_INT_NO_LATCH, SH5001_INT_LATCH + SH5001_INT_CLEAR_STATUS, //SH5001_INT_CLEAR_ANY, SH5001_INT_CLEAR_STATUS + 1, + SH5001_INT1_NORMAL, + SH5001_INT0_NORMAL, + SH5001_INT1_OUTPUT, + SH5001_INT0_OUTPUT); + + SH5001_FIFO_Reset(); + + SH5001_FIFO_Freq_Config(SH5001_FIFO_ACC_DOWNS_DIS, + SH5001_FIFO_FREQ_X1_32, + SH5001_FIFO_GYRO_DOWNS_DIS, + SH5001_FIFO_FREQ_X1_32); + + SH5001_FIFO_Data_Config(SH5001_FIFO_ACC_X_EN + | SH5001_FIFO_ACC_Y_EN + | SH5001_FIFO_ACC_Z_EN + | SH5001_FIFO_GYRO_X_EN + | SH5001_FIFO_GYRO_Y_EN + | SH5001_FIFO_GYRO_Z_EN, + 120); + + SH5001_FIFO_Mode_Set(SH5001_FIFO_MODE_FIFO); + + SH5001_INT_Enable(SH5001_INT_FIFO_WATERMARK, + SH5001_INT_EN, + SH5001_INT_MAP_INT0); + +} + + + +/****************************************************************** +* Description: 1. SH5001 read ACC_X, ACC_Y, ACC_Z, GYRO_X, GYRO_Y, GYRO_Z @FIFO +* 2. clear FIFO Watermark INT +* +* Parameters: void +* +* return: void +* +******************************************************************/ +void SH5001_ReadFIFO(void) +{ + unsigned short fifoEntriesCount = 0; + unsigned char fifoData[SH5001_FIFO_BUFFER] = {0}; + unsigned short i = 0, j = 0, dataGroup = 0; + short accData[3], gyroData[3]; + unsigned char regData = 0; + + // read FIFO entries count + SH5001_FIFO_Read_Status(&fifoEntriesCount); + + dataGroup = (unsigned short)(fifoEntriesCount/SH5001_WATERMARK_DIV); + fifoEntriesCount = dataGroup * SH5001_WATERMARK_DIV; + + SH5001_FIFO_Read_Data(fifoData, fifoEntriesCount); + + // printf("fc %d\r\n", fifoEntriesCount); + + for(i = 0; i < dataGroup; i++) + { + accData[0] = ((short)fifoData[j+1] << 8) | fifoData[j]; + accData[1] = ((short)fifoData[j+3] << 8) | fifoData[j+2]; + accData[2] = ((short)fifoData[j+5] << 8) | fifoData[j+4]; + gyroData[0] = ((short)fifoData[j+7] << 8) | fifoData[j+6]; + gyroData[1] = ((short)fifoData[j+9] << 8) | fifoData[j+8]; + gyroData[2] = ((short)fifoData[j+11] << 8) | fifoData[j+10]; + + gyro_data.x = (float)gyroData[0]; + gyro_data.y = (float)gyroData[1]; + gyro_data.z = (float)gyroData[2]; + + // printf("%d %d %d %d %d %d\r\n", accData[0], accData[1], accData[2],gyroData[0], gyroData[1], gyroData[2]); + + j = j + SH5001_WATERMARK_DIV; + } + + + // clear INT + SH5001_INT_Read_Status01(); + + +} + + #define SH5001_REGISTER_SETTING_TOTAL 18 +static int sh5001DumpReg(void) +{ + int i = 0; + int ret = 0; + uint8_t reg = 0; + uint8_t regData = 0; + + //uint8_t SH5001Reg[SH5001_REGISTER_SETTING_TOTAL] = {0x20, 0x21,0x22, 0x23, 0x24, 0x25}; + + //uint8_t SH5001Reg[SH5001_REGISTER_SETTING_TOTAL] = {0x20, 0x21,0x22, 0x23, 0x24, 0x25, 0x40, 0x41, 0x42, 0x43, 0x66}; //FIFO wm int + 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 + + //uint8_t SH3001Reg[SH3001_REGISTER_SETTING_TOTAL] = {0x28, 0x29, 0x2B, 0x23, 0x26, 0xdd}; //lpf setting + // uint8_t SH3001Reg[SH3001_REGISTER_SETTING_TOTAL] = {0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,0x2A, 0x2B}; + //uint8_t SH3001Reg[SH3001_REGISTER_SETTING_TOTAL] = {0x22, 0x23, 0x24, 0x25, 0x26, 0x35,0x36,0x37, 0x38,0x39}; + //uint8_t ST3001RegData[SH3001_REGISTER_SETTING_TOTAL] = {0x00,0x1F,0x00,0x2B,0x00}; + //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}; + //uint8_t SH3001Reg[SH3001_REGISTER_SETTING_TOTAL] = {0x35, 0x36, 0x37, 0x38, 0x39, 0x40,0x41,0x42, 0x43,0x44, 0x45,0x46, 0x47, 0xFE}; + //uint8_t SH3001Reg[SH3001_REGISTER_SETTING_TOTAL] = {0x20, 0x21, 0x0c, 0x0d}; + + for( i = 0 ; i < SH5001_REGISTER_SETTING_TOTAL ; i++ ) + { + + //read + reg = SH5001Reg[i]; + + ret = SH5001_read(SH5001_ADDRESS, reg, 1, ®Data); + if(ret != 0) + { + printf("Senodia Dump Reg 0x%x read error\r\n", reg); + return -1; + } + + printf("Senodia DR >>>>> 0x%x = 0x%x\r\n", reg, regData); + + } + + + return ret; + +} + +static void SH5001_IMU_Data_Stablize(void) +{ + unsigned char regData = 0; + + //TODO Three times maybe + //acc + SH5001_read(SH5001_ADDRESS, SH5001_ACC_CONF0, 1, ®Data); + regData &= 0xFE; + SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF0, 1, ®Data); + regData |= 0x1; + SH5001_write(SH5001_ADDRESS, SH5001_ACC_CONF0, 1, ®Data); + + + //gyro + SH5001_read(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, ®Data); + regData &= 0xFE; + SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, ®Data); + regData |= 0x1; + SH5001_write(SH5001_ADDRESS, SH5001_GYRO_CONF0, 1, ®Data); +} + +static void SH5001_OSC_FREQ(void) +{ + unsigned char regData = 0; + + SH5001_read(SH5001_ADDRESS, 0xDA, 1, ®Data); + if((regData & 0x07) != 0x07) + { + regData |= 0x07; + SH5001_write(SH5001_ADDRESS, 0xDA, 1, ®Data); + } + +} + +#if SENODIA_VDD_3V3 +short v3_acc[3] = {0}; +unsigned char use_otp_comp = 0; + +void SH5001_Get_Otpoffset(short vacc[3]) +{ + unsigned char regData[3]={0}; + unsigned char data = 0; + + //entry otp read mode + data = 0x72; + SH5001_write(SH5001_ADDRESS, 0x02, 1, &data); + + //read otp page + data = 0; + SH5001_read(SH5001_ADDRESS, 0x0, 1, &data); + printf("otp page data:0x%x\n", data); + if(data == 0x70){ + //exit otp mode + data = 0x71; + SH5001_write(SH5001_ADDRESS, 0x03, 1, &data); + + //entry otp page 2 + data = 0x70; + SH5001_write(SH5001_ADDRESS, 0x05, 1, &data); + + //entry otp read mode + data = 0x72; + SH5001_write(SH5001_ADDRESS, 0x02, 1, &data); + + } + //otp read data + SH5001_read(SH5001_ADDRESS, 0x08, 3, regData); + + //exit otp mode + data = 0x71; + SH5001_write(SH5001_ADDRESS, 0x03, 1, &data); + + if(regData[0] == 0x5f && regData[1] == 0x0 && regData[2] == 0x48) + use_otp_comp = 0; + else + use_otp_comp = 1; + printf("use_otp_comp:%d\n", use_otp_comp); + vacc[0] = ((signed char)regData[0]) * 8; + vacc[1] = ((signed char)regData[1]) * 8; + vacc[2] = ((signed char)regData[2]) * 8; + printf("%d %d %d %d %d %d \r\n", regData[0], regData[1], regData[2], vacc[0], vacc[1], vacc[2]); +} +#endif +/****************************************************************** +* Description: SH5001 initialization function +* +* Parameters: void +* +* return: SH5001_TRUE or SH5001_FALSE +* +******************************************************************/ + +uint8_t SH5001_get_chip_id(void) +{ + unsigned char regData = 0; + unsigned char i = 0; + + // SH5001 chipID = 0xA1; + while((regData != 0xA1U) && (i++ < 3U)) + { + SH5001_read(SH5001_ADDRESS, SH5001_CHIP_ID, 1, ®Data); + if((i == 3) && (regData != 0xA1U)) + { + printf("SH5001 init fail, Chip ID = 0x%x\r\n", regData); + return SH5001_FALSE; + } + } + printf("SH5001 Chip ID = 0x%x\r\n", regData); + return regData; +} + +unsigned char SH5001_init(void) +{ + unsigned char regData = 0; + unsigned char i = 0; + +#if SH5001_SPI_3WIRE_MODE + SH5001_SPI_Config(SH5001_SPI_3_WIRE); +#endif + + // SH5001 chipID = 0xA1; + while((regData != 0xA1U) && (i++ < 3U)) + { + SH5001_read(SH5001_ADDRESS, SH5001_CHIP_ID, 1, ®Data); + if((i == 3) && (regData != 0xA1U)) + { + printf("SH5001 init fail, Chip ID = 0x%x\r\n", regData); + return SH5001_FALSE; + } + } + printf("SH5001 Chip ID = 0x%x\r\n", regData); + + // reset internal module, don't modify it + SH5001_ModuleReset(); + + SH5001_OSC_FREQ(); + + #if SH5001_OIS_ENABLE + SH5001_OIS_SPI_Config(SH5001_OIS_SPI_EN); + #endif + + // 500Hz, 16G, cut off Freq(BW)=500*0.25Hz=125Hz, enable filter; + SH5001_Acc_Config(SH5001_ACC_ODR_125HZ, + SH5001_ACC_RANGE_16G, //SH5001_ACC_RANGE_8G SH5001_ACC_RANGE_16G + SH5001_ACC_ODRX040, + SH5001_ACC_FILTER_EN, + SH5001_ACC_BYPASS_EN); + + printf("SH5001 acc config ok\r\n"); + + // 800Hz, X\Y\Z 2000deg/s, cut off Freq(BW)=291Hz, enable filter; + SH5001_Gyro_Config( SH5001_GYRO_ODR_125HZ, + SH5001_GYRO_RANGE_2000, + SH5001_GYRO_ODRX040, + SH5001_GYRO_FILTER_EN, + SH5001_GYRO_BYPASS_EN); + + SH5001_IMU_Data_Stablize(); + + #if SH5001_OIS_ENABLE + SH5001_Acc_OIS_Config(SH5001_ACC_OIS_ODR_1000HZ, + SH5001_ACC_OIS_RANGE_8G, + SH5001_ACC_OIS_ODRX004, + SH5001_ACC_OIS_ENABLE); + + SH5001_Gyro_OIS_Config(SH5001_GYRO_OIS_ODR_8000HZ, + SH5001_GYRO_OIS_RANGE_2000, + SH5001_GYRO_OIS_ODRX004, + SH5001_GYRO_OIS_ENABLE); + #endif + + #if SH5001_TS_ENABLE + SH5001_TimeStamp_Config(SH5001_TS_ODR_1KHZ, SH5001_TS_EN); + #endif + + // temperature ODR is 63Hz, enable temperature measurement + SH5001_Temp_Config(SH5001_TEMP_ODR_63HZ, SH5001_TEMP_EN); + + //sh5001DumpReg(); + #ifdef SH5001_FIFO_WM_INT + SH5001_InitFIFO(); + #endif + + #ifdef SH5001_ACTIVITY_INT + SH5001_Init_Activity_Int(); + #endif + + #ifdef SH5001_DATA_READY_INT + SH5001_Init_Data_Ready_Int(); + #endif + +#if SENODIA_VDD_3V3 + SH5001_Get_Otpoffset(v3_acc); +#endif + //sh5001DumpReg(); + //sh5001DumpRegAll(); + + return SH5001_TRUE; +} + + + +/****************************************************************** +* Description: Read SH5001 gyroscope and accelerometer data +* +* Parameters: accData[3]: acc X,Y,Z; gyroData[3]: gyro X,Y,Z; +* +* return: void +* +******************************************************************/ +void SH5001_GetImuData( short accData[3], short gyroData[3] ) +{ + unsigned char regData[12]={0}; + + SH5001_read(SH5001_ADDRESS, SH5001_ACC_XL, 12, regData); + + accData[0] = ((short)regData[1] << 8) | regData[0]; + accData[1] = ((short)regData[3] << 8) | regData[2]; + accData[2] = ((short)regData[5] << 8) | regData[4]; + + gyroData[0] = ((short)regData[7] << 8) | regData[6]; + gyroData[1] = ((short)regData[9] << 8) | regData[8]; + gyroData[2] = ((short)regData[11] << 8) | regData[10]; + +#if SENODIA_VDD_3V3 + if(use_otp_comp){ + accData[0] -= v3_acc[0]; + accData[1] -= v3_acc[1]; + accData[2] -= v3_acc[2]; + } +#endif + + printf("%d %d %d %d %d %d\r\n", accData[0], accData[1], accData[2], gyroData[0], gyroData[1], gyroData[2]); +} + +void SH5001_OIS_GetTS(int timestamp[1]) +{ + unsigned char regData[3]={0}; + + SH5001_read(SH5001_ADDRESS, 0xE, 3, regData); + + timestamp[0] = ((int)regData[2] << 16) | ((int)regData[1] << 8) | regData[0]; + +} + +#if SH5001_OIS_ENABLE +void SH5001_OIS_GetImuData( short accData[3], short gyroData[3] ) +{ + unsigned char regData[12]={0}; + int i = 0; + + SH5001_OIS_read(SH5001_ADDRESS, SH5001_ACC_XL, 12, regData); + + accData[0] = ((short)regData[1] << 8) | regData[0]; + accData[1] = ((short)regData[3] << 8) | regData[2]; + accData[2] = ((short)regData[5] << 8) | regData[4]; + + gyroData[0] = ((short)regData[7] << 8) | regData[6]; + gyroData[1] = ((short)regData[9] << 8) | regData[8]; + gyroData[2] = ((short)regData[11] << 8) | regData[10]; + + //printf("%d %d %d %d %d %d\r\n", accData[0], accData[1], accData[2], gyroData[0], gyroData[1], gyroData[2]); +} +#endif + +#define SH5001_OFFSET_REG_NUM 13 +void offset_comp_save_reg(float offset[3]) +{ + unsigned char offsetData[SH5001_OFFSET_REG_NUM] = {0}; + + short offset_otp[3] = {0}; + short gain_otp[3] = {0}; + unsigned int range = 1; + + int offset_temp[3] = {0}; + short offset_new[3] = {0}; + unsigned short s_offset_new[3] = {0}; + + unsigned char i; + + + unsigned char offsetRegister[SH5001_OFFSET_REG_NUM] = { 0x8C, 0x8D, 0x8E, 0x8F, 0x98, 0x99, 0x9A, 0x9B, 0xA4, 0xA5 , 0xA6, + 0xA7, 0x24}; + + for(i=0; i> 4; + + if(offsetData[12] != 0) + { + for(i=0; i < offsetData[12] + 7; i++) + { + range = range * 2; + } + } + + #ifdef SH5001_OT_DEBUG + printf("range %d \r\n", range); + #endif + + for(i = 0; i < 3; i++) + { + offset_temp[i] = offset_otp[i] + (int)(offset[i] * ((float)range) / ((float)gain_otp[i])); // + //offset_new[i] = offset_otp[i] + (offset[i] * range / gain_otp[i]); // + } + + if(offset_temp[0] > 32767) + offset_temp[0] = 32767; + else if(offset_temp[0] < -32768) + offset_temp[0] = -32768; + if(offset_temp[1] > 32767) + offset_temp[1] = 32767; + else if(offset_temp[1] < -32768) + offset_temp[1] = -32768; + if(offset_temp[2] > 32767) + offset_temp[2] = 32767; + else if(offset_temp[2] < -32768) + offset_temp[2] = -32768; + + offset_new[0] = (short)offset_temp[0]; + offset_new[1] = (short)offset_temp[1]; + offset_new[2] = (short)offset_temp[2]; + + #ifdef SH5001_OT_DEBUG + printf("offset_new %d %d %d \r\n", offset_new[0], offset_new[1],offset_new[2]); + #endif + + s_offset_new[0] = (unsigned short)offset_new[0]; + s_offset_new[1] = (unsigned short)offset_new[1]; + s_offset_new[2] = (unsigned short)offset_new[2]; + + offsetData[3] = (unsigned char)((s_offset_new[0] & 0xFF00)>>8); + offsetData[7] = (unsigned char)((s_offset_new[1] & 0xFF00)>>8); + offsetData[11] = (unsigned char)((offset_new[2] & 0xFF00)>>8); + offsetData[2] = (unsigned char)((s_offset_new[0] & 0x00FF)); + offsetData[6] = (unsigned char)((s_offset_new[1] & 0x00FF)); + offsetData[10] = (unsigned char)((s_offset_new[2] & 0x00FF)); + + #ifdef SH5001_OT_DEBUG + printf("offsetData %x %x %x %x %x %x\r\n", offsetData[2], offsetData[3],offsetData[6], offsetData[7], offsetData[10], offsetData[11]); + #endif + + SH5001_write(SH5001_ADDRESS, 0x8E, 1, &offsetData[2]); + SH5001_write(SH5001_ADDRESS, 0x8F, 1, &offsetData[3]); + SH5001_write(SH5001_ADDRESS, 0x9A, 1, &offsetData[6]); + SH5001_write(SH5001_ADDRESS, 0x9B, 1, &offsetData[7]); + SH5001_write(SH5001_ADDRESS, 0xA6, 1, &offsetData[10]); + SH5001_write(SH5001_ADDRESS, 0xA7, 1, &offsetData[11]); + + //for test + #if 0 + for(i=0; i> 4; + + #ifdef SH5001_OT_DEBUG + printf("gain_otp %d %d %d \r\n", gain_otp[0], gain_otp[1],gain_otp[2]); + printf("temp_otp %d %d %d \r\n", beta_otp[0], beta_otp[1],beta_otp[2]); + printf("range 0x%x \r\n", tempCompData[9]); + #endif + + if(tempCompData[9] != 0) + { + for(i=0; i < tempCompData[9] + 14; i++) + { + range = range * 2; + } + } + + #ifdef SH5001_OT_DEBUG + printf("range222 %d \r\n", range); + #endif + //TODO + for(i = 0; i < 3; i++) + { + s_beta_temp[i] = beta_otp[i] - (int)(k[i] * ((float)range) / ((float)gain_otp[i])); + #ifdef SH5001_OT_DEBUG + printf("beta_ 111 %f %d\r\n", k[i] * range / gain_otp[i], (int)(k[i] * range / gain_otp[i])); + #endif + } + + if(s_beta_temp[0] > 127) + s_beta_temp[0] = 127; + else if(s_beta_temp[0] < -128) + s_beta_temp[0] = -128; + if(s_beta_temp[1] > 127) + s_beta_temp[1] = 127; + else if(s_beta_temp[1] < -128) + s_beta_temp[1] = -128; + if(s_beta_temp[2] > 127) + s_beta_temp[2] = 127; + else if(s_beta_temp[2] < -128) + s_beta_temp[2] = -128; + + s_beta_new[0] = (char)s_beta_temp[0]; + s_beta_new[1] = (char)s_beta_temp[1]; + s_beta_new[2] = (char)s_beta_temp[2]; + + beta_new[0] = (unsigned char)s_beta_new[0]; + beta_new[1] = (unsigned char)s_beta_new[1]; + beta_new[2] = (unsigned char)s_beta_new[2]; + + #ifdef SH5001_OT_DEBUG + printf("s_beta_new %d %d %d \r\n", s_beta_new[0], s_beta_new[1],s_beta_new[2]); + printf("beta_new %x %x %x \r\n", beta_new[0], beta_new[1],beta_new[2]); + #endif + + SH5001_write(SH5001_ADDRESS, 0x92, 1, &beta_new[0]); + SH5001_write(SH5001_ADDRESS, 0x9e, 1, &beta_new[1]); + SH5001_write(SH5001_ADDRESS, 0xAA, 1, &beta_new[2]); +} + +#define SH5001_ACC_REG_NUM 4 +void acc_temp_comp_save_reg(float k[3]) +{ + unsigned char tempCompData[SH5001_ACC_REG_NUM] = {0}; + signed char beta_otp[3] = {0}; + short gain_otp[3] = {0}; + unsigned int range = 1; + float rangek = 1; + unsigned char beta_new[3] = {0}; + signed char s_beta_new[3] = {0}; + int s_beta_temp[3] = {0}; + unsigned char i; + unsigned char tempCompRegister[SH5001_ACC_REG_NUM] = {0x71, 0x7c, 0x88, 0x21}; + for(i=0; i> 4; + #ifdef SH5001_OT_DEBUG + printf("temp_otp %d %d %d \r\n", beta_otp[0], beta_otp[1],beta_otp[2]); + printf("range 0x%x \r\n", tempCompData[3]); + #endif + if(tempCompData[3] != 0) + { + for(i=0; i < 6 - tempCompData[3]; i++) + { + range = range * 2; + } + } + for(i=0; i<3; i++) + { + k[i] = k[i] * range * 2.048 / 14; + } + #ifdef SH5001_OT_DEBUG + printf("k %f %f %f \r\n", k[0], k[1],k[2]); + #endif + if(tempCompData[3] != 0) + { + for(i=0; i < tempCompData[3] + 1; i++) + { + rangek = rangek * 2; + } + } + #ifdef SH5001_OT_DEBUG + printf("range222 %f \r\n", rangek); + #endif + for(i = 0; i < 3; i++) + { + s_beta_temp[i] = beta_otp[i] - (int)(k[i] * rangek); + #ifdef SH5001_OT_DEBUG + printf("beta_111 %f %d\r\n", k[i] * rangek , (int)(k[i] * rangek)); + #endif + } + if(s_beta_temp[0] > 127) + s_beta_temp[0] = 127; + else if(s_beta_temp[0] < -128) + s_beta_temp[0] = -128; + if(s_beta_temp[1] > 127) + s_beta_temp[1] = 127; + else if(s_beta_temp[1] < -128) + s_beta_temp[1] = -128; + if(s_beta_temp[2] > 127) + s_beta_temp[2] = 127; + else if(s_beta_temp[2] < -128) + s_beta_temp[2] = -128; + s_beta_new[0] = (char)s_beta_temp[0]; + s_beta_new[1] = (char)s_beta_temp[1]; + s_beta_new[2] = (char)s_beta_temp[2]; + beta_new[0] = (unsigned char)s_beta_new[0]; + beta_new[1] = (unsigned char)s_beta_new[1]; + beta_new[2] = (unsigned char)s_beta_new[2]; + #ifdef SH5001_OT_DEBUG + printf("s_beta_new %d %d %d \r\n", s_beta_new[0], s_beta_new[1],s_beta_new[2]); + printf("beta_new %x %x %x \r\n", beta_new[0], beta_new[1],beta_new[2]); + #endif + SH5001_write(SH5001_ADDRESS, 0x71, 1, &beta_new[0]); + SH5001_write(SH5001_ADDRESS, 0x7c, 1, &beta_new[1]); + SH5001_write(SH5001_ADDRESS, 0x88, 1, &beta_new[2]); +} + +#define SH5001_QUAD_REG_NUM 10 +#define SH5001_QUAD_DEBUG + +void sh5001_gyro_trim_quad(unsigned char quadval[6]) +{ + short S_Gyro_Quad[3] = {0}; + short C_Gyro_Quad[3] = {0}; + unsigned char quadData[SH5001_QUAD_REG_NUM] = {0}; + int sumGyroData[3] = {0}; + short avgGyroData[3] = {0}; + short GyroData[3] = {0}; + unsigned char temp[6]= {0}; + unsigned char i; + double Slope[3] = {560, 560, 560}; + + unsigned char quadRegister[SH5001_QUAD_REG_NUM] = {0x8B, 0x97, 0xA3, 0xD9, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC}; + unsigned char RegWrt_1[SH5001_QUAD_REG_NUM] = {0xFF, 0xFF, 0xFF, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + for(i=0; i0; i--) + { + delay_ms(1); + + SH5001_read(SH5001_ADDRESS, 0x06, 6, temp); + GyroData[0]=((short)(temp[1]<<8))|temp[0]; + GyroData[1]=((short)(temp[3]<<8))|temp[2]; + GyroData[2]=((short)(temp[5]<<8))|temp[4]; + + sumGyroData[0] += GyroData[0]; + sumGyroData[1] += GyroData[1]; + sumGyroData[2] += GyroData[2]; + + #ifdef SH5001_QUAD_DEBUG + printf("sumGyroData %d %d %d\r\n",GyroData[0], GyroData[1], GyroData[2]); + #endif + } + + for(i = 0; i < 3; i++) + { + avgGyroData[i] = sumGyroData[i] / 20; + } + + #ifdef SH5001_QUAD_DEBUG + printf("avgGyroData %d %d %d\r\n",avgGyroData[0], avgGyroData[1], avgGyroData[2]); + #endif + + for (i = 0; i < 3; i++) + { + S_Gyro_Quad[i] = (quadData[i + 7] & 0x04) >> 2; + C_Gyro_Quad[i] = quadData[i + 4] + (quadData[i + 7] & 0x03) * 256; + + #ifdef SH5001_QUAD_DEBUG + printf("raw S_Gyro_Quad[%d] : %d C_Gyro_Quad[%d]: %d \r\n",i, S_Gyro_Quad[i], i, C_Gyro_Quad[i]); + #endif + + C_Gyro_Quad[i] = (S_Gyro_Quad[i] == 0) ? C_Gyro_Quad[i]: (C_Gyro_Quad[i] * (-1) - 1); + C_Gyro_Quad[i] = (int)(C_Gyro_Quad[i] - avgGyroData[i] / Slope[i]); + + S_Gyro_Quad[i] = C_Gyro_Quad[i] >= 0 ? 0 : 1; + C_Gyro_Quad[i] = C_Gyro_Quad[i] >= 0 ? C_Gyro_Quad[i]: (C_Gyro_Quad[i] * (-1) - 1); + + RegWrt_1[i + 4] = C_Gyro_Quad[i] & 0x00FF; + RegWrt_1[i + 7] = (quadData[i + 7] & 0xF8) + S_Gyro_Quad[i] * 4 + ((C_Gyro_Quad[i] & 0x0300) >> 8); + + } + #ifdef SH5001_QUAD_DEBUG + 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], + 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]); + #endif + + + //TODO Save Reg + for(i=0; i<6; i++) { + SH5001_write(SH5001_ADDRESS, quadRegister[i + 4], 1, &RegWrt_1[i + 4]); + quadval[i] = RegWrt_1[i + 4]; + } + + for(i=0; i<4; i++) + SH5001_write(SH5001_ADDRESS, quadRegister[i], 1, &quadData[i]); +} + + +/****************************************************************** +* Description: SH5001 Acc self-test function +* +* Parameters: void +* +* return: SH3001_TRUE or SH3001_FALSE +* +******************************************************************/ + +#define SH5001_ACC_SELFTEST_REGNUM 7 +#define SH5001_ACC_SELFTEST_DEBUG + +unsigned char SH5001_AccSelfTest(void) +{ + unsigned char regAddr[SH5001_ACC_SELFTEST_REGNUM] = {0x21, 0x69, 0x74, 0x80, 0xB9, 0xBA, 0xBB}; + unsigned char regInit[SH5001_ACC_SELFTEST_REGNUM] = {0x30, 0xFF, 0xFF, 0xFF, 0x40, 0x45, 0x45}; + unsigned char regBack[SH5001_ACC_SELFTEST_REGNUM] = {0}; + unsigned char accTemp[6] = {0}; + signed int accSum[3] = {0}; + signed short accAvg1[3] = {0}, accAvg2[3] = {0}; + unsigned char i = 0; + signed short accRange[3] = {0}; + + + for(i=0; i 3900) && (accRange[0] < 9200)) + && ((accRange[1] > 4100) && (accRange[1] < 9600)) + && ((accRange[2] > 4500) && (accRange[2] < 10900))) + { + return(SH5001_TRUE); + } + else + { + return(SH5001_FALSE); + } +} + + +/****************************************************************** +* Description: SH5001 Gyro self-test function +* +* Parameters: void +* +* return: SH3001_TRUE or SH3001_FALSE +* +******************************************************************/ + +#define SH5001_GYRO_SELFTEST_REGNUM 11 +#define SH5001_GYRO_SELFTEST_DEBUG + +unsigned char SH5001_GyroSelfTest(void) +{ + unsigned char regAddr[SH5001_GYRO_SELFTEST_REGNUM] = {0x24, 0x8B, 0x97, 0xA3, 0xCA, 0xCB, 0xCC, 0xCD,\ + 0xCE, 0xCF, 0xD9}; + unsigned char regInit[SH5001_GYRO_SELFTEST_REGNUM] = {0x60, 0xFF, 0xFF, 0xFF, 0x60, 0x60, 0x60, 0x02,\ + 0x02, 0x02, 0x91}; + unsigned char regBack[SH5001_GYRO_SELFTEST_REGNUM] = {0}; + unsigned char gyroTemp[6] = {0}; + signed int gyroSum[3] = {0}; + signed short gyroAvg1[3] = {0}, gyroAvg2[3] = {0}; + unsigned char i = 0; + signed short gyroRange[3] = {0}; + + for(i=0; i -4500) && (gyroRange[0] < 7100)) + && ((gyroRange[1] > -6900) && (gyroRange[1] < 8200)) + && ((gyroRange[2] > -9300) && (gyroRange[2] < 4600))) + { + return(SH5001_TRUE); + } + else + { + return(SH5001_FALSE); + } +} + +void sh5001_adc_phase(void) +{ + unsigned char addr = 0xD0; + unsigned char regData; + + SH5001_read(SH5001_ADDRESS, addr, 1, ®Data); + //printf("0xD0 = 0x%x\r\n", regData); + + if((regData & 0x02) == 0x02) + regData &= 0xFD; + else + regData |= 0x02; + SH5001_write(SH5001_ADDRESS, addr, 1, ®Data); + //printf("0xD0 = 0x%x\r\n", regData); + +} + +#define SH5001_GYRO_ADC_S1_REGNUM 5 +#define SH5001_GYRO_ADC_S2_REGNUM 1 +//#define SH5001_GYRO_ADC__DEBUG +int adc_count = 0; +int err_count = 0; +void SH5001_Get_Adc_Polarity(short gyroPolarity[3]) +{ + unsigned char regAddrS1[SH5001_GYRO_ADC_S1_REGNUM] = {0xA3, 0xC6, 0xCC, 0xCF, 0xD0}; + unsigned char regInitS1[SH5001_GYRO_ADC_S1_REGNUM] = {0xFF, 0x00, 0x69, 0x1A, 0x0A}; + unsigned char regAddrS2[SH5001_GYRO_ADC_S2_REGNUM] = {0xD0}; + unsigned char regInitS2[SH5001_GYRO_ADC_S2_REGNUM] = {0x08}; + unsigned char regBackS1[SH5001_GYRO_ADC_S1_REGNUM] = {0}; + unsigned char gyroTemp[6] = {0}; + signed int gyroSum[3] = {0}; + signed short gyroAvg1[3] = {0}, gyroAvg2[3] = {0}; + unsigned char i = 0; + //signed short gyroPolarity[3] = {0}; + + for(i=0; i + + +#define __SUPPORT_SOFT_AGC_CONFIG__ 1 +#define GH3X2X_NEW_AGC_SLOT_NUM_LIMIT (8) +#define GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT (32-8) + +#define GH3X2X_LED_AGC_DISABLE (0) +#define GH3X2X_LED_AGC_ENABLE (1) + + +/// led agc adc num max +#define GH3X2X_AGC_ADC_NUM_MAX (4u) + +/// led agc gain limit number +#define GH3X2X_AGC_LIMIT_NUM_MAX (4u) + +/// raw data base line value +#define GH3X2X_DATA_BASE_LINE (8388608) //2^23 + +/// sys sample rate, 32kHz +#define GH3X2X_SYS_SAMPLE_RATE (32000) + +/* slot register ctrl index */ +#define GH3X2X_SLOT_REG_CTRL_0 (0) /**< slot x ctrl 0 reg */ +#define GH3X2X_SLOT_REG_CTRL_1 (1) /**< slot x ctrl 1 reg */ +#define GH3X2X_SLOT_REG_CTRL_2 (2) /**< slot x ctrl 2 reg */ +#define GH3X2X_SLOT_REG_CTRL_3 (3) /**< slot x ctrl 3 reg */ +#define GH3X2X_SLOT_REG_CTRL_4 (4) /**< slot x ctrl 4 reg */ +#define GH3X2X_SLOT_REG_CTRL_5 (5) /**< slot x ctrl 5 reg */ +#define GH3X2X_SLOT_REG_CTRL_6 (6) /**< slot x ctrl 6 reg */ +#define GH3X2X_SLOT_REG_CTRL_7 (7) /**< slot x ctrl 7 reg */ +#define GH3X2X_SLOT_REG_CTRL_8 (8) /**< slot x ctrl 8 reg */ +#define GH3X2X_SLOT_REG_CTRL_9 (9) /**< slot x ctrl 9 reg */ +#define GH3X2X_SLOT_REG_CTRL_10 (10) /**< slot x ctrl 10 reg */ +#define GH3X2X_SLOT_REG_CTRL_11 (11) /**< slot x ctrl 11 reg */ +#define GH3X2X_SLOT_REG_CTRL_12 (12) /**< slot x ctrl 12 reg */ +#define GH3X2X_SLOT_REG_CTRL_13 (13) /**< slot x ctrl 13 reg */ + +#define GH3X2X_BG_LEVEL_BIT_MASK (0x0030) +#define GH3X2X_ADC_BG_CANCEL_32_UA (0x0) +#define GH3X2X_ADC_BG_CANCEL_64_UA (0x1) +#define GH3X2X_ADC_BG_CANCEL_128_UA (0x2) +#define GH3X2X_ADC_BG_CANCEL_256_UA (0x3) + +/// amb slot select +#define GH3X2X_AGC_AMB_SLOT_DISABLE (0x0) +#define GH3X2X_AGC_AMB_SLOT_USER_DEFINED (0x1) +#define GH3X2X_AGC_AMB_SLOT_FOLLOW_CFG (0x2) + +/// get bits data +#define GH3X2X_GET_REG_BITS_U16(reg_data, lsb, msb) (((reg_data) & ((0xFFFF << (lsb)) & \ + (0xFFFF >> (15 - (msb))))) >> (lsb)) + +/// set bits data +#define GH3X2X_SET_REG_BITS_U16(reg, lsb, msb, value) ((reg) = (((reg) & ((0xFFFF << (lsb)) ^ \ + (0xFFFF >> (15 - (msb))))) | ((value) << (lsb)))) + +/// get adc gain +#define GH3X2X_GET_ADC_GAIN(reg_data, adc_no) GH3X2X_GET_REG_BITS_U16((reg_data), ((adc_no) * 4), \ + ((adc_no) * 4 + 3)) + +/// set adc gain +#define GH3X2X_SET_ADC_GAIN(reg_data, adc_no, gain) GH3X2X_SET_REG_BITS_U16((reg_data), ((adc_no) * 4), \ + ((adc_no) * 4 + 3), (gain)) + +/// get bg cancel i_dacfs +#define GH3X2X_GET_BGC_I_DACFS(reg_data, adc_no) GH3X2X_GET_REG_BITS_U16((reg_data), ((adc_no) << 1), \ + ((adc_no) * 2 + 1)) + +/// set bg cancel i_dacfs +#define GH3X2X_SET_BGC_I_DACFS(reg_data, adc_no, i_dacfs) GH3X2X_SET_REG_BITS_U16((reg_data), ((adc_no) * 2), \ + ((adc_no) * 2 + 1), (i_dacfs)) + +#define ABS(x) ((x) > 0 ? (x) : -(x)) + +/// transfer int to float +#define GH3X2X_TRANS_INT_TO_FLOAT (1.0f) + +/// agc calc seconds (250ms) +#define GH3X2X_AGC_CALC_SECONDS (0.25f) + +/// agc bgc donw cnt, 5s +#define GH3X2X_AGC_BGC_DOWN_CNT (20) + +/// slot tia gain val min +#define GH3X2X_AGC_GAIN_MIN_VAL (0) + +/// slot tia gain val max, 5s, equal (GH3X2X_SLOT_TIA_GAIN_VAL_MAX - 1) +#define GH3X2X_AGC_GAIN_MAX_VAL (12) + +/// Less than thr, include rawdata < thr +#define GH3X2X_AGC_EXCD_FLAG_LESS (0x01) + +/// greater than thr, include rawdatamix > thr | rawdata > thr +#define GH3X2X_AGC_EXCD_FLAG_GREATER (0x06) + +/// AGC failure reason +#define GH3X2X_AGC_FAILURE_REASON_1 (0x1) +#define GH3X2X_AGC_FAILURE_REASON_2 (0x2) +#define GH3X2X_AGC_FAILURE_REASON_4 (0x4) +#define GH3X2X_AGC_FAILURE_REASON_5 (0x5) +#define GH3X2X_AGC_FAILURE_REASON_6 (0x6) + +#define GH3X2X_AGC_CHECK_EN_BITS(x) (((x) & (0x03 << 8)) != 0) /**< check enable bits of ctrl3 */ +#define GH3X2X_AGC_GET_SRC_BITS(x) (((x) >> 6) & 0x03) /**< get agc src bits of ctrl3 */ +#define GH3X2X_AGC_CHECK_BG_2X2_BITS(x) (((x) & (0x03 << 4)) == 0x03) /**< check 2x2 bg lvl bits of ctrl3 */ +#define GH3X2X_AGC_SET_SRC_BITS(x, n) (((x) & 0xFF3Fu) | ((n) << 6u)) /**< set agc src bits of ctrl3 */ + +#define GH3X2X_AGC_GET_DONE_FAIL_BIT(x, i) (((x) >> (i)) & 0x01) /**< get tune done/fail bit of flag */ +#define GH3X2X_AGC_REG_BIT(x, i) (((x) >> (i)) & 0x01) /**< get reg bit value */ +#define GH3X2X_AGC_GET_RESULT_BITS(x, i) (((x) >> (i)) & 0x07) /**< get result bits of flag */ +#define GH3X2X_AGC_RESULT_BITS_SIZE (3u) /**< one result 3 bits size of flag */ + +#define GH3X2X_FRAME_FLAG_NUM 8 +#define GH3X2X_AGC_MAIN_SLOT_NUM 8 + +/** + * @brief soft lead result + */ +typedef struct +{ + GU8 uchAmbSampleEn : 2; /**< AMB sampling enable */ + GU8 uchAmbSlot : 3; /**< slot of amb sampling */ + GU8 uchRes : 3; /**< reserved */ +} STAmbSlotCtrl; + + /** + * @brief gain limit + */ +typedef struct +{ + GU8 uchGainLimitBg32uA : 4; /**< gain limit bg current */ + GU8 uchGainLimitBg64uA : 4; + GU8 uchGainLimitBg128uA : 4; + GU8 uchGainLimitBg256uA : 4; +} STSoftAgcGainLimit; + + /** + * @brief soft agc parameter + */ +typedef struct +{ + GU8 uchSlotxSoftAgcAdjEn; /**< soft agc enable */ + GU8 uchSlotxSoftBgAdjEn; /**< soft bg cancel adjust enable */ + STAmbSlotCtrl stAmbSlotCtrl; /**< amb slot ctrl */ + GU8 uchRes0; /**< reserved */ + GU8 uchSpo2RedSlotCfgEn; + GU8 uchSpo2IrSlotCfgEn; + STSoftAgcGainLimit stSoftAgcGainLimit; /**< soft gain limit */ + GU32 unAgcTrigThd_H; /**< trig threshold(high) of soft agc */ + GU32 unAgcTrigThd_L; /**< trig threshold(low) of soft agc */ + GU32 unAgcRestrainThd_H; /**< restrain threshold(high) of soft agc */ + GU32 unAgcRestrainThd_L; /**< restrain threshold(low) of soft agc */ +} STSoftAgcCfg; + + + +typedef struct +{ + GU8 uchEnable; + GU8 uchSpo2ChnlIndex; //0: is not spo2 channel N(N > 0): is spo2 channl + GU8 uchSlotAdc; + GU8 uchCurrentTiaGain; + GU8 uchCurrentDrv; + GU8 uchTiaGainUpLimit; + GU8 uchHaveBakRegFlag; + GU8 uchBakRegAgcEn; + GU8 uchBakRegAgcSrc; + GU8 uchBakRegLedCurrentMin; + GU8 uchBakRegLedCurrentMax; + GU8 uchBakTiaGain; +} STGh3x2xNewAgcMainChnlInfo; + +typedef struct +{ + GU16 Sat_CheckCnt[GH3X2X_AGC_MAIN_SLOT_NUM]; /* num of data checked*/ + GU16 Sat_cnt[GH3X2X_AGC_MAIN_SLOT_NUM]; /* sat num of each channel*/ + GU8 Sat_flag; /* sat flag one bit each channel*/ +} STGh3x2xNewAgcMainChnlSat; + +typedef struct +{ + GU32 unMaxRawdata; + GU32 unMinRawdata; + GU32 unSumAdjust; // cacluate drv current and gain + GU32 unSumTrige; // judge whether AGC + GU32 unRawdataMean; + GU32 unLastRawdataMean; + GU16 usSampleRate; + GU16 usAnalysisCnt; // numble of nalysis data + GU8 uchHaveAgcAtLastReadPrd; //0: no agc action at last fifo read period 1: have agc action at last fifo read preiod + GU8 uchDropFlag; +} STGh3x2xNewAgcMainChnlMeanInfo; + +typedef struct +{ + GU8 uchIniteFirst; // inite first time 0:yes 1:not + GU8 uchSeconsCnt; // +} STGh3x2xNewAgcMainChnlIdaelAdjInfo; + +typedef struct +{ + GU32 unLastRawdata; + GU32 unLastLastRawdata; + GU32 unRawdataSum; + GU16 usAnalysisCnt; + GU16 usMoreThanUpLimitPointCnt; + GU16 usMoreThanUpLimitPointCntForBiggerGain; + GU16 usTrigeUpLimitForBiggerGain; // rawdate/256 + GU8 uchEn; + GU8 uchSlotAdcNo; + GU8 uchCurrentGain; +}STGh3x2xNewAgcSubChnlRxInfo; + + +void GH3X2X_LedAgcReset(void); +void GH3X2X_LedAgcPramWrite(GU16 usRegAddr, GU16 usRegData); +void GH3X2X_LedAgcInit(STGh3x2xAgcInfo *STGh3x2xAgcInfo); +void GH3X2X_LedAgc_Close(void); +void GH3X2X_LedAgc_Open(void); +void Gh3x2xNewAgcSubChnlModuleReset(void); +GU8 GH3x2xNewAgcSetNewSubChnl(GU8 uchSlotNo, GU8 uchRxEn, STGh3x2xAgcInfo *STGh3x2xAgcInfo); +void GH3X2X_LedAgcProcess(GU8* puchReadFifoBuffer, GU16 usFifoLen, STGh3x2xAgcInfo *STGh3x2xAgcInfo); +void GH3X2X_LedAgcInit(STGh3x2xAgcInfo *STGh3x2xAgcInfo); +void GH3X2X_LedAgcPramConfig(STSoftAgcCfg* stSoftAgcCfg); +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 index 000000000..e1d45e907 --- /dev/null +++ b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_demo.h @@ -0,0 +1,68 @@ +#ifndef __GH3X2X_AFE_DEMO_H__ +#define __GH3X2X_AFE_DEMO_H__ +#include "gh3x2x_afe_drv.h" + +/** + * @brief channel map for function id + */ +#define GH3X2X_FUNC_OFFSET_ADT (0) /**<0 ADT FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_HR (1) /**<1 HR FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_HRV (2) /**<2 HRV FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_HSM (3) /**<3 HSM FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_FPBP (4) /**<4 BPD FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_PWA (5) /**<5 PFA FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_SPO2 (6) /**<6 SPO2 FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_ECG (7) /**<7 ECG FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_PWTT (8) /**<8 PWTT FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_SOFT_ADT_GREEN (9) /**<9 SOFT ADT GREEN FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_BT (10) /**<10 BT FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_RESP (11) /**<11 RESP FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_AF (12) /**<12 AF ADT FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_TEST1 (13) /**<13 TEST1 FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_TEST2 (14) /**<14 TEST2 ADT FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_SOFT_ADT_IR (15) /**<15 SOFT ADT IR FUNC_OFFSET */ +#define GH3X2X_FUNC_OFFSET_RS0 (16) /**<16 */ +#define GH3X2X_FUNC_OFFSET_RS1 (17) /**<17 */ +#define GH3X2X_FUNC_OFFSET_RS2 (18) /**<18 */ +#define GH3X2X_FUNC_OFFSET_LEAD_DET (19) /**<19 */ +#define GH3X2X_FUNC_OFFSET_MAX (20) + +/* Function mode. */ +#define GH3X2X_NO_FUNCTION (0) /**<0x00000000 NO function */ +#define GH3X2X_FUNCTION_ADT ((0x1) << (GH3X2X_FUNC_OFFSET_ADT)) /**<0x00000001 ADT function */ +#define GH3X2X_FUNCTION_HR ((0x1) << (GH3X2X_FUNC_OFFSET_HR)) /**<0x00000002 HR function */ +#define GH3X2X_FUNCTION_HRV ((0x1) << (GH3X2X_FUNC_OFFSET_HRV)) /**<0x00000004 HRV function */ +#define GH3X2X_FUNCTION_HSM ((0x1) << (GH3X2X_FUNC_OFFSET_HSM)) /**<0x00000008 HSM function */ +#define GH3X2X_FUNCTION_FPBP ((0x1) << (GH3X2X_FUNC_OFFSET_FPBP)) /**<0x00000010 FPBP function */ +#define GH3X2X_FUNCTION_PWA ((0x1) << (GH3X2X_FUNC_OFFSET_PWA)) /**<0x00000020 PWA function */ +#define GH3X2X_FUNCTION_SPO2 ((0x1) << (GH3X2X_FUNC_OFFSET_SPO2)) /**<0x00000040 SPO2 function */ +#define GH3X2X_FUNCTION_ECG ((0x1) << (GH3X2X_FUNC_OFFSET_ECG)) /**<0x00000080 ECG function */ +#define GH3X2X_FUNCTION_PWTT ((0x1) << (GH3X2X_FUNC_OFFSET_PWTT)) /**<0x00000100 PWTT function */ +#define GH3X2X_FUNCTION_SOFT_ADT_GREEN ((0x1) << (GH3X2X_FUNC_OFFSET_SOFT_ADT_GREEN)) /**<0x00000200 SOFT ADT GREEN function */ +#define GH3X2X_FUNCTION_BT ((0x1) << (GH3X2X_FUNC_OFFSET_BT)) /**<0x00000400 BT function */ +#define GH3X2X_FUNCTION_RESP ((0x1) << (GH3X2X_FUNC_OFFSET_RESP)) /**<0x00000800 RESP function */ +#define GH3X2X_FUNCTION_AF ((0x1) << (GH3X2X_FUNC_OFFSET_AF)) /**<0x00001000 AF function */ +#define GH3X2X_FUNCTION_TEST1 ((0x1) << (GH3X2X_FUNC_OFFSET_TEST1)) /**<0x00002000 TEST1 function */ +#define GH3X2X_FUNCTION_TEST2 ((0x1) << (GH3X2X_FUNC_OFFSET_TEST2)) /**<0x00004000 TEST2 function */ +#define GH3X2X_FUNCTION_SOFT_ADT_IR ((0x1) << (GH3X2X_FUNC_OFFSET_SOFT_ADT_IR)) /**<0x00008000 SOFT ADT IR function */ +#define GH3X2X_FUNCTION_RS0 ((0x1) << (GH3X2X_FUNC_OFFSET_RS0)) +#define GH3X2X_FUNCTION_RS1 ((0x1) << (GH3X2X_FUNC_OFFSET_RS1)) +#define GH3X2X_FUNCTION_RS2 ((0x1) << (GH3X2X_FUNC_OFFSET_RS2)) +#define GH3X2X_FUNCTION_LEAD_DET ((0x1) << (GH3X2X_FUNC_OFFSET_LEAD_DET)) + +#define GH3X2X_ADT_FUNC_ENABLE (1) +#define GH3X2X_ECG_FUNC_ENABLE (1) + +#define GH3X2X_ECG_SLOT_NUM (0) +#define GH3X2X_ADT_SLOT_NUM (1) + +#define GH3X2X_ADT_ADC_NUM (0) + +#define GH3X2X_ECG_DOWN_FS (250) //ecg fs:800, 320, 256 +#define GH3X2X_ECG_FS (320) //down sample ecg fs: 500 OR 250 +#define GH3X2X_PPG_DOWN_FS (250) //down sample ppg fs: + +void GH3X2X_DemoLedAgcPramConfig(void); + +#endif + 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 index 000000000..95f900cf5 --- /dev/null +++ b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_drv.h @@ -0,0 +1,453 @@ +/** + * @copyright (c) 2003 - 2022, Goodix Co., Ltd. All rights reserved. + * + * @file gh3x2x_afe_drv.h + * + * @brief gh3x2x afe driver functions + * + * @version v3.2.4.6 + * + * @author Gooidx Iot Team + * + */ +#ifndef __GH3X2X_AFE_DRV_H__ +#define __GH3X2X_AFE_DRV_H__ + +#include "gh3x2x_afe_user.h" +#include "gh3x2x_afe_version.h" +#include + +#ifndef GH3X2X_AFE_UNUSED_VAR +#define GH3X2X_AFE_UNUSED_VAR(X) ((void)(X)) +#endif // GH3X2X_AFE_UNUSED_VAR + + +#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */ + #ifndef __weak + #define __weak __attribute__((weak)) + #endif /* __weak */ + #ifndef __packed + #define __packed __attribute__((__packed__)) + #endif /* __packed */ +#endif /* __GNUC__ */ + + + + + + +/* type redefine */ +typedef unsigned char GU8; /**< 8bit unsigned integer type */ +typedef signed char GS8; /**< 8bit signed integer type */ +typedef unsigned short GU16; /**< 16bit unsigned integer type */ +typedef signed short GS16; /**< 16bit signed integer type */ +typedef int GS32; /**< 32bit signed integer type */ +typedef unsigned int GU32; /**< 32bit unsigned integer type */ +typedef float GF32; /**< float type */ +typedef double GD64; /**< double type */ +typedef char GCHAR; /**< char type */ +typedef unsigned char GBOOL; +typedef long long GS64; /**< 64bit signed integer type */ + + + + +#define GH3020_ID (0x00) +#define GH3026_ID (0x01) + +#define GH3220_ID (0x03) + +#define GH3X2X_MP_DISABLE (0) +#define GH3X2X_MP_ENABLE (1) + +/********************* communication interface type******************************/ +#define GH3X2X_AFE_COM_INTERFACE_SPI 0 +#define GH3X2X_AFE_COM_INTERFACE_I2C 1 + + +/********************* spi type ************************************************/ +#define GH3X2X_AFE_SPI_SOFTWARE_CS 0 +#define GH3X2X_AFE_SPI_HARDWEAR_CS 1 + + +/********************* chip process type ***************************************/ +#define GH3X2X_AFE_PRO_BY_INT 0 +#define GH3X2X_AFE_PRO_BY_POLLING 1 + +/********************* chip reset type ***************************************/ +#define GH3X2X_AFE_RESET_HARDWARE 0 +#define GH3X2X_AFE_RESET_SOFTWARE 1 + + + +#define GH3X2X_AFE_SPI_CS_CTRL_LOW 0 +#define GH3X2X_AFE_SPI_CS_CTRL_HIGH 1 + + + + +#define GH3X2X_AFE_CMD_SLEEP 0xC4 +#define GH3X2X_AFE_CMD_WAKEUP 0xC3 +#define GH3X2X_AFE_CMD_RESET 0xC2 +#define GH3X2X_AFE_SPI_CMD_WRITE (0xF0) +#define GH3X2X_AFE_SPI_CMD_READ (0xF1) + + + +#define GH3X2X_AFE_RET_OK (0) /**< there is no error */ +#define GH3X2X_AFE_RET_GENERIC_ERROR (-1) /**< a generic error happens */ + +// special reg addr +#define GH3X2X_AFE_FIFO_REG_ADDR (0xAAAA) /**< fifo reg addr */ +#define GH3X2X_AFE_I2C_CMD_ADDR (0xDDDD) /**< i2c cmd reg addr */ + + +#define GH3X2X_AFE_SPI_END_DELAY_X_US (3) +#define GH3X2X_AFE_SPI_WAIT_DELAY_X_US (4) + +#define GH3X2X_AFE_WAKE_UP_CMD_DELAY_X_US (500) +#define GH3X2X_AFE_HARD_RESET_DELAY_X_US (100) + +/// null val +#define GH3X2X_PTR_NULL ((void *) 0) + + + +#define GH3X2X_AFE_CHANGE_BYTE_U16(x) ((((u16)(((u8*)(&x))[0]))<<8) + ((u16)(((u8 *)(&x))[1]))) +/// get high byte from word +#define GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(sValue) ((GU8)(((sValue) >> 8) & 0xFFU)) +/// get low byte from word +#define GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(sValue) ((GU8)((sValue) & 0xFFU)) +#define GH3X2X_AFE_MAKEUP_WORD(uchHighByte, uchLowByte) ((GU16)(((((GU16)(uchHighByte)) << 8)& 0xFF00) |\ + (((GU16)(uchLowByte))& 0x00FF))) + +/// makeup dword from bytes +#define GH3X2X_AFE_MAKEUP_DWORD(uchByte3, uchByte2, uchByte1, uchByte0) (((((GU32)(uchByte3)) << 24) & 0xFF000000U)|\ + ((((GU32)(uchByte2)) << 16) & 0x00FF0000U) |\ + ((((GU32)(uchByte1)) << 8) & 0x0000FF00U) |\ + (((GU32)(uchByte0)) & 0x000000FFU)) + + +/// rawdata clear all flag +#define GH3X2X_RAWDATA_CLEAR_ALL_FLAG(x) ((x) & 0x00FFFFFF) + + +/// macro of val get bits +#define GH3X2X_AFE_VAL_GET_BIT(x, b) ((x) &= (b)) + + + +#define GH3X2X_AFE_EVENT_BIT(x) ((GU16)1 << x) + + + +#define GH3X2X_AFE_REG_IS_VALID(x) ((x) <= 0x0780) +/// macro of val clear bits +#define GH3X2X_VAL_CLEAR_BIT(x, b) ((x) &= (~(b))) +/// macro of val set bits +#define GH3X2X_VAL_SET_BIT(x, b) ((x) |= (b)) + + +#define GH3X2X_PIN_STATUS_CS_0_MISO_0 (0) +#define GH3X2X_PIN_STATUS_CS_1_MISO_0 (1) +#define GH3X2X_PIN_STATUS_CS_0_MISO_1 (2) +#define GH3X2X_PIN_STATUS_CS_1_MISO_1 (3) + + +/// get byte3 from dword +#define GH3X2X_AFE_GET_BYTE3_FROM_DWORD(unValue) ((GU8)(((unValue) >> 24) & 0x000000FFU)) +/// get byte2 from dword +#define GH3X2X_AFE_GET_BYTE2_FROM_DWORD(unValue) ((GU8)(((unValue) >> 16) & 0x000000FFU)) +/// get byte1 from dword +#define GH3X2X_AFE_GET_BYTE1_FROM_DWORD(unValue) ((GU8)(((unValue) >> 8) & 0x000000FFU)) +/// get byte0 from dword +#define GH3X2X_AFE_GET_BYTE0_FROM_DWORD(unValue) ((GU8)((unValue) & 0x000000FFU)) + +/// macro of val set bits +#define GH3X2X_VAL_SET_BIT(x, b) ((x) |= (b)) + +/// macro of clear bits +#define GH3X2X_CLEAR_BIT(x, b) ((x) & (~(b))) + +/// macro of val clear bits +#define GH3X2X_VAL_CLEAR_BIT(x, b) ((x) &= (~(b))) + +/// macro of val get bits +#define GH3X2X_VAL_GET_BIT(x, b) ((x) &= (b)) + + +#define GH3X2X_AFE_I2C_DEVICE_BASE (0x28) +#define GH3X2X_AFE_I2C_DEVICE_ADDR (GH3X2X_AFE_I2C_DEVICE_BASE | (GH3X2X_AFE_I2C_DEVICE_CTRL_PIN_STATUS << 1)) + + +#define GH3X2X_AFE_FIFO_RAWDATA_SIZE (4) +#define GH3X2X_AFE_SLOT_ADC_NUM_BITS (0xF8) +#define GH3X2X_AFE_CHANNEL_MAP_GET(x) ((x) & GH3X2X_AFE_SLOT_ADC_NUM_BITS) + +/// number of channel map id +#define CHANNEL_MAP_ID_NUM (32) +/// number of channel map id +#define CHANNEL_SLOT_NUM (8) + + +/** + * @brief register struct + */ +typedef struct +{ + GU16 usRegAddr; /**< register address */ + GU16 usRegData; /**< register val */ +} STGH3X2X_AFEReg; + +typedef struct +{ + GU8 uchAddrOffset; + GU8 uchMsb; + GU8 uchLsb; +} STGh3x2xAgcReg; + +typedef struct +{ + /// save gain + GU8 uchTiaGainRecord[CHANNEL_MAP_ID_NUM]; + GU8 uchTiaGainAfterSoftAgc[CHANNEL_MAP_ID_NUM]; + /// save current of drv0 and drv1 + GU16 uchDrvCurrentAfterSoftAgc[CHANNEL_SLOT_NUM]; + GU16 uchDrvCurrentRecord[CHANNEL_SLOT_NUM]; +} STGh3x2xAgcInfo; + +extern void GH3X2X_AFE_SpiSendCmd(GU8 uchCmd); +extern void GH3X2X_AFE_SpiWriteReg(GU16 usRegAddr, GU16 usRegValue); +extern GU16 GH3X2X_AFE_SpiReadReg(GU16 usRegAddr); +extern void GH3X2X_AFE_SpiReadRegs(GU16 usRegAddr, GU16 *pusRegValueBuffer, GU8 uchLen); + +extern void GH3X2X_AFE_SpiWriteRegHardwareCs(GU16 usRegAddr, GU16 usRegValue); +extern void GH3X2X_AFE_SpiReadRegsHardwareCs(GU16 usRegAddr, GU16 *pusRegValueBuffer, GU8 uchLen); +extern GU16 GH3X2X_AFE_SpiReadRegHardwareCs(GU16 usRegAddr); +extern void GH3X2X_AFE_I2cWriteReg(GU16 usRegAddr, GU16 usRegValue); +extern GU16 GH3X2X_AFE_I2cReadReg(GU16 usRegAddr); +extern void GH3X2X_I2cReadRegs(GU16 usRegAddr, GU16 *pusRegValueArr, GU8 uchLen); +extern void GH3X2X_AFE_Reset(void); +extern void GH3X2X_AFE_SpiSendCmdHardwareCs(GU8 uchCmd); +extern void GH3X2X_AFE_I2cSendCmd(GU8 uchCmd); + + +/**************** cmd/read/write funciton define **************************/ +#if(GH3X2X_AFE_COM_INTERFACE_TYPE == GH3X2X_AFE_COM_INTERFACE_SPI) +#if(GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS) +#define GH3X2X_AFE_SEND_CMD(cmd) GH3X2X_AFE_SpiSendCmd(cmd) +#define GH3X2X_AFE_WRITE_REG(usRegAddr, usRegValue) GH3X2X_AFE_SpiWriteReg(usRegAddr, usRegValue) +#define GH3X2X_AFE_READ_REG(usRegAddr) GH3X2X_AFE_SpiReadReg(usRegAddr) +#define GH3X2X_AFE_READ_FIFO(buf, len) GH3X2X_AFE_SpiReadFifo(buf, len) +#define GH3X2X_AFE_READ_REGS(usRegAddr,pusRegValueBuffer,uchLen) GH3X2X_AFE_SpiReadRegs(usRegAddr,pusRegValueBuffer,uchLen) +#else +#define GH3X2X_AFE_SEND_CMD(cmd) GH3X2X_AFE_SpiSendCmdHardwareCs(cmd) +#define GH3X2X_AFE_WRITE_REG(usRegAddr, usRegValue) GH3X2X_AFE_SpiWriteRegHardwareCs(usRegAddr, usRegValue) +#define GH3X2X_AFE_READ_REG(usRegAddr) GH3X2X_AFE_SpiReadRegHardwareCs(usRegAddr) +#define GH3X2X_AFE_READ_FIFO(buf, len) GH3X2X_AFE_SpiReadFifoHardwareCs(buf, len) +#define GH3X2X_AFE_READ_REGS(usRegAddr,pusRegValueBuffer,uchLen) GH3X2X_AFE_SpiReadRegsHardwareCs(usRegAddr,pusRegValueBuffer,uchLen) + +#endif +#else +#define GH3X2X_AFE_SEND_CMD(cmd) GH3X2X_AFE_I2cSendCmd(cmd) +#define GH3X2X_AFE_WRITE_REG(usRegAddr, usRegValue) GH3X2X_AFE_I2cWriteReg(usRegAddr, usRegValue) +#define GH3X2X_AFE_READ_REG(usRegAddr) GH3X2X_AFE_I2cReadReg(usRegAddr) +#define GH3X2X_AFE_READ_FIFO(buf, len) GH3X2X_AFE_I2cReadFifo(buf, len) +#define GH3X2X_AFE_READ_REGS(usRegAddr,pusRegValueBuffer,uchLen) GH3X2X_I2cReadRegs(usRegAddr,pusRegValueBuffer,uchLen) + +#endif + + +/***************************** GH3X2X event *************************************************/ + +#define GH3X2X_AFE_EVENT_COM_READY (0) +#define GH3X2X_AFE_EVENT_LEAD_ON (1) +#define GH3X2X_AFE_EVENT_LEAD_OFF (2) +#define GH3X2X_AFE_EVENT_FAST_RECOVER_DONE (3) +#define GH3X2X_AFE_EVENT_ADC_DONE (4) +#define GH3X2X_AFE_EVENT_FIFO_FULL (5) +#define GH3X2X_AFE_EVENT_FIFO_OV (6) +#define GH3X2X_AFE_EVENT_FIFO_UN (7) +#define GH3X2X_AFE_EVENT_LED_TUNE_FAIL (8) +#define GH3X2X_AFE_EVENT_LED_TUNE_DONE (9) +#define GH3X2X_AFE_EVENT_WEAR_ON (10) +#define GH3X2X_AFE_EVENT_WEAR_OFF (11) +#define GH3X2X_AFE_EVENT_SLOT_TIME_OUT (12) +#define GH3X2X_AFE_EVENT_SAMPLE_RATE_ERROR (13) +#define GH3X2X_AFE_EVENT_ERSET (14) + + + + + + +/***************************** GH3X2X registers *********************************************/ + + +#define GH3X2X_AFE_REG_INT_EVENT_ADDR 0x0508 +#define GH3X2X_AFE_REG_FIFO_USE_ADDR 0x050A +#define GH3X2X_AFE_REG_CHIP_READY_CODE_REG_ADDR 0x0036 +#define GH3X2X_AFE_REG_SLOT_TMR0_REG_ADDR 0x01EC +#define GH3X2X_AFE_REG_INT_EVENT_EN_ADDR 0x0502 + +#define GH3X2X_AFE_REG_SLOT_EN_ADDR 0x0108 + + +#define GH3X2X_AFE_REG_START_ADDR 0x0000 +#define GH3X2X_AFE_REG_START_MSB 0 +#define GH3X2X_AFE_REG_START_LSB 0 + + +/**************************** GH3X2X ppg control reg index ***********************************************/ +#define GH3X2X_AFE_PPG_CTRL_REG_AGC_EN 0 +#define GH3X2X_AFE_PPG_CTRL_REG_LED_CURRENT_UP_LIMIT 1 +#define GH3X2X_AFE_PPG_CTRL_REG_LED_CURRENT_DOWN_LIMIT 2 +#define GH3X2X_AFE_PPG_CTRL_REG_LED_CURRENT_DRV0 3 +#define GH3X2X_AFE_PPG_CTRL_REG_LED_CURRENT_DRV1 4 +#define GH3X2X_AFE_PPG_CTRL_REG_TIA_GAIN_RX0 5 +#define GH3X2X_AFE_PPG_CTRL_REG_TIA_GAIN_RX1 6 +#define GH3X2X_AFE_PPG_CTRL_REG_TIA_GAIN_RX2 7 +#define GH3X2X_AFE_PPG_CTRL_REG_TIA_GAIN_RX3 8 +#define GH3X2X_AFE_PPG_CTRL_REG_AGC_SRC 9 +#define GH3X2X_AFE_PPG_CTRL_REG_BG_CANCEL_RX0 10 +#define GH3X2X_AFE_PPG_CTRL_REG_BG_CANCEL_RX1 11 +#define GH3X2X_AFE_PPG_CTRL_REG_BG_CANCEL_RX2 12 +#define GH3X2X_AFE_PPG_CTRL_REG_BG_CANCEL_RX3 13 +#define GH3X2X_AFE_PPG_CTRL_REG_SR_MULIPLIPER 14 +#define GH3X2X_AFE_PPG_CTRL_ECG_PPG_RX_EN 15 + +#define GH3X2X_DRV0_FULL_SCAL_CURRENT_LSB (4) +#define GH3X2X_DRV0_FULL_SCAL_CURRENT_MSB (5) + +#define GH3X2X_DRV1_FULL_SCAL_CURRENT_LSB (0) +#define GH3X2X_DRV1_FULL_SCAL_CURRENT_MSB (1) + +#define GH3X2X_WHO_AM_I_LSB (5) +#define GH3X2X_WHO_AM_I_MSB (7) + +#define GH3X2X_EFUSE_MODE_LSB (0) +#define GH3X2X_EFUSE_MODE_MSB (1) + +#define GH3X2X_EFUSE_CHOOSE_LSB (2) +#define GH3X2X_EFUSE_CHOOSE_MSB (3) + +#define GH3X2X_EFUSE_START_LSB (4) +#define GH3X2X_EFUSE_START_MSB (4) + +#define GH3X2X_EFUSE_CLK_EN_LSB (5) +#define GH3X2X_EFUSE_CLK_EN_MSB (5) + + + + +#define GH3X2X_LED_DRV_AD_REG_REG_ADDR (0x0692) +#define GH3X2X_WHO_AM_I_REG_ADDR (0x0724) + + +// efuse_ctrl block, start addr: 0x0700 +#define GH3X2X_EFUSE_CTRL_CMD_REG_ADDR (0x0700) +#define GH3X2X_EFUSE_CTRL_PASSWORD_REG_ADDR (0x0702) +#define GH3X2X_EFUSE_CTRL_TIMING_CFG_0_REG_ADDR (0x0704) +#define GH3X2X_EFUSE_CTRL_TIMING_CFG_1_REG_ADDR (0x0706) +#define GH3X2X_EFUSE_CTRL_WDATA_0_REG_ADDR (0x0708) +#define GH3X2X_EFUSE_CTRL_WDATA_1_REG_ADDR (0x070A) +#define GH3X2X_EFUSE_CTRL_WDATA_2_REG_ADDR (0x070C) +#define GH3X2X_EFUSE_CTRL_WDATA_3_REG_ADDR (0x070E) +#define GH3X2X_EFUSE_CTRL_RDATA_0_REG_ADDR (0x0710) +#define GH3X2X_EFUSE_CTRL_RDATA_1_REG_ADDR (0x0712) +#define GH3X2X_EFUSE_CTRL_RDATA_2_REG_ADDR (0x0714) +#define GH3X2X_EFUSE_CTRL_RDATA_3_REG_ADDR (0x0716) +#define GH3X2X_EFUSE_CTRL_STATUS_REG_ADDR (0x0718) +#define GH3X2X_EFUSE_CTRL_REG_MODE_REG_ADDR (0x071A) + + +extern GU8 g_uchGh3x2xAfeIntCallBackIsCalled; + + +extern void GH3X2X_AFE_SetNeedWakeUpGh3x2xFlag(GU8 uchFlag); +extern void hal_gh3x2x_afe_DelayUs(GU16 usUsec); +extern void hal_gh3x2x_afe_DelayMs(GU16 usMsec); + +extern void hal_gh3x2x_afe_i2c_init(void); +extern GU8 hal_gh3x2x_afe_i2c_write(GU8 device_id, const GU8 write_buffer[], GU16 length); +extern GU8 hal_gh3x2x_afe_i2c_read(GU8 device_id, const GU8 write_buffer[], GU16 write_length, GU8 read_buffer[], GU16 read_length); + +extern void hal_gh3x2x_afe_spi_init(void); +extern GU8 hal_gh3x2x_afe_spi_write(GU8 write_buffer[], GU16 length); +extern GU8 hal_gh3x2x_afe_spi_read(GU8 read_buffer[], GU16 length); +extern GU8 hal_gh3x2x_afe_spi_write_F1_and_read(GU8 read_buffer[], GU16 length); +extern void hal_gh3x2x_afe_spi_cs_ctrl(GU8 cs_pin_level); + +extern void hal_gh3x2x_afe_reset_pin_init(void); +extern void hal_gh3x2x_afe_reset_pin_ctrl(GU8 pin_level); + +extern void hal_gh3x2x_afe_int_init(void); +extern void hal_gh3x2x_afe_int_handler_call_back(void); + +extern void GH3X2X_AFE_Log(GCHAR *log_string); + + + + + +extern void GH3X2X_AFE_ChipPro(void); +extern void GH3X2X_AFE_Init(void); +extern void GH3X2X_AFE_StartSampling(GU8 SlotCfgEnable); +extern void GH3X2X_AFE_StopSampling(void); +extern void GH3X2X_AFE_SwitchSlot(GU8 SlotCfgEnable); + +extern void GH3x2xSetPpgCtrlReg(GU8 uchPpgCtrlReg, GU8 uchSlot, GU16 usValue); +extern GU16 GH3x2xGetPpgCtrlReg(GU8 uchPpgCtrlReg, GU8 uchSlot); + +GU16 GH3X2X_AFE_SetLedDrvCurrent(GU8 uchCurrent_mA, GU8 uchDrvNum, GS8 chECODE); +GF32 GH3X2X_AFE_GetLedDrvCurrent(GU16 usDrvCode, GU8 uchDrvNum, GS8 chECODE); +void GH3X2X_AFE_GetEfuseCode(GS8* pchLedDrvEcode,GS8* pchTiaEcode,GS8* pchEcgEcode); +GF32 GH3X2X_AFE_GetTiaCalCode(GS8 chECODE); +GF32 GH3X2X_AFE_GetEcgCalCode(GS8 chECODE); +GCHAR *GH3X2X_GetAfeLibVersion(void); +GU8 GH3X2X_AFE_GetChipId(void); +GS8 GH3X2X_AFE_CheckChipId(void); +void GH3X2X_AFE_LoadEfuse(GU8* puchEfuseBuffer,GU16 EfuseByteLen); +GS8 GH3X2X_AFE_CheckEfuseCrc(void); +void GH3X2X_AFE_WriteRegBitField(GU16 usRegAddr, GU8 uchLsb, GU8 uchMsb, GU16 usValue); +GU16 GH3X2X_AFE_ReadRegBitField(GU16 usRegAddr, GU8 uchLsb, GU8 uchMsb); +GU8 GH3X2X_AFE_GetSoftEvent(void); +void GH3X2X_AFE_SetSoftEvent(GU32 unEvent); +void GH3X2X_AFE_ClearSoftEvent(GU32 unEvent); +void GH3X2X_AFE_StartFunction(GU32 unFuncMode); + +void GH3x2x_AFESetAgcReg(GU8 uchAgcReg, GU8 uchSlot, GU16 usValue); +GU16 GH3x2x_AFEGetAgcReg(GU8 uchAgcReg, GU8 uchSlot); +void *GH3X2X_Memcpy(void *pDest, const void *pSrc, GU32 unByteSize); +void *GH3X2X_Memset(void* pDest, GCHAR chVal, GU32 unByteSize); +void GH3X2X_RecordAgcInfo(void); +void GH3X2X_UpdateAgcInfo(void); + +void gh3x2x_control(char* mode, uint8_t enable); + +/*********************************************** master-slaver interface lib function *********************************/ +#define GH3X2X_INFO_LOG(...) do {\ + char GH3X2X_AFE_GH3X2X_INFO_LOG[128] = {0};\ + snprintf(GH3X2X_AFE_GH3X2X_INFO_LOG, 128, __VA_ARGS__);\ + GH3X2X_AFE_Log((char *)GH3X2X_AFE_GH3X2X_INFO_LOG);\ + } while(0) + + + + +#endif + + + + + + + + + + + + + + + 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 index 000000000..50d3c8d4c --- /dev/null +++ b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_ecg.h @@ -0,0 +1,110 @@ +#ifndef __GH3X2X_AFE_ECG_H__ +#define __GH3X2X_AFE_ECG_H__ +#include "gh3x2x_afe_drv.h" + +/** + * @brief Downsample Function +*/ +typedef enum +{ + DOWNSAMPLE_ECG = 0, + DOWNSAMPLE_PPG, +}EmDownSampleFunction; + +/** + * @brief Downsample type +*/ +typedef enum +{ + DOWNSAMPLE_DEFAULT = 0, + DOWNSAMPLE_800HZ_TO_500HZ = 1, + DOWNSAMPLE_800HZ_TO_250HZ = 2, + DOWNSAMPLE_400HZ_TO_250HZ = 3, + DOWNSAMPLE_320HZ_TO_250HZ = 4, + DOWNSAMPLE_256HZ_TO_250HZ = 5, +}EmDownSampleType; + +typedef struct +{ + GS32 snRsXbuf[100/1 + 1]; + GS32 snBufHead; + GS32 snRsFirState; + GU32 nRsIcounter; + GU32 nRrsDcounter; + GU8 uchFlagFrPrev; + GU32 nRsLastRaw; + GU32 fDownStep; + GU8 uchLinearInterState; + GU8 uchLinearDataUpdate; +} STGh3x2xRsInfo; + + +typedef struct +{ + GS32 snCounter; + GS32 sniqCounter; + long long snniVal; + long long snnqVal; + GU8 uchFlagFrPrev; + GU8 uchFastRecoryHistory; + long long snniqAmp[5]; +} STGh3x2xSoftLeadOffDetInfo; + + +typedef struct +{ + GU8 uchRsFirOrder; + GU8 uchRsI; + GU8 uchRsD; + GU8 uchRsFirCoefNum; + GU8 uchRsBufSize; + GU8 uchRsEnable; + GU32 ufStep; + GS32* rsFirCoef; + GU8 uchDownSampleType; +} STGh3x2xDownSampleCalParamInfo; + +#define __SUPPORT_ECG_PPG_DOWNSAMP__ 0 + +/* ecg sample event type */ +#define ECG_SAMPLE_EVENT_TYPE_SAMPLE (0x01) /**< sample evt type sample config */ +#define ECG_SAMPLE_EVENT_TYPE_SLOT (0x02) /**< sample evt type slot config */ +#define ECG_SAMPLE_EVENT_TYPE_LEAD (0x04) /**< sample evt type lead irq */ +#define ECG_SAMPLE_EVENT_ALL (ECG_SAMPLE_EVENT_TYPE_SAMPLE | ECG_SAMPLE_EVENT_TYPE_SLOT | \ + ECG_SAMPLE_EVENT_TYPE_LEAD) /**< sample evt all */ + +#define GH3X2X_ECG_CTRL_REG_ADDR (0x01EA) +#define GH3X2X_ECG_FAST_RECV_EN_LSB (10) /**< ecg fast recv en lsb @GH3X2X_ECG_CTRL_REG */ +#define GH3X2X_ECG_FAST_RECV_EN_MSB (10) /**< ecg fast recv en msb @GH3X2X_ECG_CTRL_REG */ +/// ecg fast recover enable config +#define ECG_FAST_RECV_EN_CONFIG(en) do {\ + GH3X2X_AFE_WriteRegBitField(GH3X2X_ECG_CTRL_REG_ADDR, \ + GH3X2X_ECG_FAST_RECV_EN_LSB, GH3X2X_ECG_FAST_RECV_EN_MSB, (en)); \ + } while (0) + +#define GH3X2X_ADT_LEADON_CR_REG_ADDR (0x0400) +#define GH3X2X_ECG_LEAD_DET_EN_LSB (0) /**< ecg lead det en lsb @GH3X2X_ADT_LEADON_CR_REG */ +#define GH3X2X_ECG_LEAD_DET_EN_MSB (0) /**< ecg lead det en msb @GH3X2X_ADT_LEADON_CR_REG */ + + /// ecg lead detect enable config +#define ECG_LEAD_DET_EN_CONFIG(en) do {\ + GH3X2X_AFE_WriteRegBitField(GH3X2X_ADT_LEADON_CR_REG_ADDR, \ + GH3X2X_ECG_LEAD_DET_EN_LSB, GH3X2X_ECG_LEAD_DET_EN_MSB, (en)); \ + } while (0) + + +#define GET_ECG_LEAD_DET_EN_VAL() (GH3X2X_AFE_ReadRegBitField(GH3X2X_ADT_LEADON_CR_REG_ADDR, \ + GH3X2X_ECG_LEAD_DET_EN_LSB, GH3X2X_ECG_LEAD_DET_EN_MSB)) + + + +GU8 GH3X2X_AFE_EcgRsHandle(GU8* puchFifoBuffer, GU16* pusFifoBufferLen, GU8 uchEcgSlotNum, GU16 usEcgSampleRate); +GS32 GH3X2X_LeadOffDetectInit(void); +void GH3X2X_ECGResampleConfig(GU16 usEcgSampleRate); +void GH3X2X_PPGResampleConfig(GU16 usEcgSampleRate); +GU8 GH3X2X_LeadOffDetect(GU8* puchFifoBuffer, GU16* pusFifoBufferLen, GU8 uchEcgSlotNum); +void GH3X2X_AFE_Leadon_hook(void); +void GH3X2X_AFE_Leadoff_hook(void); +void GH3x2xSetEcgOutputFs(GU16 usEcgOutputFs); + +#endif 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 index 000000000..4ccc448a9 --- /dev/null +++ b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_user.h @@ -0,0 +1,52 @@ +/* + * @Author: penglei 1624952103@qq.com + * @Date: 2025-01-13 10:11:20 + * @LastEditors: penglei 1624952103@qq.com + * @LastEditTime: 2025-02-17 11:32:58 + * @FilePath: /sdk615/code/sdk/zhihui/drivers/ppg/gh3x2x/inc/gh3x2x_afe_user.h + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +#ifndef __GH3X2X_AFE_USER_H__ +#define __GH3X2X_AFE_USER_H__ +#include "gh3x2x_afe_drv.h" + + +#define GH3X2X_CHIP_ID GH3220_ID +#define GH3X2X_AFE_MP_MODE GH3X2X_MP_ENABLE + + +/****** communication type config **************************/ +#define GH3X2X_AFE_COM_INTERFACE_TYPE GH3X2X_AFE_COM_INTERFACE_I2C +#define GH3X2X_AFE_SPI_TYPE GH3X2X_AFE_SPI_SOFTWARE_CS + + +/****** I2C device id ***************************************/ +#define GH3X2X_AFE_I2C_DEVICE_CTRL_PIN_STATUS GH3X2X_PIN_STATUS_CS_0_MISO_0 + + + +/****** chip process type config ***************************/ +#define GH3X2X_AFE_PRO_TYPE GH3X2X_AFE_PRO_BY_INT + + + +/****** chip reset type config ***************************/ +#define GH3X2X_AFE_RESET_TYPE GH3X2X_AFE_RESET_SOFTWARE + +void hal_gh3x2x_afe_int_init(void); +void hal_gh3x2x_afe_int_deinit(void); + +#endif + + + + + + + + + + + + + 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 index 000000000..a5b762085 --- /dev/null +++ b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_afe_version.h @@ -0,0 +1,45 @@ + +/** + * @copyright (c) 2003 - 2022, Goodix Co., Ltd. All rights reserved. + * + * @file gh3x2x_afe_version.h + * + * @brief gh3x2x afe driver version and change log + * + * @par history: + * @verbatim + * Date Version Notes + * 2021-11-04 v3.2.4.2 1.add calibration code + * 2021-11-05 v3.2.4.4 1.fix Efuse calibration bug + * 2021-11-05 v3.2.4.5 1.add Ffuse Crc Process + * 2.add Check Chip Id process + * + * 2021-11-05 v3.2.4.6 1.update Head file + * 2021-11-05 v3.2.4.7 1.add ecg lead off det lib + * 2021-11-05 v3.2.4.8 1.add 5Hz adt + * 2023-12-06 v3.2.4.9 1.update ecg and agc + * @endverbatim */ + +#ifndef _GH3X2X_AFE_VERSION_H_ +#define _GH3X2X_AFE_VERSION_H_ + + +#define GH3X2X_DRV_MAJOR_VERSION_NUMBER 3 /**< major version number */ +#define GH3X2X_DRV_MINOR_VERSION_NUMBER 2 /**< minor version number */ +#define GH3X2X_DRV_REVISION_VERSION_NUMBER 4 /**< revision version number */ +#define GH3X2X_DRV_FIXED_VERSION_NUMBER 9 /**< fixed version number */ + +#define GH3X2X_TO_STRING(x) #x /**< number to char */ +#define GH3X2X_STR(x) GH3X2X_TO_STRING(x) /**< number to char */ + +/// makeup version string +#define GH3X2X_VERSION_STRING "v" GH3X2X_STR(GH3X2X_DRV_MAJOR_VERSION_NUMBER)\ + "." GH3X2X_STR(GH3X2X_DRV_MINOR_VERSION_NUMBER)\ + "." GH3X2X_STR(GH3X2X_DRV_REVISION_VERSION_NUMBER)\ + "." GH3X2X_STR(GH3X2X_DRV_FIXED_VERSION_NUMBER)\ + " (build:"__DATE__"_"__TIME__")" + + +#endif /* _GH3X2X_AFE_VERSION_H_ */ + +/********END OF FILE********* Copyright (c) 2003 - 2022, Goodix Co., Ltd. ********/ 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 index 000000000..f9485fc23 --- /dev/null +++ b/code/sdk/drivers/peripheral/ppg/gh3x2x/inc/gh3x2x_hal.h @@ -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 index 000000000..561922b67 --- /dev/null +++ b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_adt.c @@ -0,0 +1,156 @@ +/** + * @copyright (c) 2003 - 2022, Goodix Co., Ltd. All rights reserved. + * + * @file gh3x2x_afe_adt.c + * + * @brief gh3x2x led agc process functions + * + * @version + * + */ + + +#include +#include "gh3x2x_afe_adt.h" + +#define GH3X2X_MOVINF_AVA_WINDOW_SIZE 6 + + + +EMWearDetectType g_uchWearDetectStatus = WEAR_DETECT_WEAR_ON; + +GU32 g_punGh3x2xMovingAvaFilterBuf[GH3X2X_MOVINF_AVA_WINDOW_SIZE]; +GU8 g_uchGh3x2xMovingAvaFilterPointCnt; +GU8 g_Gh3x2xFilterHaveOutputFlag; + + + +void Gh3x2xMovingAvaFilterInit(void) +{ + g_uchGh3x2xMovingAvaFilterPointCnt = 0; + g_Gh3x2xFilterHaveOutputFlag = 0; +} +GU8 Gh3x2xMovingAvaFilter(GU32 *Rawdata, GU8 uchBypass) +{ + GU32 unSum = 0; + + if(uchBypass) + { + return 1; + } + else + { + if(g_uchGh3x2xMovingAvaFilterPointCnt >= GH3X2X_MOVINF_AVA_WINDOW_SIZE) + { + for(GU8 uchCnt = 1; uchCnt < GH3X2X_MOVINF_AVA_WINDOW_SIZE; uchCnt ++) + { + g_punGh3x2xMovingAvaFilterBuf[uchCnt - 1] = g_punGh3x2xMovingAvaFilterBuf[uchCnt]; + } + g_uchGh3x2xMovingAvaFilterPointCnt = GH3X2X_MOVINF_AVA_WINDOW_SIZE - 1; + } + g_punGh3x2xMovingAvaFilterBuf[g_uchGh3x2xMovingAvaFilterPointCnt] = Rawdata[0]; + g_uchGh3x2xMovingAvaFilterPointCnt ++; + + if(g_uchGh3x2xMovingAvaFilterPointCnt > 1) + { + for(GU8 uchCnt = 0; uchCnt < g_uchGh3x2xMovingAvaFilterPointCnt - 1; uchCnt ++) + { + unSum += g_punGh3x2xMovingAvaFilterBuf[uchCnt]; + } + Rawdata[0] = unSum/(g_uchGh3x2xMovingAvaFilterPointCnt - 1); + } + return 1; + } +} + + + + + + + + + +GS8 GH3x2xAdtAlgoInit(void) +{ + Gh3x2xMovingAvaFilterInit(); + g_uchWearDetectStatus = WEAR_DETECT_WEAR_ON; + return GH3X2X_AFE_RET_OK; +} +GS8 GH3x2xAdtAlgoDeinit(void) +{ + return GH3X2X_AFE_RET_OK; +} + +void GH3x2xAdtAlgoExe(GU32* punRawdata,EMWearStatus* pemWearStatus) +{ + + GU32 unCurrentFrameRawdata; + + GU32 unRawDataBeforeFilter; + unCurrentFrameRawdata = *punRawdata; + unRawDataBeforeFilter = *punRawdata; + GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe] punFrameRawdata = %d\r\n", unCurrentFrameRawdata); + + Gh3x2xMovingAvaFilter(&unCurrentFrameRawdata, 0); + GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe] punFrameRawdata after filter = %d\r\n", unCurrentFrameRawdata); + + + + GS32 snDiffRawdata; + + GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe] start check...\r\n"); + + snDiffRawdata = (GS32)unRawDataBeforeFilter - (GS32)unCurrentFrameRawdata; + + if(WEAR_DETECT_WEAR_ON == g_uchWearDetectStatus) + { + + *pemWearStatus = WEAR_STATUS_WEAR_OFF; + if((unRawDataBeforeFilter > __HARD_ADT_WAER_ON_THRD__)&&((snDiffRawdata > (GS32)__HARD_ADT_WAER_ON_DIFF_THRD__))) + { + *pemWearStatus = WEAR_STATUS_WEAR_ON; + g_uchWearDetectStatus = WEAR_DETECT_WEAR_OFF; + GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe] wear on !\r\n"); + } + else + { + if(unRawDataBeforeFilter > __HARD_ADT_WAER_ON_THRD__) + { + GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe] wear on condition is not match ! r = %d, r_diff = %d\r\n",unCurrentFrameRawdata,snDiffRawdata); + } + } + if(snDiffRawdata > 30000) + { + GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe]ppg 5Hz diff big event, Rawdata = %d, unRawdataDiff = %d\r\n",*punRawdata,snDiffRawdata); + } + } + else if(WEAR_DETECT_WEAR_OFF == g_uchWearDetectStatus) + { + *pemWearStatus = WEAR_STATUS_WEAR_ON; + if(unRawDataBeforeFilter < __HARD_ADT_WAER_OFF_THRD__) + { + *pemWearStatus = WEAR_STATUS_WEAR_OFF; + g_uchWearDetectStatus = WEAR_DETECT_WEAR_ON; + GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe]ppg 5Hz wear off event, Rawdata = %d, unRawdataDiff = %d\r\n",*punRawdata,snDiffRawdata); + GH3X2X_INFO_LOG("[GH3x2xAdtAlgoExe] wear off !\r\n"); + } + } +} + + + + + + + + + + + + + + + + + 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 index 000000000..7cfbe6d8e --- /dev/null +++ b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_agc.c @@ -0,0 +1,1131 @@ +/** + * @copyright (c) 2003 - 2022, Goodix Co., Ltd. All rights reserved. + * + * @file gh3x2x_afe_agc.c + * + * @brief gh3x2x led agc process functions + * + * @version + * + */ + + +#include +#include "gh3x2x_afe_agc.h" +#include "gh3x2x_afe_drv.h" + +#define __GH3X2X_AGC_GENERAL_TRIG_H_THD__ ((8388608 + 8388608*0.85f)) +#define __GH3X2X_AGC_GENERAL_TRIG_L_THD__ ((8388608 + 8388608*0.15f)) +#define __GH3X2X_AGC_GENERAL_IDEAL_VALUE__ ((8388608 + 8388608*0.56f)) +#define __GH3X2X_AGC_SPO2_TRIG_H_THD__ ((8388608 + 8388608*0.9f)) +#define __GH3X2X_AGC_SPO2_TRIG_L_THD__ ((8388608 + 8388608*0.5f)) +#define __GH3X2X_AGC_SPO2_IDEAL_VALUE__ ((8388608 + 8388608*0.7f)) +#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. + +//sub channel + +#define GH3X2X_NEW_AGC_SUB_CHNNL_ANAYLSIS_TIME_SEC 1 + +#define GH3X2X_AGC_REG_AGC_EN 0 +#define GH3X2X_AGC_REG_LED_CURRENT_UP_LIMIT 1 +#define GH3X2X_AGC_REG_LED_CURRENT_DOWN_LIMIT 2 +#define GH3X2X_AGC_REG_LED_CURRENT_DRV0 3 +#define GH3X2X_AGC_REG_LED_CURRENT_DRV1 4 +#define GH3X2X_AGC_REG_TIA_GAIN_RX0 5 +#define GH3X2X_AGC_REG_TIA_GAIN_RX1 6 +#define GH3X2X_AGC_REG_TIA_GAIN_RX2 7 +#define GH3X2X_AGC_REG_TIA_GAIN_RX3 8 +#define GH3X2X_AGC_REG_AGC_SRC 9 +#define GH3X2X_AGC_REG_BG_CANCEL_RX0 10 +#define GH3X2X_AGC_REG_BG_CANCEL_RX1 11 +#define GH3X2X_AGC_REG_BG_CANCEL_RX2 12 +#define GH3X2X_AGC_REG_BG_CANCEL_RX3 13 +#define GH3X2X_AGC_REG_SR_MULIPLIPER 14 +#define GH3X2X_AGC_ECG_PPG_RX_EN 15 + + +#if __SUPPORT_SOFT_AGC_CONFIG__ +//main chnl +STGh3x2xNewAgcMainChnlInfo g_pstGh3x2xNewAgcMainChnlInfoEntity[GH3X2X_NEW_AGC_SLOT_NUM_LIMIT]; +STGh3x2xNewAgcMainChnlMeanInfo g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[GH3X2X_NEW_AGC_SLOT_NUM_LIMIT]; +STGh3x2xNewAgcMainChnlIdaelAdjInfo g_pstGh3x2xNewAgcMainChnlIdaelAdjInfoEntity[GH3X2X_NEW_AGC_SLOT_NUM_LIMIT]; +//sub chnl +#if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0 +STGh3x2xNewAgcSubChnlRxInfo g_pstGh3x2xNewAgcSubChnlRxInfoEntity[GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT]; +#endif + + +STGh3x2xNewAgcMainChnlSat g_pstGh3x2xNewAgcMainChnlSat; +const GU32 g_unNewAgcSpo2Trig_H_Thd = __GH3X2X_AGC_SPO2_TRIG_H_THD__; +const GU32 g_unNewAgcSpo2Trig_L_Thd = __GH3X2X_AGC_SPO2_TRIG_L_THD__; +const GU32 g_unNewAgcSpo2Ideal_value = __GH3X2X_AGC_SPO2_IDEAL_VALUE__; +const GU32 g_unNewAgcGeneTrig_H_Thd = __GH3X2X_AGC_GENERAL_TRIG_H_THD__; +const GU32 g_unNewAgcGeneTrig_L_Thd = __GH3X2X_AGC_GENERAL_TRIG_L_THD__; +const GU32 g_unNewAgcGeneIdeal_value = __GH3X2X_AGC_GENERAL_IDEAL_VALUE__; +const GU8 g_uchAgcConvergence_level = __GH3X2X_AGC_CONVERGENCE_LEVEL__; + + +// soft agc parameter +static STSoftAgcCfg g_stSoftAgcCfg; +extern const GU16 g_usGH3x2xTiaGainR[]; + +GU8 g_Gh3x2xNewAgcInitFlag = 0; + +void GH3X2X_LedAgcPramConfig(STSoftAgcCfg* stSoftAgcCfg) +{ + g_stSoftAgcCfg.uchSlotxSoftAgcAdjEn = stSoftAgcCfg->uchSlotxSoftAgcAdjEn; //bit0: slot0 + g_stSoftAgcCfg.uchSlotxSoftBgAdjEn = stSoftAgcCfg->uchSlotxSoftBgAdjEn; + g_stSoftAgcCfg.stAmbSlotCtrl.uchAmbSampleEn = stSoftAgcCfg->stAmbSlotCtrl.uchAmbSampleEn; + g_stSoftAgcCfg.uchSpo2RedSlotCfgEn = stSoftAgcCfg->uchSpo2RedSlotCfgEn; + g_stSoftAgcCfg.uchSpo2IrSlotCfgEn = stSoftAgcCfg->uchSpo2IrSlotCfgEn; + g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg32uA = stSoftAgcCfg->stSoftAgcGainLimit.uchGainLimitBg32uA; + g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg64uA = stSoftAgcCfg->stSoftAgcGainLimit.uchGainLimitBg64uA; + g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg128uA = stSoftAgcCfg->stSoftAgcGainLimit.uchGainLimitBg128uA; + g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg256uA = stSoftAgcCfg->stSoftAgcGainLimit.uchGainLimitBg256uA; + g_stSoftAgcCfg.unAgcTrigThd_H = stSoftAgcCfg->unAgcTrigThd_H; + g_stSoftAgcCfg.unAgcTrigThd_L = stSoftAgcCfg->unAgcTrigThd_L; + g_stSoftAgcCfg.unAgcRestrainThd_H = stSoftAgcCfg->unAgcRestrainThd_H; + g_stSoftAgcCfg.unAgcRestrainThd_L = stSoftAgcCfg->unAgcRestrainThd_L; + + GH3X2X_INFO_LOG("uchSlotxSoftAgcAdjEn = 0x%X, uchSlotxSoftBgAdjEn = 0x%X\r\n",(int)g_stSoftAgcCfg.uchSlotxSoftAgcAdjEn,(int)g_stSoftAgcCfg.uchSlotxSoftBgAdjEn); + GH3X2X_INFO_LOG("uchAmbSampleEn = 0x%X, uchAmbSlot = 0x%X\r\n",(int)g_stSoftAgcCfg.stAmbSlotCtrl.uchAmbSampleEn,(int)g_stSoftAgcCfg.stAmbSlotCtrl.uchAmbSlot); + GH3X2X_INFO_LOG("uchSpo2RedSlotCfgEn = 0x%X,uchSpo2IrSlotCfgEn = 0x%X\r\n",(int)g_stSoftAgcCfg.uchSpo2RedSlotCfgEn,(int)g_stSoftAgcCfg.uchSpo2IrSlotCfgEn); + 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); + GH3X2X_INFO_LOG("unAgcTrigThd_H = %d,unAgcTrigThd_L = %d\r\n",(int)g_stSoftAgcCfg.unAgcTrigThd_H,(int)g_stSoftAgcCfg.unAgcTrigThd_L); + GH3X2X_INFO_LOG("unAgcRestrainThd_H = %d,unAgcRestrainThd_L = %d\r\n",(int)g_stSoftAgcCfg.unAgcRestrainThd_H,(int)g_stSoftAgcCfg.unAgcRestrainThd_L); + +} + +void GH3X2X_StoreRxTiaGainAfterAgc(GU8 uchGain, GU8 uchSlotNo, GU8 uchAdcNo, GU8* puchGainRecord) +{ + puchGainRecord[uchSlotNo*4 + uchAdcNo] = uchGain; +} + +void GH3X2X_StoreDrvCurrentAfterAgc(GU8 DrvCurrent, GU8 uchSlotNo, GU8 uchDrvIndex, GU16* puchDrvCurrentRecord) +{ + if(!uchDrvIndex) + { + puchDrvCurrentRecord[uchSlotNo] = (puchDrvCurrentRecord[uchSlotNo]&0xFF00)|DrvCurrent; + } + else + { + puchDrvCurrentRecord[uchSlotNo] = (puchDrvCurrentRecord[uchSlotNo]&0x00FF)|(DrvCurrent<<8); + } +} + + +void GH3x2xNewAgcModuleReset(void) +{ + g_Gh3x2xNewAgcInitFlag = 0; + GH3X2X_Memset((GU8*)g_pstGh3x2xNewAgcMainChnlInfoEntity,0,(GU16)GH3X2X_NEW_AGC_SLOT_NUM_LIMIT*sizeof(STGh3x2xNewAgcMainChnlInfo)); + GH3X2X_Memset( (GU8*)(&g_pstGh3x2xNewAgcMainChnlSat),0,sizeof(STGh3x2xNewAgcMainChnlSat)); // init variable + GH3X2X_Memset((GU8*)g_pstGh3x2xNewAgcMainChnlMeanInfoEntity,0,(GU16)GH3X2X_NEW_AGC_SLOT_NUM_LIMIT*sizeof(STGh3x2xNewAgcMainChnlMeanInfo)); + GH3X2X_Memset((GU8*)g_pstGh3x2xNewAgcMainChnlIdaelAdjInfoEntity,0,(GU16)GH3X2X_NEW_AGC_SLOT_NUM_LIMIT*sizeof(STGh3x2xNewAgcMainChnlIdaelAdjInfo)); + + #if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0 + Gh3x2xNewAgcSubChnlModuleReset(); + #endif +} + +void GH3X2X_NewAgcRecoveryAgcRegToMainChnl(GU8 uchSlotIdx, STGh3x2xNewAgcMainChnlInfo *pstAgcMainChnlInfo) +{ + GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_UP_LIMIT, uchSlotIdx, pstAgcMainChnlInfo ->uchBakRegLedCurrentMax); + GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_DOWN_LIMIT, uchSlotIdx, pstAgcMainChnlInfo ->uchBakRegLedCurrentMin); + GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_AGC_SRC, uchSlotIdx, pstAgcMainChnlInfo ->uchBakRegAgcSrc); + GH3X2X_INFO_LOG("[NewAgc] recover agc src:agc_src = %d, SlotNo = %d\r\n",pstAgcMainChnlInfo ->uchBakRegAgcSrc,uchSlotIdx); +} + +GU8 GH3X2X_NewAgcFindSubChnlSlotInfo(GU8 uchSlot) +{ + for(GU8 uchSlotCnt = 0; uchSlotCnt < GH3X2X_NEW_AGC_SLOT_NUM_LIMIT; uchSlotCnt ++) + { + STGh3x2xNewAgcMainChnlInfo *pstAgcMainChnlInfo = &g_pstGh3x2xNewAgcMainChnlInfoEntity[uchSlotCnt]; + if(pstAgcMainChnlInfo ->uchEnable) + { + if(uchSlot == (pstAgcMainChnlInfo ->uchSlotAdc >> 2)) + { + return uchSlotCnt; + } + } + } + return 0; +} + +GU16 GH3x2xCalTrigerUpLimitForBiggerGain(GU8 uchCurrentGain ,GU8 uchSlotNo) +{ + GU32 unTempRawdata; + GU32 unTempTrigThd_H; + + GU8 uchSlotCnt = GH3X2X_NewAgcFindSubChnlSlotInfo(uchSlotNo); + STGh3x2xNewAgcMainChnlInfo *pstAgcMainChnlInfo = &g_pstGh3x2xNewAgcMainChnlInfoEntity[uchSlotCnt]; + if(pstAgcMainChnlInfo->uchSpo2ChnlIndex) + { + unTempTrigThd_H = g_unNewAgcSpo2Trig_H_Thd; + }else + { + unTempTrigThd_H = g_unNewAgcGeneTrig_H_Thd; + } + + if(12 <= uchCurrentGain) + { + return 0xFFFF; + } + else + { + unTempRawdata = unTempTrigThd_H - 8388608; + unTempRawdata = 8388608 + (GU32)(((float)unTempRawdata)/(float)1.3*(float)g_usGH3x2xTiaGainR[uchCurrentGain]/(float)g_usGH3x2xTiaGainR[uchCurrentGain + 1]); + return unTempRawdata>>8; + } +} + + +#if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0 +void GH3x2xNewAgcSubChnlClearAnalysisCntAndSetGain(GU8 uchSlotNo, GU8 uchRxEn ,GU8 uchNextGain) +{ + for(GU8 uchRxCnt = 0; uchRxCnt < 4; uchRxCnt ++) + { + if(uchRxEn&(1 << uchRxCnt)) + { + for(GU8 uchChnlCnt = 0; uchChnlCnt < GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT; uchChnlCnt ++) + { + STGh3x2xNewAgcSubChnlRxInfo *pstSTGh3x2xNewAgcSubChnlRxInfo = &(g_pstGh3x2xNewAgcSubChnlRxInfoEntity[uchChnlCnt]); + if(pstSTGh3x2xNewAgcSubChnlRxInfo->uchEn) + { + if(((uchSlotNo << 2) + uchRxCnt) == pstSTGh3x2xNewAgcSubChnlRxInfo ->uchSlotAdcNo) + { + pstSTGh3x2xNewAgcSubChnlRxInfo ->usAnalysisCnt = 0; + if(0xFF != uchNextGain) + { + GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_TIA_GAIN_RX0 + uchRxCnt, uchSlotNo, 0); + pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain = uchNextGain; + pstSTGh3x2xNewAgcSubChnlRxInfo ->usTrigeUpLimitForBiggerGain = GH3x2xCalTrigerUpLimitForBiggerGain(uchNextGain,pstSTGh3x2xNewAgcSubChnlRxInfo->uchSlotAdcNo >> 2); + } + } + } + } + } + } +} +#endif + + +void GH3x2xNewAgcMeanInfoReset(GU8 uchSlotEnChange) +{ + for(GU8 uchSlotCnt = 0; uchSlotCnt < 8; uchSlotCnt++) + { + if( uchSlotEnChange & (1<> 2) & 0x0f); + GU8 uchEnable = g_pstGh3x2xNewAgcMainChnlInfoEntity[uchAgcSlotCnt].uchEnable; + if( uchEnable ) + { + if( uchSlotIdx == uchSlotCnt) + { + g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[uchAgcSlotCnt].usAnalysisCnt = 0; + #if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0 + GH3x2xNewAgcSubChnlClearAnalysisCntAndSetGain(uchSlotIdx, 0x0F, 0xFF); //clear all rx analysis cnt in this slot + #endif + } + } + } + } + } +} + +GU8 GH3x2xGetDrvCurrent(GU8 uchSlotIdx ,GU8 uchAgcEn) +{ + GU8 uchTempDrv; + if(2 == uchAgcEn) + { + uchTempDrv = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_DRV1, uchSlotIdx); + } + else + { + uchTempDrv = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_DRV0, uchSlotIdx); + } + return uchTempDrv; +} + +void GH3x2xNewAgcChnlInfoInit(STGh3x2xAgcInfo *STGh3x2xAgcInfo) +{ + if(0 == GH3X2X_NEW_AGC_SLOT_NUM_LIMIT) + { + return; + } + if(0 == g_Gh3x2xNewAgcInitFlag) + { + GU8 uchNewAgcSlotCnt = 0; + for(GU8 uchSlotCnt = 0; uchSlotCnt < 8; uchSlotCnt ++) + { + if((g_stSoftAgcCfg.uchSlotxSoftAgcAdjEn & (1 << uchSlotCnt))) + { + if(uchNewAgcSlotCnt < GH3X2X_NEW_AGC_SLOT_NUM_LIMIT) + { + g_pstGh3x2xNewAgcMainChnlInfoEntity[uchNewAgcSlotCnt].uchEnable = 1; + g_pstGh3x2xNewAgcMainChnlInfoEntity[uchNewAgcSlotCnt].uchSlotAdc = (uchSlotCnt << 2); + + /******* slot function Distinguish START******************************************************/ + if((g_stSoftAgcCfg.uchSpo2RedSlotCfgEn & (1 << uchSlotCnt))||(g_stSoftAgcCfg.uchSpo2IrSlotCfgEn & (1 << uchSlotCnt))) + { + g_pstGh3x2xNewAgcMainChnlInfoEntity[uchNewAgcSlotCnt].uchSpo2ChnlIndex = 1; + GH3X2X_INFO_LOG("[NewAgc] uchNewAgcSpo2SlotCnt = %d\r\n",uchNewAgcSlotCnt); + } + /******* slot function Distinguish END******************************************************/ + GH3X2X_INFO_LOG("[NewAgc] uchNewAgcSlotCnt = %d\r\n",uchNewAgcSlotCnt); + uchNewAgcSlotCnt ++; + } + else + { + GH3X2X_INFO_LOG("[NewAgc] error !!! main chnl info is no enough! \r\n"); + while(1); + } + } + } + g_Gh3x2xNewAgcInitFlag = 1; + } + + for(GU8 uchSlotCnt = 0; uchSlotCnt < GH3X2X_NEW_AGC_SLOT_NUM_LIMIT; uchSlotCnt ++) + { + STGh3x2xNewAgcMainChnlInfo *pstAgcMainChnlInfo = &g_pstGh3x2xNewAgcMainChnlInfoEntity[uchSlotCnt]; + //GH3X2X_INFO_LOG_PARAM("AGC_InitValue %d: Enable = %d, AgcAdjEn = %d\r\n",uchSlotCnt, pstAgcMainChnlInfo->uchEnable,g_stSoftAgcCfg.uchSlotxSoftAgcAdjEn); + if(pstAgcMainChnlInfo->uchEnable) + { + GU8 uchSlotIdx; + uchSlotIdx = pstAgcMainChnlInfo ->uchSlotAdc >> 2; + //GH3X2X_INFO_LOG_PARAM("AGC_InitFlag%d: SlotCfgX=%d, Vaule = %d\r\n",uchSlotCnt, uchSlotIdx, pstAgcMainChnlInfo->uchHaveBakRegFlag); + if(0 == pstAgcMainChnlInfo ->uchHaveBakRegFlag) + { + GU8 uchBgCancel; + GU8 uchGainLimit; + GU16 usSampleRate; + GU16 usEcgPpgRxEn; + + //bak reg + pstAgcMainChnlInfo ->uchBakRegAgcEn = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_AGC_EN, uchSlotIdx); + pstAgcMainChnlInfo ->uchBakRegAgcSrc = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_AGC_SRC, uchSlotIdx); + pstAgcMainChnlInfo ->uchSlotAdc = (uchSlotIdx << 2) + pstAgcMainChnlInfo ->uchBakRegAgcSrc; + pstAgcMainChnlInfo ->uchBakRegLedCurrentMax = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_UP_LIMIT, uchSlotIdx); + pstAgcMainChnlInfo ->uchBakRegLedCurrentMin = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_DOWN_LIMIT, uchSlotIdx); + pstAgcMainChnlInfo ->uchBakTiaGain = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_TIA_GAIN_RX0 + pstAgcMainChnlInfo ->uchBakRegAgcSrc, uchSlotIdx); + pstAgcMainChnlInfo ->uchCurrentTiaGain = pstAgcMainChnlInfo ->uchBakTiaGain; + pstAgcMainChnlInfo ->uchCurrentDrv = GH3x2xGetDrvCurrent(uchSlotIdx, pstAgcMainChnlInfo->uchBakRegAgcEn); + //GH3X2X_StoreDrvCurrentAfterAgc(pstAgcMainChnlInfo ->uchCurrentDrv, uchSlotIdx,g_pstGh3x2xAgcInfo->uchDrvCurrentAfterSoftAgc); + uchBgCancel = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_BG_CANCEL_RX0 + pstAgcMainChnlInfo ->uchBakRegAgcSrc, uchSlotIdx); + GH3X2X_StoreRxTiaGainAfterAgc(pstAgcMainChnlInfo->uchBakTiaGain, uchSlotIdx, pstAgcMainChnlInfo->uchBakRegAgcSrc, STGh3x2xAgcInfo->uchTiaGainAfterSoftAgc); + if(0 == uchBgCancel) + { + uchGainLimit = g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg32uA; + } + else if(1 == uchBgCancel) + { + uchGainLimit = g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg64uA; + } + else if(2 == uchBgCancel) + { + uchGainLimit = g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg128uA; + } + else + { + uchGainLimit = g_stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg256uA; + } + GH3X2X_INFO_LOG("[NewAgc] uchGainLimit = %d, uchSlotIdx = %d\r\n",uchGainLimit, uchSlotIdx); + pstAgcMainChnlInfo ->uchTiaGainUpLimit = uchGainLimit; + usSampleRate = 1000/(GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_SR_MULIPLIPER, uchSlotIdx) + 1); + usEcgPpgRxEn = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_ECG_PPG_RX_EN, uchSlotIdx); + GH3X2X_INFO_LOG("[NewAgc] usEcgPpgRxEn = 0x%X\r\n",usEcgPpgRxEn); + if(usEcgPpgRxEn&0x0001) // ecg is enable + { + usEcgPpgRxEn = ((usEcgPpgRxEn>>1) & (~0x0008)); //clear RX3 enable bit + } + else + { + usEcgPpgRxEn = (usEcgPpgRxEn>>1); + } + usEcgPpgRxEn &= (~(1 << pstAgcMainChnlInfo ->uchBakRegAgcSrc)); //clear main channel RX enable bit + + g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[uchSlotCnt].usSampleRate = usSampleRate; //init + GH3X2X_INFO_LOG("[AgcInit] SlotCnt = %d, SampleRate = %d\r\n", uchSlotCnt, usSampleRate); + //sub channel slot +#if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0 + GH3x2xNewAgcSetNewSubChnl(uchSlotIdx,usEcgPpgRxEn,STGh3x2xAgcInfo); +#endif + pstAgcMainChnlInfo ->uchHaveBakRegFlag = 1; + GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_AGC_EN, uchSlotIdx, 0); // disable hardware agc + } + else + { + pstAgcMainChnlInfo ->uchCurrentTiaGain = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_TIA_GAIN_RX0 + pstAgcMainChnlInfo ->uchBakRegAgcSrc, uchSlotIdx); + pstAgcMainChnlInfo ->uchCurrentDrv = GH3x2xGetDrvCurrent(uchSlotIdx, pstAgcMainChnlInfo->uchBakRegAgcEn); + //GH3X2X_INFO_LOG_PARAM("Drv Gian inite read %d: IniteDrv = %d, IniteGain = %d\r\n",uchSlotIdx, pstAgcMainChnlInfo ->uchCurrentDrv, pstAgcMainChnlInfo ->uchCurrentTiaGain); + ////get initial DRV and current in case them change before StartSampling() +// GH3X2X_NewAgcRecoveryAgcRegToMainChnl(uchSlotIdx,pstAgcMainChnlInfo); + } + } + } +} + + +GU32 GH32x2xMedSel(GU32 unData0, GU32 unData1, GU32 unData2) +{ + if((unData0 >= unData1)&&(unData0 <= unData2)) + { + return unData0; + } + if((unData0 >= unData2)&&(unData0 <= unData1)) + { + return unData0; + } + if((unData1 >= unData0)&&(unData1 <= unData2)) + { + return unData1; + } + if((unData1 >= unData2)&&(unData1 <= unData0)) + { + return unData1; + } + return unData2; +} + +float GH3X2X_CalcfRelativeVpp(GU32 unRawdata, GU8 uchDrv, GU8 uchGain) +{ + return ((float)unRawdata/(float)uchDrv/(float)g_usGH3x2xTiaGainR[uchGain]); +} + +void GH3X2X_StoreTiaGainAfterAgc(GU16 usGainRegValue, GU8 uchSlotNo, GU8* puchGainRecord) +{ + for(GU8 uchAdcCnt = 0; uchAdcCnt < 4; uchAdcCnt ++) + { + puchGainRecord[uchSlotNo*4 + uchAdcCnt] = (usGainRegValue>>(uchAdcCnt*4))&0x000F; + GH3X2X_INFO_LOG("StoreTiaGainAfterAgc slot no = %d, adc no = %d, usGainRegValue = %d\r\n", uchSlotNo,uchAdcCnt,usGainRegValue); + } +} + +void GH3X_AgcGetThreshold( GU8 uchSpo2ChnlIndex, GU32* punTemp_H_Thd, GU32* punTemp_L_Thd ) +{ + if(uchSpo2ChnlIndex) // is spo2 slot + { + *punTemp_H_Thd = g_unNewAgcSpo2Trig_H_Thd; + *punTemp_L_Thd = g_unNewAgcSpo2Trig_L_Thd; + }else + { + *punTemp_H_Thd = g_unNewAgcGeneTrig_H_Thd; + *punTemp_L_Thd = g_unNewAgcGeneTrig_L_Thd; + } +} + +#if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0 +void Gh3x2xNewAgcSubChnlModuleReset(void) +{ + #if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0 + GH3X2X_Memset((GU8*)g_pstGh3x2xNewAgcSubChnlRxInfoEntity,0,(GU16)GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT*sizeof(STGh3x2xNewAgcSubChnlRxInfo)); + #endif +} + +GU8 GH3x2xNewAgcSetNewSubChnl(GU8 uchSlotNo, GU8 uchRxEn, STGh3x2xAgcInfo *STGh3x2xAgcInfo) +{ + GU8 uchSetSuccess = 1; + for(GU8 uchRxCnt = 0; uchRxCnt < 4; uchRxCnt ++) + { + if(uchRxEn&(1 << uchRxCnt)) + { + uchSetSuccess = 0; + for(GU8 uchChnlCnt = 0; uchChnlCnt < GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT; uchChnlCnt ++) + { + STGh3x2xNewAgcSubChnlRxInfo *pstSTGh3x2xNewAgcSubChnlRxInfo = &(g_pstGh3x2xNewAgcSubChnlRxInfoEntity[uchChnlCnt]); + if(0 == pstSTGh3x2xNewAgcSubChnlRxInfo->uchEn) + { + pstSTGh3x2xNewAgcSubChnlRxInfo->uchEn = 1; + pstSTGh3x2xNewAgcSubChnlRxInfo->uchSlotAdcNo = (uchSlotNo << 2) + uchRxCnt; + //read current gain + pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain = GH3x2x_AFEGetAgcReg(GH3X2X_AGC_REG_TIA_GAIN_RX0 + uchRxCnt, uchSlotNo); + GH3X2X_INFO_LOG("[NewAgc] Sub chnl current Gain = %d, Slot = %d, Rx = %d\r\n",pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain,uchSlotNo,uchRxCnt); + pstSTGh3x2xNewAgcSubChnlRxInfo ->usTrigeUpLimitForBiggerGain = GH3x2xCalTrigerUpLimitForBiggerGain(pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain, uchSlotNo); + GH3X2X_INFO_LOG("[NewAgc] usTrigeUpLimitForBiggerGain = %d, Slot = %d, Rx = %d\r\n",((GU32)pstSTGh3x2xNewAgcSubChnlRxInfo ->usTrigeUpLimitForBiggerGain)<<8,uchSlotNo,uchRxCnt); + GH3X2X_StoreRxTiaGainAfterAgc(pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain, uchSlotNo, uchRxCnt, STGh3x2xAgcInfo->uchTiaGainAfterSoftAgc); + uchSetSuccess = 1; + break; + } + } + if(0 == uchSetSuccess) + { + GH3X2X_INFO_LOG("[NewAgc] Set new sub chnl fail !!! Slot = %d, Rx = %d\r\n",uchSlotNo,uchRxCnt); + while(1); + } + } + } + return uchSetSuccess; +} +#endif + +#if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0 +void GH3X2X_NewAgcSubChnlGainAdj(GU8* puchReadFifoBuffer, GU16 usFifoLen, STGh3x2xAgcInfo *STGh3x2xAgcInfo) +{ + for(GU8 uchChnlCnt = 0; uchChnlCnt < GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT; uchChnlCnt ++) + { + GU16 usAnalysisDiscardLen; + GU16 usAnalysisEndLen; + GU8 uchSlotCnt; + GU8 uchSlotIdx; + GU8 uchAdcNo; + GU32 unTempTrigThd_L; + GU32 unTempTrigThd_H; + STGh3x2xNewAgcSubChnlRxInfo *pstSTGh3x2xNewAgcSubChnlRxInfo = &(g_pstGh3x2xNewAgcSubChnlRxInfoEntity[uchChnlCnt]); + uchSlotIdx = pstSTGh3x2xNewAgcSubChnlRxInfo ->uchSlotAdcNo >> 2; + uchAdcNo = pstSTGh3x2xNewAgcSubChnlRxInfo ->uchSlotAdcNo&0x03; + uchSlotCnt = GH3X2X_NewAgcFindSubChnlSlotInfo(uchSlotIdx); + GU16 usSampleRate = g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[uchSlotCnt].usSampleRate; + GU8 uchTiaGainLimit = g_pstGh3x2xNewAgcMainChnlInfoEntity[uchSlotCnt].uchTiaGainUpLimit; + usAnalysisDiscardLen = (usSampleRate<<1)/5; // 2/5 Fs + usAnalysisEndLen = usAnalysisDiscardLen + usSampleRate * GH3X2X_NEW_AGC_SUB_CHNNL_ANAYLSIS_TIME_SEC; + + GH3X_AgcGetThreshold(g_pstGh3x2xNewAgcMainChnlInfoEntity[uchSlotCnt].uchSpo2ChnlIndex,&unTempTrigThd_H, &unTempTrigThd_L); + + if(pstSTGh3x2xNewAgcSubChnlRxInfo ->uchEn) + { + // prevent unRawdataSum(GU32) overflow + if( (usAnalysisEndLen - usAnalysisDiscardLen) > 200 ) + { + usAnalysisDiscardLen = usAnalysisEndLen - 200; // maximum number of accumulated rawdata is 200 + } + + for (GU16 usIndex = 0; usIndex < usFifoLen; usIndex += GH3X2X_AFE_FIFO_RAWDATA_SIZE) + { + GU32 unFifoVal; + GU8 uchSlotAdcNo; + GU32 unDataRaw; + unFifoVal = GH3X2X_AFE_MAKEUP_DWORD(puchReadFifoBuffer[usIndex], puchReadFifoBuffer[usIndex + 1], + puchReadFifoBuffer[usIndex + 2], puchReadFifoBuffer[usIndex + 3]); + uchSlotAdcNo = ((unFifoVal >> 27)&0x0000001F); + unDataRaw = GH3X2X_RAWDATA_CLEAR_ALL_FLAG(unFifoVal); + if(uchSlotAdcNo == pstSTGh3x2xNewAgcSubChnlRxInfo ->uchSlotAdcNo) + { + if(usAnalysisDiscardLen == pstSTGh3x2xNewAgcSubChnlRxInfo->usAnalysisCnt) //init + { + pstSTGh3x2xNewAgcSubChnlRxInfo ->unRawdataSum = 0; + pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastLastRawdata = unDataRaw; + pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastRawdata = unDataRaw; + pstSTGh3x2xNewAgcSubChnlRxInfo ->usMoreThanUpLimitPointCnt = 0; + pstSTGh3x2xNewAgcSubChnlRxInfo ->usMoreThanUpLimitPointCntForBiggerGain = 0; + } + if(pstSTGh3x2xNewAgcSubChnlRxInfo->usAnalysisCnt < usAnalysisEndLen) //analysising + { + GU32 unTempRawdata = GH32x2xMedSel(pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastLastRawdata, pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastRawdata, unDataRaw); + if(usAnalysisDiscardLen == pstSTGh3x2xNewAgcSubChnlRxInfo->usAnalysisCnt) + { + GH3X2X_INFO_LOG("[NewAgc] sub chnl unTempRawdata = %d, Slot = %d, rx = %d\r\n",unTempRawdata, uchSlotIdx, uchAdcNo); + } + pstSTGh3x2xNewAgcSubChnlRxInfo ->unRawdataSum += unTempRawdata; + if(unTempRawdata > unTempTrigThd_H) + { + pstSTGh3x2xNewAgcSubChnlRxInfo->usMoreThanUpLimitPointCnt ++; + } + if((unTempRawdata >> 8) > pstSTGh3x2xNewAgcSubChnlRxInfo->usTrigeUpLimitForBiggerGain) + { + pstSTGh3x2xNewAgcSubChnlRxInfo->usMoreThanUpLimitPointCntForBiggerGain ++; + } + pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastLastRawdata = pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastRawdata; + pstSTGh3x2xNewAgcSubChnlRxInfo ->unLastRawdata = unDataRaw; + pstSTGh3x2xNewAgcSubChnlRxInfo->usAnalysisCnt ++; + } + else //anlysis finished + { + GU32 unAvaRawdata; + GU16 unRealAnaylsisNum = usAnalysisEndLen - usAnalysisDiscardLen; + GU8 uchNextGain = 0xFF; + GU8 uchCurrentGain = pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain; + unAvaRawdata = pstSTGh3x2xNewAgcSubChnlRxInfo ->unRawdataSum/unRealAnaylsisNum; + GH3X2X_INFO_LOG("[NewAgc] sub chnl rawdata ava = %d,DownLimit = %d, Slot = %d, rx = %d\r\n",unAvaRawdata, unTempTrigThd_L,uchSlotIdx, uchAdcNo); + GH3X2X_INFO_LOG("[NewAgc] usMoreThanUpLimitPointCnt = %d,UpLimit = %d, Slot = %d, rx = %d\r\n",pstSTGh3x2xNewAgcSubChnlRxInfo ->usMoreThanUpLimitPointCnt, unTempTrigThd_H,uchSlotIdx, uchAdcNo); + GH3X2X_INFO_LOG("[NewAgc] usMoreThanUpLimitPointCntForBiggerGain = %d,UpLimit = %d, Slot = %d, rx = %d\r\n",pstSTGh3x2xNewAgcSubChnlRxInfo ->usMoreThanUpLimitPointCntForBiggerGain, ((GU32)pstSTGh3x2xNewAgcSubChnlRxInfo->usTrigeUpLimitForBiggerGain)<<8, uchSlotIdx, uchAdcNo); + if(pstSTGh3x2xNewAgcSubChnlRxInfo ->usMoreThanUpLimitPointCnt > (unRealAnaylsisNum >> 3)) // 1/8 points is bigger than trige up limit + { + if(uchCurrentGain > 0) + { + uchNextGain = uchCurrentGain - 1; + } + } + if((pstSTGh3x2xNewAgcSubChnlRxInfo ->usMoreThanUpLimitPointCntForBiggerGain < (unRealAnaylsisNum >> 3))&&(unAvaRawdata < unTempTrigThd_L)) + { + if(uchCurrentGain < uchTiaGainLimit) + { + uchNextGain = uchCurrentGain + 1; + } + } + if(0xFF != uchNextGain) + { + GH3X2X_INFO_LOG("[NewAgc] sub chnl gain change: NewGain = %d, OldGain = %d, Slot = %d, rx = %d\r\n",uchNextGain,uchCurrentGain, uchSlotIdx, uchAdcNo); + GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_TIA_GAIN_RX0 + uchAdcNo, uchSlotIdx, uchNextGain); + pstSTGh3x2xNewAgcSubChnlRxInfo ->uchCurrentGain = uchNextGain; + pstSTGh3x2xNewAgcSubChnlRxInfo ->usTrigeUpLimitForBiggerGain = GH3x2xCalTrigerUpLimitForBiggerGain(uchNextGain, uchSlotIdx); + GH3X2X_StoreRxTiaGainAfterAgc(uchNextGain, uchSlotIdx, uchAdcNo, STGh3x2xAgcInfo->uchTiaGainAfterSoftAgc); + } + pstSTGh3x2xNewAgcSubChnlRxInfo->usAnalysisCnt = 0; + } + } + } + } + } +} + +#endif + + +/*********************************************self-test function start*****************************************/ +#define GH3X2X_SPO2_SELF_TEST 0 + +#if GH3X2X_SPO2_SELF_TEST +const GU32 g_uchSpo2AgcSelftestSlotAdc = 0x01; //slot0, adc1 +const GU32 g_usSpo2AgcFifoLen = 25*4; +const GU32 g_unSpo2AgcRawdata[] = +{ + 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 +}; + +GU8 g_uchSpo2AgcFifoBuffer[4*100]; + +void GH3X2X_Spo2AgcFifoDataGen(void) +{ + for (GU16 usIndex = 0; usIndex < g_usSpo2AgcFifoLen; usIndex += GH3X2X_AFE_FIFO_RAWDATA_SIZE) + { + if(usIndex >= sizeof(g_uchSpo2AgcFifoBuffer)) + { + break; + } + g_uchSpo2AgcFifoBuffer[usIndex + 0] = (g_uchSpo2AgcSelftestSlotAdc<<3); + g_uchSpo2AgcFifoBuffer[usIndex + 1] = (0x000000FF&(g_unSpo2AgcRawdata[usIndex/4] >> 16)); + g_uchSpo2AgcFifoBuffer[usIndex + 2] = (0x000000FF&(g_unSpo2AgcRawdata[usIndex/4] >> 8)); + g_uchSpo2AgcFifoBuffer[usIndex + 3] = (0x000000FF&(g_unSpo2AgcRawdata[usIndex/4] >> 0)); + } +} +#endif +/*********************************************self-test function end*****************************************/ + + +/**************************************************************** +* Description: calculate mean value of main channel +* Input: rawdata +* Return: none +******************************************************************/ +static void GH3X2X_NewAgcMainChnlMeanValueCal(GU8* puchReadFifoBuffer, GU16 usFifoLen, GU32 *punRawdataMean, GU8 *pAdjFlag) +{ + for(GU8 uchSlotCnt = 0; uchSlotCnt < GH3X2X_NEW_AGC_SLOT_NUM_LIMIT; uchSlotCnt ++) + { + STGh3x2xNewAgcMainChnlInfo *pstAgcMainChnlInfo = &g_pstGh3x2xNewAgcMainChnlInfoEntity[uchSlotCnt]; + GU8 uchMainChnlSlotAdcNo = pstAgcMainChnlInfo ->uchSlotAdc; + + if(pstAgcMainChnlInfo ->uchEnable) // is enabled slot + { + GU32 unTemp_Trig_H_Thd; + GU32 unTemp_Trig_L_Thd; + GU32 unTemp_Ideal_value; + GU16 usAnalysisEndLen; + GU16 usAnalysisDiscardLenAdjust = 0; + GU16 usAnalysisDiscardLenTrige; + GU32 TrigeMean = 0; + + if(pstAgcMainChnlInfo->uchSpo2ChnlIndex) // is spo2 slot + { + unTemp_Ideal_value= g_unNewAgcSpo2Ideal_value; + }else + { + unTemp_Ideal_value= g_unNewAgcGeneIdeal_value; + } + GH3X_AgcGetThreshold( pstAgcMainChnlInfo->uchSpo2ChnlIndex, &unTemp_Trig_H_Thd, &unTemp_Trig_L_Thd); + + STGh3x2xNewAgcMainChnlMeanInfo *pstNewAgcMainChnlMeanInfo = &g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[uchSlotCnt]; + STGh3x2xNewAgcMainChnlIdaelAdjInfo *pstNewAgcMainChnlIdaelAdjInfo = &g_pstGh3x2xNewAgcMainChnlIdaelAdjInfoEntity[uchSlotCnt]; + GU16 usSampleRate = pstNewAgcMainChnlMeanInfo->usSampleRate; + usAnalysisEndLen = (usSampleRate<<2)/5; // 4/5 Fs + usAnalysisDiscardLenTrige = (usSampleRate<<1)/5; // drop the first 2/5 data + //have agc motion at last fifo read period or first init + if(pstNewAgcMainChnlMeanInfo->uchHaveAgcAtLastReadPrd) + { + usAnalysisDiscardLenAdjust = (usSampleRate<<1)/5; // drop the first 2/5 data + //// After AGC, the previous data is drop to calcluate precise mean + if(!pstNewAgcMainChnlMeanInfo->uchDropFlag) + { // The frame count is only cleared for the first time to prevent data num cannot to be SampleRate + pstNewAgcMainChnlMeanInfo->usAnalysisCnt = 0; + pstNewAgcMainChnlMeanInfo->uchDropFlag = 1; + } + } + //The data fluctuates when initializing the early stage + if(!pstNewAgcMainChnlIdaelAdjInfo->uchIniteFirst) + { + usAnalysisDiscardLenAdjust = (usSampleRate<<1)/5; // drop the first 2/5 data + } + + // prevent unSumAdjust(GU32) overflow + if( (usAnalysisEndLen - usAnalysisDiscardLenAdjust) > 200 ) + { + usAnalysisDiscardLenAdjust = usAnalysisEndLen - 200; // maximum number of accumulated rawdata is 200 + } + + if( (usAnalysisEndLen - usAnalysisDiscardLenTrige) > 200 ) + { + usAnalysisDiscardLenTrige = usAnalysisEndLen - 200; + } + + for (GU16 usIndex = 0; usIndex < usFifoLen; usIndex += GH3X2X_AFE_FIFO_RAWDATA_SIZE) + { + GU32 unFifoVal; + GU8 uchSlotAdcNo; + GU32 unDataRaw; + unFifoVal = GH3X2X_AFE_MAKEUP_DWORD(puchReadFifoBuffer[usIndex], puchReadFifoBuffer[usIndex + 1], + puchReadFifoBuffer[usIndex + 2], puchReadFifoBuffer[usIndex + 3]); + uchSlotAdcNo = ((unFifoVal >> 27)&0x0000001F); + unDataRaw = GH3X2X_RAWDATA_CLEAR_ALL_FLAG(unFifoVal); + //GH3X2X_INFO_LOG_SPO2("uchSlotAdcNo = %d\r\n",uchSlotAdcNo); + //GH3X2X_INFO_LOG_SPO2("uchMainChnlSlotAdcNo = %d\r\n",uchMainChnlSlotAdcNo); + if(uchSlotAdcNo == uchMainChnlSlotAdcNo) + { + // begin Saturation judge + { + GU16 usSat_Check_Num_Max = (usSampleRate<<2) + usSampleRate; //// 5 seconds window + g_pstGh3x2xNewAgcMainChnlSat.Sat_CheckCnt[uchSlotCnt]++; + if( unDataRaw > unTemp_Trig_H_Thd) + { + g_pstGh3x2xNewAgcMainChnlSat.Sat_cnt[uchSlotCnt]++; + } + //// as soon as posible set the Saturation flag + if( g_pstGh3x2xNewAgcMainChnlSat.Sat_cnt[uchSlotCnt] >= (usSat_Check_Num_Max>>4) ) // about 8% of all checked data + { + g_pstGh3x2xNewAgcMainChnlSat.Sat_flag |= (1<= usSat_Check_Num_Max ) + { + g_pstGh3x2xNewAgcMainChnlSat.Sat_cnt[uchSlotCnt] = 0; + g_pstGh3x2xNewAgcMainChnlSat.Sat_CheckCnt[uchSlotCnt] = 0; + } + } + // end Saturation judge + + //// begin mean calculate + ////GH3X2X_INFO_LOG_PARAM("slot = %d, uchSlotAdcNo = %d\r\n",uchSlotCnt,uchSlotAdcNo); + + if(usAnalysisDiscardLenAdjust == pstNewAgcMainChnlMeanInfo->usAnalysisCnt) //init + { + pstNewAgcMainChnlMeanInfo->unSumAdjust = 0; + pstNewAgcMainChnlMeanInfo->unMaxRawdata = 0; + pstNewAgcMainChnlMeanInfo->unMinRawdata = 16777216; + } + + if(usAnalysisDiscardLenTrige == pstNewAgcMainChnlMeanInfo->usAnalysisCnt) //init + { + pstNewAgcMainChnlMeanInfo->unSumTrige = 0; + } + + if(pstNewAgcMainChnlMeanInfo->usAnalysisCnt < usAnalysisEndLen) //analysising + { + pstNewAgcMainChnlMeanInfo->unSumAdjust += unDataRaw; + pstNewAgcMainChnlMeanInfo->unSumTrige += unDataRaw; + pstNewAgcMainChnlMeanInfo->usAnalysisCnt++; + pstNewAgcMainChnlMeanInfo->unMaxRawdata = ((unDataRaw > pstNewAgcMainChnlMeanInfo->unMaxRawdata)? unDataRaw: pstNewAgcMainChnlMeanInfo->unMaxRawdata ); // Max of rawdata + pstNewAgcMainChnlMeanInfo->unMinRawdata = ((unDataRaw < pstNewAgcMainChnlMeanInfo->unMinRawdata)? unDataRaw: pstNewAgcMainChnlMeanInfo->unMinRawdata ); // Min of rawdata + } + else //anlysis finished calculate mean and judge whether AGC + { + // mean value to calculate gain and current + if(usAnalysisEndLen > usAnalysisDiscardLenAdjust) + { + punRawdataMean[uchSlotCnt] = pstNewAgcMainChnlMeanInfo->unSumAdjust/(usAnalysisEndLen - usAnalysisDiscardLenAdjust); + TrigeMean = pstNewAgcMainChnlMeanInfo->unSumTrige / (usAnalysisEndLen - usAnalysisDiscardLenTrige); + }else // The normal case will not be executed, in case the division by 0 in abnormal case + { + punRawdataMean[uchSlotCnt] = unDataRaw; + TrigeMean = unDataRaw; + } + pstNewAgcMainChnlMeanInfo ->unRawdataMean = punRawdataMean[uchSlotCnt]; + pstNewAgcMainChnlMeanInfo->usAnalysisCnt=0; + // The mean calculation key variable is cleared (Prevent mean calculation from being too small:Accumulation lost some data, but numble of raw is all) + usAnalysisDiscardLenAdjust = 0; + pstNewAgcMainChnlMeanInfo->uchHaveAgcAtLastReadPrd = 0; // clear after caculate mean!!! + //// end mean calculate + + ///////////////////// whether AGC and adjust the mean value to calculate gain and current + if( (TrigeMean < unTemp_Trig_L_Thd) || (TrigeMean > unTemp_Trig_H_Thd) ) + { + *pAdjFlag |= (1<unMaxRawdata > unTemp_Trig_H_Thd) + { + /////////// Pay attention to data truncation, use 64-bi + unTempMean = (GS64)unTemp_Ideal_value*(GS64)(pstNewAgcMainChnlMeanInfo->unMaxRawdata)/15099494; // to adjust the max data to (0.8*2^23 + 2^23) + *pAdjFlag |= (1< unTemp_Ideal_value) + { + // adjust the mean value to calculate gain and current (reduce the DC amount) + punRawdataMean[uchSlotCnt] = ( (punRawdataMean[uchSlotCnt]>unTempMean)? punRawdataMean[uchSlotCnt]:unTempMean ); + *pAdjFlag |= (1<unMaxRawdata > unTemp_Trig_H_Thd) + { + punRawdataMean[uchSlotCnt] = unTempMean; // Increasing the mean value to reduce the DC amount + } + } + //////////////////////////////////////////////////// + //////////////begin ideal value adjust + if( (!((*pAdjFlag) & (1<unRawdataMean< ((unTemp_Ideal_value*(g_uchAgcConvergence_level-1))/g_uchAgcConvergence_level) ) \ + || (pstNewAgcMainChnlMeanInfo->unRawdataMean > ((unTemp_Ideal_value*(g_uchAgcConvergence_level+1))/g_uchAgcConvergence_level))) \ + &&( 10*pstNewAgcMainChnlMeanInfo->unMaxRawdata< 12*pstNewAgcMainChnlMeanInfo->unMinRawdata) ) + { + if( !pstNewAgcMainChnlIdaelAdjInfo->uchIniteFirst ) //// Inite First time + { + pstNewAgcMainChnlIdaelAdjInfo->uchIniteFirst = 1; + *pAdjFlag |= (1<uchSeconsCnt++; + if(pstNewAgcMainChnlIdaelAdjInfo->uchSeconsCnt >= 19) + { + *pAdjFlag |= (1<uchSeconsCnt = 0; + } + } + } + else + { + pstNewAgcMainChnlIdaelAdjInfo->uchSeconsCnt = 0; + } + } + else + { + pstNewAgcMainChnlIdaelAdjInfo->uchSeconsCnt = 0; + } + pstNewAgcMainChnlIdaelAdjInfo->uchIniteFirst = 1; //// Must be set to 1 after the first second!!! + ////end ideal value adjust + //GH3X2X_INFO_LOG_PARAM("Mean cal: Slot_num = %d, Rawmean = %d, Adjmean = %d, TrigeMean = %d, AdjFlag= %d\r\n", uchSlotCnt,pstNewAgcMainChnlMeanInfo->unRawdataMean, punRawdataMean[uchSlotCnt]); + //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); + //GH3X2X_INFO_LOG_PARAM("Ideal adjust: SeconsCnt = %d\r\n", pstNewAgcMainChnlIdaelAdjInfo->uchSeconsCnt); + //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); + g_pstGh3x2xNewAgcMainChnlSat.Sat_flag &= (~(1<uchBakTiaGain; + GU8 uchGainUpLimit = pstAgcMainChnlInfo->uchTiaGainUpLimit; + GU8 uchLedCurrentMin = pstAgcMainChnlInfo->uchBakRegLedCurrentMin; + GU8 uchLedCurrentMax = pstAgcMainChnlInfo->uchBakRegLedCurrentMax; + GU8 uchCurrentDrv = pstAgcMainChnlInfo->uchCurrentDrv; + GU8 uchCurrentTiaGain = pstAgcMainChnlInfo->uchCurrentTiaGain; + + GU8 uchNewGain = uchDefaultGain; + GU32 unIdealRawdata_no; + GU32 unTempDrvCurrent; + GU8 uchChangeFlag = 0; //bit0: drv current flag bit1: gain flag + GU8 uchCalFinish = 0; + GU32 unTrigUpLimit; + GU8 unCalNum = 12; + + if(0 != pstAgcMainChnlInfo->uchSpo2ChnlIndex) // is spo2 slot + { + unTrigUpLimit = g_unNewAgcSpo2Trig_H_Thd; + unIdealRawdata_no= g_unNewAgcSpo2Ideal_value - 8388608; + }else + { + unTrigUpLimit = g_unNewAgcGeneTrig_H_Thd; + unIdealRawdata_no = g_unNewAgcGeneIdeal_value - 8388608; + } + + //GH3X2X_INFO_LOG_PARAM("Drv cal: UpLimit = %d, Mean = %d, LastMean = %d\r\n",unTrigUpLimit, pstMainChnlExtralInfo->unRawdataMean, pstMainChnlExtralInfo->unLastRawdataMean); + // reduce rawdata as soon as posible + if((unTrigUpLimit < pstMainChnlExtralInfo->unRawdataMean)&&(unTrigUpLimit < pstMainChnlExtralInfo->unLastRawdataMean)&&(uchCurrentTiaGain > 0)) + { + uchNewGain = 0; + unTempDrvCurrent = uchLedCurrentMin; + uchCalFinish = 1; + } + pstMainChnlExtralInfo ->unLastRawdataMean = pstMainChnlExtralInfo ->unRawdataMean; + + if(0 == uchCalFinish) + { + //remove offset + if(CurRawdata > (8388608 + 2048)) //// Can't open DC Cance !!! + { + CurRawdata -= 8388608; + } + else + { + //The value may be less than 2^23, preventing division by 0 + CurRawdata = 2048; // Take an appropriately large number to prevent calculated DRV current overflow 32bit + } + //Rawdata stretch (The principle of magnification: the mean divided by the ideal target value is the data reduction factor ) + if(CurRawdata < 8000000) + { + } + else if(CurRawdata < 8100000) + { + CurRawdata = 8000000 + (CurRawdata - 8000000)*6; + } + else if(CurRawdata < 8200000) + { + CurRawdata = 8000000 + ((CurRawdata - 8000000)<<3); + } + else + { + // The more saturated the data, the bigger the stretch, the key is that the data is really saturated + CurRawdata = 8000000 + (CurRawdata - 8000000)*14; // Blood oxygen drops 1 times, heart rate drops 2.5 times + } + + //find new drv current and gain + do + { + unTempDrvCurrent = (GS64)(((GU32)uchCurrentDrv*(GU32)g_usGH3x2xTiaGainR[uchCurrentTiaGain]))* \ + (GS64)unIdealRawdata_no/g_usGH3x2xTiaGainR[uchNewGain]/CurRawdata; + +#if 0 + //GH3X2X_INFO_LOG_PARAM("Drv cal %d: CurrentDrv = %d, CurrentGain = %d, IdealRawdata_no = %d\r\n",uchMainChnlInfoIndex, uchCurrentDrv, uchCurrentTiaGain, unIdealRawdata_no); + //GH3X2X_INFO_LOG_PARAM("Drv cal %d: unTempDrvCurrent = %d, uchNewGain = %d, Meanraw = %d, CurRawdata = %d\r\n",uchMainChnlInfoIndex,unTempDrvCurrent, uchNewGain, pstMainChnlExtralInfo->unRawdataMean, CurRawdata); +#endif + + if(unTempDrvCurrent > uchLedCurrentMax) //drv is too big, need increase gain + { + if(uchNewGain < uchGainUpLimit) + { + uchNewGain ++ ; + } + else + { + unTempDrvCurrent = uchLedCurrentMax; + break; + } + } + else if(unTempDrvCurrent < uchLedCurrentMin) //drv is too small, need dncrease gain + { + if(uchNewGain > 0) + { + uchNewGain -- ; + } + else + { + unTempDrvCurrent = uchLedCurrentMin; + break; + } + } + else //got right drv + { + break; + } + unCalNum --; + } + while (unCalNum); + } + + puchIdealDrvCurrent[0] = (GU8)unTempDrvCurrent; + puchIdealGain[0] = (GU8)uchNewGain; + + if(puchIdealDrvCurrent[0] != uchCurrentDrv) + { + uchChangeFlag |= 0x01; + //GH3X2X_INFO_LOG_PARAM("Drv change %d: CurrentDrv = %d, IdealDrv = %d\r\n",uchMainChnlInfoIndex, uchCurrentDrv, puchIdealDrvCurrent[0]); + } + if(puchIdealGain[0] != uchCurrentTiaGain) + { + uchChangeFlag |= 0x02; + //GH3X2X_INFO_LOG_PARAM("Gain change %d: CurrentGain = %d, IdealGain = %d\r\n",uchMainChnlInfoIndex, uchCurrentTiaGain, puchIdealGain[0]); + } + + return uchChangeFlag; +} + +GU8 NewAgcMainChelFlag = 0; + +void GH3X2X_NewAgcMainChnlPro(GU8* puchReadFifoBuffer, GU16 usFifoLen, STGh3x2xAgcInfo *STGh3x2xAgcInfo) +{ + GU32 unNewAgcRawdataMeanChnl[8] = {0}; + GU8 uchAdjFlag = 0; // Local variables used as judgments must be initialized to 0 + GU8 uchNewDrvCurrent; + GU8 uchNewGain; + GU8 uchChangeFlag = 0; //bit0: drv current flag bit1: gain flag + + if(0 == GH3X2X_NEW_AGC_SLOT_NUM_LIMIT) + { + return; + } + +#if GH3X2X_SPO2_SELF_TEST + + GH3X2X_Spo2AgcFifoDataGen(); + puchReadFifoBuffer = g_uchSpo2AgcFifoBuffer; + usFifoLen = g_usSpo2AgcFifoLen; +#endif + + + GH3X2X_NewAgcMainChnlMeanValueCal( puchReadFifoBuffer,usFifoLen,unNewAgcRawdataMeanChnl,&uchAdjFlag); // caculate mean and whther adjust gain current + + for(GU8 uchSlotCnt = 0; uchSlotCnt < GH3X2X_NEW_AGC_SLOT_NUM_LIMIT; uchSlotCnt ++) + { + if( uchAdjFlag & (1<uchSlotAdc >> 2) & 0x0f); + if(uchChangeFlag&0x02) //write tia gain to chip + { + GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_TIA_GAIN_RX0 + pstAgcMainChnlInfo ->uchBakRegAgcSrc, uchSlotIdx, uchNewGain); + pstAgcMainChnlInfo->uchCurrentTiaGain = uchNewGain; + GH3X2X_StoreRxTiaGainAfterAgc(uchNewGain, uchSlotIdx, pstAgcMainChnlInfo ->uchBakRegAgcSrc, STGh3x2xAgcInfo->uchTiaGainAfterSoftAgc); + } + if(uchChangeFlag&0x01) //write drv current to chip + { + //change drv0/1 + pstAgcMainChnlInfo ->uchCurrentDrv = uchNewDrvCurrent; + + if((pstAgcMainChnlInfo ->uchBakRegAgcEn)&0x01) + { + GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_DRV0, uchSlotIdx, uchNewDrvCurrent); + GH3X2X_StoreDrvCurrentAfterAgc(pstAgcMainChnlInfo ->uchCurrentDrv, uchSlotIdx,0,STGh3x2xAgcInfo->uchDrvCurrentAfterSoftAgc); + } + if((pstAgcMainChnlInfo ->uchBakRegAgcEn)&0x02) + { + GH3x2x_AFESetAgcReg(GH3X2X_AGC_REG_LED_CURRENT_DRV1, uchSlotIdx, uchNewDrvCurrent); + GH3X2X_StoreDrvCurrentAfterAgc(pstAgcMainChnlInfo ->uchCurrentDrv, uchSlotIdx,1,STGh3x2xAgcInfo->uchDrvCurrentAfterSoftAgc); + } + #if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0 + GH3x2xNewAgcSubChnlClearAnalysisCntAndSetGain(uchSlotIdx, 0x0F, 0xFF); //clear all rx analysis cnt in this slot + #endif + } + if(uchChangeFlag) + { + g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[uchSlotCnt].uchHaveAgcAtLastReadPrd = 1; // current or gain change at last time + g_pstGh3x2xNewAgcMainChnlMeanInfoEntity[uchSlotCnt].uchDropFlag = 0; + NewAgcMainChelFlag |= (1<> (8*uchByteCnt))&0x00FF); + usByteOffset = (usRegPosi * 2) + uchByteCnt; + if(usByteOffset < sizeof(g_stSoftAgcCfg)) + { + GH3X2X_Memcpy(((GU8 *)(&g_stSoftAgcCfg)) + usByteOffset, (GU8*)(&uchByteVal), 1); + } + } +} + +/** + * @fn void GH3X2X_LedAgcReset(void) + * + * @brief reset agc parameter + * + * @attention None + * + * @param[in] None + * @param[out] None + * + * @return None + */ +void GH3X2X_LedAgcReset(void) +{ + GH3X2X_Memset(&g_stSoftAgcCfg, 0, sizeof(STSoftAgcCfg)); + GH3x2xNewAgcModuleReset(); +} + +/** + * @fn void GH3X2X_LedAgcProcess(GU8* puchReadFifoBuffer, GU16 usFifoLen) + * + * @brief led agc process function + * + * @attention None + * + * @param[in] puchReadFifoBuffer pointer to read fifo data buffer + * @param[in] usFifoLen read fifo data buffer length + * @param[out] None + * + * @return None + */ + +void GH3X2X_LedAgcProcess(GU8* puchReadFifoBuffer, GU16 usFifoLen, STGh3x2xAgcInfo *STGh3x2xAgcInfo) +{ + GH3X2X_UpdateAgcInfo(); + if(usFifoLen==0) + { + return; + } + + GH3X2X_NewAgcMainChnlPro(puchReadFifoBuffer, usFifoLen,STGh3x2xAgcInfo); + +#if GH3X2X_NEW_AGC_SUB_CHNL_NUM_LIMIT > 0 + GH3X2X_NewAgcSubChnlGainAdj(puchReadFifoBuffer, usFifoLen,STGh3x2xAgcInfo); +#endif + +} +#endif +#endif +/********END OF FILE********* Copyright (c) 2003 - 2022, Goodix Co., Ltd. ********/ 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 index 000000000..211b1e080 --- /dev/null +++ b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_demo.c @@ -0,0 +1,104 @@ +/* + * @Author: penglei 1624952103@qq.com + * @Date: 2025-01-13 11:45:20 + * @LastEditors: penglei 1624952103@qq.com + * @LastEditTime: 2025-02-12 10:50:38 + * @FilePath: /sdk615/code/sdk/zhihui/drivers/ppg/gh3x2x/src/gh3x2x_afe_demo.c + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +#include "gh3x2x_afe_ecg.h" +#include "gh3x2x_afe_adt.h" +#include "gh3x2x_afe_agc.h" +#include "gh3x2x_afe_demo.h" + + + +GU32 g_unFuncMode = GH3X2X_NO_FUNCTION; + + + +void GH3X2X_AFE_StartFunction(GU32 unFuncMode) +{ + //红外佩戴检测 + if(unFuncMode & (GH3X2X_FUNCTION_ADT)) + { + GH3x2xAdtAlgoInit(); + GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_SLOT_EN_ADDR,GH3X2X_ADT_SLOT_NUM,GH3X2X_ADT_SLOT_NUM,1); + } + + //心电图 + if(unFuncMode & (GH3X2X_FUNCTION_ECG)) + { + GH3X2X_LeadOffDetectInit(); + GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_SLOT_EN_ADDR,GH3X2X_ECG_SLOT_NUM,GH3X2X_ECG_SLOT_NUM,1); + ECG_FAST_RECV_EN_CONFIG(1); + } + + if(g_unFuncMode == GH3X2X_NO_FUNCTION) + { + GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_START_ADDR,GH3X2X_AFE_REG_START_LSB,GH3X2X_AFE_REG_START_MSB,1); + } + g_unFuncMode |= unFuncMode; + +} + + +void GH3X2X_AFE_StopFunction(GU32 unFuncMode) +{ + if(unFuncMode & (GH3X2X_FUNCTION_ADT)) + { + GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_SLOT_EN_ADDR,GH3X2X_ADT_SLOT_NUM,GH3X2X_ADT_SLOT_NUM,0); + GH3x2xAdtAlgoDeinit(); + } + if(unFuncMode & (GH3X2X_FUNCTION_ECG)) + { + GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_SLOT_EN_ADDR,GH3X2X_ECG_SLOT_NUM,GH3X2X_ECG_SLOT_NUM,0); + ECG_FAST_RECV_EN_CONFIG(0); + + } + g_unFuncMode &= (~unFuncMode); + if(g_unFuncMode == GH3X2X_NO_FUNCTION) + { + GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_START_ADDR,GH3X2X_AFE_REG_START_LSB,GH3X2X_AFE_REG_START_MSB,0); + } + +} + + +void GH3X2X_AFE_Leadon_hook(void) +{ + GH3X2X_AFE_StartFunction(GH3X2X_FUNCTION_ECG); +} + +void GH3X2X_AFE_Leadoff_hook(void) +{ + GH3X2X_AFE_StopFunction(GH3X2X_FUNCTION_ECG); + ECG_LEAD_DET_EN_CONFIG(0);// enable lead detect + ECG_LEAD_DET_EN_CONFIG(1);// enable lead detect + +} + + +void GH3X2X_DemoLedAgcPramConfig(void) +{ + static STSoftAgcCfg stSoftAgcCfg; + + stSoftAgcCfg.uchSlotxSoftAgcAdjEn = 1; //bit0-bit7: slot0 -slot7 + stSoftAgcCfg.uchSlotxSoftBgAdjEn = 0; + stSoftAgcCfg.stAmbSlotCtrl.uchAmbSampleEn = 0; + stSoftAgcCfg.uchSpo2RedSlotCfgEn = 2; //bit0-bit7: slot0 -slot7 for spo2 red + stSoftAgcCfg.uchSpo2IrSlotCfgEn = 4; //bit0-bit7: slot0 -slot7 for spo2 ir + stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg32uA = 8; + stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg64uA = 6; + stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg128uA = 5; + stSoftAgcCfg.stSoftAgcGainLimit.uchGainLimitBg256uA = 4; + stSoftAgcCfg.unAgcTrigThd_H = (GU32)(8388608 + 8388608*0.85f); + stSoftAgcCfg.unAgcTrigThd_L = (GU32)(8388608 + 8388608*0.15f); + stSoftAgcCfg.unAgcRestrainThd_H = 12868608; + stSoftAgcCfg.unAgcRestrainThd_L = 10692608; + + GH3X2X_LedAgcPramConfig(&stSoftAgcCfg); +} + + + 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 index 000000000..5fe8a90d6 --- /dev/null +++ b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_drv.c @@ -0,0 +1,1541 @@ +/** + * @copyright (c) 2019 - 2024, Goodix Co., Ltd. All rights reserved. + * + * @file gh3x2x_afe_drv.c + * + * @brief gh3x2x driver example code + * + * @author Gooidx Iot Team + * + * @attention + * This file just show how to init and control gh3x2x sampling. + */ +#include "stdio.h" +#include "gh3x2x_afe_drv.h" +#include "gh3x2x_afe_user.h" +#include "gh3x2x_afe_ecg.h" +#include "gh3x2x_afe_agc.h" +#include "gh3x2x_afe_adt.h" +#include "gh3x2x_afe_demo.h" + +#include "custom_utils.h" + + +#define SWAP_SIZE_OF_GU16 (2) +#define SWAP_INDEX_OF_NEXT_BYTE (1) + +#define GH3X2X_I2C_BUS I2C_BUS_2 + +//extern void GH3X2X_SoftLedADJAutoADJInt(void); +//extern void GH3X2X_LedAgcProcess(GU8* puchReadFifoBuffer, GU16 usFifoLen); +//extern void GH3X2X_LedAgcReset(void); +//extern void GH3X2X_LedAgcPramWrite(void); +//extern void GH3X2X_LedAgcInit(void); + +STGh3x2xAgcInfo g_stGh3x2xAgcInfo = {0}; +STGh3x2xAgcInfo *g_pstGh3x2xAgcInfo = &g_stGh3x2xAgcInfo; + +GU8 g_uchNeedWakeUpGh3x2xAfe = 1; // 0: do not need wake up gh3x2x 1: need wake up gh3x2x +GU8 g_uchGh3x2xAfeIntCallBackIsCalled = 0; //0: no new interrupt 1: have new interrupt + +/*********************************************** reg cfg package *******************************************/ +STGH3X2X_AFEReg GH3X2X_AFE_reg_list[] = +{ +// {0x0000, 0x0610}, {0x0004, 0x001F}, {0x0006, 0x0001}, {0x000A, 0x0010}, {0x000E, 0x000D}, {0x0100, 0x0100}, +// {0x010A, 0x27FC}, {0x0110, 0x0F65}, {0x0114, 0x00AA}, {0x011E, 0x021F}, {0x0120, 0x041F}, {0x0122, 0x137F}, +// {0x0126, 0xC77C}, {0x012C, 0x0C10}, {0x012E, 0x2222}, {0x0130, 0x00AA}, {0x013A, 0x010C}, {0x013C, 0x0400}, +// {0x01EC, 0x027C}, {0x01EE, 0x00AC}, {0x0200, 0x0120}, {0x0208, 0x0551}, {0x0280, 0x0A00}, {0x0282, 0xF530}, +// {0x0284, 0x9388}, {0x0286, 0xC45C}, {0x0288, 0xA328}, {0x0408, 0x0001}, {0x0410, 0x49F0}, {0x0412, 0x0082}, +// {0x0414, 0x49F0}, {0x0416, 0x0082}, {0x0422, 0x0011}, {0x0424, 0x0901}, {0x0426, 0x0108}, {0x0428, 0x0102}, +// {0x0502, 0x4360}, {0x0504, 0x000A}, {0x0588, 0x0008}, {0x0692, 0x0233}, {0x0694, 0x0400}, {0x0698, 0x2310}, +// {0x0700, 0x0000}, + +// {0x0000, 0x0602}, {0x0004, 0x0013}, {0x0006, 0x0201}, {0x000A, 0x005F}, {0x000E, 0x000D}, {0x0074, 0x0048}, +// {0x0100, 0x0100}, {0x010A, 0x0462}, {0x010C, 0x0000}, {0x010E, 0x0000}, {0x0110, 0x0000}, {0x0120, 0x0400}, +// {0x0126, 0xC73C}, {0x0128, 0x0404}, {0x012A, 0x0404}, {0x012C, 0x0C10}, {0x012E, 0x2222}, {0x0130, 0x00AA}, +// {0x0136, 0x00FF}, {0x013A, 0x000C}, {0x013C, 0x0400}, {0x01EA, 0x0033}, {0x01EC, 0x0030}, {0x01EE, 0x0098}, +// {0x0200, 0x1020}, {0x0402, 0x5555}, {0x0404, 0x4120}, {0x0406, 0x0041}, {0x0408, 0x0001}, {0x0410, 0x49F0}, +// {0x0412, 0x0082}, {0x0414, 0x49F0}, {0x0416, 0x0082}, {0x0422, 0x0011}, {0x0424, 0x0901}, {0x0426, 0x0109}, +// {0x0428, 0x0108}, {0x0480, 0x6550}, {0x0502, 0x4C66}, {0x0506, 0x0020}, {0x0588, 0x0008}, {0x0692, 0x0233}, +// {0x0694, 0x0404}, {0x0698, 0x3310}, {0x069A, 0x1101}, {0x0700, 0x0000}, {0x0400, 0x5557}, {0x1000, 0x0000}, +// {0x1002, 0x3197}, {0x1004, 0x0000}, {0x1006, 0x6C91}, {0x1008, 0x2CE1}, {0x100A, 0x0001}, {0x10E0, 0x0000}, +// {0x10E2, 0xFFFF}, {0x10E4, 0xFFFF}, {0x10E6, 0xFFFF}, {0x10E8, 0x0202}, {0x10EA, 0x0202}, {0x10EC, 0x0202}, +// {0x10EE, 0x0202}, {0x1120, 0x005F}, {0x1122, 0x0005}, {0x1124, 0x0000}, {0x2000, 0x0004}, {0x2002, 0x2A22}, +// {0x2004, 0x3A32}, {0x20EE, 0x0001}, {0x20F0, 0x001C}, {0x2880, 0x0005}, {0x288E, 0x00FA}, {0x3000, 0x0101}, +// {0x3002, 0x0000}, {0x3004, 0x49F0}, {0x3006, 0x0082}, {0x4500, 0x46C9}, {0x4502, 0x0F0F}, {0x4504, 0x0002}, +// {0x4506, 0x0140}, {0xFFFF, 0x0001} + + {0x0000, 0x0610}, {0x0004, 0x001F}, {0x0006, 0x0001}, {0x000A, 0x0050}, {0x000E, 0x000D}, {0x0100, 0x0100}, + {0x010A, 0x277C}, {0x0110, 0x0D14}, {0x0112, 0x5555}, {0x0114, 0x00AA}, {0x011E, 0x0019}, {0x0120, 0x0400}, + {0x0122, 0x0CFF}, {0x0126, 0xC704}, {0x0128, 0x0001}, {0x012A, 0x0000}, {0x012C, 0x0C10}, {0x012E, 0x4442}, + {0x0130, 0x0002}, {0x0136, 0x0003}, {0x013A, 0x010C}, {0x013C, 0x0400}, {0x01EC, 0x0136}, {0x01EE, 0x00AC}, + {0x0200, 0x0120}, {0x0208, 0x0551}, {0x0280, 0x0A00}, {0x0282, 0xF530}, {0x0284, 0x9388}, {0x0286, 0xC45C}, + {0x0288, 0xA328}, {0x0408, 0x0001}, {0x0410, 0x49F0}, {0x0412, 0x0082}, {0x0414, 0x49F0}, {0x0416, 0x0082}, + {0x0422, 0x0011}, {0x0424, 0x0901}, {0x0426, 0x0108}, {0x0428, 0x0102}, {0x0502, 0x4F60}, {0x0504, 0x000A}, + {0x0588, 0x0008}, {0x0692, 0x0233}, {0x0694, 0x0400}, {0x0698, 0x2310}, {0x0700, 0x0000}, {0x1000, 0x0000}, + {0x1002, 0x3197}, {0x1004, 0x0000}, {0x1006, 0x6904}, {0x1008, 0x2AF6}, {0x100A, 0x0001}, {0x10E0, 0x0000}, + {0x10E2, 0xFFFF}, {0x10E4, 0xFFFF}, {0x10E6, 0xFFFF}, {0x10E8, 0x0202}, {0x10EA, 0x0202}, {0x10EC, 0x0202}, + {0x10EE, 0x0202}, {0x1100, 0x0004}, {0x1102, 0x0000}, {0x1120, 0x0050}, {0x1122, 0x0005}, {0x1124, 0x0000}, + {0x1140, 0x0000}, {0x1142, 0x00C8}, {0x1144, 0x0001}, {0x1160, 0x0001}, {0x1162, 0x0000}, {0x1164, 0x0000}, + {0x1166, 0x4568}, {0x1168, 0xCCCC}, {0x116A, 0x00EC}, {0x116C, 0x3333}, {0x116E, 0x0093}, {0x1170, 0x5C00}, + {0x1172, 0x00C4}, {0x1174, 0x2800}, {0x1176, 0x00A3}, {0x2000, 0x0001}, {0x2002, 0x0022}, {0x2022, 0x0004}, + {0x2024, 0x0901}, {0x2026, 0x1911}, {0x2880, 0x0005}, {0x2882, 0x0019}, {0x3000, 0x0001}, {0x3002, 0x0000}, + {0x3004, 0x49F0}, {0x3006, 0x0082}, {0xFFFF, 0x0001} +}; + +GU16 GH3X2X_AFE_reg_list_len = sizeof(GH3X2X_AFE_reg_list) / sizeof(GH3X2X_AFE_reg_list[0]); + + +void GH3X2X_SwapLittleBigEndianData(GU8 *puchDataBuffer, GU16 usDataLength) +{ + GU16 usIndex = 0; + + for (usIndex = 0; usIndex < (usDataLength / SWAP_SIZE_OF_GU16); usIndex++) + { + puchDataBuffer[usIndex * SWAP_SIZE_OF_GU16] ^= \ + puchDataBuffer[usIndex * SWAP_SIZE_OF_GU16 + SWAP_INDEX_OF_NEXT_BYTE]; + puchDataBuffer[usIndex * SWAP_SIZE_OF_GU16 + SWAP_INDEX_OF_NEXT_BYTE] ^= \ + puchDataBuffer[usIndex * SWAP_SIZE_OF_GU16]; + puchDataBuffer[usIndex * SWAP_SIZE_OF_GU16] ^= \ + puchDataBuffer[usIndex * SWAP_SIZE_OF_GU16 + SWAP_INDEX_OF_NEXT_BYTE]; + } +} + + +#if ( GH3X2X_AFE_COM_INTERFACE_TYPE == GH3X2X_AFE_COM_INTERFACE_SPI ) + + +/** + * @fn static void GH3X2X_AFE_SpiSendCmd(GU8 uchCmd) + * + * @brief Send cmd via spi + * + * @attention None + * + * @param[in] uchCmd spi cmd + * @param[out] None + * + * @return None + */ +#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS) +void GH3X2X_AFE_SpiSendCmd(GU8 uchCmd) +{ + GU8 uchBuffArr[1]; + + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW); + uchBuffArr[0] = uchCmd; + hal_gh3x2x_afe_spi_write(uchBuffArr, 1); + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US); +} +#endif + +#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_HARDWEAR_CS) +void GH3X2X_AFE_SpiSendCmdHardwareCs(GU8 uchCmd) +{ + GU8 uchBuffArr[1]; + uchBuffArr[0] = uchCmd; + hal_gh3x2x_afe_spi_write(uchBuffArr, 1); +} +#endif + + +/** + * @fn static void GH3X2X_AFE_SpiWriteReg(GU16 usRegAddr, GU16 usRegValue) + * + * @brief Write register via spi + * + * @attention None + * + * @param[in] usRegAddr register addr + * @param[in] usRegValue register data + * @param[out] None + * + * @return None + */ +#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS) +void GH3X2X_AFE_SpiWriteReg(GU16 usRegAddr, GU16 usRegValue) +{ + GU8 uchBuffArr[7]; + + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW); + uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_WRITE; + uchBuffArr[1] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegAddr); + uchBuffArr[2] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegAddr); + uchBuffArr[3] = 0; + uchBuffArr[4] = 2; + uchBuffArr[5] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegValue); + uchBuffArr[6] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegValue); + hal_gh3x2x_afe_spi_write(uchBuffArr, 7); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US); + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US); +} +#endif + +#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_HARDWEAR_CS) +void GH3X2X_AFE_SpiWriteRegHardwareCs(GU16 usRegAddr, GU16 usRegValue) +{ + GU8 puchWriteBuf[7]; + puchWriteBuf[0] = 0xF0; + puchWriteBuf[1] = usRegAddr>>8; + puchWriteBuf[2] = usRegAddr&0x00FF; + puchWriteBuf[3] = 0; + puchWriteBuf[4] = 2; + puchWriteBuf[5] = usRegValue>>8; + puchWriteBuf[6] = usRegValue&0x00FF; + hal_gh3x2x_afe_spi_write(puchWriteBuf, 7); +} +#endif + + + + + + + +/** + * @fn static GU16 GH3X2X_AFE_SpiReadReg(GU16 usRegAddr) + * + * @brief Read register via spi + * + * @attention None + * + * @param[in] usRegAddr register addr + * @param[out] None + * + * @return register data + */ + +#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS) +GU16 GH3X2X_AFE_SpiReadReg(GU16 usRegAddr) +{ + GU8 uchBuffArr[3] = {0}; + + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW); + uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_WRITE; + uchBuffArr[1] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegAddr); + uchBuffArr[2] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegAddr); + hal_gh3x2x_afe_spi_write(uchBuffArr, 3); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US); + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US); + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW); + uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_READ; + hal_gh3x2x_afe_spi_write(uchBuffArr, 1); + hal_gh3x2x_afe_spi_read(uchBuffArr, 2); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US); + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US); + return GH3X2X_AFE_MAKEUP_WORD(uchBuffArr[0], uchBuffArr[1]); +} + +/** + * @fn void GH3X2X_SpiReadRegs(GU16 usRegAddr, GU16 *pusRegValueBuffer, GU8 uchLen) + * + * @brief Read multi register via spi + * + * @attention None + * + * @param[in] usRegAddr register addr + * @param[in] pusRegValueBuffer pointer to register value buffer + * @param[in] uchLen registers len + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_SpiReadRegs(GU16 usRegAddr, GU16 *pusRegValueBuffer, GU8 uchLen) +{ + GU8 uchBuffArr[3] = {0}; + + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW); + uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_WRITE; + uchBuffArr[1] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegAddr); + uchBuffArr[2] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegAddr); + hal_gh3x2x_afe_spi_write(uchBuffArr, 3); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US); + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US); + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW); + uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_READ; + hal_gh3x2x_afe_spi_write(uchBuffArr, 1); + hal_gh3x2x_afe_spi_read((GU8 *)pusRegValueBuffer, uchLen * 2); + GH3X2X_SwapLittleBigEndianData((GU8 *)pusRegValueBuffer, (GU16)((GU16)uchLen * 2)); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US); + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US); +} + +#endif + +#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_HARDWEAR_CS) +GU16 GH3X2X_AFE_SpiReadRegHardwareCs(GU16 usRegAddr) +{ + GU8 puchWriteBuf[7]; + GU8 puchReadBuf[2]; + puchWriteBuf[0] = 0xF0; + puchWriteBuf[1] = usRegAddr>>8; + puchWriteBuf[2] = usRegAddr&0x00FF; + hal_gh3x2x_afe_spi_write(puchWriteBuf, 3); + hal_gh3x2x_afe_spi_write_F1_and_read(puchReadBuf, 2); + return ((((GU16)puchReadBuf[0])<<8) + puchReadBuf[1]); +} + + + +void GH3X2X_AFE_SpiReadRegsHardwareCs(GU16 usRegAddr, GU16 *pusRegValueBuffer, GU8 uchLen) +{ + GU8 puchWriteBuf[3]; + puchWriteBuf[0] = 0xF0; + puchWriteBuf[1] = usRegAddr>>8; + puchWriteBuf[2] = usRegAddr&0x00FF; + hal_gh3x2x_afe_spi_write(puchWriteBuf, 3); + hal_gh3x2x_afe_spi_write_F1_and_read((GU8 *)pusRegValueBuffer, uchLen * 2); + GH3X2X_SwapLittleBigEndianData((GU8 *)pusRegValueBuffer, (GU16)((GU16)uchLen * 2)); +} + + +#endif + + + + + +/** + * @fn static void GH3X2X_AFE_SpiReadFifo(GU8 *puchDataBuffer, GU16 usLen) + * + * @brief Read fifo via spi + * + * @attention None + * + * @param[in] puchDataBuffer pointer to buffer for fifo rawdata + * @param[in] usLen fifo bytes len + * @param[out] None + * + * @return None + */ + +#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS) +static void GH3X2X_AFE_SpiReadFifo(GU8 *puchDataBuffer, GU16 usLen) +{ + GU8 uchBuffArr[3] = {0}; + + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW); + uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_WRITE; + uchBuffArr[1] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(GH3X2X_AFE_FIFO_REG_ADDR); + uchBuffArr[2] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(GH3X2X_AFE_FIFO_REG_ADDR); + hal_gh3x2x_afe_spi_write(uchBuffArr, 3); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US); + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US); + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_LOW); + uchBuffArr[0] = GH3X2X_AFE_SPI_CMD_READ; + hal_gh3x2x_afe_spi_write(uchBuffArr, 1); + hal_gh3x2x_afe_spi_read(puchDataBuffer, usLen); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_WAIT_DELAY_X_US); + hal_gh3x2x_afe_spi_cs_ctrl(GH3X2X_AFE_SPI_CS_CTRL_HIGH); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_SPI_END_DELAY_X_US); +} + +#endif + + +#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_HARDWEAR_CS) +void GH3X2X_AFE_SpiReadFifoHardwareCs(GU8 *puchDataBuffer, GU16 usLen) +{ + GU8 puchWriteBuf[3]; + puchWriteBuf[0] = 0xF0; + puchWriteBuf[1] = 0xAAAA>>8; + puchWriteBuf[2] = 0xAAAA&0x00FF; + hal_gh3x2x_afe_spi_write(puchWriteBuf, 3); + hal_gh3x2x_afe_spi_write_F1_and_read(puchDataBuffer, usLen); +} +#endif + +#endif + +#if ( GH3X2X_AFE_COM_INTERFACE_TYPE == GH3X2X_AFE_COM_INTERFACE_I2C ) + +/** + * @fn static void GH3X2X_AFE_I2cSendCmd(GU8 uchCmd) + * + * @brief Send cmd via i2c + * + * @attention None + * + * @param[in] uchCmd i2c cmd + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_I2cSendCmd(GU8 uchCmd) +{ + GU8 uchBuffArr[3] = {0}; + + uchBuffArr[0] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(GH3X2X_AFE_I2C_CMD_ADDR); + uchBuffArr[1] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(GH3X2X_AFE_I2C_CMD_ADDR); + uchBuffArr[2] = uchCmd; + hal_gh3x2x_afe_i2c_write(GH3X2X_AFE_I2C_DEVICE_BASE, uchBuffArr, 3); +} + +/** + * @fn static void GH3X2X_AFE_I2cWriteReg(GU16 usRegAddr, GU16 usRegValue) + * + * @brief Write register via i2c + * + * @attention None + * + * @param[in] usRegAddr register addr + * @param[in] usRegValue register data + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_I2cWriteReg(GU16 usRegAddr, GU16 usRegValue) +{ + GU8 uchBuffArr[4] = {0}; + + uchBuffArr[0] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegAddr); + uchBuffArr[1] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegAddr); + uchBuffArr[2] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegValue); + uchBuffArr[3] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegValue); + hal_gh3x2x_afe_i2c_write(GH3X2X_AFE_I2C_DEVICE_BASE, uchBuffArr, 4); +} + + + +/** + * @fn static GU16 GH3X2X_I2cReadReg(GU16 usRegAddr) + * + * @brief Read register via i2c + * + * @attention None + * + * @param[in] usRegAddr register addr + * @param[out] None + * + * @return register data + */ +GU16 GH3X2X_AFE_I2cReadReg(GU16 usRegAddr) +{ + GU8 uchCmdBuffArr[2] = {0}; + GU8 uchReadBuffArr[2] = {0}; + + uchCmdBuffArr[0] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegAddr); + uchCmdBuffArr[1] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegAddr); + hal_gh3x2x_afe_i2c_read(GH3X2X_AFE_I2C_DEVICE_BASE, uchCmdBuffArr, 2, uchReadBuffArr, 2); + + return GH3X2X_AFE_MAKEUP_WORD(uchReadBuffArr[0], uchReadBuffArr[1]); +} + +/** + * @fn void GH3X2X_I2cReadRegs(GU16 usRegAddr, GU16 *pusRegValueArr, GU8 uchLen) + * + * @brief Read multi register via i2c + * + * @attention None + * + * @param[in] usRegAddr register addr + * @param[in] pusRegValueBuffer pointer to register value buffer + * @param[in] uchLen registers len + * @param[out] None + * + * @return None + */ +void GH3X2X_I2cReadRegs(GU16 usRegAddr, GU16 *pusRegValueArr, GU8 uchLen) +{ + GU8 uchBuffArr[2] = {0}; + + uchBuffArr[0] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegAddr); + uchBuffArr[1] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegAddr); + + hal_gh3x2x_afe_i2c_read(GH3X2X_AFE_I2C_DEVICE_BASE, uchBuffArr, 2, \ + (GU8 *)pusRegValueArr, uchLen * 2); + GH3X2X_SwapLittleBigEndianData((GU8 *)pusRegValueArr, (GU16)uchLen * 2); +} + + + + +/** + * @fn static void GH3X2X_I2cReadFifo(GU8 *puchDataBuffer, GU16 usLen) + * + * @brief Read fifo via i2c + * + * @attention None + * + * @param[in] puchDataBuffer pointer to buffer for fifo rawdata + * @param[in] usLen fifo bytes len + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_I2cReadFifo(GU8 *puchDataBuffer, GU16 usLen) +{ + GU8 uchCmdBuffArr[2] = {0}; + + uchCmdBuffArr[0] = GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(GH3X2X_AFE_FIFO_REG_ADDR); + uchCmdBuffArr[1] = GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(GH3X2X_AFE_FIFO_REG_ADDR); + hal_gh3x2x_afe_i2c_read(GH3X2X_AFE_I2C_DEVICE_BASE, uchCmdBuffArr, 2, puchDataBuffer, usLen); +} + +#endif + +/** + * @fn void GH3X2X_WriteRegBitField(GU16 usRegAddr, GU8 uchLsb, GU8 uchMsb, GU16 usValue) + * + * @brief write register bit field via i2c or spi + * + * @attention None + * + * @param[in] usRegAddr register addr + * @param[in] uchLsb lsb of bit field + * @param[in] uchMsb msb of bit field + * @param[in] usRegValue register data + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_WriteRegBitField(GU16 usRegAddr, GU8 uchLsb, GU8 uchMsb, GU16 usValue) +{ + GU16 usMakData = ((((GU16)0x0001) << (uchMsb - uchLsb + 1)) - 1) << uchLsb; + GU16 usRegData = 0; + usRegData = GH3X2X_AFE_READ_REG(usRegAddr); + GH3X2X_VAL_CLEAR_BIT(usRegData, usMakData); + GH3X2X_VAL_SET_BIT(usRegData, (usValue << uchLsb) & usMakData); + GH3X2X_AFE_WRITE_REG(usRegAddr, usRegData); +} + +/** + * @fn GU16 GH3X2X_AFE_READ_REGBitField(GU16 usRegAddr, GU8 uchLsb, GU8 uchMsb) + * + * @brief Read register bit field via i2c or spi + * + * @attention None + * + * @param[in] usRegAddr register addr + * @param[in] uchLsb lsb of bit field + * @param[in] uchMsb msb of bit field + * @param[out] None + * + * @return register bit field data + */ +GU16 GH3X2X_AFE_ReadRegBitField(GU16 usRegAddr, GU8 uchLsb, GU8 uchMsb) +{ + GU16 usMakData = ((((GU16)0x0001) << (uchMsb - uchLsb + 1)) - 1) << uchLsb; + GU16 usRegData = 0; + usRegData = GH3X2X_AFE_READ_REG(usRegAddr); + GH3X2X_AFE_VAL_GET_BIT(usRegData, usMakData); + usRegData >>= uchLsb; + return usRegData; +} + + +void GH3X2X_AFE_SetNeedWakeUpGh3x2xFlag(GU8 uchFlag) +{ + g_uchNeedWakeUpGh3x2xAfe = uchFlag; +} + +GU8 GH3X2X_AFE_GetNeedWakeUpGh3x2xFlag(void) +{ + return g_uchNeedWakeUpGh3x2xAfe; +} + + + +void GH3X2X_AFE_ExitLowPowerMode(void) +{ + GH3X2X_AFE_SEND_CMD(GH3X2X_AFE_CMD_WAKEUP); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_WAKE_UP_CMD_DELAY_X_US); +} + +void GH3X2X_AFE_EnterLowPowerMode(void) +{ + GH3X2X_AFE_SEND_CMD(GH3X2X_AFE_CMD_SLEEP); + GH3X2X_AFE_SetNeedWakeUpGh3x2xFlag(1); +} + + +void GH3X2X_AFE_ClearEvent(GU16 usEvent) +{ + GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_INT_EVENT_ADDR,usEvent); +} + + + + + + + + +/** + * @fn void GH3X2X_AFE_SendRegPackage(STGH3X2X_AFEReg* GH3X2X_AFE_reg_list, GU16 reg_list_len) + * + * @brief send register package (for initialize GH3X2X_AFE chip) + * + * @attention + * + * @param[in] GH3X2X_AFE_reg_list reg list that will be written to GH3X2X_AFE + * @param[in] reg_list_len reg count that contained in reg list + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_SendRegPackage(STGH3X2X_AFEReg* GH3X2X_AFE_reg_list, GU16 reg_list_len) +{ + GU16 luwIndex = 0; + + if ((GH3X2X_AFE_reg_list != NULL) && (reg_list_len > 0)) + { + for (luwIndex = 0; luwIndex < reg_list_len; luwIndex++) + { + if (GH3X2X_AFE_REG_IS_VALID(GH3X2X_AFE_reg_list->usRegAddr)) + { + GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_reg_list->usRegAddr, GH3X2X_AFE_reg_list->usRegData); + } + GH3X2X_AFE_reg_list++; + } + } + + if(GH3X2X_AFE_PRO_TYPE == GH3X2X_AFE_PRO_BY_POLLING) + { + //int pin should not action when poling mode + GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_INT_EVENT_EN_ADDR, 0); + } + +} + + + +/** + * @fn GS8 GH3X2X_HardReset(void) + * + * @brief Gh3x2x softreset via i2c/spi, can read&write reg with gh3x2x after reset + * + * @attention None + * + * @param[in] None + * @param[out] None + * + * @return None + * @retval #GH3X2X_RET_OK return successfully + * @retval #GH3X2X_RET_GENERIC_ERROR reset pin control function not register + */ +void GH3X2X_AFE_Reset(void) +{ + GH3X2X_AFE_ClearEvent(0xFFFF); + #if(GH3X2X_AFE_RESET_TYPE == GH3X2X_AFE_RESET_HARDWARE) + hal_gh3x2x_afe_reset_pin_ctrl(0); + hal_gh3x2x_afe_DelayUs(GH3X2X_AFE_HARD_RESET_DELAY_X_US); + hal_gh3x2x_afe_reset_pin_ctrl(1); + #else + GH3X2X_AFE_SEND_CMD(GH3X2X_AFE_CMD_RESET); + #endif + hal_gh3x2x_afe_DelayMs(10); +} + + + +/** + * @fn GS8 GH3X2X_CommunicateConfirm(void) + * + * @brief Communication operation interface confirm + * + * @attention None + * + * @param[in] None + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_CommunicateConfirm(void) +{ + GU16 uchReadData; + GU16 uchWriteData; + + if (GH3X2X_AFE_READ_REG(GH3X2X_AFE_REG_CHIP_READY_CODE_REG_ADDR) == 0xAA55) + { + uchReadData = GH3X2X_AFE_READ_REG(GH3X2X_AFE_REG_SLOT_TMR0_REG_ADDR); + GH3X2X_INFO_LOG("slot_time0 reg = %d\r\n", (int)uchReadData); + uchWriteData = ~uchReadData; + GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_SLOT_TMR0_REG_ADDR, uchWriteData); + uchReadData = GH3X2X_AFE_READ_REG(GH3X2X_AFE_REG_SLOT_TMR0_REG_ADDR); + GH3X2X_INFO_LOG("slot_time0 reg = %d\r\n", (int)uchReadData); + if (uchWriteData == uchReadData) + { + uchWriteData = ~uchReadData; + GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_SLOT_TMR0_REG_ADDR, uchWriteData); + } + else + { + GH3X2X_INFO_LOG("[%s]read fail or write fail!!! \r\n", __FUNCTION__); + while(1); + } + } + else + { + 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)); + while(1); + } + + GH3X2X_INFO_LOG("[%s]Comunication confirm ok. \r\n", __FUNCTION__); + + + + +} + + + + + + + +/*********************************************** init function*******************************************/ + +/** + * @fn void GH3X2X_AFE_Init(void) + * + * @brief init GH3X2X_AFE chip + * + * @attention + * + * @param[in] None + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_Init(void) +{ + /* Step 1: init communicate interface. */ + #if(GH3X2X_AFE_COM_INTERFACE_TYPE == GH3X2X_AFE_COM_INTERFACE_SPI) + hal_gh3x2x_afe_spi_init(); + #else + hal_gh3x2x_afe_i2c_init(); + #endif + + /* Step 2: init interupt pin */ + #if(GH3X2X_AFE_PRO_TYPE == GH3X2X_AFE_PRO_BY_INT) + hal_gh3x2x_afe_int_init(); + #endif + + + /* Step 3: Reset GH3X2X_AFE chip */ + #if(GH3X2X_AFE_RESET_TYPE == GH3X2X_AFE_RESET_HARDWARE) + hal_gh3x2x_afe_reset_pin_init(); + #endif + GH3X2X_AFE_Reset(); + + /* Step 4: Check conmunication and chip id is ok or not */ + GH3X2X_AFE_CommunicateConfirm(); + GH3X2X_AFE_CheckChipId(); + GH3X2X_AFE_CheckEfuseCrc(); + + + /* Step 5: Init GH3X2X_AFE chip */ + GH3X2X_AFE_SendRegPackage(GH3X2X_AFE_reg_list, GH3X2X_AFE_reg_list_len); + + /* Step 6: agc module reset and set parm*/ + GH3X2X_LedAgcReset(); + GH3X2X_DemoLedAgcPramConfig(); + //GH3X2X_LedAgcPramWrite(); + + /* Step 7: enter low power mode */ + GH3X2X_AFE_EnterLowPowerMode(); + +} + +/*********************************************** sample control handle function*******************************************/ + +/** + * @fn void GH3X2X_AFE_StartSampling(GU8 SlotCfgEnable) + * + * @brief start sample + * + * @attention + * + * @param[in] SlotCfgEnable slot enable bit bit0 control slot0, bit1 control slot1, bit2 control slot2... + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_StartSampling(GU8 SlotCfgEnable) +{ + GH3X2X_AFE_ExitLowPowerMode(); + + //agc init + GH3X2X_LedAgcInit(g_pstGh3x2xAgcInfo); + + //write slot enable + GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_SLOT_EN_ADDR, (GU16)SlotCfgEnable); + //start sample + GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_START_ADDR,GH3X2X_AFE_REG_START_LSB,GH3X2X_AFE_REG_START_MSB,1); + + GH3X2X_AFE_EnterLowPowerMode(); +} + +/** + * @fn void GH3X2X_AFE_StopSampling(void) + * + * @brief stop sample + * + * @attention + * + * @param[in] None + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_StopSampling(void) +{ + GH3X2X_AFE_ExitLowPowerMode(); + + //stop sample + GH3X2X_AFE_WriteRegBitField(GH3X2X_AFE_REG_START_ADDR,GH3X2X_AFE_REG_START_LSB,GH3X2X_AFE_REG_START_MSB,0); + + GH3X2X_AFE_EnterLowPowerMode(); +} + +/** + * @fn void GH3X2X_AFE_SwitchSlot(GU8 SlotCfgEnable) + * + * @brief switch sample slot. + * + * @attention this function can only be used during sampling, after call GH3X2X_AFE_StartSampling + * + * @param[in] SlotCfgEnable slot enable bit bit0 control slot0, bit1 control slot1, bit2 control slot2... + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_SwitchSlot(GU8 SlotCfgEnable) +{ + GH3X2X_AFE_ExitLowPowerMode(); + + //write slot enable + GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_SLOT_EN_ADDR, (GU16)SlotCfgEnable); + + GH3X2X_AFE_EnterLowPowerMode(); +} + +/********************************* interrupt handle:fifo read and analysis ***************************/ +#define GH3X2X_AFE_READ_FIFO_BUF_LEN (800) +GU32 GH3X2X_AFE_ReadFifoBuffer[(GU16)GH3X2X_AFE_READ_FIFO_BUF_LEN]; + +/* + FIFO rawdata decode +*/ +typedef struct +{ + GU32 uiAdcCode; //sampling rawdata of ADC + GU8 ubSlotNo; //slot number + GU8 ubAdcNo; //adc number + GU8 ubFlagLedAdjIsAgc_EcgRecover; //adj flag of ppg data or fast recover flag of ecg data + GU8 ubFlagLedAdjAgcUp; //adj up flag of ppg data +}StFifoDataInformation; + +/** + * @fn GU32 EndienRev32(GU32 luiTempData) + * + * @brief reverse data endien + * + * @attention + * + * @param[in] luiTempData input data + * @param[out] None + * + * @return output data + */ +static GU32 EndienRev32(GU32 luiTempData) +{ + GU8 *lpubIn; + GU8 *lpubOut; + + GU32 luiOutData; + + lpubIn = (GU8 *)(&luiTempData); + lpubOut = (GU8 *)(&luiOutData); + + for(GU8 i = 0; i < 4; i ++) + { + lpubOut[i] = lpubIn[3 - i]; + } + + return luiOutData; +} + +void GH3X2X_UpdateAgcInfo(void) +{ + GH3X2X_Memcpy(g_pstGh3x2xAgcInfo->uchTiaGainRecord, g_pstGh3x2xAgcInfo->uchTiaGainAfterSoftAgc, sizeof(g_pstGh3x2xAgcInfo->uchTiaGainRecord)); + GH3X2X_Memcpy(g_pstGh3x2xAgcInfo->uchDrvCurrentRecord, g_pstGh3x2xAgcInfo->uchDrvCurrentAfterSoftAgc, sizeof(g_pstGh3x2xAgcInfo->uchDrvCurrentRecord)); + + +} + +void GH3X2X_RecordAgcInfo(void) +{ + GU16 usDrv0CurRegData = 0; + GU16 usDrv0CurRegAddr = 0; + GU16 usDrv1CurRegData = 0; + GU16 usDrv1CurRegAddr = 0; + GU16 uchTIAData = 0; + + // record TIA + for (GU8 uchSlotIndex = 0; uchSlotIndex < 8; uchSlotIndex++) + { + uchTIAData = GH3X2X_AFE_READ_REG(0x0112 + (uchSlotIndex * 0x001C)); + + for (GU8 nAdcCnt = 0; nAdcCnt < 4; nAdcCnt++) + { + uchTIAData = (GU8)(((uchTIAData) >> (4 * nAdcCnt)) & 0x000F); + g_pstGh3x2xAgcInfo->uchTiaGainAfterSoftAgc[uchSlotIndex*4 + nAdcCnt] = uchTIAData; + } + } + + //Record Drv + usDrv0CurRegAddr = 0x011E; + usDrv1CurRegAddr = 0x0120; + for (GU8 uchSlotIndexCnt = 0; uchSlotIndexCnt < 8; uchSlotIndexCnt++) + { + usDrv0CurRegData = (GH3X2X_AFE_READ_REG(usDrv0CurRegAddr + (uchSlotIndexCnt * 0x001C)) & 0xFF); + usDrv1CurRegData = (GH3X2X_AFE_READ_REG(usDrv1CurRegAddr + (uchSlotIndexCnt * 0x001C)) & 0xFF); + g_pstGh3x2xAgcInfo->uchDrvCurrentAfterSoftAgc[uchSlotIndexCnt] = (GU16)(usDrv0CurRegData << 0x0); + g_pstGh3x2xAgcInfo->uchDrvCurrentAfterSoftAgc[uchSlotIndexCnt] |= (GU16)(usDrv1CurRegData << 0x0); + } +} + +/** + * @fn void GH3X2X_AFE_FifoDataAnalysis(GU16 luwFifoDataCnt) + * + * @brief analysis fifo data + * + * @attention + * + * @param[in] luwFifoDataCnt the number of rawdata + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_FifoDataAnalysis(GU16 luwFifoDataCnt) +{ + StFifoDataInformation stTempFifoInfo = {0}; + GU16 luwFifoCnt = 0; + + GU32 luiTempFifoData = 0; + + GH3X2X_INFO_LOG("Received rawdata sample num = %d \r\n", (int)luwFifoDataCnt); + + for(luwFifoCnt = 0; luwFifoCnt < luwFifoDataCnt; luwFifoCnt++) + { + luiTempFifoData = EndienRev32(GH3X2X_AFE_ReadFifoBuffer[luwFifoCnt]); //big endien -> little endien + + stTempFifoInfo.uiAdcCode = ((luiTempFifoData >> 0) & 0x00FFFFFF); + stTempFifoInfo.ubSlotNo = ((luiTempFifoData >> 29) & 0x00000007); + stTempFifoInfo.ubAdcNo = ((luiTempFifoData >> 27) & 0x00000003); + stTempFifoInfo.ubFlagLedAdjIsAgc_EcgRecover = ((luiTempFifoData >> 26) & 0x00000001); + stTempFifoInfo.ubFlagLedAdjAgcUp = ((luiTempFifoData >> 25) & 0x00000001); + #if GH3X2X_ADT_FUNC_ENABLE + if(stTempFifoInfo.ubSlotNo == GH3X2X_ADT_SLOT_NUM && stTempFifoInfo.ubAdcNo == GH3X2X_ADT_ADC_NUM) + { + EMWearStatus emWearStatus; + GH3x2xAdtAlgoExe(&stTempFifoInfo.uiAdcCode,&emWearStatus); + } + #endif + GH3X2X_INFO_LOG("Received rawdata:slot:%d,adc:%d,data:%d\r\n", stTempFifoInfo.ubSlotNo, stTempFifoInfo.ubAdcNo,stTempFifoInfo.uiAdcCode); + //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]); + + + + /******************************** add your fifo date process code******************************/ + //you can combine frame rawdata according to stTempFifoInfo + //and then excute algorithm calculate + + + } +} + + +/** + * @fn void GH3X2X_AFE_ChipPro(void) + * + * @brief interrupt handle function + * + * @attention + * + * @param[in] None + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_ChipPro(void) +{ + GU16 luwGH3X2X_AFEFifoLen = 0; + GU16 luwGotEvent = 0; + + +#if (GH3X2X_AFE_PRO_TYPE == GH3X2X_AFE_PRO_BY_INT) + if(0 == g_uchGh3x2xAfeIntCallBackIsCalled) + { + GH3X2X_INFO_LOG("InterruptProcess:invalid call, do not process.\r\n"); + return; + } + g_uchGh3x2xAfeIntCallBackIsCalled = 0; + +#endif + + if (GH3X2X_AFE_GetNeedWakeUpGh3x2xFlag()) + { + GH3X2X_AFE_ExitLowPowerMode(); + } + + + luwGH3X2X_AFEFifoLen = 0; + + //read event + luwGotEvent = GH3X2X_AFE_READ_REG(GH3X2X_AFE_REG_INT_EVENT_ADDR); + GH3X2X_INFO_LOG("Received irq = %d \r\n", (int)luwGotEvent); + //clear event + GH3X2X_AFE_WRITE_REG(GH3X2X_AFE_REG_INT_EVENT_ADDR,luwGotEvent); //clear event + + //read fifo use + luwGH3X2X_AFEFifoLen = GH3X2X_AFE_READ_REG(GH3X2X_AFE_REG_FIFO_USE_ADDR); + if(luwGH3X2X_AFEFifoLen > GH3X2X_AFE_READ_FIFO_BUF_LEN) + { + luwGH3X2X_AFEFifoLen = GH3X2X_AFE_READ_FIFO_BUF_LEN; + } + + // read fifo data + if(0 != luwGH3X2X_AFEFifoLen) + { + GH3X2X_AFE_READ_FIFO((GU8 *)GH3X2X_AFE_ReadFifoBuffer,luwGH3X2X_AFEFifoLen * 4); + } + + + //ECG_LEAD OFF DET & resample + #if GH3X2X_ECG_FUNC_ENABLE + + GU16 luwGH3X2X_AFEFifoByteLen = luwGH3X2X_AFEFifoLen * 4; + luwGotEvent &= (~GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_LEAD_OFF)); + + GU8 lubRet = GH3X2X_LeadOffDetect((GU8 *)GH3X2X_AFE_ReadFifoBuffer, &luwGH3X2X_AFEFifoByteLen, 0); + if(lubRet != 0) + { + luwGotEvent |= (GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_LEAD_OFF)); + } + + GH3X2X_INFO_LOG("before Rs luwGH3X2X_AFEFifoLen = %d\r\n",luwGH3X2X_AFEFifoLen); + GH3X2X_AFE_EcgRsHandle((GU8 *)GH3X2X_AFE_ReadFifoBuffer, &luwGH3X2X_AFEFifoByteLen,0,GH3X2X_ECG_DOWN_FS); + luwGH3X2X_AFEFifoLen = luwGH3X2X_AFEFifoByteLen/4; + GH3X2X_INFO_LOG("after Rs luwGH3X2X_AFEFifoLen = %d\r\n",luwGH3X2X_AFEFifoLen); + #endif + + if(0 != (luwGotEvent & GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_WEAR_ON))) + { + GH3X2X_INFO_LOG("Received wear on event\r\n"); + } + + if(0 != (luwGotEvent & GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_WEAR_OFF))) + { + GH3X2X_INFO_LOG("Received wear off event\r\n"); + } + + if(0 != (luwGotEvent & GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_LEAD_ON))) + { + GH3X2X_INFO_LOG("Received lead on event\r\n"); + GH3X2X_AFE_Leadon_hook(); + } + + if(0 != (luwGotEvent & GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_LEAD_OFF))) + { + GH3X2X_INFO_LOG("Received lead off event\r\n"); + GH3X2X_AFE_Leadoff_hook(); + + } + + if(0 != (luwGotEvent & GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_LED_TUNE_FAIL))) + { + GH3X2X_INFO_LOG("Received tune fail event\r\n"); + } + + if(0 != (luwGotEvent & GH3X2X_AFE_EVENT_BIT(GH3X2X_AFE_EVENT_LED_TUNE_DONE))) + { + GH3X2X_INFO_LOG("Received tune done event\r\n"); + } + + + //you can add some code to adjust ppg sample parameter, such as led drv current GU16 usTempDrvCurrent; + + //GH3x2xSetPpgCtrlReg(GH3X2X_AFE_PPG_CTRL_REG_AGC_EN,1,0); + //GH3x2xSetPpgCtrlReg(GH3X2X_AFE_PPG_CTRL_REG_LED_CURRENT_DRV0,1,60); + //GH3X2X_INFO_LOG("change slot0 drv0 current.\r\n"); + //GH3X2X_INFO_LOG("Get slot0 drv0 current = %d.\r\n",(int)GH3x2xGetPpgCtrlReg(GH3X2X_AFE_PPG_CTRL_REG_LED_CURRENT_DRV0,0)); + + GH3X2X_LedAgcProcess((GU8 *)GH3X2X_AFE_ReadFifoBuffer, luwGH3X2X_AFEFifoLen * 4, g_pstGh3x2xAgcInfo); + + GH3X2X_AFE_EnterLowPowerMode(); + + + if(0 != luwGH3X2X_AFEFifoLen) + { + GH3X2X_AFE_FifoDataAnalysis(luwGH3X2X_AFEFifoLen); + } +} + +const GU16 g_usGH3x2xTiaGainR[] = +{ + 10, + 25, + 50, + 75, + 100, + 250, + 500, + 750, + 1000, + 1250, + 1500, + 1750, + 2000, +}; + +const GU16 g_usGH3x2xSlotRegBase[8] = +{ + 0x0100, + 0x011C, + 0x0138, + 0x0154, + 0x0170, + 0x018C, + 0x01A8, + 0x01C4, +}; + + +const STGh3x2xAgcReg g_pstGH3x2xAgcReg[] = +{ + {0x10, 9, 8}, //0: agc en + {0x22, 7, 0}, //1: led current up limit + {0x22, 15, 8}, //2: led current down limit + {0x1E, 7, 0}, //3: led current drv0 + {0x20, 7, 0}, //4: led current drv1 + {0x12, 3, 0}, //5: rx0 tia gain + {0x12, 7, 4}, //6: rx1 tia gain + {0x12, 11, 8}, //7: rx2 tia gain + {0x12, 15, 12}, //8: rx3 tia gain + {0x10, 7,6}, //9: agc src + {0x1A, 1,0}, //10: rx0 bg cancel + {0x1A, 3,2}, //11: rx1 bg cancel + {0x1A, 5,4}, //12: rx2 bg cancel + {0x1A, 7,6}, //13: rx2 bg cancel + {0x0A, 15,8}, //14: sr mulipliper + {0x0A, 5,1}, //15: ecg en& rx0~rx1 en +}; + +void GH3x2x_AFESetAgcReg(GU8 uchAgcReg, GU8 uchSlot, GU16 usValue) +{ + GH3X2X_AFE_WriteRegBitField(g_usGH3x2xSlotRegBase[uchSlot] + g_pstGH3x2xAgcReg[uchAgcReg].uchAddrOffset, g_pstGH3x2xAgcReg[uchAgcReg].uchLsb, g_pstGH3x2xAgcReg[uchAgcReg].uchMsb, usValue); +} + +GU16 GH3x2x_AFEGetAgcReg(GU8 uchAgcReg, GU8 uchSlot) +{ + return GH3X2X_AFE_ReadRegBitField(g_usGH3x2xSlotRegBase[uchSlot] + g_pstGH3x2xAgcReg[uchAgcReg].uchAddrOffset, g_pstGH3x2xAgcReg[uchAgcReg].uchLsb, g_pstGH3x2xAgcReg[uchAgcReg].uchMsb); +} + +/** + * @fn void GH3X2X_AFE_GetEfuseCode(GS8* pchLedDrvEcode,GS8* pchTiaEcode,GS8* pchEcgEcode) + * + * @brief: Get Efuse Code + * + * @attention + * + * @param[in] + * @param[out] pchLedDrvEcode + * pchTiaEcode + * pchEcgEcode + * @return : none + */ +void GH3X2X_AFE_GetEfuseCode(GS8* pchLedDrvEcode,GS8* pchTiaEcode,GS8* pchEcgEcode) +{ + GU16 usRegVal; + GH3X2X_AFE_WRITE_REG(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,0x0020); + GH3X2X_AFE_WRITE_REG(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,0x0030); + + while(0 == GH3X2X_AFE_ReadRegBitField(GH3X2X_EFUSE_CTRL_STATUS_REG_ADDR,0,0)); + usRegVal = GH3X2X_AFE_READ_REG(GH3X2X_EFUSE_CTRL_RDATA_1_REG_ADDR); + *pchLedDrvEcode = (GS8)GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegVal); + *pchTiaEcode = (GS8)GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegVal); + *pchEcgEcode = (GS8)GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(GH3X2X_AFE_READ_REG(GH3X2X_EFUSE_CTRL_RDATA_2_REG_ADDR)); +} + + +/** + * @fn GU16 GH3X2X_AFE_SetLedDrvCurrent(GU8 uchCurrent_mA,GU8 uchDrvNum, GS8 chECODE) + * + * @brief: led drv calibration + * + * @attention + * + * @param[in] GU8 uchCurrent_mA:led drv current, unit: mA + GU8 uchDrvNum :led Drv num,0 or 1 + GS8 chECODE :Led Drv Ecode from efuse + * @param[out] None + * + * @return : Drv code + */ +GU16 GH3X2X_AFE_SetLedDrvCurrent(GU8 uchCurrent_mA, GU8 uchDrvNum, GS8 chECODE) +{ + GF32 fEr; + GF32 fY; + GU8 uchN; + GU16 usDrvCode; + GU16 usDrvScale; + + if(uchDrvNum == 0) + { + fY = 0.1; + usDrvScale = GH3X2X_AFE_ReadRegBitField(GH3X2X_LED_DRV_AD_REG_REG_ADDR,GH3X2X_DRV0_FULL_SCAL_CURRENT_LSB,GH3X2X_DRV0_FULL_SCAL_CURRENT_MSB); + } + else + { + fY = 0.01; + usDrvScale = GH3X2X_AFE_ReadRegBitField(GH3X2X_LED_DRV_AD_REG_REG_ADDR,GH3X2X_DRV1_FULL_SCAL_CURRENT_LSB,GH3X2X_DRV1_FULL_SCAL_CURRENT_MSB); + + } + uchN = 1 << (3 - usDrvScale); + + fEr = (GF32)((GF32)chECODE/256) + 1.0f; + usDrvCode = (GU16)(0.5f+((GF32)fEr*255*(GF32)uchN)/(0.225f/((GF32)uchCurrent_mA/1000) - fY)); + + return usDrvCode; +} + + +/** + * @fn GF32 GH3X2X_AFE_GetLedDrvCurrent(GU16 usDrvCode, GU8 uchDrvNum, GS8 chECODE) + * + * @brief: get led drv calibration current + * + * @attention + * + * @param[in] GU16 usDrvCode :led drv code + GU8 uchDrvNum :led Drv num,0 or 1 + GS8 chECODE :Led Drv Ecode from efuse + * @param[out] None + * + * @return : calibration current + */ + +GF32 GH3X2X_AFE_GetLedDrvCurrent(GU16 usDrvCode, GU8 uchDrvNum, GS8 chECODE) +{ + GF32 fEr; + GF32 fY; + GU8 uchN; + GF32 fDrvCurrent; + GU16 usDrvScale; + + if(uchDrvNum == 0) + { + fY = 0.1; + usDrvScale = GH3X2X_AFE_ReadRegBitField(GH3X2X_LED_DRV_AD_REG_REG_ADDR,GH3X2X_DRV0_FULL_SCAL_CURRENT_LSB,GH3X2X_DRV0_FULL_SCAL_CURRENT_MSB); + } + else + { + fY = 0.01; + usDrvScale = GH3X2X_AFE_ReadRegBitField(GH3X2X_LED_DRV_AD_REG_REG_ADDR,GH3X2X_DRV1_FULL_SCAL_CURRENT_LSB,GH3X2X_DRV1_FULL_SCAL_CURRENT_MSB); + } + uchN = 1 << (3 - usDrvScale); + fEr = (GF32)((GF32)chECODE/256) + 1; + fDrvCurrent = 0.225f/(fEr*255*(GF32)uchN/(GF32)usDrvCode + fY); + return fDrvCurrent*1000; + +} + +/** + * @fn GF32 GH3X2X_AFE_GetTiaCalCode(GS8 chECODE) + + * + * @brief: Get Tia Calibration Code + * + * @attention + * + * @param[in] GS8 chECODE :Tia Ecode from efuse + * @param[out] None + * + * @return : calibration Code + */ +GF32 GH3X2X_AFE_GetTiaCalCode(GS8 chECODE) +{ + GF32 fEr; + fEr = (GF32)((GF32)chECODE/512) + 1; + return fEr; +} + +/** + * @fn GF32 GH3X2X_AFE_GetEcgCalCode(GS8 chECODE) + + * + * @brief: Get ECG Calibration Code + * + * @attention + * + * @param[in] GS8 chECODE :ECG Ecode from efuse + * @param[out] None + * + * @return : calibration Code + */ +GF32 GH3X2X_AFE_GetEcgCalCode(GS8 chECODE) +{ + GF32 fEr; + fEr = (GF32)((GF32)chECODE/1024) + 1; + return fEr; +} + + +/** + * @fn GCHAR *GH3X2X_GetAfeLibVersion(void) + * + * @brief Get afe driver version + * + * @attention None + * + * @param[in] None + * @param[out] None + * + * @return library version string + */ +GCHAR *GH3X2X_GetAfeLibVersion(void) +{ + return (GCHAR *)GH3X2X_VERSION_STRING; +} + + +GU8 GH3X2X_AFE_GetChipId(void) +{ + return (GU8)GH3X2X_AFE_ReadRegBitField(GH3X2X_WHO_AM_I_REG_ADDR,GH3X2X_WHO_AM_I_LSB,GH3X2X_WHO_AM_I_MSB); +} + +GS8 GH3X2X_AFE_CheckChipId(void) +{ + GS8 chRet = GH3X2X_AFE_RET_OK; + GS8 chipd_id = GH3X2X_AFE_GetChipId(); + if(GH3X2X_CHIP_ID != chipd_id) + { + GH3X2X_INFO_LOG("wrong chip id!! 0x%x\r\n",chipd_id); + chRet = GH3X2X_AFE_RET_GENERIC_ERROR; + } + else + { + GH3X2X_INFO_LOG("check chip id success!! 0x%x\r\n",chipd_id); + } + return chRet; +} + +/** + * @fn void *GH3X2X_Memcpy(void *pDest, const void *pSrc, GU32 unByteSize) + * + * @brief memcpy() Re-implementation + * + * @attention None + * + * @param[in] pSrc pointer to source buffer + * @param[in] unByteSize source buffer byte size + * @param[out] pDest pointer to destination buffer + * + * @return pointer to destination buffer + */ +void *GH3X2X_Memcpy(void *pDest, const void *pSrc, GU32 unByteSize) +{ + GU8 *puchSrc = (GU8 *)pSrc; + GU8 *puchDest = (GU8 *)pDest; + GU32 unAlign = ((GU32)puchDest | (GU32)puchSrc) << 30; + + if ((pDest == GH3X2X_PTR_NULL) || (pSrc == GH3X2X_PTR_NULL) || (0 == unByteSize)) + { + return GH3X2X_PTR_NULL; + } + if (unAlign == 0) // if align 4 + { + while (unByteSize >= 4) + { + *(GU32 *)puchDest = *(GU32 *)puchSrc; + puchSrc += 4; + puchDest += 4; + unByteSize -= 4; + } + } + while (unByteSize) // bytes + { + *(GU8 *)puchDest = *(GU8 *)puchSrc; + puchSrc++; + puchDest++; + unByteSize--; + } + return pDest; +} + +/** + * @fn void *GH3X2X_Memset(void* pDest, GCHAR chVal, GU32 unByteSize) + * + * @brief memset() Re-implementation + * + * @attention None + * + * @param[in] chVal char val for set + * @param[in] unByteSize source buffer len + * @param[out] pDest pointer to destination buffer + * + * @return pointer to destination buffer + */ +void *GH3X2X_Memset(void* pDest, GCHAR chVal, GU32 unByteSize) +{ + GU8 *puchDest = (GU8 *)pDest; + GU32 unAlign = ((GU32)puchDest) << 30; + GU32 unWordVal = GH3X2X_AFE_MAKEUP_DWORD(chVal, chVal, chVal, chVal); + + if (pDest == GH3X2X_PTR_NULL) + { + return GH3X2X_PTR_NULL; + } + if (unAlign == 0) // if align 4 + { + while (unByteSize >= 4) + { + *(GU32 *)puchDest = unWordVal; + puchDest += 4; + unByteSize -= 4; + } + } + while (unByteSize) // bytes + { + *(GU8 *)puchDest = (GU8)chVal; + puchDest++; + unByteSize--; + } + return pDest; +} + +GU8 _crc8(GU8 *ptr,GS32 len) +{ + GS32 i; + GU8 crc = 0x00; + while(len--) + { + crc ^= *ptr++; + for(i=8;i>0;--i) + { + if(crc&0x80) + { + crc = (crc<<1)^0x31; + } + else + { + crc = (crc<<1); + } + crc = crc & 0xff; + } + } + return (GU8)(crc); +} + +void GH3X2X_AFE_LoadEfuse(GU8* puchEfuseBuffer,GU16 EfuseByteLen) +{ + if(EfuseByteLen < 24) + { + GH3X2X_INFO_LOG("EfuseByteLen is too short!!\r\n"); + return; + } + + GU16 usRegVal; + GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_MODE_LSB,GH3X2X_EFUSE_MODE_MSB,0); + GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_CHOOSE_LSB,GH3X2X_EFUSE_CHOOSE_MSB,0); + GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_CLK_EN_LSB,GH3X2X_EFUSE_CLK_EN_MSB,1); + GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_START_LSB,GH3X2X_EFUSE_START_MSB,1); + while(0 == GH3X2X_AFE_ReadRegBitField(GH3X2X_EFUSE_CTRL_STATUS_REG_ADDR,0,0)); + for(GU8 i = 0; i < 4; i++) + { + usRegVal = GH3X2X_AFE_READ_REG(GH3X2X_EFUSE_CTRL_RDATA_0_REG_ADDR + 2 * i); + puchEfuseBuffer[2*i] = (GU8)GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegVal); + puchEfuseBuffer[2*i + 1] = (GU8)GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegVal); + } + + GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_CHOOSE_LSB,GH3X2X_EFUSE_CHOOSE_MSB,1); + GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_START_LSB,GH3X2X_EFUSE_START_MSB,1); + while(0 == GH3X2X_AFE_ReadRegBitField(GH3X2X_EFUSE_CTRL_STATUS_REG_ADDR,0,0)); + for(GU8 i = 0; i < 4; i++) + { + usRegVal = GH3X2X_AFE_READ_REG(GH3X2X_EFUSE_CTRL_RDATA_0_REG_ADDR + 2 * i); + puchEfuseBuffer[8 + 2*i] = (GU8)GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegVal); + puchEfuseBuffer[8 + 2*i + 1] = (GU8)GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegVal); + } + + GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_CHOOSE_LSB,GH3X2X_EFUSE_CHOOSE_MSB,2); + GH3X2X_AFE_WriteRegBitField(GH3X2X_EFUSE_CTRL_CMD_REG_ADDR,GH3X2X_EFUSE_START_LSB,GH3X2X_EFUSE_START_MSB,1); + while(0 == GH3X2X_AFE_ReadRegBitField(GH3X2X_EFUSE_CTRL_STATUS_REG_ADDR,0,0)); + for(GU8 i = 0; i < 4; i++) + { + usRegVal = GH3X2X_AFE_READ_REG(GH3X2X_EFUSE_CTRL_RDATA_0_REG_ADDR + 2 * i); + puchEfuseBuffer[16 + 2*i] = (GU8)GH3X2X_AFE_GET_LOW_BYTE_FROM_WORD(usRegVal); + puchEfuseBuffer[16 + 2*i + 1] = (GU8)GH3X2X_AFE_GET_HIGH_BYTE_FROM_WORD(usRegVal); + } + + +} + +GS8 GH3X2X_AFE_CheckEfuseCrc(void) +{ + GS8 chRet = GH3X2X_AFE_RET_OK; + GU8 uchEfuseBuffArr[24]; + GH3X2X_AFE_LoadEfuse(uchEfuseBuffArr,24); + GU8 uchCrcArr[3]; + uchCrcArr[0] = _crc8(uchEfuseBuffArr,7); + uchCrcArr[1] = _crc8((uchEfuseBuffArr + 8),3); + uchCrcArr[2] = _crc8((uchEfuseBuffArr + 12),10); + if(uchCrcArr[0] != uchEfuseBuffArr[7] || uchCrcArr[1] != uchEfuseBuffArr[11] ||uchCrcArr[2] != uchEfuseBuffArr[22]) + { + GH3X2X_INFO_LOG("Efuse crc error!!\r\n"); + chRet = GH3X2X_AFE_RET_GENERIC_ERROR; + } + return chRet; +} + +void gh3x2x_control(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); + // GH3X2X_AFE_StartFunction(mode); + GH3X2X_AFE_Init(); + GH3X2X_AFE_StartSampling(1); + + } else { + + // uapi_pm_control(PM_APP_WAKE_NONEED); + GH3X2X_AFE_StopSampling(); + } +} \ 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 index 000000000..b1e628af0 --- /dev/null +++ b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_lead_off.c @@ -0,0 +1,748 @@ +#include "gh3x2x_afe_ecg.h" +#include "gh3x2x_afe_demo.h" + +#define RESAMPLE_800HZ_TO_500HZ 0 +#define RESAMPLE_800HZ_TO_250HZ 0 +#define RESAMPLE_320HZ_TO_250HZ 1 +#define RESAMPLE_256HZ_TO_250HZ 0 + + +#if __SUPPORT_ECG_PPG_DOWNSAMP__ +#define RESAMPLE_400HZ_TO_250HZ 1 +#else +#define RESAMPLE_400HZ_TO_250HZ 0 +#endif + +#define GH3X2X_PPG_START_SLOT 1 +#define GH3X2X_ECG_START_SLOT 0 + +#define GH3X2X_AFE_GET_ECG_CHANNEL_MAP(slotNum) (((slotNum << 5) | (3 <<3)) &0xF8) +#define GH3X2X_AFE_GET_PPG_CHANNEL_MAP(slotNum) (((slotNum << 5) | (0 <<3)) &0xF8) + +STGh3x2xSoftLeadOffDetInfo g_pstGh3x2xSoftLeadOffDetInfoEntity[1]; +STGh3x2xRsInfo g_pstGh3x2xEcgRsInfoEntity[1]; +const GU8 g_uchGh3x2xEcgChnlNumLimit = 1; +STGh3x2xSoftLeadOffDetInfo * const g_pstGh3x2xSoftLeadOffDetInfo = g_pstGh3x2xSoftLeadOffDetInfoEntity; +STGh3x2xRsInfo * const g_pstGh3x2xEcgRsInfo = g_pstGh3x2xEcgRsInfoEntity; + + +#if __SUPPORT_ECG_PPG_DOWNSAMP__ +#define GH3X2X_PPG_DOWNSAMP_CHNL_NUM 1 +const GU32 g_uchPPGDownSampleChnlNumLimit = GH3X2X_PPG_DOWNSAMP_CHNL_NUM; +STGh3x2xRsInfo g_pstGh3x2xPPGRsInfoEntity[GH3X2X_PPG_DOWNSAMP_CHNL_NUM]; +STGh3x2xRsInfo * const g_pstGh3x2xPPGRsInfo = g_pstGh3x2xPPGRsInfoEntity; +#endif + +//Ecg sample rate from hardware +static GU16 g_usEcgInputFs = GH3X2X_ECG_FS; // ecg sample rate 800/320/256 +static GU16 g_usEcgOutputFs = GH3X2X_ECG_DOWN_FS; // ecg down sample rate 500/250 + +/// down sample lead module(ECG PPG) +static GU8 g_uchDownSampleModule = DOWNSAMPLE_ECG; + +#define ADCREF 1800 +#define ADC_OFFSET (1<<23) +#define PI 3.14159265 +#define ABS(x) ( (x)>0?(x):(-(x)) ) +#define AMP_NUM 5 +#define IQ_NUM 48 + +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}; +#define winAmpCoef 4082 +//unsigned char gscFlagFrPrev = 0; +GU32 g_nLeadOffDetIqAmpThr = 1500;//unit: uv +long long g_lLeadOffDetIqAmp; +long long g_lLeadOffDetIqAmpThrRaw; +long long g_lLeadOffDetIqAmpFrThrRaw; + +GU32 g_nLeadOffDetIqAmpDiffThr = 1000;//unit: uv +long long g_lLeadOffDetIqAmpDiff; +long long g_lLeadOffDetIqAmpDiffThrRaw; +long long g_lLeadOffDetIqAmpDiffFrThrRaw; + +int COND_VAL_VALID_TIME = 1; +GU32 g_nLeadOffDetValThr = 80;//unit: mv +int g_LeadOffDetValThrRaw; + +#define SHIFTBITS 30 + +#if RESAMPLE_800HZ_TO_500HZ + 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, + -1747635, -1419445, -920670, -255820, 557070, 1485515, 2482735, 3488860, 4433375, 5238695, 5824850, 6114965, 6041350, 5551740, 4615280, 3227790, 1415785, -761100, -3209770, -5805610, -8396875, -10811545, -12866385, + -14377925, -15174745, -15110485, -14076620, -12014295, -8924190, -4873605, 0, 5489625, 11323885, 17176845, 22682405, 27452740, 31100030, 33260510, 33619540, 31936265, 28066360, 21981325, 13782945, 3711580, -7852615, + -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 }; +#endif +#if RESAMPLE_800HZ_TO_250HZ + 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, + 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, + -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, + 5149865, 1931900, -1612575, -5431990, -9464450, -13638290, -17872830, -22079425, -26162660, -30021820, -33552510, -36648435, -39203325, -41112955, -42277200, -42602135, -42002095, -40401670, -37737600, -33960495, -29036370, -22947970, -15695790, + -7298825, 2204995, 12758710, 24286615, 36694830, 49872305, 63692080, 78012930, 92681285, 107533410, 122397830, 137097950, 151454790, 165289835, 178427925, 190700125, 201946505, 212018845, 220783110, 228121755, 233935695, 238146055, 240695490, 241549195 }; +#endif + +#if RESAMPLE_400HZ_TO_250HZ +//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}; +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,}; +#endif + +#if RESAMPLE_320HZ_TO_250HZ + 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,}; +#endif +#if RESAMPLE_256HZ_TO_250HZ + 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,}; +#endif + +GS32* rsFirCoef; +GS32* rsFirCoef1; + +STGh3x2xDownSampleCalParamInfo pstECGDownSampCalParamInfo[1]; +#if __SUPPORT_ECG_PPG_DOWNSAMP__ +STGh3x2xDownSampleCalParamInfo pstPPGDownSampCalParamInfo[1]; +#endif + +void GH3X2X_DownSampleMarcoIni(GU16 usEcgSampleRate) +{ + switch (g_usEcgInputFs) + { + case 800: + if( usEcgSampleRate == 500) + { + pstECGDownSampCalParamInfo->uchDownSampleType = DOWNSAMPLE_800HZ_TO_500HZ; + } + else + { + pstECGDownSampCalParamInfo->uchDownSampleType = DOWNSAMPLE_800HZ_TO_250HZ; + } + break; + case 320: + if( usEcgSampleRate == 250) + { + pstECGDownSampCalParamInfo->uchDownSampleType = DOWNSAMPLE_320HZ_TO_250HZ; + } + break; + case 256: + if( usEcgSampleRate == 250) + { + pstECGDownSampCalParamInfo->uchDownSampleType = DOWNSAMPLE_256HZ_TO_250HZ; + } + break; + default: // do nothing + break; + } + + // ppg downsample ini + #if __SUPPORT_ECG_PPG_DOWNSAMP__ + pstPPGDownSampCalParamInfo->uchDownSampleType = DOWNSAMPLE_400HZ_TO_250HZ; + #endif +} + +void RsFirResetSingle(GU8 uchChipIndex, GU8 uchMode) +{ + STGh3x2xRsInfo * pstRsInfo; + GU8 uchChnNum = 0; + #if __SUPPORT_ECG_PPG_DOWNSAMP__ + if(DOWNSAMPLE_PPG == uchMode) + { + pstRsInfo = g_pstGh3x2xPPGRsInfo; + uchChnNum = g_uchPPGDownSampleChnlNumLimit; + } + #endif + + if(DOWNSAMPLE_ECG == uchMode) + { + pstRsInfo = g_pstGh3x2xEcgRsInfo; + uchChnNum = uchChipIndex+1; + } + + for( GU8 i=0; iuchDownSampleType) + { + pstECGDownSampCalParamInfo->rsFirCoef= (GS32*)rsFirCoef_800_500hz; + pstECGDownSampCalParamInfo->uchRsFirOrder = 182; + pstECGDownSampCalParamInfo->uchRsI = 5; + pstECGDownSampCalParamInfo->uchRsD = 8; + pstECGDownSampCalParamInfo->uchRsEnable = 1; + } + #endif + } + else if(usEcgSampleRate == 250) + { + #if RESAMPLE_800HZ_TO_250HZ + if(DOWNSAMPLE_800HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType) + { + pstECGDownSampCalParamInfo->rsFirCoef= (GS32*)rsFirCoef_800_250hz; + pstECGDownSampCalParamInfo->uchRsFirOrder = 250; + pstECGDownSampCalParamInfo->uchRsI = 5; + pstECGDownSampCalParamInfo->uchRsD = 16; + pstECGDownSampCalParamInfo->uchRsEnable = 1; + } + #endif + + #if RESAMPLE_320HZ_TO_250HZ + if(DOWNSAMPLE_320HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType) + { + pstECGDownSampCalParamInfo->rsFirCoef= (GS32*)rsFirCoef_320_250hz; + pstECGDownSampCalParamInfo->uchRsFirOrder = 50; + pstECGDownSampCalParamInfo->uchRsI = 1; + pstECGDownSampCalParamInfo->uchRsD = 1; + pstECGDownSampCalParamInfo->uchRsEnable = 1; + pstECGDownSampCalParamInfo->ufStep = 128; + } + #endif + + #if RESAMPLE_256HZ_TO_250HZ + if(DOWNSAMPLE_256HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType) + { + pstECGDownSampCalParamInfo->rsFirCoef= (GS32*)rsFirCoef_256_250hz; + pstECGDownSampCalParamInfo->uchRsFirOrder = 100; + pstECGDownSampCalParamInfo->uchRsI = 1; + pstECGDownSampCalParamInfo->uchRsD = 1; + pstECGDownSampCalParamInfo->uchRsEnable = 1; + pstECGDownSampCalParamInfo->ufStep = 1024; + } + #endif + } + else + { + pstECGDownSampCalParamInfo->uchRsEnable = 0; + return; + } + + if(pstECGDownSampCalParamInfo->uchRsFirOrder % 2) + { + pstECGDownSampCalParamInfo->uchRsFirCoefNum = ((pstECGDownSampCalParamInfo->uchRsFirOrder+1)/2) ; + } + else + { + pstECGDownSampCalParamInfo->uchRsFirCoefNum = ((pstECGDownSampCalParamInfo->uchRsFirOrder+2)/2); + } + pstECGDownSampCalParamInfo->uchRsBufSize = (pstECGDownSampCalParamInfo->uchRsFirOrder / pstECGDownSampCalParamInfo->uchRsI + 1); +} + +#if __SUPPORT_ECG_PPG_DOWNSAMP__ +void GH3X2X_PPGResampleConfig(GU16 usPPGSampleRate) +{ + RsFirReset(DOWNSAMPLE_PPG); + GH3X2X_DownSampleMarcoIni(usPPGSampleRate); + if(usPPGSampleRate == 250) + { + #if RESAMPLE_400HZ_TO_250HZ + pstPPGDownSampCalParamInfo->rsFirCoef = (GS32*)rsFirCoef_250hz2; + pstPPGDownSampCalParamInfo->uchRsFirOrder = 126; + pstPPGDownSampCalParamInfo->uchRsI = 5; + pstPPGDownSampCalParamInfo->uchRsD = 8; + pstPPGDownSampCalParamInfo->uchRsEnable = 1; + #else + pstPPGDownSampCalParamInfo->uchRsEnable = 0; + #endif + } + else + { + pstPPGDownSampCalParamInfo->uchRsEnable = 0; + return; + } + + if(pstPPGDownSampCalParamInfo->uchRsFirOrder % 2) + { + pstPPGDownSampCalParamInfo->uchRsFirCoefNum = ((pstPPGDownSampCalParamInfo->uchRsFirOrder+1)/2) ; + } + else + { + pstPPGDownSampCalParamInfo->uchRsFirCoefNum = ((pstPPGDownSampCalParamInfo->uchRsFirOrder+2)/2); + } + pstPPGDownSampCalParamInfo->uchRsBufSize = (pstPPGDownSampCalParamInfo->uchRsFirOrder / pstPPGDownSampCalParamInfo->uchRsI + 1); +} +#else +void GH3X2X_PPGResampleConfig(GU16 usPPGSampleRate) +{ + return; +} +#endif + +void GH3X2X_LeadOffDetectResetSingleChip(GU8 uchChipIndex) +{ + int i; + STGh3x2xSoftLeadOffDetInfo * pstSoftLeadOffDetInfo = g_pstGh3x2xSoftLeadOffDetInfo + uchChipIndex; + pstSoftLeadOffDetInfo -> snCounter = 0; + pstSoftLeadOffDetInfo -> sniqCounter = 0; + pstSoftLeadOffDetInfo -> snniVal = 0; + pstSoftLeadOffDetInfo -> snnqVal = 0; + pstSoftLeadOffDetInfo -> uchFastRecoryHistory = 0; + for (i = 0; i < AMP_NUM; i++) + pstSoftLeadOffDetInfo -> snniqAmp[i] = 0; +} + +void GH3X2X_LeadOffDetectReset(void) +{ + GH3X2X_LeadOffDetectResetSingleChip(0); +} + +void GH3X2X_ConfigLeadOffThr(GU32 uIQAmpThr, GU32 uIQAmpDiffThr,GU32 uValThr) +{ + g_nLeadOffDetIqAmpThr = uIQAmpThr; + g_lLeadOffDetIqAmp = ((long long)g_nLeadOffDetIqAmpThr * 20 * ADC_OFFSET / ADCREF/1000*IQ_NUM*1000/winAmpCoef); + g_lLeadOffDetIqAmpThrRaw = (g_lLeadOffDetIqAmp*g_lLeadOffDetIqAmp); + g_lLeadOffDetIqAmpFrThrRaw = (g_lLeadOffDetIqAmp*g_lLeadOffDetIqAmp / 20 / 20); + + g_nLeadOffDetIqAmpDiffThr = uIQAmpDiffThr; + g_lLeadOffDetIqAmpDiff = ((long long)g_nLeadOffDetIqAmpDiffThr * 20 * ADC_OFFSET / ADCREF/1000*IQ_NUM*1000/winAmpCoef); + g_lLeadOffDetIqAmpDiffThrRaw = (g_lLeadOffDetIqAmpDiff*g_lLeadOffDetIqAmpDiff); + g_lLeadOffDetIqAmpDiffFrThrRaw = (g_lLeadOffDetIqAmpDiff*g_lLeadOffDetIqAmpDiff / 20 / 20); + + g_nLeadOffDetValThr = uValThr; + g_LeadOffDetValThrRaw = (g_nLeadOffDetValThr * (20 * ADC_OFFSET / ADCREF)); +} + +GS32 GH3X2X_LeadOffDetectInit(void) +{ + GH3X2X_ECGResampleConfig(g_usEcgOutputFs); + + #if __SUPPORT_ECG_PPG_DOWNSAMP__ + GH3X2X_PPGResampleConfig(GH3X2X_PPG_DOWN_FS); + #endif + + GH3X2X_ConfigLeadOffThr(g_nLeadOffDetIqAmpThr, g_nLeadOffDetIqAmpDiffThr, g_nLeadOffDetValThr); + GH3X2X_LeadOffDetectReset(); + return 0; +} + +/** + * @fn GU8 GH3X2X_LeadOffDetect(GU8* puchFifoBuffer, GU16 usFifoBufferLen) + * + * @brief Lead off Detection, suppose the increment of normal ECG value in LEADOFF_DET_POINT_NUM+1 samples point + * not exceed LEADOFF_DET_THR_mV + * + * @attention None + * + * @param[in] puchFifoBuffer pointer to read fifo data buffer + * @param[in] usFifoBufferLen read fifo buffer len + * @param[out] None + * + * @return lead off status output + * @retval #0 not detect lead off + * @retval bit0=1 AdcValue larger than thresh + * @retval bit1=1 IQ Value larger than thresh + */ + +GU8 GH3X2X_LeadOffDetectSingleChip(GU8* puchFifoBuffer, GU16* pusFifoBufferLen, GU8 unChipIndex, GU8 uchEcgSlotNum) +{ + GU16 usByteIndexTmp = 0; + GS32 j; + GU8 uchRet = 0; + GU32 fifoVal; + GS32 adcVal; + GU8 flagFastRecovery; + GS32 absAdcVal; //ABS of adcVal + GS64 temp; + + STGh3x2xSoftLeadOffDetInfo * pstSoftLeadOffDetInfo = g_pstGh3x2xSoftLeadOffDetInfo + unChipIndex; + + for (usByteIndexTmp = 0; usByteIndexTmp < *pusFifoBufferLen; usByteIndexTmp += GH3X2X_AFE_FIFO_RAWDATA_SIZE) + { + if (GH3X2X_AFE_CHANNEL_MAP_GET(puchFifoBuffer[usByteIndexTmp]) == GH3X2X_AFE_GET_ECG_CHANNEL_MAP(uchEcgSlotNum)) + { + fifoVal = GH3X2X_AFE_MAKEUP_DWORD(puchFifoBuffer[usByteIndexTmp], puchFifoBuffer[usByteIndexTmp + 1],puchFifoBuffer[usByteIndexTmp + 2], puchFifoBuffer[usByteIndexTmp + 3]); + adcVal = (GS32)((fifoVal & 0x00FFFFFF)) - ADC_OFFSET; + flagFastRecovery = (fifoVal >> 26) & 0x01; + if(flagFastRecovery) + { + pstSoftLeadOffDetInfo->uchFastRecoryHistory = 1; + //GH3X2X_INFO_LOG("has fast recovery!!!!\r\n"); + } + if(0 == pstSoftLeadOffDetInfo->uchFastRecoryHistory) + { + //GH3X2X_INFO_LOG("Warning: No fast recovery!!!!\r\n"); + continue; + } + if (pstSoftLeadOffDetInfo-> uchFlagFrPrev != flagFastRecovery) + { + GH3X2X_LeadOffDetectReset(); + pstSoftLeadOffDetInfo->uchFastRecoryHistory = 1; + } + pstSoftLeadOffDetInfo-> uchFlagFrPrev = flagFastRecovery; + + //sample counter + if (pstSoftLeadOffDetInfo -> snCounter < 20000) + pstSoftLeadOffDetInfo -> snCounter++; + + if (flagFastRecovery == 0 && pstSoftLeadOffDetInfo -> snCounter>COND_VAL_VALID_TIME) + { + absAdcVal = ABS(adcVal); + if (absAdcVal > g_LeadOffDetValThrRaw) + uchRet |= 0x01; + } + if (pstSoftLeadOffDetInfo -> sniqCounter < IQ_NUM / 2) + { + temp = (GS64)adcVal*winCoef[pstSoftLeadOffDetInfo -> sniqCounter]; + } + else + { + temp = (GS64)adcVal*winCoef[IQ_NUM-1 - pstSoftLeadOffDetInfo -> sniqCounter]; + } + switch (pstSoftLeadOffDetInfo -> sniqCounter%4) + { + case 0: + pstSoftLeadOffDetInfo -> snniVal += temp; + break; + case 1: + pstSoftLeadOffDetInfo -> snnqVal += temp; + break; + case 2: + pstSoftLeadOffDetInfo -> snniVal -= temp; + break; + case 3: + pstSoftLeadOffDetInfo -> snnqVal -= temp; + break; + default: + break; + } + if (pstSoftLeadOffDetInfo -> sniqCounter == (IQ_NUM - 1)) + { + for (j = AMP_NUM-1; j >0; j--) + { + pstSoftLeadOffDetInfo -> snniqAmp[j] = pstSoftLeadOffDetInfo -> snniqAmp[j - 1]; + } + pstSoftLeadOffDetInfo -> snniVal = pstSoftLeadOffDetInfo -> snniVal >> 31; + pstSoftLeadOffDetInfo -> snnqVal = pstSoftLeadOffDetInfo -> snnqVal >> 31; + pstSoftLeadOffDetInfo -> snniqAmp[0] = pstSoftLeadOffDetInfo -> snniVal*(int)pstSoftLeadOffDetInfo -> snniVal + pstSoftLeadOffDetInfo -> snnqVal*(int)pstSoftLeadOffDetInfo -> snnqVal; + pstSoftLeadOffDetInfo -> snniVal = 0; + pstSoftLeadOffDetInfo -> snnqVal = 0; + + if (flagFastRecovery == 0) + { + if (pstSoftLeadOffDetInfo -> snniqAmp[0] > g_lLeadOffDetIqAmpThrRaw && pstSoftLeadOffDetInfo -> snniqAmp[1] > g_lLeadOffDetIqAmpThrRaw) + uchRet |= 0x02; + + if ((pstSoftLeadOffDetInfo -> snniqAmp[0] - pstSoftLeadOffDetInfo -> snniqAmp[2]) > g_lLeadOffDetIqAmpDiffThrRaw && (pstSoftLeadOffDetInfo -> snniqAmp[1] - pstSoftLeadOffDetInfo -> snniqAmp[2]) > g_lLeadOffDetIqAmpDiffThrRaw) + { + if(pstSoftLeadOffDetInfo ->snCounter > 2 * IQ_NUM) + { + uchRet |= 0x04; + } + } + } + else + { + if (pstSoftLeadOffDetInfo -> snniqAmp[0] > g_lLeadOffDetIqAmpFrThrRaw && pstSoftLeadOffDetInfo -> snniqAmp[1] > g_lLeadOffDetIqAmpFrThrRaw) + uchRet |= 0x08; + } + } + pstSoftLeadOffDetInfo -> sniqCounter++; + pstSoftLeadOffDetInfo -> sniqCounter = pstSoftLeadOffDetInfo -> sniqCounter%(IQ_NUM); + } // end of if (GH3X2X_AFE_CHANNEL_MAP_GET(puchFifoBuffer[usByteIndexTmp]) == g_uchEcgLeadChannelMap) + } // end of for (usByteIndexTmp = 0; usByteIndexTmp < usFifoBufferLen; usByteIndexTmp += GH3X2X_AFE_FIFO_RAWDATA_SIZE) + + return uchRet; +} + + + +void GH3x2xSetEcgOutputFs(GU16 usEcgOutputFs) +{ + g_usEcgOutputFs = usEcgOutputFs; +} + +GU8 GH3X2X_LeadOffDetect(GU8* puchFifoBuffer, GU16* pusFifoBufferLen, GU8 uchEcgSlotNum) +{ + GU8 uchRet = 0; + uchRet |= GH3X2X_LeadOffDetectSingleChip(puchFifoBuffer, pusFifoBufferLen, 0, uchEcgSlotNum); + if(g_uchGh3x2xEcgChnlNumLimit > 1) + { + uchRet |= GH3X2X_LeadOffDetectSingleChip(puchFifoBuffer, pusFifoBufferLen, 1, uchEcgSlotNum); + } + return uchRet; +} + +void GH3X2X_DownSampleCal( GU8 *puchFifoBuffer, GU16 usByteIndexTmp, GU16 *usRawdataBufIdx, GU16 usSampleRate, STGh3x2xRsInfo * pstRsInfo ,STGh3x2xDownSampleCalParamInfo * pstDownSampCalParamInfo) +{ + GU32 fifoVal; + GS32 adcVal; + GU8 chNo; + GU8 flagFastRecovery; + GS32 j; + + fifoVal = GH3X2X_AFE_MAKEUP_DWORD(puchFifoBuffer[usByteIndexTmp], puchFifoBuffer[usByteIndexTmp + 1], puchFifoBuffer[usByteIndexTmp + 2], puchFifoBuffer[usByteIndexTmp + 3]); + chNo = (fifoVal >> 27); + adcVal = (GS32)((fifoVal & 0x00FFFFFF)) - ADC_OFFSET; + + if(g_uchDownSampleModule == DOWNSAMPLE_ECG) + { + flagFastRecovery = (fifoVal >> 26) & 0x01; + if (pstRsInfo ->uchFlagFrPrev != flagFastRecovery) + { + GH3X2X_ECGResampleConfig(usSampleRate); + } + pstRsInfo ->uchFlagFrPrev = flagFastRecovery; + } + + #if __SUPPORT_ECG_PPG_DOWNSAMP__ + else if(g_uchDownSampleModule == DOWNSAMPLE_PPG) + { + flagFastRecovery = (fifoVal >> 26) & 0x01; + if (pstRsInfo ->uchFlagFrPrev != 1) + { + if(usSampleRate) + { + GH3X2X_PPGResampleConfig(usSampleRate); + } + } + pstRsInfo ->uchFlagFrPrev = 1; + } + #endif + + // ECG downsample + #if RESAMPLE_320HZ_TO_250HZ || RESAMPLE_256HZ_TO_250HZ + if((DOWNSAMPLE_320HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType) || (DOWNSAMPLE_256HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType)) + { + GS32 LinerAdcVal; + if(pstDownSampCalParamInfo->uchRsEnable) + { + GS32 k; + GS64 y; + + //?? + if (pstRsInfo ->snRsFirState > 0) + { + pstRsInfo ->snBufHead = pstRsInfo ->snBufHead - 1; + pstRsInfo ->snBufHead = pstRsInfo ->snBufHead < 0 ? (pstDownSampCalParamInfo->uchRsBufSize - 1) : pstRsInfo ->snBufHead; + pstRsInfo ->snRsXbuf[pstRsInfo ->snBufHead] = adcVal; + } + else + { + for (j = 0; j < pstDownSampCalParamInfo->uchRsFirOrder / pstDownSampCalParamInfo->uchRsI + 1; j++) + pstRsInfo ->snRsXbuf[j] = adcVal; + pstRsInfo ->snBufHead = pstDownSampCalParamInfo->uchRsBufSize - 1; + } + + k = pstRsInfo ->snBufHead; + y = 0; + for (j = 1; j < pstDownSampCalParamInfo->uchRsFirCoefNum; j = j + 1) // + { + y += ((GS64)pstRsInfo ->snRsXbuf[k] * pstDownSampCalParamInfo->rsFirCoef[j]); + k = (k + 1) % pstDownSampCalParamInfo->uchRsBufSize; + } + for (; j <(pstDownSampCalParamInfo->uchRsFirOrder+1); j = j + 1) // + { + y += ((GS64)pstRsInfo ->snRsXbuf[k] * pstDownSampCalParamInfo->rsFirCoef[pstDownSampCalParamInfo->uchRsFirOrder - j]); + k = (k + 1) % pstDownSampCalParamInfo->uchRsBufSize; + } + + y = y >> SHIFTBITS; + k = (GS32)y + ADC_OFFSET; // + if (k < 0) + k = 0; + else if (k>=(ADC_OFFSET * 2)) + k = (ADC_OFFSET * 2-1); + + // ??????? + if(pstRsInfo->uchLinearInterState >0) + { + #if RESAMPLE_320HZ_TO_250HZ + if(DOWNSAMPLE_320HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType) + { + if(pstRsInfo->fDownStep <=100) + { + LinerAdcVal = ((GU32)k*pstRsInfo->fDownStep + (100-pstRsInfo->fDownStep)*pstRsInfo->nRsLastRaw)/100; + pstRsInfo->nRsLastRaw = (GU32)k; + pstRsInfo->fDownStep = pstRsInfo->fDownStep + pstDownSampCalParamInfo->ufStep - 100; + pstRsInfo->uchLinearDataUpdate = 1; + } + else + { + pstRsInfo->nRsLastRaw = (GU32)k; + pstRsInfo->fDownStep = pstRsInfo->fDownStep - 100; + pstRsInfo->uchLinearDataUpdate = 0; + } + } + #endif + + #if RESAMPLE_256HZ_TO_250HZ + if(DOWNSAMPLE_256HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType) + { + if(pstRsInfo->fDownStep <=1000) + { + LinerAdcVal = (GU32)(((GS64)(k)*(GS64)(pstRsInfo->fDownStep) + (GS64)((1000-pstRsInfo->fDownStep)*(GS64)(pstRsInfo->nRsLastRaw)))/1000); + pstRsInfo->nRsLastRaw = (GU32)k; + pstRsInfo->fDownStep = pstRsInfo->fDownStep + pstDownSampCalParamInfo->ufStep - 1000; + pstRsInfo->uchLinearDataUpdate = 1; + } + else + { + pstRsInfo->nRsLastRaw = (GU32)k; + pstRsInfo->fDownStep = pstRsInfo->fDownStep - 1000; + pstRsInfo->uchLinearDataUpdate = 0; + } + } + #endif + } + else + { + LinerAdcVal = (GU32)k; + pstRsInfo->nRsLastRaw = (GU32)k; + pstRsInfo->fDownStep = pstRsInfo->fDownStep + pstDownSampCalParamInfo->ufStep; + pstRsInfo->uchLinearInterState =1; + pstRsInfo->uchLinearDataUpdate = 1; + } + + if(pstRsInfo->uchLinearDataUpdate == 1) + { + fifoVal = (((GU8)chNo)<<27) + (((GU8)flagFastRecovery)<<26) + ((GU32)LinerAdcVal/5); + puchFifoBuffer[*usRawdataBufIdx] = GH3X2X_AFE_GET_BYTE3_FROM_DWORD(fifoVal); + puchFifoBuffer[*usRawdataBufIdx + 1] = GH3X2X_AFE_GET_BYTE2_FROM_DWORD(fifoVal); + puchFifoBuffer[*usRawdataBufIdx + 2] = GH3X2X_AFE_GET_BYTE1_FROM_DWORD(fifoVal); + puchFifoBuffer[*usRawdataBufIdx + 3] = GH3X2X_AFE_GET_BYTE0_FROM_DWORD(fifoVal); + + *usRawdataBufIdx += GH3X2X_AFE_FIFO_RAWDATA_SIZE; + } + } + } + #endif + + #if RESAMPLE_800HZ_TO_500HZ ||RESAMPLE_800HZ_TO_250HZ || (RESAMPLE_400HZ_TO_250HZ & (__SUPPORT_ECG_PPG_DOWNSAMP__)) + if((DOWNSAMPLE_800HZ_TO_500HZ == pstECGDownSampCalParamInfo->uchDownSampleType)||(DOWNSAMPLE_800HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType)||(DOWNSAMPLE_400HZ_TO_250HZ == pstECGDownSampCalParamInfo->uchDownSampleType)) + { + if(pstDownSampCalParamInfo->uchRsEnable) + { + GS32 k; + GS64 y; + GS32 delta; + if (pstRsInfo ->snRsFirState > 0) + { + pstRsInfo ->snBufHead = pstRsInfo ->snBufHead - 1; + pstRsInfo ->snBufHead = pstRsInfo ->snBufHead < 0 ? (pstDownSampCalParamInfo->uchRsBufSize - 1) : pstRsInfo ->snBufHead; + pstRsInfo ->snRsXbuf[pstRsInfo ->snBufHead] = adcVal; + pstRsInfo ->nRsIcounter += pstDownSampCalParamInfo->uchRsI; + } + else + { + for (j = 0; j < pstDownSampCalParamInfo->uchRsFirOrder / pstDownSampCalParamInfo->uchRsI + 1; j++) + pstRsInfo ->snRsXbuf[j] = adcVal; + pstRsInfo ->nRsIcounter = 0; + pstRsInfo ->snRsFirState = 1; + pstRsInfo ->snBufHead = pstDownSampCalParamInfo->uchRsBufSize - 1; + } + + if (pstRsInfo ->nRrsDcounter >= pstRsInfo ->nRsIcounter && pstRsInfo ->nRrsDcounter < (pstRsInfo ->nRsIcounter + pstDownSampCalParamInfo->uchRsI)) + { + delta = pstRsInfo ->nRrsDcounter - pstRsInfo ->nRsIcounter; + k = pstRsInfo ->snBufHead; + y = 0; + for (j = delta; j < pstDownSampCalParamInfo->uchRsFirCoefNum; j = j + pstDownSampCalParamInfo->uchRsI) + { + y += ((GS64)pstRsInfo ->snRsXbuf[k] * pstDownSampCalParamInfo->rsFirCoef[j]); + k = (k + 1) % pstDownSampCalParamInfo->uchRsBufSize; + } + for (j = j; j <(pstDownSampCalParamInfo->uchRsFirOrder+1); j = j + pstDownSampCalParamInfo->uchRsI) + { + y += ((GS64)pstRsInfo ->snRsXbuf[k] * pstDownSampCalParamInfo->rsFirCoef[pstDownSampCalParamInfo->uchRsFirOrder - j]); + k = (k + 1) % pstDownSampCalParamInfo->uchRsBufSize; + } + pstRsInfo ->nRrsDcounter += pstDownSampCalParamInfo->uchRsD; + + y = y >> SHIFTBITS; + k = (GS32)y + ADC_OFFSET; + if (k < 0) + k = 0; + else if (k>=(ADC_OFFSET * 2)) + k = (ADC_OFFSET * 2-1); + fifoVal = (((GU8)chNo)<<27) + (((GU8)flagFastRecovery)<<26) + ((GU32)k); + puchFifoBuffer[*usRawdataBufIdx] = GH3X2X_AFE_GET_BYTE3_FROM_DWORD(fifoVal); + puchFifoBuffer[*usRawdataBufIdx + 1] = GH3X2X_AFE_GET_BYTE2_FROM_DWORD(fifoVal); + puchFifoBuffer[*usRawdataBufIdx + 2] = GH3X2X_AFE_GET_BYTE1_FROM_DWORD(fifoVal); + puchFifoBuffer[*usRawdataBufIdx + 3] = GH3X2X_AFE_GET_BYTE0_FROM_DWORD(fifoVal); + *usRawdataBufIdx += GH3X2X_AFE_FIFO_RAWDATA_SIZE; + } + } + } +#endif +} + +void GH3X2X_EcgPPGRsHandleSingleChip(GU8 *puchFifoBuffer, GU16 *pusFifoBufferLen, GU8 uchChipIndex, GU8 uchEcgSlotNum ,GU16 usSampleRate) +{ + GU16 usByteIndexTmp = 0; + GU16 usRawdataBufIdx = 0; + GU8 usCheckDataType = 0; // 1:ECG 2:PPG 0:other + + for (usByteIndexTmp = 0; usByteIndexTmp < *pusFifoBufferLen; usByteIndexTmp += GH3X2X_AFE_FIFO_RAWDATA_SIZE) + { + if (GH3X2X_AFE_CHANNEL_MAP_GET(puchFifoBuffer[usByteIndexTmp]) == GH3X2X_AFE_GET_ECG_CHANNEL_MAP((GU8)(GH3X2X_ECG_START_SLOT + uchEcgSlotNum))) + { + STGh3x2xRsInfo * pstRsInfo_ECG = g_pstGh3x2xEcgRsInfo + uchChipIndex; + g_uchDownSampleModule = DOWNSAMPLE_ECG; + GH3X2X_DownSampleCal( puchFifoBuffer, usByteIndexTmp, &usRawdataBufIdx, usSampleRate,pstRsInfo_ECG,pstECGDownSampCalParamInfo); + usCheckDataType =1; + } + + #if __SUPPORT_ECG_PPG_DOWNSAMP__ + if(g_uchPPGDownSampleChnlNumLimit && pstPPGDownSampCalParamInfo->uchRsEnable==1) + { + for(GU8 uchPPGSlotNumTmp = 0; uchPPGSlotNumTmp < g_uchPPGDownSampleChnlNumLimit; uchPPGSlotNumTmp++) + { + if (GH3X2X_AFE_CHANNEL_MAP_GET(puchFifoBuffer[usByteIndexTmp]) == GH3X2X_AFE_GET_PPG_CHANNEL_MAP((GU8)(GH3X2X_PPG_START_SLOT + uchPPGSlotNumTmp))) + { + STGh3x2xRsInfo * pstRsInfo_PPG = g_pstGh3x2xPPGRsInfo + uchPPGSlotNumTmp; + g_uchDownSampleModule = DOWNSAMPLE_PPG; + GH3X2X_DownSampleCal(puchFifoBuffer, usByteIndexTmp, &usRawdataBufIdx, usSampleRate,pstRsInfo_PPG,pstPPGDownSampCalParamInfo); + usCheckDataType =2; + } + } + } + #endif + if(!usCheckDataType) + { + if(pstECGDownSampCalParamInfo->uchRsEnable) + { + //this rawdata is not ECG data + puchFifoBuffer[usRawdataBufIdx] = puchFifoBuffer[usByteIndexTmp]; + puchFifoBuffer[usRawdataBufIdx + 1] = puchFifoBuffer[usByteIndexTmp + 1]; + puchFifoBuffer[usRawdataBufIdx + 2] = puchFifoBuffer[usByteIndexTmp + 2]; + puchFifoBuffer[usRawdataBufIdx + 3] = puchFifoBuffer[usByteIndexTmp + 3]; + usRawdataBufIdx += GH3X2X_AFE_FIFO_RAWDATA_SIZE; + } + } + usCheckDataType = 0; + } // end of for (usByteIndexTmp = 0; usByteIndexTmp < usFifoBufferLen; usByteIndexTmp += GH3X2X_AFE_FIFO_RAWDATA_SIZE) + *pusFifoBufferLen = usRawdataBufIdx; +} + +GU8 GH3X2X_AFE_EcgRsHandle(GU8* puchFifoBuffer, GU16* pusFifoBufferLen, GU8 uchEcgSlotNum, GU16 usEcgSampleRate) +{ + if(pstECGDownSampCalParamInfo->uchRsEnable == 1) + { + GH3X2X_EcgPPGRsHandleSingleChip(puchFifoBuffer, pusFifoBufferLen, 0,uchEcgSlotNum,usEcgSampleRate); + return 1; + } + else + { + return 0; + } +} + +/********END OF FILE********* Copyright (c) 2003 - 2022, Goodix Co., Ltd. ********/ + + 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 index 000000000..c067d1a5b --- /dev/null +++ b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_afe_user.c @@ -0,0 +1,468 @@ +#include "gh3x2x_afe_user.h" +#include "gh3x2x_afe_drv.h" +#include "pinctrl_porting.h" +#include "hal_gpio.h" +#include "i2c.h" +#include "pm_definition.h" +#if GH3X2X_AFE_MP_MODE +// #include "gh3x2x_mp_common.h" +#endif + +#include "los_tick.h" +#include "debug_print.h" + +#ifdef GOODIX_DEMO_PLATFORM +#include "gh3x2x_demo_goodix_PLATFORM.h" +#else + + +#include "spi.h" + +#include "custom_utils.h" + +#define GOODIX_PLATFORM_SPI_WRITE_ENTITY(write_buffer, length) +#define GOODIX_PLATFORM_SPI_READ_ENTITY() +#define GOODIX_PLATFORM_SPI_CS_CTRL_ENTITY() +#define GOODIX_PLATFORM_SPI_RESET_PIN_ENTITY() +#define GOODIX_PLATFORM_INT_HANDLER_CALL_BACK_ENTITY() +#define GOODIX_PLATFORM_LOG_ENTITY() +#define GOODIX_PLATFORM_DELAY_US_ENTITY() +#define GOODIX_PLATFORM_DELAY_MS_ENTITY() +#define GOODIX_PLATFORM_DELAY_MS_ENTITY() +#define GOODIX_PLATFORM_INT_INIT_ENTITY() +#define GOODIX_PLATFORM_RESET_PIN_INIT_ENTITY() +#define GOODIX_PLATFORM_SPI_INIT_ENTITY() +#define GOODIX_PLATFORM_I2C_WRITE_ENTITY(device_id, write_buffer,length) +#define GOODIX_PLATFORM_I2C_INIT_ENTITY() +#define GOODIX_PLATFORM_I2C_READ_ENTITY(device_id, write_buffer, write_length, read_buffer, read_length) +#endif + +#define GH3X2X_CS S_MGPIO3 +#define GH3X2X_CLK S_MGPIO2 +#define GH3X2X_MOSI S_MGPIO1 +#define GH3X2X_MISO S_MGPIO0 + +#define H_INT S_AGPIO_R6 + +#define GH3X2X_SPI_BUS SPI_BUS_0 +#define GH3X2X_I2C_BUS I2C_BUS_2 + +/** + * @fn void hal_gh3x2x_afe_DelayUs(GU16 usUsec) + * + * @brief Delay in us,user should register this function into driver lib + * + * @attention None + * + * @param[in] None + * @param[out] None + * + * @return None + */ + +void hal_gh3x2x_afe_DelayUs(GU16 usUsec) +{ + // GH3X2X_AFE_UNUSED_VAR(usUsec); + // GOODIX_PLATFORM_DELAY_US_ENTITY(); + LOS_Udelay(usUsec); + +} + +/** + * @fn void hal_gh3x2x_afe_BspDelayMs(GU16 usMsec) + * + * @brief Delay in ms + * + * @attention None + * + * @param[in] None + * @param[out] None + * + * @return None + */ +void hal_gh3x2x_afe_DelayMs(GU16 usMsec) +{ + // GH3X2X_AFE_UNUSED_VAR(usMsec); + // GOODIX_PLATFORM_DELAY_MS_ENTITY(); + LOS_Mdelay(usMsec); +} + + + + + + +#if ( GH3X2X_AFE_COM_INTERFACE_TYPE == GH3X2X_AFE_COM_INTERFACE_I2C ) + +/* i2c interface */ +/** + * @fn void hal_gh3x2x_afe_i2c_init(void) + * + * @brief hal i2c init for gh3x2x_afe + * + * @attention None + * + * @param[in] None + * @param[out] None + * + * @return None + */ +void hal_gh3x2x_afe_i2c_init(void) +{ + + /* code implement by user */ + GOODIX_PLATFORM_I2C_INIT_ENTITY(); + +} + +/** + * @fn uint8_t hal_gh3x2x_afe_i2c_write(uint8_t device_id, const uint8_t write_buffer[], uint16_t length) + * + * @brief hal i2c write for gh3x2x_afe + * + * @attention device_id is 8bits, if platform i2c use 7bits addr, should use (device_id >> 1) + * + * @param[in] device_id device addr + * @param[in] write_buffer write data buffer + * @param[in] length write data len + * @param[out] None + * + * @return status + * @retval #1 return successfully + * @retval #0 return error + */ +GU8 hal_gh3x2x_afe_i2c_write(GU8 device_id, const GU8 write_buffer[], GU16 length) +{ + // custom_i2c_transfer(0x14,write_buffer, length, NULL, 0, GH3X2X_I2C_BUS); + custom_i2c_write_reg(0x14, 0, 0, write_buffer, length, GH3X2X_I2C_BUS); + return 1; +} + +/** + * @fn uint8_t hal_gh3x2x_afe_i2c_read(uint8_t device_id, const uint8_t write_buffer[], uint16_t write_length, + * uint8_t read_buffer[], uint16_t read_length) + * + * @brief hal i2c read for gh3x2x_afe + * + * @attention device_id is 8bits, if platform i2c use 7bits addr, should use (device_id >> 1) + * + * @param[in] device_id device addr + * @param[in] write_buffer write data buffer + * @param[in] write_length write data len + * @param[in] read_length read data len + * @param[out] read_buffer pointer to read buffer + * + * @return status + * @retval #1 return successfully + * @retval #0 return error + */ +GU8 hal_gh3x2x_afe_i2c_read(GU8 device_id, const GU8 write_buffer[], GU16 write_length, GU8 read_buffer[], GU16 read_length) +{ + // custom_i2c_transfer(0x14,write_buffer, write_length, read_buffer, read_length, GH3X2X_I2C_BUS); + // custom_i2c_write_reg(0x14, 0, 0, write_buffer, length, GH3X2X_I2C_BUS); + custom_i2c_read_regs(0x14, write_buffer, write_length, read_buffer,read_length, GH3X2X_I2C_BUS); + return 1; +} + +#else + +/* spi interface */ +/** + * @fn void hal_gh3x2x_afe_spi_init(void) + * + * @brief hal spi init for gh3x2x_afe + * + * @attention None + * + * @param[in] None + * @param[out] None + * + * @return None + */ + +void hal_gh3x2x_afe_spi_init(void) +{ + /* init spi and cs pin */ + GOODIX_PLATFORM_SPI_INIT_ENTITY(); +} + +/** + * @fn GU8 hal_gh3x2x_afe_spi_write(GU8 write_buffer[], GU16 length) + * + * @brief hal spi write for gh3x2x_afe + * + * @attention if __gh3x2x_afe_SPI_TYPE__ == __gh3x2x_afe_SPI_TYPE_SOFTWARE_CS__ , user need generate timming: write_buf[0](W) + write_buf[1](W) + ... + * @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 + * + * @param[in] write_buffer write data buffer + * @param[in] length write data len + * @param[out] None + * + * @return status + * @retval #1 return successfully + * @retval #0 return error + */ +GU8 hal_gh3x2x_afe_spi_write(GU8 write_buffer[], GU16 length) +{ + uint8_t cnt = pm_veto_get_id_cnt(PM_ID_HEART); + if (cnt == 0) + { + uapi_pm_add_sleep_veto(PM_ID_HEART); + } + + errcode_t ret; + + // GOODIX_PLATFORM_SPI_WRITE_ENTITY(write_buffer, length); + spi_xfer_data_t sdata ={0} ; + sdata.tx_buff = write_buffer; + sdata.tx_bytes = length; + sdata.rx_buff = NULL; + sdata.rx_bytes = 0; + + ret = uapi_spi_master_write(GH3X2X_SPI_BUS, &sdata, 0XFF); + if (ret != ERRCODE_SUCC) + printf("spi write data fail! ret=0x%x\n", ret); + + cnt = pm_veto_get_id_cnt(PM_ID_HEART); + if (cnt == 1) + { + uapi_pm_remove_sleep_veto(PM_ID_HEART); + } + + return 1; +} + + +#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS) +/** + * @fn GU8 hal_gh3x2x_afe_spi_read(GU8 read_buffer[], GU16 length) + * + * @brief hal spi read for gh3x2x_afe + * + * @attention user need generate timming: read_buf[0](R) + write_buf[1](R) + ... + * + * @param[in] read_length read data len + * @param[out] read_buffer pointer to read buffer + * + * @return status + * @retval #1 return successfully + * @retval #0 return error + */ +GU8 hal_gh3x2x_afe_spi_read(GU8 read_buffer[], GU16 length) +{ + uint8_t cnt = pm_veto_get_id_cnt(PM_ID_HEART); + if (cnt == 0) + { + uapi_pm_add_sleep_veto(PM_ID_HEART); + } + + errcode_t ret; + // GH3X2X_AFE_UNUSED_VAR(read_buffer); + // GH3X2X_AFE_UNUSED_VAR(length); + // GOODIX_PLATFORM_SPI_READ_ENTITY(); + + spi_xfer_data_t sdata ={0} ; + sdata.tx_buff = NULL; + sdata.tx_bytes = 0; + sdata.rx_buff = read_buffer; + sdata.rx_bytes = length; + + ret = uapi_spi_master_read(GH3X2X_SPI_BUS, &sdata, 0XFF); + + cnt = pm_veto_get_id_cnt(PM_ID_HEART); + if (cnt == 1) + { + uapi_pm_remove_sleep_veto(PM_ID_HEART); + } + + return 1; +} +#elif (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_HARDWEAR_CS) +/** + * @fn GU8 hal_gh3x2x_afe_spi_write_F1_and_read(GU8 read_buffer[], GU16 length) + * + * @brief hal spi write F1 and read for gh3x2x_afe + * + * @attention user need generate timming: CS LOW + F1(W) + read_buf[0](R) + read_buf[1](R) + ... + CS HIGH + * + * @param[in] write_buf write data + * @param[in] length write data len + * + * @return status + * @retval #1 return successfully + * @retval #0 return error + */ +GU8 hal_gh3x2x_afe_spi_write_F1_and_read(GU8 read_buffer[], GU16 length) +{ + // GU8 ret = 1; + // GH3X2X_AFE_UNUSED_VAR(read_buffer); + // GH3X2X_AFE_UNUSED_VAR(length); + // GOODIX_PLATFORM_SPI_READ_ENTITY(); + + // return ret; + + errcode_t ret = 1; + // GH3X2X_AFE_UNUSED_VAR(read_buffer); + // GH3X2X_AFE_UNUSED_VAR(length); + // GOODIX_PLATFORM_SPI_READ_ENTITY(); + + spi_xfer_data_t sdata ={0} ; + sdata.tx_buff = NULL; + sdata.tx_bytes = 0; + sdata.rx_buff = read_buffer; + sdata.rx_bytes = length; + + ret = uapi_spi_master_read(GH3X2X_SPI_BUS, &sdata, 0XFF); + if (ret != ERRCODE_SUCC) + printf("spi read data fail! ret=0x%x\n", ret); + return 1; +} +#endif + +/** + * @fn void hal_gh3x2x_afe_spi_cs_ctrl(GU8 cs_pin_level) + * + * @brief hal spi cs pin ctrl for gh3x2x_afe + * + * @attention pin level set 1 [high level] or 0 [low level] + * + * @param[in] cs_pin_level spi cs pin level + * @param[out] None + * + * @return None + */ + + + +#if (GH3X2X_AFE_SPI_TYPE == GH3X2X_AFE_SPI_SOFTWARE_CS) +void hal_gh3x2x_afe_spi_cs_ctrl(GU8 cs_pin_level) +{ + // GH3X2X_AFE_UNUSED_VAR(cs_pin_level); + // GOODIX_PLATFORM_SPI_CS_CTRL_ENTITY(); + + uapi_pin_set_mode(GH3X2X_CS, (pin_mode_t)HAL_PIO_FUNC_SPI0); + uapi_gpio_set_dir(GH3X2X_CS, GPIO_DIRECTION_OUTPUT); + uapi_gpio_set_val(GH3X2X_CS, cs_pin_level); + +} +#endif + +#endif + +#if (GH3X2X_AFE_RESET_TYPE == GH3X2X_AFE_RESET_HARDWARE) +/** + * @fn void hal_gh3x2x_afe_int_init(void) + * + * @brief gh3x2x_afe int init + * + * @attention None + * + * @param[in] None + * @param[out] None + * + * @return None + */ + + + +void hal_gh3x2x_afe_reset_pin_init(void) +{ + GOODIX_PLATFORM_RESET_PIN_INIT_ENTITY(); +} + +/** + * @fn void hal_gh3x2x_afe_reset_pin_ctrl(GU8 pin_level) + * + * @brief hal reset pin ctrl for gh3x2x_afe + * + * @attention pin level set 1 [high level] or 0 [low level] + * + * @param[in] pin_level reset pin level + * @param[out] None + * + * @return None + */ + +void hal_gh3x2x_afe_reset_pin_ctrl(GU8 pin_level) +{ + GH3X2X_AFE_UNUSED_VAR(pin_level); + GOODIX_PLATFORM_SPI_RESET_PIN_ENTITY(); +} + +#endif + +/** + * @fn void hal_gh3x2x_afe_int_init(void) + * + * @brief gh3x2x_afe int init + * + * @attention None + * + * @param[in] None + * @param[out] None + * + * @return None + */ + + +void hal_gh3x2x_afe_int_init(void) +{ + // GOODIX_PLATFORM_INT_INIT_ENTITY(); + uapi_pin_set_ie(H_INT,HAL_PIO_IE_ENBALE); +} + +void hal_gh3x2x_afe_int_deinit(void) +{ + // GOODIX_PLATFORM_INT_INIT_ENTITY(); + uapi_pin_set_ie(H_INT,HAL_PIO_IE_DISABLE); +} + +#if (GH3X2X_AFE_PRO_BY_INT == GH3X2X_AFE_PRO_TYPE) +/** + * @fn void hal_gh3x2x_afe_int_handler_call_back(void) + * + * @brief call back of gh3x2x_afe int handler + * + * @attention None + * + * @param[in] None + * @param[out] None + * + * @return None + */ +void hal_gh3x2x_afe_int_handler_call_back(void) +{ +/****************** DO NOT MODITY ****************************************************************/ + GH3X2X_AFE_SetNeedWakeUpGh3x2xFlag(0); //not need wake up gh3x2x_afe when process int event + g_uchGh3x2xAfeIntCallBackIsCalled = 1; +#if GH3X2X_AFE_MP_MODE + // GH3X2X_MP_SET_INT_FLAG(); //gh3x2x mp test must call it +#endif +/****************** DO NOT MODITY ****************************************************************/ + + + + GOODIX_PLATFORM_INT_HANDLER_CALL_BACK_ENTITY(); +} + +#endif + +/** + * @fn void GH3X2X_AFE_Log(char *log_string) + * + * @brief for debug version, log + * + * @attention this function must define that use debug version lib + * + * @param[in] log_string pointer to log string + * @param[out] None + * + * @return None + */ +void GH3X2X_AFE_Log(GCHAR *log_string) +{ + // GH3X2X_AFE_UNUSED_VAR(log_string); + // GOODIX_PLATFORM_LOG_ENTITY(); + PRINT("%s", log_string); +} + 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 index 000000000..385077b6b --- /dev/null +++ b/code/sdk/drivers/peripheral/ppg/gh3x2x/src/gh3x2x_hal.c @@ -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 +#include +#include +#include +#include +#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 diff --git a/code/sdk/drivers/peripheral/ppg/hal/ppg_hal.c b/code/sdk/drivers/peripheral/ppg/hal/ppg_hal.c index 4c4887112..a38e2d030 100644 --- a/code/sdk/drivers/peripheral/ppg/hal/ppg_hal.c +++ b/code/sdk/drivers/peripheral/ppg/hal/ppg_hal.c @@ -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: * @@ -33,6 +33,11 @@ #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(); diff --git a/code/sdk/drivers/peripheral/ppg/hal/ppg_hal.h b/code/sdk/drivers/peripheral/ppg/hal/ppg_hal.h index d878a71b9..8cda8ad72 100644 --- a/code/sdk/drivers/peripheral/ppg/hal/ppg_hal.h +++ b/code/sdk/drivers/peripheral/ppg/hal/ppg_hal.h @@ -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 diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_bsp.c b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_bsp.c index a208d8120..f6b2a8e6a 100644 --- a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_bsp.c +++ b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_bsp.c @@ -2,7 +2,7 @@ * @Author: penglei 1624952103@qq.com * @Date: 2025-05-27 11:09:04 * @LastEditors: penglei 1624952103@qq.com - * @LastEditTime: 2025-06-04 15:38:48 + * @LastEditTime: 2025-06-09 14:27:54 * @FilePath: /sdk615/code/sdk/zhihui/drivers/ppg/pah8009/sensor/pah800x_bsp.c * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ @@ -11,6 +11,10 @@ #include "custom_utils.h" #include "systick.h" +#ifdef SUPPORT_CYWEE_SERVICE +#include "cywee_hal.h" +#endif + //============================================================================ // Definition //============================================================================ @@ -81,5 +85,11 @@ void pah_print( void ReadGSensor(float *x, float *y, float *z) { - +#ifdef SUPPORT_CYWEE_SERVICE + gsenson_t data = {0}; + gsensor_get_n_data(1,&data); + *x = data.x; + *y = data.y; + *z = data.z; +#endif } diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_main.c b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_main.c index 6cb58fa9d..f824d6350 100644 --- a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_main.c +++ b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah800x_main.c @@ -507,6 +507,7 @@ void hr_alg_task(void) // data = cywee_wear_status; // func(PPG_MSG_TYPE_WEARSTAT_UPDATE, &data, 1); time_cnt = 0; + hr = 0; } #endif report_hr_data(&ppg_mems_data_alg, ret, hr, hr_grader); @@ -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. /***********************G sensor explanation end***********************************/ - ppg_mems_data.MEMS_Data[0] = mems_data[0];//ReadGSensorX(); - ppg_mems_data.MEMS_Data[1] = mems_data[1];//ReadGSensorY(); - ppg_mems_data.MEMS_Data[2] = mems_data[2];//ReadGSensorZ(); + ReadGSensor(&mems_data[0],&mems_data[1],&mems_data[2]); + + ppg_mems_data.MEMS_Data[0] = mems_data[0] * 2048 / 10;//ReadGSensorX(); + ppg_mems_data.MEMS_Data[1] = mems_data[1] * 2048 / 10;//ReadGSensorY(); + ppg_mems_data.MEMS_Data[2] = mems_data[2] * 2048 / 10;//ReadGSensorZ(); + // 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]); ppg_mems_data.duration = duration; ppg_mems_data.ppg_data = ppg_data ; diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_8009_reg_arr_default_20220623.h b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_8009_reg_arr_default_20220623.h index abf28f21c..a05c1c17f 100644 --- a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_8009_reg_arr_default_20220623.h +++ b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_8009_reg_arr_default_20220623.h @@ -84,6 +84,13 @@ static const uint8_t PAH8009_REG_DIW_4MM_G_IR_PPG[][2] = { { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8] { 0x4E,0x00 },//R_TouchDetection_Count_Th[4:0] { 0x4F,0x00 },//R_NoTouchDetection_Count_Th[4:0] +// #ifdef TOUCH_DETECT_TRH_1 +// { 0x4C,0x20 },//R_TouchDetection_Th_Low[7:0] +// { 0x4D,0x03 },//R_TouchDetection_Th_Low[13:8] //1800 ir阈值 +// #else +// { 0x4C,0x00 },//R_TouchDetection_Th_Low[7:0] //1280 ir阈值 +// { 0x4D,0x05 },//R_TouchDetection_Th_Low[13:8] +// #endif { 0xEB,0x80 },//update_flag }; diff --git a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x_config.h b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x_config.h index 0e3d8530f..f02f9dcfb 100644 --- a/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x_config.h +++ b/code/sdk/drivers/peripheral/ppg/pah8009/sensor/pah_800x_config.h @@ -9,7 +9,7 @@ * Select LED Supplier * If Use new Supplier LED , Need to define LED_SUPPLIER_NEW */ -//#define LED_SUPPLIER_NEW +#define LED_SUPPLIER_NEW /* diff --git a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.c b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.c index 314b0b295..f9225cecc 100644 --- a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.c +++ b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.c @@ -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"); diff --git a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.h b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.h index 60ded8314..eb4170a67 100644 --- a/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.h +++ b/code/sdk/drivers/peripheral/rotary_encoder/mixo/mixo_service.h @@ -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 */ diff --git a/code/sdk/drivers/peripheral/slip/cat1Service/cat1_ctl.cpp b/code/sdk/drivers/peripheral/slip/cat1Service/cat1_ctl.cpp index a087994b5..26dfa8a74 100644 --- a/code/sdk/drivers/peripheral/slip/cat1Service/cat1_ctl.cpp +++ b/code/sdk/drivers/peripheral/slip/cat1Service/cat1_ctl.cpp @@ -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 diff --git a/code/sdk/drivers/peripheral/utils/custom_utils.c b/code/sdk/drivers/peripheral/utils/custom_utils.c index a7e3f5e44..2d4ff83bb 100644 --- a/code/sdk/drivers/peripheral/utils/custom_utils.c +++ b/code/sdk/drivers/peripheral/utils/custom_utils.c @@ -79,6 +79,10 @@ #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) { diff --git a/code/sdk/middleware/chips/brandy/pm/include/pm_definition.h b/code/sdk/middleware/chips/brandy/pm/include/pm_definition.h index 15be90f31..b4eb91933 100755 --- a/code/sdk/middleware/chips/brandy/pm/include/pm_definition.h +++ b/code/sdk/middleware/chips/brandy/pm/include/pm_definition.h @@ -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; diff --git a/code/sdk/middleware/chips/brandy/pm/pm.c b/code/sdk/middleware/chips/brandy/pm/pm.c index 6c66f12c6..4fb1675ba 100755 --- a/code/sdk/middleware/chips/brandy/pm/pm.c +++ b/code/sdk/middleware/chips/brandy/pm/pm.c @@ -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 index 000000000..aa0af424c 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 index 000000000..12f9d8bda 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 index 000000000..40adc6ff8 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 index 000000000..6f04c269e Binary files /dev/null and b/code/sdk/middleware/services/gui/uikit/brandy-native-js-n9/libuikit_ext.a differ diff --git a/code/sdk/middleware/services/gui/uikit/proprietary/src/service/src/graphic_service_wrapper.cpp b/code/sdk/middleware/services/gui/uikit/proprietary/src/service/src/graphic_service_wrapper.cpp index 8024e6377..eb630120e 100755 --- a/code/sdk/middleware/services/gui/uikit/proprietary/src/service/src/graphic_service_wrapper.cpp +++ b/code/sdk/middleware/services/gui/uikit/proprietary/src/service/src/graphic_service_wrapper.cpp @@ -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 index 000000000..cddab4546 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 index 000000000..6feed1e55 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 index 000000000..d8a248b6e 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 index 000000000..aaa672c05 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 index 000000000..eae8d083f 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 index 000000000..d4c567f44 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 index 000000000..265db3d5c 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 index 000000000..c3950703e Binary files /dev/null and b/code/sdk/open_source/openharmony/third_party/jerryscript/brandy-native-js-n9/libjerryscript.a differ