soft version 2.32

Feature or issues
- Add silent OTA function
- The FMR's buzzer is dynamically modified based on the battery voltage
- Prohibit OTA and FMR from working at the same time
- The backlight time is changed from 3 seconds to 5 seconds

bug: N/A
test: manual
Change-Id: Id29b2718db3b7c6f86b245d8e03c3b051142891f
diff --git a/vendor/827x_ble_remote/app.c b/vendor/827x_ble_remote/app.c
index 9ead7e2..2b7bfa2 100644
--- a/vendor/827x_ble_remote/app.c
+++ b/vendor/827x_ble_remote/app.c
@@ -1561,8 +1561,6 @@
     ////////////////// OTA relative ////////////////////////
     bls_ota_clearNewFwDataArea(); //must
 
-    bls_ota_init_handle(OTA_CMD_OUT_DP_H);
-
 #endif
     app_ui_init_normal();
     advertise_tick_retime();
@@ -1732,7 +1730,11 @@
     app_backlight_task();
 
     #if (BATT_CHECK_ENABLE)
-        if(battery_get_detect_enable() && clock_time_exceed(lowBattDet_tick, 300000) ){
+        u32 my_battery_detect_interval = 300000;
+        if(app_fmr_is_busy()){
+            my_battery_detect_interval = 150000;
+        }
+        if(battery_get_detect_enable() && clock_time_exceed(lowBattDet_tick, my_battery_detect_interval) ){
             lowBattDet_tick = clock_time();
             #if(VBAT_LEAKAGE_PROTECT_EN)
 
diff --git a/vendor/827x_ble_remote/app_att.c b/vendor/827x_ble_remote/app_att.c
index c4ecc90..405aa00 100644
--- a/vendor/827x_ble_remote/app_att.c
+++ b/vendor/827x_ble_remote/app_att.c
@@ -35,6 +35,7 @@
 #include "app_test.h"
 #include "./app_find_me/app_fms.h"
 #include "../../version.h"
+#include "./app_fmr/app_buzzer.h"
 
 typedef struct
 {
@@ -300,7 +301,7 @@
 static const u8 my_OtaUUID[16]           = {TELINK_SPP_DATA_OTA};
 static const u8 my_OtaServiceUUID[16]    = TELINK_OTA_UUID_SERVICE;
 
-static u8 my_OtaData         = 0x00;
+static u8 my_OtaData         = 0x01;
 _attribute_data_retention_ u16 my_Otaccc = 0;
 
 static const u8  my_OtaName[] = {'O', 'T', 'A'};
@@ -609,6 +610,12 @@
 
     result = app_ota_write(p);
 
+    /* FMR task */
+#if FIND_ME_ENABLE
+    app_fmr_task();
+    app_buzzer_task();
+#endif
+
     return result;
 }
 
diff --git a/vendor/827x_ble_remote/app_custom.c b/vendor/827x_ble_remote/app_custom.c
index f4bc7df..ad87325 100644
--- a/vendor/827x_ble_remote/app_custom.c
+++ b/vendor/827x_ble_remote/app_custom.c
@@ -804,7 +804,7 @@
     u16 my_BoostGpio = 0x00;
 
     flash_read_page(APP_EN_BACKLIGHT,   sizeof(my_Backlight), &my_Backlight);
-    flash_read_page(APP_BOOST_PIN,      sizeof(my_BoostGpio), &my_BoostGpio);
+    flash_read_page(APP_BOOST_PIN,      sizeof(my_BoostGpio), (u8 *)&my_BoostGpio);
 
     /* disable backlight when the value is 0xff */
     app_backlight_set_ability(my_Backlight, my_BoostGpio);
diff --git a/vendor/827x_ble_remote/app_fmr/app_buzzer.c b/vendor/827x_ble_remote/app_fmr/app_buzzer.c
index 4c37800..de875cb 100644
--- a/vendor/827x_ble_remote/app_fmr/app_buzzer.c
+++ b/vendor/827x_ble_remote/app_fmr/app_buzzer.c
@@ -26,6 +26,7 @@
 #include "drivers.h"
 #include "stack/ble/ble.h"
 #include "../app_ui.h"
+#include "../app_ota.h"
 
 #include "app_buzzer.h"
 #include "app_buzzer_song.h"
@@ -51,11 +52,37 @@
 
 
 
+
+
+
+
 typedef struct{
-    app_buzzer_symbol_t* song;
-    int size;
+    app_buzzer_symbol_t*    song;
+    int                     size;
 }app_buzzer_song_t;
 
+typedef struct {
+    APP_BUZZER_STATUS_T     status;
+    unsigned char           sound_level;
+
+    unsigned char           song_index;
+    unsigned char           song_note_index;
+    unsigned short          song_size;
+
+    unsigned short          note_duration;
+    unsigned int            note_timer_tick;
+    unsigned int            song_start_tick;
+}app_buzzer_ctrl_t;
+
+enum{
+    BUZZER_DUTY_MAX = 100,
+    BUZZER_DUTY_50  = 50,
+    BUZZER_DUTY_30  = 30,
+    BUZZER_DUTY_15  = 15,
+    BUZZER_DUTY_5   = 5,
+    BUZZER_DUTY_MIN = 0,
+};
+
 /**********************************************************************
  * GLOBAL VARIABLES
  */
@@ -72,15 +99,13 @@
 };
 
 _attribute_data_retention_ static app_buzzer_ctrl_t s_app_buzzer_ctrl={0};
+_attribute_data_retention_ static u32 s_buzzer_silence_tick = 0;
+
+
 /**********************************************************************
  * LOCAL FUNCTIONS
  */
 
-void app_buzzer_buffer_init(void){
-    /* clear buffer data */
-    memset(&s_app_buzzer_ctrl, 0x00, sizeof(app_buzzer_ctrl_t) );
-}
-
 void app_buzzer_pwm_init(void){
 
 //    pwm_set_clk(CLOCK_SYS_CLOCK_HZ, BUZZER_CLOCK);
@@ -89,7 +114,17 @@
     pwm_set_mode(BUZZER_PWM_ID, PWM_NORMAL_MODE);
 }
 
-u8 app_buzzer_is_buzy(){
+
+/**********************************************************************
+ * GLOBAL FUNCTIONS
+ */
+
+void app_buzzer_buffer_init(void){
+    /* clear buffer data */
+    memset(&s_app_buzzer_ctrl, 0x00, sizeof(app_buzzer_ctrl_t) );
+}
+
+u8 app_buzzer_is_buzy(void){
     return s_app_buzzer_ctrl.status;
 }
 
@@ -97,18 +132,27 @@
 
     if(s_app_buzzer_ctrl.song_index == index && s_app_buzzer_ctrl.status == status){
         /* Dynamically modify the volume of the song */
-        s_app_buzzer_ctrl.sound_level = sound_level;
+        s_app_buzzer_ctrl.sound_level = min(sound_level, BUZZER_DUTY_MAX);
         return;
     }
 
+    /* Using a buzzer will cause the battery voltage to drop a lot. So stop OTA first */
+    if(ota_is_working){
+        app_ota_terminate(GOOGLE_OTA_USER_TERMINATE);
+        printf("play buzzer during OTA\n");
+    }
+    app_ota_ClearDelayCount();
+
     device_led_setup(led_cfg[LED_BUZZER]);
 
-    s_app_buzzer_ctrl.song_index = index;
+    /* Prevent index parameter errors */
+    s_app_buzzer_ctrl.song_index = min(index, APP_BUZZER_PLAY_INDEX_RINGTONE_0);
 
+    app_buzzer_clear_silence_tick();
     app_buzzer_pwm_init();
 
-    s_app_buzzer_ctrl.status = status;
-    s_app_buzzer_ctrl.sound_level = sound_level;
+    s_app_buzzer_ctrl.status = min(status, APP_BUZZER_STATUS_PLAY_LOOP);
+    s_app_buzzer_ctrl.sound_level = min(sound_level, BUZZER_DUTY_MAX);
 
     s_app_buzzer_ctrl.song_note_index = 0;
     s_app_buzzer_ctrl.song_size = app_song[s_app_buzzer_ctrl.song_index].size;
@@ -140,6 +184,47 @@
     app_buzzer_buffer_init();
 }
 
+u32 app_buzzer_get_silence_tick(void){
+    return s_buzzer_silence_tick;
+}
+
+void app_buzzer_clear_silence_tick(void){
+    s_buzzer_silence_tick = 0;
+}
+
+u8 app_buzzer_set_and_get_pwm_duty_by_voltage(void){
+
+    enum{ MAX_BAT_VOL = 3200 };
+
+    extern u16 get_battery_voltage(void);
+    u16 my_bat_vol = get_battery_voltage();
+    my_bat_vol = min(my_bat_vol, MAX_BAT_VOL);
+
+    u8 my_buzzer_duty = BUZZER_DUTY_50;
+
+    switch (my_bat_vol)
+    {
+    case 2600 ... 3300:     /*  When the battery voltage is between 2.6V to 3.2V, keep the default PWM duty. */
+        break;
+    case 2500 ... 2599:     /*  When the battery voltage is between 2.5V to 2.59V, change PWM duty to 30%.   */
+        my_buzzer_duty = BUZZER_DUTY_30;
+        break;
+    case 2350 ... 2499:     /*  When the battery voltage is between 2.35V to 2.49V, change PWM duty to 15%.   */
+        my_buzzer_duty = BUZZER_DUTY_15;
+        break;
+    case 2250 ... 2349:     /*  When the battery voltage is between 2.25V to 2.24V, change PWM duty to 5%.    */
+        my_buzzer_duty = BUZZER_DUTY_5;
+        break;
+    default:
+        my_buzzer_duty = BUZZER_DUTY_MIN;
+        break;
+    }
+
+    s_app_buzzer_ctrl.sound_level = min(my_buzzer_duty, BUZZER_DUTY_MAX);
+
+    return s_app_buzzer_ctrl.sound_level;
+}
+
 void app_buzzer_task(void){
 
     if(!s_app_buzzer_ctrl.status) return;
@@ -171,10 +256,18 @@
 
         if(note){
             u16 counter = BUZZER_CLOCK/note;
+
+            /* The value of s_app_buzzer_ctrl.sound_level will not exceed 100 when assigned. If this happens, set duty to the lowest value */
+            if(s_app_buzzer_ctrl.sound_level > 100){
+                s_app_buzzer_ctrl.sound_level = BUZZER_DUTY_MIN;
+            }
+
             pwm_set_cycle_and_duty(BUZZER_PWM_ID, counter, counter*s_app_buzzer_ctrl.sound_level/100);
+            app_buzzer_clear_silence_tick();
         }else{
             /* A cmp_tick of 0 will cause the PWM to continuously output low level. cycle_tick only requires non-0. */
             pwm_set_cycle_and_duty(BUZZER_PWM_ID, /* any non-zero value */32000, 0);
+            s_buzzer_silence_tick = clock_time()|1;
         }
 
         BUZZER_DEBUG_LOG("song_note_index: [%d] FREQ:[%d] duty:[%d] counter:[%d]", s_app_buzzer_ctrl.song_note_index, note, s_app_buzzer_ctrl.sound_level, counter);
@@ -183,4 +276,3 @@
         s_app_buzzer_ctrl.note_duration = duration;
     }
 }
-
diff --git a/vendor/827x_ble_remote/app_fmr/app_buzzer.h b/vendor/827x_ble_remote/app_fmr/app_buzzer.h
index 8b93e04..e942d25 100644
--- a/vendor/827x_ble_remote/app_fmr/app_buzzer.h
+++ b/vendor/827x_ble_remote/app_fmr/app_buzzer.h
@@ -31,6 +31,10 @@
  * GLOBAL DEFINE
  */
 
+#define APP_BUZZER_SILENCE_TIME_MS          (500)       //500ms
+
+
+
 typedef enum{
     APP_BUZZER_STATUS_IDLE      = 0,
     APP_BUZZER_STATUS_PLAY_ONCE,
@@ -41,36 +45,68 @@
     APP_BUZZER_PLAY_INDEX_RINGTONE_0,
 }APP_BUZZER_INDEX_T;
 
-typedef struct {
-    unsigned int     note;        // musical notes. refer APP_BUZZER_NOTE_T
-    unsigned short        duration;    // note duration
-}app_buzzer_symbol_t;
-
-
-typedef struct {
-    APP_BUZZER_STATUS_T   status;
-    unsigned char         sound_level;
-
-    unsigned char         song_index;
-    unsigned char         song_note_index;
-    unsigned short        song_size;
-
-    unsigned short        note_duration;
-    unsigned int          note_timer_tick;
-    unsigned int          song_start_tick;
-}app_buzzer_ctrl_t;
-
 
 /**********************************************************************
  * GLOBAL FUNCTIONS
  */
 
+/**
+ * @brief      Clear parameters of app_buzzer
+ * @param[in]  none
+ * @return     none
+ */
 void app_buzzer_buffer_init(void);
+
+/**
+ * @brief      Get buzzer status
+ * @param[in]  none
+ * @return     unsigned char  0: Idle other: busy
+ */
+unsigned char app_buzzer_is_buzy(void);
+
+/**
+ * @brief      Get buzzer status
+ * @param[in]  index        This parameter can be specified when the module provides multiple songs.
+ * @param[in]  status       1:play the song only once  2:play the same song in loop  other:illegal value
+ * @param[in]  sound_level  PWM duty value. The range is 0-100
+ * @return     none
+ */
 void app_buzzer_play(APP_BUZZER_INDEX_T index, APP_BUZZER_STATUS_T status, unsigned char sound_level);
+
+/**
+ * @brief      This function is used to stop the buzzer
+ * @param[in]  none
+ * @return     none
+ */
 void app_buzzer_stop(void);
+
+/**
+ * @brief      This function is used to obtain the starting system tick of the buzzer's silence.
+ * @param[in]  none
+ * @return     unsigned int 0:Non-silence state other:tick of silence
+ */
+unsigned int app_buzzer_get_silence_tick(void);
+
+/**
+ * @brief      This function is used to clear the start tick of silence.
+ * @param[in]  none
+ * @return     none
+ */
+void app_buzzer_clear_silence_tick(void);
+
+/**
+ * @brief      This function is used to dynamically modify the PWM duty according to the battery voltage.
+ * @param[in]  none
+ * @return     unsigned char PWM duty set according to voltage
+ */
+unsigned char app_buzzer_set_and_get_pwm_duty_by_voltage(void);
+
+/**
+ * @brief      The buzzer task. It needs to be executed regularly when the buzzer is working,
+ *             so this function needs to be placed in the main loop.
+ * @param[in]  none
+ * @return     none
+ */
 void app_buzzer_task(void);
 
-
-unsigned char app_buzzer_is_buzy();
-
 #endif /* APP_BUZZER_H_ */
diff --git a/vendor/827x_ble_remote/app_fmr/app_buzzer_song.h b/vendor/827x_ble_remote/app_fmr/app_buzzer_song.h
index 2246371..a79c4dc 100644
--- a/vendor/827x_ble_remote/app_fmr/app_buzzer_song.h
+++ b/vendor/827x_ble_remote/app_fmr/app_buzzer_song.h
@@ -81,6 +81,11 @@
 
 }APP_BUZZER_NOTE_TIME_T;
 
+typedef struct {
+    unsigned int            note;        // musical notes. refer APP_BUZZER_NOTE_T
+    unsigned short          duration;    // note duration
+}app_buzzer_symbol_t;
+
 const app_buzzer_symbol_t app_song_loop[] =
 {
     {B_R_N0,    B_NT_50},
diff --git a/vendor/827x_ble_remote/app_fmr/app_fmr.c b/vendor/827x_ble_remote/app_fmr/app_fmr.c
index 5489aef..44eaf5c 100644
--- a/vendor/827x_ble_remote/app_fmr/app_fmr.c
+++ b/vendor/827x_ble_remote/app_fmr/app_fmr.c
@@ -43,6 +43,8 @@
 
 #define FMR_DEBUG_LOG(...)
 
+#define fmr_buzzer_play(duty)     app_buzzer_play(APP_BUZZER_PLAY_INDEX_RINGTONE_0, APP_BUZZER_STATUS_PLAY_LOOP, duty);
+
 
 /**********************************************************************
  * LOCAL TYPES
@@ -75,16 +77,15 @@
 const u8 app_fmr_service_uuid[16]   = WRAPPING_BRACES(GOOGLE_FMR_SERVICE_UUID);
 const u8 app_fmr_char_uuid[16]      = WRAPPING_BRACES(GOOGL_FMR_CHAR_UUID);
 
-_attribute_data_retention_ volatile u8 app_fmr_data[3]  = {0x00};
-_attribute_data_retention_ u16 app_fmr_ccc  = 0;
-_attribute_data_retention_ u32 s_fmr_counter_tick  = 0;
-
 const u8 app_fmr_char_val[19] = {
     CHAR_PROP_READ | CHAR_PROP_NOTIFY | CHAR_PROP_WRITE_WITHOUT_RSP,
     U16_LO(APP_FMR_CMD_OUT_DP_H), U16_HI(APP_FMR_CMD_OUT_DP_H),
     GOOGL_FMR_CHAR_UUID,
 };
 
+_attribute_data_retention_ volatile u8 app_fmr_data[3]  = {0x00};
+_attribute_data_retention_ u16 app_fmr_ccc  = 0;
+
 /**********************************************************************
  * GLOBAL VARIABLES
  */
@@ -92,24 +93,16 @@
 /**********************************************************************
  * LOCAL VARIABLES
  */
+_attribute_data_retention_ u32 s_fmr_counter_tick  = 0;
+
 _attribute_data_retention_ app_fmr_ctrl_t s_fmr_ctrl = {0};
 
 /**********************************************************************
  * LOCAL FUNCTIONS
  */
 
-#define fmr_buzzer_play()     app_buzzer_play(APP_BUZZER_PLAY_INDEX_RINGTONE_0, APP_BUZZER_STATUS_PLAY_LOOP, 50);
 
 
-
-u8 app_fmr_is_fmr_en(void){
-    return s_fmr_ctrl.en_fmr;
-}
-
-void app_fmr_set_fmr_en(u8 en){
-    s_fmr_ctrl.en_fmr = en;
-}
-
 fmr_event_t app_fmr_get_event(void){
 
     return app_fmr_data[0];
@@ -159,19 +152,6 @@
     }
 }
 
-u8 app_fmr_is_busy(void){
-
-    u8 my_event = app_fmr_get_event();
-    u16 my_duration = app_fmr_get_duration();
-
-    u8 my_flag_busy = 1;
-    if( (GOOGLE_FMR_EVENT_RCU_FOUND == my_event) || (0 == my_duration) ){
-        my_flag_busy = 0;
-    }
-
-    return my_flag_busy;
-}
-
 void app_fmr_set_fmr_para(fmr_event_t event, u16 duration){
 
     /* Is set in the response to write operation when the provided remaining buzz duration is too large.
@@ -190,16 +170,19 @@
     array_printf((u8 *)app_fmr_data, sizeof(app_fmr_data));
 }
 
-void app_fmr_on_button_event(void){
+/**********************************************************************
+ * GLOBAL FUNCTIONS
+ */
 
-    if(app_fmr_is_busy() == 0) return;
-
-    /* Set when the user picks up the remote or presses any button while in the buzz mode. */
-    app_buzzer_stop();
-//    app_led_pwm_disable(ALP_CFG_INDEX_FMR);
-    app_fmr_set_fmr_para(GOOGLE_FMR_EVENT_RCU_FOUND, 0);
+u8 app_fmr_is_fmr_en(void){
+    return s_fmr_ctrl.en_fmr;
 }
 
+void app_fmr_set_fmr_en(u8 en){
+    s_fmr_ctrl.en_fmr = en;
+}
+
+
 int app_fmr_write_cb(void * p){
 
     rf_packet_att_data_t *req = (rf_packet_att_data_t*)p;
@@ -207,7 +190,7 @@
 
     // TODO
 
-    #define FMR_LOW_VOLTABE     (2500)      //mv
+    #define FMR_LOW_VOLTABE     (2250)      //mv
 
     if(get_battery_voltage() < FMR_LOW_VOLTABE){
         app_fmr_set_fmr_para(GOOGLE_FMR_EVENT_LOW_BATTERY, 0);
@@ -229,7 +212,9 @@
     if(my_duration){
         /* buzzer ON. The value that is implied by every successful write operation.*/
         s_fmr_counter_tick = clock_time()|1;
-        fmr_buzzer_play();
+
+        fmr_buzzer_play(app_buzzer_set_and_get_pwm_duty_by_voltage());
+
 //        app_led_pwm_enable(ALP_CFG_INDEX_FMR, 0);
         app_fmr_set_fmr_para(GOOGLE_FMR_EVENT_REQUEST, my_duration);
     }else{
@@ -242,7 +227,38 @@
     return 0;
 }
 
+void app_fmr_parameter_init(void){
 
+    app_fmr_data[0] = 0x00;
+    app_fmr_data[1] = 0x00;
+    app_fmr_data[2] = 0x00;
+
+    s_fmr_counter_tick  = 0;
+    app_buzzer_buffer_init();
+}
+
+u8 app_fmr_is_busy(void){
+
+    u8 my_event = app_fmr_get_event();
+    u16 my_duration = app_fmr_get_duration();
+
+    u8 my_flag_busy = 1;
+    if( (GOOGLE_FMR_EVENT_RCU_FOUND == my_event) || (0 == my_duration) ){
+        my_flag_busy = 0;
+    }
+
+    return my_flag_busy;
+}
+
+void app_fmr_on_button_event(void){
+
+    if(app_fmr_is_busy() == 0) return;
+
+    /* Set when the user picks up the remote or presses any button while in the buzz mode. */
+    app_buzzer_stop();
+//    app_led_pwm_disable(ALP_CFG_INDEX_FMR);
+    app_fmr_set_fmr_para(GOOGLE_FMR_EVENT_RCU_FOUND, 0);
+}
 
 void app_fmr_task(void){
 
diff --git a/vendor/827x_ble_remote/app_fmr/app_fmr.h b/vendor/827x_ble_remote/app_fmr/app_fmr.h
index 6759c86..27a0010 100644
--- a/vendor/827x_ble_remote/app_fmr/app_fmr.h
+++ b/vendor/827x_ble_remote/app_fmr/app_fmr.h
@@ -27,17 +27,9 @@
 
 
 /**********************************************************************
- * ATT SERVICE
+ * GLOBAL DEFINES
  */
 
-extern const unsigned char app_fmr_service_uuid[16];
-extern const unsigned char app_fmr_char_uuid[16];
-
-extern volatile unsigned char app_fmr_data[3];
-extern unsigned short app_fmr_ccc;
-
-extern const unsigned char app_fmr_char_val[19];
-
 #define APP_FMR_HANDLE                          \
             APP_FMR_PS_H,                       \
             APP_FMR_CMD_OUT_CD_H,               \
@@ -49,29 +41,82 @@
     {4,ATT_PERMISSIONS_READ, 2, 16,                         (u8*)(&my_primaryServiceUUID),  (u8*)(&app_fmr_service_uuid),   0},                     \
     {0,ATT_PERMISSIONS_READ, 2, sizeof(app_fmr_char_val),   (u8*)(&my_characterUUID),       (u8*)(app_fmr_char_val),        0},                     \
     {0,ATT_PERMISSIONS_RDWR, 16,sizeof(app_fmr_data),       (u8*)(&app_fmr_char_uuid),      (u8*)(app_fmr_data),            &app_fmr_write_cb, 0},  \
-    {0,ATT_PERMISSIONS_RDWR, 2, sizeof(app_fmr_ccc),        (u8*)(&clientCharacterCfgUUID), (u8*)(&app_fmr_ccc),            0},
+    {0,ATT_PERMISSIONS_RDWR, 2, sizeof(app_fmr_ccc),        (u8*)(&clientCharacterCfgUUID), (u8*)(&app_fmr_ccc),            0},                     \
 
 
+/**********************************************************************
+ * ATT SERVICE VARIABLES
+ */
+
+/* FMR UUID */
+extern const unsigned char app_fmr_service_uuid[16];
+extern const unsigned char app_fmr_char_uuid[16];
+
+/* FMR  attribute values */
+extern const unsigned char app_fmr_char_val[19];
+
+/* FMR data */
+extern volatile unsigned char app_fmr_data[3];
+extern unsigned short app_fmr_ccc;
+
 
 /**********************************************************************
  * GLOBAL FUNCTIONS
  */
 
-int app_fmr_write_cb(void * p);
-
-void app_fmr_on_button_event(void);
-
-unsigned char app_fmr_is_busy(void);
-
-void app_fmr_task(void);
-
+/**
+ * @brief This function is used to get whether FMR is enabled
+ *
+ * @param p the pointer of buffer
+ * @return unsigned char 1:enable 0:disable
+ */
 unsigned char app_fmr_is_fmr_en(void);
 
+/**
+ * @brief       This function is used to set whether FMR is enabled or disabled
+ *
+ * @param       en 1:enable 0:disable
+ * @return      none
+ */
+
 void app_fmr_set_fmr_en(unsigned char en);
 
 /**
- * periodic wake-up ADV
+ * @brief       This function is the write callback of the FMR service. Registered in FMR ATT table.
+ *
+ * @param       p the pointer of buffer
+ * @return      int Always returns 0
  */
+int app_fmr_write_cb(void * p);
+
+/**
+ * @brief       This function is used to clear all parameters related to FMR
+ * @param[in]   none
+ * @return      none
+ */
+void app_fmr_parameter_init(void);
+
+/**
+ * @brief       This function is used to confirm whether FMR is busy
+ * @param[in]   none
+ * @return      unsigned char 1:busy 0:idle
+ */
+unsigned char app_fmr_is_busy(void);
+
+/**
+ * @brief       This function is almost equal to FMR stop. Only used after keystroke discovery.
+ * @param[in]   none
+ * @return      none
+ */
+void app_fmr_on_button_event(void);
+
+/**
+ * @brief      The FMR task. It needs to be executed regularly when the buzzer is working,
+ *             so this function needs to be placed in the main loop.
+ * @param[in]  none
+ * @return     none
+ */
+void app_fmr_task(void);
 
 void app_fmr_set_periodic_wakeup(unsigned char en, unsigned short interval);
 
diff --git a/vendor/827x_ble_remote/app_ota.h b/vendor/827x_ble_remote/app_ota.h
index cc9bbb7..3dfb533 100644
--- a/vendor/827x_ble_remote/app_ota.h
+++ b/vendor/827x_ble_remote/app_ota.h
@@ -28,18 +28,19 @@
 #define APP_OTA_H_
 
 
-#define CMD_REPORT_VERSION                    0xfe00
-#define CMD_CONTROL                           0xfe01
+#define OTA_PROTECT_VOLTAGE                     (2400)    //mv
 
-#define OTA_PROTECT_VOLTAGE                   2400    //mv
+#define CLIENT_REPORT_CMD                       (0xfe)
 
-#define CLIENT_REPORT_CMD                     0xfe
+#define app_ota_notify_result(...)              app_ota_notify_data(TYPE_OTA_RESULT, __VA_ARGS__)
+#define app_ota_notify_ver(...)                 app_ota_notify_data(TYPE_VERSION, __VA_ARGS__)
+#define app_ota_notify_auth_data(...)           app_ota_notify_data(TYPE_AUTHENTICATION_DATA, __VA_ARGS__)
 
 
 //report type
 enum{
     TYPE_VERSION = 0,
-    TYPE_SINATURE_DATA,
+    TYPE_AUTHENTICATION_DATA,
     TYPE_CONTROL_DATA,
     TYPE_OTA_RESULT,
 };
@@ -55,6 +56,7 @@
     OTA_VER_CHECK,    //Includes battery voltage detection
     OTA_AUTHENTICATION,
     OTA_PROCESS,
+    OTA_SUCC_READY_REBOOT,
 }ota_status_type_t;
 
 enum{
@@ -72,6 +74,8 @@
      GOOGLE_OTA_USER_TERMINATE,   //9
      GOOGLE_OTA_SIGNATURE_ERR,   //
 
+     GOOGLE_OTA_REBOOT_PENDING,     // b
+
 };
 
 void bls_ota_init_handle(u16 handle);
@@ -90,6 +94,11 @@
 int app_ota_write(void * p);
 void app_ota_proc(void);
 
+
+u8 app_ota_notify_data(u8 data_type, u8 *p_buf, u8 buf_len);
+
+void app_ota_ClearDelayCount(void);
+unsigned short app_ota_isEnDelayReboot(void);
 //extern u16 ota_ctl_flag;
 
 #endif /* APP_OTA_H_ */
diff --git a/vendor/827x_ble_remote/app_ui.c b/vendor/827x_ble_remote/app_ui.c
index 986411a..31d17fd 100644
--- a/vendor/827x_ble_remote/app_ui.c
+++ b/vendor/827x_ble_remote/app_ui.c
@@ -48,6 +48,7 @@
 #include "app_custom_lib.h"
 #include "./app_find_me/app_fms.h"
 #include "./app_fmr/app_fmr.h"
+#include "./app_fmr/app_buzzer.h"
 #include "./app_backlight/app_backlight.h"
 
 
@@ -168,7 +169,8 @@
         {APP_LED_RED,     1,   100,      100 ,   5,      0,  },    //5Hz for 5 seconds
         {APP_LED_RED,     1,   50,       50,     4,      0,  },
         {APP_LED_RED,     1,   100,      0,      0,      1,  },
-        {APP_LED_RED,     1,   0,        1000,   3,      1,  },
+//        {APP_LED_RED,     1,   0,        1000,   3,      1,  },
+        {APP_LED_RED,     1,   0,        100,    1,      0,  },
         {APP_LED_RED,     1,   100,      100 ,   1,      0,  },    //5Hz for 3 seconds
         {APP_LED_RED,     1,   1000,     1000 ,  15,     0,  },    //5Hz for 3 seconds
 };
@@ -271,27 +273,18 @@
 #if (BLE_REMOTE_OTA_ENABLE)
 #include "app_ota.h"
 extern u8  mac_public[6];
-u8 app_enter_ota_mode(u8 *data)
-{
-    printf("start data:");
-    array_printf(data,4);
-    extern u32 ota_program_offset;
-    extern int ota_program_bootAddr;
-    printf("ota_program_offset=%x\r\n",ota_program_offset);
-    printf("ota_program_offset=%x\r\n",ota_program_bootAddr);
+u8 app_enter_ota_mode(u8 *data){
 
-    u8 check_data[4];
-    bls_ota_get_random(check_data);
-
-    if(memcmp(check_data,data,4 )){
-
-        u8 report_data[3] ={CLIENT_REPORT_CMD, TYPE_OTA_RESULT, GOOGLE_OTA_START_KEY_ERR};
-
-        bls_att_pushNotifyData(OTA_CMD_OUT_DP_H, report_data, 3);
-        printf("OTA_START_KEY_ERR\n");
-
+    /* FMR will cause the battery voltage to drop. So avoid performing OTA during FMR */
+    if(app_buzzer_is_buzy()){
         return 1;
     }
+
+    extern u32 ota_program_offset;
+    extern int ota_program_bootAddr;
+    printf("ota_program_offset:[%X]  ota_program_bootAddr:[%X]\r\n", ota_program_offset, ota_program_bootAddr);
+
+
     bls_pm_setSuspendMask (SUSPEND_DISABLE);
     ota_flag = 1;
 
@@ -352,35 +345,38 @@
 
 void app_ota_result(u8 result)
 {
-    printf("google_ota_result result=%x\r\n",result);
-    u8 report_data[3];
-    report_data[0] = CLIENT_REPORT_CMD;
-    report_data[1] = TYPE_OTA_RESULT;
-    report_data[2] = (u8)result;
+    printf("OTA result:[%d]\r\n",result);
+    ota_is_working = 0;
+
     if(device_in_connection_state)
     {
         u16 i = 0;
-        while(bls_att_pushNotifyData(OTA_CMD_OUT_DP_H, report_data, 3) &&  i < 2000){
-        sleep_us(100);
-        i++;
+
+        while(app_ota_notify_result(&result, 1) &&  i < 2000){
+            sleep_us(100);
+            i++;
         }
 
-        i = 0;
-        while(app_terminate(HCI_ERR_REMOTE_USER_TERM_CONN) &&  i < 2000){
-        sleep_us(100);
-        i++;
+        if(0 == app_ota_isEnDelayReboot()){
+            i = 0;
+            while(app_terminate(HCI_ERR_REMOTE_USER_TERM_CONN) &&  i < 2000){
+                sleep_us(100);
+                i++;
+            }
+
+            i = 0;
+            while(blc_ll_getTxFifoNumber() &&  i < 400){
+                sleep_us(10000);//printf("waiting TX fifo is empty\n"); //waiting TX fifo is empty
+                i++;
+            }
         }
 
-        i = 0;
-        while(blc_ll_getTxFifoNumber() &&  i < 400){
-        sleep_us(10000);//printf("waiting TX fifo is empty\n"); //waiting TX fifo is empty
-        i++;
-        }
     }
     if(result == 0)
     {
         printf("ota end red led off\r\n");
         device_led_setup(led_cfg[LED_OTA_END]);
+//        device_led_off();
         printf("ota_suc and write_ana\r\n");
         analog_write(USED_DEEP_ANA_REG, analog_read(USED_DEEP_ANA_REG) | OTA_FLG);
         printf("analog_read(USED_DEEP_ANA_REG)=%x\r\n",analog_read(USED_DEEP_ANA_REG));
@@ -446,10 +442,12 @@
 void app_ota_slave_terminate(void)
 {
     printf("app_ota_slave_terminate\n");
-    u8 report_data[3] = {CLIENT_REPORT_CMD, TYPE_OTA_RESULT, GOOGLE_OTA_USER_TERMINATE};
+
+    u8 my_ota_result[1] = {GOOGLE_OTA_USER_TERMINATE};
 
     u16 i = 0;
-    while(bls_att_pushNotifyData(OTA_CMD_OUT_DP_H, report_data, 3) &&  i < 2000){
+
+    while(app_ota_notify_result(my_ota_result, 1) &&  i < 2000){
        sleep_us(100);
        i++;
     }
@@ -505,17 +503,22 @@
 
 void app_schedule_ota_send_notify_to_continue_ota(void)
 {
-    u8 dat[2] = {0};
-    u8 report_data[4] = {CLIENT_REPORT_CMD,0x04,0x73,0x6f};
+#define OTA_SCHEDULE_CONSUMER_KEY       (0x6f73)
+#define OTA_SCHEDULE_DATA_TYPE          (0x04)
+
+//    u8 report_data[4] = {CLIENT_REPORT_CMD,0x04,0x73,0x6f}; // 0xfe, 0x04,0x73,0x6f
     u8 data = analog_read(DEEP_ANA_REG2);
 
-    dat[0] = 0x73;
-    dat[1] = 0x6f;
+//    dat[0] = U16_LO(OTA_SCHEDULE_CONSUMER_KEY); // 0x73;
+//    dat[1] = U16_HI(OTA_SCHEDULE_CONSUMER_KEY); // 0x6f;
+
+    u8 my_consumer_key[2] = {U16_LO(OTA_SCHEDULE_CONSUMER_KEY), U16_HI(OTA_SCHEDULE_CONSUMER_KEY)};
+
     if((APP_WAKEUP_SRC_DEEP_TIMER == app_ui_get_wakeup_src()) && (data))//wake up for timer
     {
         printf("app_schedule_ota_send_notify_to_continue_ota\r\n");
-        bls_att_pushNotifyData(HID_CONSUME_REPORT_INPUT_DP_H, dat, 2);
-        bls_att_pushNotifyData(OTA_CMD_OUT_DP_H, report_data, 4);
+        bls_att_pushNotifyData(HID_CONSUME_REPORT_INPUT_DP_H, my_consumer_key, sizeof(my_consumer_key));
+        app_ota_notify_data(OTA_SCHEDULE_DATA_TYPE, my_consumer_key, sizeof(my_consumer_key));
         analog_write(DEEP_ANA_REG2, 0);
     }
 }
@@ -1387,7 +1390,6 @@
     }
     else if(kb_event.cnt == 1)
     {
-        app_backlight_start();
 
         //retime
         advertise_tick_retime();
@@ -1430,6 +1432,8 @@
              * When FMR is ON, the remote should avoid sending key events
              * (neither BLE,nor IR, nor Assistant) while in buzz mode. */
         }else{
+            app_backlight_start();
+
         #if (BLE_AUDIO_ENABLE)
             if(device_in_connection_state)
             {
@@ -1694,6 +1698,7 @@
 #endif
 
     if (det_key){
+        app_ota_ClearDelayCount();
 #if (MP_TEST_MODE)
         if (test_get_mode() == MODE_TEST) test_proc_key();
         else
diff --git a/version.h b/version.h
index 9d68bff..db0a2a8 100644
--- a/version.h
+++ b/version.h
@@ -27,6 +27,6 @@
 #ifndef VERSION_H_
 #define VERSION_H_
 
-#define FW_VERSION                  0x34210230//FW:v3.4.2  SW:v2.30
+#define FW_VERSION                  0x34210232//FW:v3.4.2  SW:v2.32
 
 #endif /* VERSION_H_ */