/* ****************************************************************************** * * @file vox_module.c * @brief VOL/R module * @ic sy8837/8 * * @version 1.0 * @date 2024/12/02 09:59:40 * @author Alex Xu * * Copyright (c) 2013-2099,Tkplusemi Technology Co.,Ltd. * All Rights Reserved * * History: * Revision Date Author Desc * 1.0.0 2024/12/02 Alex build this file ****************************************************************************** */ #include "vox_module.h" #include "led.h" #include "system.h" #include "discharge_module.h" #include "sleep.h" #include "bat.h" #include "hall.h" #include "key.h" #include "sys_tim.h" #include "adc.h" #include "userapp.h" #include "vox_comm.h" #ifdef VOX_COVER_ENABLE bit Vox_Vout_Enable; //Vox功率输出标志位 #else bit Vor_Vout_Enable; //Vor功率输出标志位 bit Vol_Vout_Enable; //Vol功率输出标志位 #endif bit Boost_Open_Flag; bit Vox_Output_Short_Flag; #if VOX_ENABLE /******************************************************************************\ Macro definitions \******************************************************************************/ #if VOX_FOLLOW_CHG #define VOX_FOLLOW_CHG_NOWCURCHK_CNT 5 #define VOX_FOLLOW_CHG_VOLTAGE_ADJUST_CNT 2 //PMID调压周期 #endif /******************************************************************************\ Variables definitions \******************************************************************************/ #if VOX_FOLLOW_CHG idata uint8_t Vox_Follow_Init_Deb; idata uint16_t Vox_Follow_Chg_Debounce; g_Vox_Fllow_Chg_Cfg Vox_Fllow_Chg; e_Vox_Follow_Chg_Sta Follow_Chg_Sta; #endif idata uint8_t EarPhone_Num; bit Vox_Ocp_Flag; bit OpenCover_TX_Cmd_Flag; /******************************************************************************\ Functions definitions \******************************************************************************/ #ifdef VOX_ADT_ENABLE /* ******************************************************************************* * uint8_t VOL_EN_Type(VOL_Enable_Type_e VOL_Enable_Type) * * Description : VOL Open(EN_VO) * 使能信号优先级 * EN_COM EN_VO EN_ADT PD1K VOX_STATE * 1 X X X COMM * 0 1 X X 5V * 0 0 1 X Auto DET * 0 0 0 1 PD1K * Arguments : * Returns : * Notes : * ******************************************************************************* */ void VOL_EN_Type(VOX_Enable_Mode_e VOL_Enable_Mode) { switch(VOL_Enable_Mode) { case VOX_TRANS_Mode: //关闭自动识别负载的上拉电阻。 break; case VOX_COMM_Mode_Uart: COMM_CTL |= Vol_EN_COMR | Vol_SWDR ; //开启VOX通讯使能,选择UART通讯模式。 COMM_CTL &= ~( Vol_SW_MD | Vol_SWDT ); SFRADDR = COMM_CON; //Vox通讯电平选择,3.0V,打开50K上拉电阻。 SFRDATA &= ~0x0D; SFRDATA |= VOX_COMM_VOLTAGE_SET | VOX_COMM_PULL_UP_SET; break; case VOX_COMM_Mode_Reg: COMM_CTL |= Vol_EN_COMR | Vol_SW_MD; //开启VOX通讯使能,选择寄存器通讯模式。 SFRADDR = COMM_CON; //Vox通讯电平选择,5.0V,关闭50K上拉电阻。 SFRDATA &= ~ VOX_COMM_PULL_UP_SET; SFRDATA |= Vox_COMM_PULL_Vol_5_0; break; case VOX_VOUT_Mode: //Vox的通讯功能优先级比Vout 5V高。 COMM_CTL &= ~( Vol_EN_COMR ); VOX_CTL0 &=~( EN_VOL_VOUT ); VOX_CTL0 |= EN_VOL_VOUT; break; case VOX_ADT_Mode: VOX_CTL0 &=~( EN_VOL_VOUT ); VOX_CTL0 |= EN_VOL_ADTL; //开启ADT模式 COMM_CTL &=~( Vol_EN_COMR ); break; case VOX_PD1K_Mode: VOX_CTL0 &=~( EN_VOL_VOUT | EN_VOL_ADTL ); COMM_CTL &=~( Vol_EN_COMR ); SFRADDR = VOX_CON0; //Vox通过1K电阻下拉到GND SFRDATA |= Vol_Pull_Down; break; default: break; } } /* ******************************************************************************* * void VOR_EN_Type(VOR_Enable_Type_e VOR_Enable_Type) * * Description : VOL Open(EN_VO) * 使能信号优先级 * EN_COM EN_VO EN_ADT PD1K VOX_STATE * 1 X X X COMM * 0 1 X X 5V * 0 0 1 X Auto DET * 0 0 0 1 PD1K * Arguments : * Returns : * Notes : * ******************************************************************************* */ void VOR_EN_Type(VOX_Enable_Mode_e VOR_Enable_Mode) { switch(VOR_Enable_Mode) { case VOX_TRANS_Mode: //关闭自动识别负载的上拉电阻。 break; case VOX_COMM_Mode_Uart: COMM_CTL |= Vor_EN_COMR | Vor_SWDR ; //开启VOX通讯使能,选择UART通讯模式。 COMM_CTL &= ~( Vor_SW_MD | Vor_SWDT ); SFRADDR = COMM_CON; //Vox通讯电平选择,3.0V,打开50K上拉电阻。 SFRDATA &= ~0x0D; SFRDATA |= VOX_COMM_VOLTAGE_SET | VOX_COMM_PULL_UP_SET; break; case VOX_COMM_Mode_Reg: COMM_CTL |= Vor_EN_COMR | Vor_SW_MD; //开启VOX通讯使能,选择寄存器通讯模式。 SFRADDR = COMM_CON; //Vox通讯电平选择,5.0V,关闭50K上拉电阻。 SFRDATA &= ~ VOX_COMM_PULL_UP_SET; SFRDATA |= Vox_COMM_PULL_Vol_5_0; break; case VOX_VOUT_Mode: //Vox的通讯功能优先级比Vout 5V高。 COMM_CTL &= ~( Vor_EN_COMR ); VOX_CTL0 &=~( EN_VOR_VOUT ); VOX_CTL0 |= EN_VOR_VOUT; break; case VOX_ADT_Mode: VOX_CTL0 &=~( EN_VOR_VOUT ); VOX_CTL0 |= EN_VOR_ADTR ; //开启ADT模式 COMM_CTL &=~( Vor_EN_COMR ); break; case VOX_PD1K_Mode: VOX_CTL0 &=~( EN_VOR_VOUT | EN_VOR_ADTR ); COMM_CTL &=~( Vor_EN_COMR ); SFRADDR = VOX_CON0; //Vox通过1K电阻下拉到GND SFRDATA |= Vor_Pull_Down ; break; default: break; } } #else /* ******************************************************************************* * void VOX_EN_Type(VOR_Enable_Type_e VOR_Enable_Type) * * Description : VOL Open(EN_VO) * 使能信号优先级 * EN_COM EN_VO EN_ADT PD1K VOX_STATE * 1 X X X COMM * 0 1 X X 5V * 0 0 1 X Auto DET * 0 0 0 1 PD1K * Arguments : * Returns : * Notes : * ******************************************************************************* */ void VOX_EN_Type(VOX_Enable_Mode_e VOX_Enable_Mode) { switch(VOX_Enable_Mode) { case VOX_TRANS_Mode: //关闭自动识别负载的上拉电阻。 break; case VOX_COMM_Mode_Uart: COMM_CTL |= Vor_EN_COMR | Vol_EN_COMR | Vol_SWDR | Vor_SWDR; //开启VOX通讯使能,选择UART通讯模式。 COMM_CTL &= ~( Vor_SW_MD | Vol_SW_MD | Vol_SWDT | Vor_SWDT ); SFRADDR = COMM_CON; //Vox通讯电平选择,3.0V,打开50K上拉电阻。 SFRDATA &= ~0x0D; SFRDATA |= VOX_COMM_VOLTAGE_SET | VOX_COMM_PULL_UP_SET; break; case VOX_COMM_Mode_Reg: COMM_CTL |= Vor_EN_COMR | Vol_EN_COMR | Vor_SW_MD | Vol_SW_MD; //开启VOX通讯使能,选择寄存器通讯模式。 SFRADDR = COMM_CON; //Vox通讯电平选择,5.0V,关闭50K上拉电阻。 SFRDATA &= ~ VOX_COMM_PULL_UP_SET; SFRDATA |= Vox_COMM_PULL_Vol_5_0; break; case VOX_VOUT_Mode: //Vox的通讯功能优先级比Vout 5V高。 COMM_CTL &= ~( Vor_EN_COMR | Vol_EN_COMR ); VOX_CTL0 &=~( EN_VOR_VOUT | EN_VOL_VOUT ); VOX_CTL0 |= EN_VOR_VOUT | EN_VOL_VOUT; break; case VOX_ADT_Mode: VOX_CTL0 &=~( EN_VOR_VOUT | EN_VOL_VOUT ); VOX_CTL0 |= EN_VOR_ADTR | EN_VOL_ADTL; //开启ADT模式 COMM_CTL &=~( Vor_EN_COMR | Vol_EN_COMR ); break; case VOX_PD1K_Mode: VOX_CTL0 &=~( EN_VOR_VOUT | EN_VOL_VOUT | EN_VOR_ADTR | EN_VOL_ADTL ); COMM_CTL &=~( Vor_EN_COMR | Vol_EN_COMR ); SFRADDR = VOX_CON0; //Vox通过1K电阻下拉到GND SFRDATA |= Vor_Pull_Down | Vol_Pull_Down; break; default: break; } } #endif #ifdef VOX_ADT_ENABLE #define VOX_LOADON_DET_DEBOUNCE 2 //Vox Loadon信号检测延时计数,loadon信号软件数字滤波,根据实际耳机进行调试; #define VOX_NO_LOADON_CNT 5 //耳机充满后,断内部下拉电阻延时计数,根据实际应用调整。 #define VOX_IOFF_DET_DEBOUNCE 50 //Vox Ioff检测延时5s,重载转轻载延时计数。 Vox_State_e Vol_State; bit Vol_GetOut_Box_Flag; //Vol 出盒标志,用于耳机抽电灯效。 /* ******************************************************************************* * void Vol_Det_Machine(void) * * Description : Vol Detect:耳机识别。 (100ms调用周期) * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ void Vol_Det_Machine(void) { static uint8_t nVol_Loadon_Det_Debounce; //loadon标志检测延时计数 static uint8_t nVol_Output_Debounce; //Vox重载转轻载延时计数 static bit nVol_Chg_Full_Flag; //耳机充满标志 static bit nVol_GetOut_Box_Flag; static bit nVol_Outbox_Disp_Flag; static bit nVol_Intobox_Disp_Flag; static bit nVol_Get_Chip_STA_Flag; static uint8_t nCHIP_STA1_Vol; if( gBoost_Prepared_Flag ) { switch( Vol_State ) { case VOX_GET_INTO_BOX: //耳机入仓 /*开启Vox Vout 5V前需要先开Boost。*/ if( !Boost_Open_Flag ) { DisCharge_Boost_Open(OFF,BOOST_VOUT_MAX); Boost_Open_Flag = TRUE; #ifdef _DEBUG_VOX printf("Boost Open.(line:%d)\r\n",(u16)__LINE__); #endif return; } VOL_EN_Type(VOX_VOUT_Mode); //Vox开启Vout 5V输出 Vol_Vout_Enable = ON; Boost_Open_Flag = FALSE; nVol_Chg_Full_Flag = FALSE; nVol_GetOut_Box_Flag = FALSE; nVol_Intobox_Disp_Flag = FALSE; nVol_Outbox_Disp_Flag = FALSE; nVol_Output_Debounce = 0; /*重启跟随充*/ #if VOX_FOLLOW_CHG Vox_Fllow_Chg.Vox_Follow_Start = OFF; Vox_Fllow_Chg.Vox_Follow_Stop = OFF; Follow_Chg_Sta = Vox_Follow_Chg_InitSta; #endif Vol_State = VOX_STAY_IN_BOX; break; case VOX_STAY_IN_BOX: //耳机在仓 if ( ( CHIP_STA1 & ( VOL_LoadOn | VOL_Ioff ) ) == ( VOL_LoadOn | VOL_Ioff ) ) //充电过程中出现只有IOFF,则出现如下三种情况:1、耳机出仓;2、耳机电池充满;3、耳机电池锂保。 { if( nVol_Intobox_Disp_Flag ) //Vol耳机在正常充电过程中,被拔出。 { nVol_Outbox_Disp_Flag = TRUE; nVol_Intobox_Disp_Flag = FALSE; nVol_GetOut_Box_Flag = TRUE; Vol_GetOut_Box_Flag = TRUE; //左耳出盒标志置1,用于抽电灯效 #ifdef _DEBUG_VOX printf("Vol Get Out.(line:%d)\r\n",(u16)__LINE__); #endif } nVol_Output_Debounce++; if( nVol_Output_Debounce >= VOX_IOFF_DET_DEBOUNCE ) //重载转轻载(耳机出仓后)需延时5s,Vox掉Vout 5V后转入ADT模式。 { nVol_Output_Debounce = 0; VOL_EN_Type(VOX_ADT_Mode); nVol_Chg_Full_Flag = TRUE; #ifdef _DEBUG_VOX printf("Vol Full And In ADT.(line:%d)\r\n",(u16)__LINE__); #endif } } else if ( ( CHIP_STA1 & ( VOL_LoadOn | VOL_Ioff ) ) == VOL_LoadOn ) //无IOFF有Loadon,说明:1、耳机出仓后4s内,耳机再次入仓;2、10分钟未满,耳机电池退出锂保状态,进入正常充电; { nVol_Output_Debounce = 0; nVol_Intobox_Disp_Flag = TRUE; if( nVol_Chg_Full_Flag ) //Vox在ADT模式后检测到loadon标志,则说明耳机已充满,不再抽电,等loadon消失,判断耳机出盒。 { Vol_Vout_Enable = OFF; #ifdef _DEBUG_VOX printf("Vol Full.(line:%d)\r\n",(u16)__LINE__); #endif } else { if( nVol_Outbox_Disp_Flag ) //左耳4s内再次入盒,左耳对应的入盒灯效闪一次。 { nVol_Outbox_Disp_Flag = FALSE; if( nVol_GetOut_Box_Flag ) { nVol_GetOut_Box_Flag = FALSE; /*重启跟随充*/ #if VOX_FOLLOW_CHG Vox_Fllow_Chg.Vox_Follow_Start = OFF; Vox_Fllow_Chg.Vox_Follow_Stop = OFF; Follow_Chg_Sta = Vox_Follow_Chg_InitSta; #endif Earphone_Chg_Flag_led = TRUE; //用于灯效显示 #ifdef LED_DISPLAY LED_On_Flag = TRUE; #endif #ifdef _DEBUG_VOX printf("Vol Get In Again.(line:%d)\r\n",(u16)__LINE__); #endif } } Vol_Vout_Enable = ON; //正常充电标志置ON。 Vol_GetOut_Box_Flag = FALSE; #ifdef _DEBUG_VOX printf("Vol Ching.(line:%d)\r\n",(u16)__LINE__); #endif } } else if ( !( CHIP_STA1 & VOL_LoadOn ) ) //无Loadon,说明,耳机出仓 { nVol_Loadon_Det_Debounce++; if( nVol_Loadon_Det_Debounce >= VOX_NO_LOADON_CNT ) //耳机充满后,断开内部下拉电阻延时计数,根据实际应用调整。 { nVol_Loadon_Det_Debounce = 0; nVol_Intobox_Disp_Flag = FALSE; nVol_Outbox_Disp_Flag = FALSE; nVol_GetOut_Box_Flag = FALSE; Vol_State = VOX_NONE_IN_BOX; #ifdef _DEBUG_VOX printf("Vol Out Box.(line:%d)\r\n",(u16)__LINE__); #endif } } break; case VOX_NONE_IN_BOX: //空仓 VOL_EN_Type(VOX_ADT_Mode); Vol_Vout_Enable = OFF; Vol_GetOut_Box_Flag = TRUE; //左耳出盒标志置1,用于抽电灯效 if( CHIP_STA1 & VOL_LoadOn ) //adt模式下出现loadon信号,则说明Vol通道有耳机入盒。 { nVol_Loadon_Det_Debounce++; if( nVol_Loadon_Det_Debounce >= VOX_LOADON_DET_DEBOUNCE ) //Vox Loadon信号检测延时计数,loadon信号软件数字滤波,根据实际耳机进行调试; { nVol_Loadon_Det_Debounce = 0; Vol_State = VOX_GET_INTO_BOX; /*置灯效显示标志*/ Earphone_Chg_Flag_led = TRUE; #ifdef LED_DISPLAY LED_On_Flag = TRUE; #endif #ifdef _DEBUG_VOX printf("Vol Det Loadon.(line:%d)\r\n",(u16)__LINE__); #endif } } else { nVol_Loadon_Det_Debounce = 0; } break; default: break; } } else //bat保护后,VOX恢复到最初状态。 { Vol_State = VOX_GET_INTO_BOX; Vol_Vout_Enable = OFF; if( !nVol_Get_Chip_STA_Flag ) { nVol_Get_Chip_STA_Flag = TRUE; VOL_EN_Type(VOX_ADT_Mode); //VOL Disable 5V And Enable VOR ADT nCHIP_STA1_Vol = CHIP_STA1 & VOL_LoadOn; } else { /*耳机出入盒判断*/ if( nCHIP_STA1_Vol != ( CHIP_STA1 & VOL_LoadOn ) ) //查询耳机loadon状态,loadon状态改变,则说明有耳机出入盒。 { if( CHIP_STA1 & VOL_LoadOn ) //Vox入盒 { Earphone_Chg_Flag_led = TRUE; //用于灯效显示 #ifdef LED_DISPLAY LED_On_Flag = TRUE; #endif #ifdef _DEBUG_VOX printf("VOL Get Into Box Bat Low.(line:%d)\r\n",(u16)__LINE__); #endif } nCHIP_STA1_Vol = CHIP_STA1 & VOL_LoadOn; } } } } Vox_State_e Vor_State; bit Vor_GetOut_Box_Flag; //Vor 出盒标志,用于耳机抽电灯效。 /* ******************************************************************************* * void Vor_Det_Machine(void) * * Description : Vor Detect:耳机识别。 (100ms调用周期) * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ void Vor_Det_Machine(void) { static uint8_t nVor_Loadon_Det_Debounce; //loadon标志检测延时计数 static uint8_t nVor_Output_Debounce; //Vox重载转轻载延时计数 static bit nVor_Chg_Full_Flag; //耳机充满标志 static bit nVor_GetOut_Box_Flag; static bit nVor_Outbox_Disp_Flag; static bit nVor_Intobox_Disp_Flag; static bit nVor_Get_Chip_STA_Flag; static uint8_t nCHIP_STA1_Vor; if( gBoost_Prepared_Flag ) { switch( Vor_State ) { case VOX_GET_INTO_BOX: //耳机入仓 /*开启Vox Vout 5V前需要先开Boost。*/ if( !Boost_Open_Flag ) { DisCharge_Boost_Open(OFF,BOOST_VOUT_MAX); Boost_Open_Flag = TRUE; #ifdef _DEBUG_VOX printf("Boost Open.(line:%d)\r\n",(u16)__LINE__); #endif return; } VOR_EN_Type(VOX_VOUT_Mode); //Vox开启Vout 5V输出 Vor_Vout_Enable = ON; Boost_Open_Flag = FALSE; nVor_Chg_Full_Flag = FALSE; nVor_GetOut_Box_Flag = FALSE; nVor_Intobox_Disp_Flag = FALSE; nVor_Outbox_Disp_Flag = FALSE; nVor_Output_Debounce = 0; /*重启跟随充*/ #if VOX_FOLLOW_CHG Vox_Fllow_Chg.Vox_Follow_Start = OFF; Vox_Fllow_Chg.Vox_Follow_Stop = OFF; Follow_Chg_Sta = Vox_Follow_Chg_InitSta; #endif #ifdef _DEBUG_VOX printf("Vor Get Into Box.(line:%d)\r\n",(u16)__LINE__); #endif Vor_State = VOX_STAY_IN_BOX; break; case VOX_STAY_IN_BOX: //耳机在仓 if ( ( CHIP_STA1 & ( VOR_LoadOn | VOR_Ioff ) ) == ( VOR_LoadOn | VOR_Ioff ) ) //充电过程中出现只有IOFF,则出现如下三种情况:1、耳机出仓;2、耳机电池充满;3、耳机电池锂保。 { if( nVor_Intobox_Disp_Flag ) //Vor耳机在正常充电过程中,被拔出。 { nVor_Outbox_Disp_Flag = TRUE; nVor_Intobox_Disp_Flag = FALSE; nVor_GetOut_Box_Flag = TRUE; Vor_GetOut_Box_Flag = TRUE; //右耳出盒标志置1,用于抽电灯效 #ifdef _DEBUG_VOX printf("Vor Get Out.(line:%d)\r\n",(u16)__LINE__); #endif } nVor_Output_Debounce++; if( nVor_Output_Debounce >= VOX_IOFF_DET_DEBOUNCE ) //重载转轻载(耳机出仓后)需延时5s,Vox掉Vout 5V后转入ADT模式。 { nVor_Output_Debounce = 0; VOR_EN_Type(VOX_ADT_Mode); nVor_Chg_Full_Flag = TRUE; #ifdef _DEBUG_VOX printf("Vor Full And In ADT.(line:%d)\r\n",(u16)__LINE__); #endif } } else if ( ( CHIP_STA1 & ( VOR_LoadOn | VOR_Ioff ) ) == VOR_LoadOn ) //无IOFF有Loadon,说明:1、耳机出仓后4s内,耳机再次入仓;2、10分钟未满,耳机电池退出锂保状态,进入正常充电; { nVor_Output_Debounce = 0; nVor_Intobox_Disp_Flag = TRUE; if( nVor_Chg_Full_Flag ) //Vox在ADT模式后检测到loadon标志,则说明耳机已充满,不再抽电,等loadon消失,判断耳机出盒。 { Vor_Vout_Enable = OFF; #ifdef _DEBUG_VOX printf("Vor Full.(line:%d)\r\n",(u16)__LINE__); #endif } else { if( nVor_Outbox_Disp_Flag ) //左耳4s内再次入盒,左耳对应的入盒灯效闪一次。 { nVor_Outbox_Disp_Flag = FALSE; if( nVor_GetOut_Box_Flag ) { nVor_GetOut_Box_Flag = FALSE; /*重启跟随充*/ #if VOX_FOLLOW_CHG Vox_Fllow_Chg.Vox_Follow_Start = OFF; Vox_Fllow_Chg.Vox_Follow_Stop = OFF; Follow_Chg_Sta = Vox_Follow_Chg_InitSta; #endif Earphone_Chg_Flag_led = TRUE; //用于灯效显示 #ifdef LED_DISPLAY LED_On_Flag = TRUE; #endif #ifdef _DEBUG_VOX printf("Vor Get In Again.(line:%d)\r\n",(u16)__LINE__); #endif } } Vor_Vout_Enable = ON; //正常充电标志置ON。 Vor_GetOut_Box_Flag = FALSE; #ifdef _DEBUG_VOX printf("Vor Ching.(line:%d)\r\n",(u16)__LINE__); #endif } } else if ( !( CHIP_STA1 & VOR_LoadOn ) ) //无Loadon,说明,耳机出仓 { nVor_Loadon_Det_Debounce++; if( nVor_Loadon_Det_Debounce >= VOX_NO_LOADON_CNT ) //耳机充满后,断开内部下拉电阻延时计数,根据实际应用调整。 { nVor_Loadon_Det_Debounce = 0; nVor_Intobox_Disp_Flag = FALSE; nVor_Outbox_Disp_Flag = FALSE; nVor_GetOut_Box_Flag = FALSE; Vor_State = VOX_NONE_IN_BOX; #ifdef _DEBUG_VOX printf("Vor Out Box.(line:%d)\r\n",(u16)__LINE__); #endif } } else { nVor_Loadon_Det_Debounce = 0; } break; case VOX_NONE_IN_BOX: //空仓 VOR_EN_Type(VOX_ADT_Mode); Vor_Vout_Enable = OFF; Vor_GetOut_Box_Flag = TRUE; //右耳出盒标志置1,用于抽电灯效 if( CHIP_STA1 & VOR_LoadOn ) //adt模式下出现loadon信号,则说明Vor通道有耳机入盒。 { nVor_Loadon_Det_Debounce++; if( nVor_Loadon_Det_Debounce >= VOX_LOADON_DET_DEBOUNCE ) //Vox Loadon信号检测延时计数,loadon信号软件数字滤波,根据实际耳机进行调试; { nVor_Loadon_Det_Debounce = 0; Vor_State = VOX_GET_INTO_BOX; /*置灯效显示标志*/ Earphone_Chg_Flag_led = TRUE; #ifdef LED_DISPLAY LED_On_Flag = TRUE; #endif #ifdef _DEBUG_VOX printf("Vor Det Loadon.(line:%d)\r\n",(u16)__LINE__); #endif } } break; default: break; } } else //bat保护后,VOX恢复到最初状态。 { Vor_State = VOX_GET_INTO_BOX; Vor_Vout_Enable = OFF; if( !nVor_Get_Chip_STA_Flag ) { nVor_Get_Chip_STA_Flag = TRUE; VOR_EN_Type(VOX_ADT_Mode); //VOR Disable 5V And Enable VOR ADT nCHIP_STA1_Vor = CHIP_STA1 & VOR_LoadOn; } else { /*耳机出入盒判断*/ if( nCHIP_STA1_Vor != ( CHIP_STA1 & VOR_LoadOn ) ) //查询耳机loadon状态,loadon状态改变,则说明有耳机出入盒。 { if( CHIP_STA1 & VOR_LoadOn ) //Vox入盒 { Earphone_Chg_Flag_led = TRUE; //用于灯效显示 #ifdef LED_DISPLAY LED_On_Flag = TRUE; #endif #ifdef _DEBUG_VOX printf("VOR Get Into Box Bat Low.(line:%d)\r\n",(u16)__LINE__); #endif } nCHIP_STA1_Vor = CHIP_STA1 & VOR_LoadOn; } } } } #else /* ******************************************************************************* * void Vox_Det_Machine(void) * * Description : Vox Detect:耳机识别。 (100ms调用周期) * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ /* 1、关盖开启Boost denounce一段时间(ms级延时)后开启Vox 5v;显示灯效。 2、开盖开启Boost denounce一段时间(ms级延时)后开启Vox 5v至少500ms用于唤醒耳机;后发送开盖指令,持续10s,间隔250-300ms。 3、发送开盖指令间隔(250-300ms)期间,Vox转入ADT模式,检测都Loadon状态需要有灯效。 4、两只耳机电池都充满或仓低电,则发送关机指令。 */ void Vox_Det_Machine(void) { static bit Get_CHIP_STA1_Flag0; static bit nVox_Comm_Flag; static bit nVox_Comm_Over_Flag; static bit Cover_Close_Flag; static bit Cover_Close_Flag1; static bit Cover_Close_Force_Vout_Flag; static bit Cover_Open_Flag; static bit Cover_Open_5V_Flag; static bit Bat_Low_Pro_Flag; static bit Vox_Chg_Full_Flag; static bit Vox_Getinto_Sleep_Flag; static uint8_t CHIP_STA1_BK; static uint8_t Vox_Voltage_Hold_Timer; static uint8_t Vox_TX_Timer; static bit Vox_Chn_Select; static uint8_t Vox_Output_Debounce; static uint8_t Vox_Output_Cnt; static bit CoverEvent_Flg1; static bit Vox_Vol_Up_Flg; if( gBoost_Prepared_Flag ) { if( CoverEvent_Flg ) //Hall事件触发。 { if( !Boost_Open_Flag ) { DisCharge_Boost_Open(OFF,BOOST_VOUT_MAX); //开关盖Boost输出5.2V,保证耳机一定能被唤醒。Boost Enable;异常时由硬件主动关闭。开启Boost,开启Vox 5v会在开启Boost之后(100ms延时)。 Boost_Open_Flag = TRUE; return; } VOX_EN_Type(VOX_VOUT_Mode); //VOX Enable 5V Vox_Output_Debounce = 0; Vox_Voltage_Hold_Timer = 0; //关盖清0,开盖使用 Vox_TX_Timer = 0; Get_CHIP_STA1_Flag0 = FALSE; nVox_Comm_Flag = FALSE; nVox_Comm_Over_Flag = FALSE; CoverEvent_Flg1 = TRUE; if( CoverStatus == CLOSE ) //1、关盖关闭COM_CTRL;显示灯效。(无需查询Loadon、IOFF状态,无论耳机是否在仓,Vox 5V输出。) { Earphone_Chg_Flag_led = FALSE; //关盖取消耳机入盒灯效,显示关盖灯效。 Cover_Close_Flag = TRUE; Cover_Close_Flag1 = TRUE; Cover_Open_Flag = FALSE; Vox_Chg_Full_Flag = FALSE; Cover_Close_Force_Vout_Flag = FALSE; Vox_Getinto_Sleep_Flag = FALSE; Vox_Chn_Select = FALSE; Vox_Vout_Enable = ON; Wkup_Earphone_Flag = FALSE; #if VOX_FOLLOW_CHG Vox_Fllow_Chg.Vox_Follow_Start = OFF; Vox_Fllow_Chg.Vox_Follow_Stop = OFF; Follow_Chg_Sta = Vox_Follow_Chg_InitSta; #endif #ifdef _DEBUG_VOX printf("Box Close.(line:%d)\r\n",(u16)__LINE__); #endif } else //2、开盖处理:5v 500ms 转0V 500ms,后转ADT模式。 { Cover_Close_Flag = FALSE; Cover_Close_Flag1 = FALSE; Cover_Open_Flag = TRUE; Cover_Open_5V_Flag = FALSE; #ifdef _DEBUG_VOX printf("Box Open.(line:%d)\r\n",(u16)__LINE__); #endif } Boost_Open_Flag = FALSE; Vox_Output_Short_Flag = FALSE; Vox_Ocp_Flag = FALSE; CoverEvent_Flg = FALSE; } /* 开关盖后,VOX先升压5.2V 一段时间,唤醒耳机,后转入ADT,获取盒内耳机数量。 */ if( Vox_Voltage_Hold_Timer < HALL_EVENT_VOX_5V_DEBOUNCE ) //开盖后5V N00ms。 { Vox_Voltage_Hold_Timer++; return; } if ( CoverEvent_Flg1 ) { CoverEvent_Flg1 = FALSE; VOX_EN_Type(VOX_ADT_Mode); return; } else { if ( !Get_CHIP_STA1_Flag0 ) //获取耳机在盒数量。 { Get_CHIP_STA1_Flag0 = TRUE; if ( CHIP_STA1 & ( VOR_LoadOn | VOL_LoadOn ) ) { if ( ( CHIP_STA1 & ( VOR_LoadOn | VOL_LoadOn ) ) == ( VOR_LoadOn | VOL_LoadOn ) ) { EarPhone_Num = 2; } else { EarPhone_Num = 1; } } else { EarPhone_Num = 0; } #ifdef _DEBUG_VOX printf( "Open/Close Box,Earphones In Box(Num:%d)(VoxSta:0x%x).\r\n",(u16)EarPhone_Num, (u16)(CHIP_STA1) ); #endif } } /* 发送开盖指令*/ if( Cover_Open_Flag ) /*开盖后,5V持续N00ms后0V持续N00ms,保证耳机能被唤醒;之后发开盖码。*/ { #if VOX_0V_WAKEUP_EAR if( Vox_TX_Timer < HALL_OPEN_VOX_0V_DEBOUNCE ) //转0V N00ms { VOX_EN_Type(VOX_PD1K_Mode); Vox_TX_Timer++; } else #endif { #ifdef VOX_COMM_ENABLE /* 双向通讯,开盖发码。 */ if( !nVox_Comm_Flag ) { Vox_Comm_Cfg_Clear(); gVox_Comm.Cover_Open_Flag = TRUE; //置开盖发码标志位 nVox_Comm_Flag = TRUE; #ifdef _DEBUG_VOX printf("TX Comm Cover Open.(line:%d)\r\n ", (u16)__LINE__); #endif return; } else #endif { #ifdef VOX_COMM_ENABLE if( !gVox_Comm.Cover_Open_Flag ) //开盖发码完成 #endif { if ( !nVox_Comm_Over_Flag ) { nVox_Comm_Over_Flag = TRUE; VOX_EN_Type(VOX_ADT_Mode); OpenCover_TX_Cmd_Flag = TRUE; Vox_Vout_Enable = OFF; #ifdef _DEBUG_VOX printf("Open Box CMD TX Over.\r\n"); #endif } } else { return; } } if( Event_key == KEY_EVENT_Empty ) { if( OpenCover_TX_Cmd_Flag ) { OpenCover_TX_Cmd_Flag = FALSE; nVox_Comm_Over_Flag = TRUE; CHIP_STA1_BK = CHIP_STA1 & ( VOR_LoadOn | VOL_LoadOn ); } else { if( nVox_Comm_Over_Flag ) { /*耳机出入盒判断*/ if( CHIP_STA1_BK != ( CHIP_STA1 & ( VOR_LoadOn | VOL_LoadOn ) ) ) //查询耳机loadon状态,loadon状态改变,则说明有耳机出入盒。 { if ( CHIP_STA1 & ( VOR_LoadOn | VOL_LoadOn ) ) { Earphone_Chg_Flag_led = TRUE; #ifdef LED_DISPLAY LED_On_Flag = TRUE; #endif } #ifdef _DEBUG_VOX printf( "Open Box And Earphone GetIn(Num:%d)(VoxSta:0x%x).\r\n",(u16)EarPhone_Num, (u16)(CHIP_STA1) ); #endif CHIP_STA1_BK = ( CHIP_STA1 & ( VOR_LoadOn | VOL_LoadOn ) ); } } } } } } if( Cover_Close_Flag ) { if( Wkup_Earphone_Flag ) //保护、断充电后,VOX需自动升压唤醒耳机。 { if( !Boost_Open_Flag ) { DisCharge_Boost_Open(OFF, BOOST_VOUT_MAX); //Boost Enable;异常时由硬件主动关闭。开启Boost,开启Vox 5v会在开启Boost之后(100ms延时)。 Boost_Open_Flag = TRUE; Vox_Vout_Enable = ON; #if VOX_FOLLOW_CHG Vox_Fllow_Chg.Vox_Follow_Start = OFF; Vox_Fllow_Chg.Vox_Follow_Stop = OFF; Follow_Chg_Sta = Vox_Follow_Chg_InitSta; #endif Vox_Voltage_Hold_Timer = 0; Vox_Chg_Full_Flag = FALSE; CoverEvent_Flg1 = TRUE; Get_CHIP_STA1_Flag0 = FALSE; Cover_Close_Force_Vout_Flag = TRUE; Vox_Vol_Up_Flg = TRUE; return; } if( Vox_Vol_Up_Flg ) //VOX VOUT 5V只开一次。 { Vox_Vol_Up_Flg = FALSE; VOX_EN_Type(VOX_VOUT_Mode); //VOX Enable 5V } #ifdef _DEBUG_VOX printf("Close Box And Force Voltage Up.\r\n "); #endif Boost_Open_Flag = FALSE; Cover_Close_Flag1 = TRUE; if( Vox_Voltage_Hold_Timer <= HALL_CLOSE_VOX_5V_HOLD_CNT ) //关盖Boost VOUT 5V保持时间。 { Vox_Voltage_Hold_Timer++; return; } Wkup_Earphone_Flag = FALSE; } else { #ifdef VOX_COMM_ENABLE if( !Cover_Close_Force_Vout_Flag ) { #if VOX_0V_WAKEUP_EAR /*关盖后,5V持续N00ms后0V持续N00ms,保证耳机能被唤醒;之后发关盖码。*/ if( Vox_TX_Timer < HALL_CLOSE_VOX_0V_DEBOUNCE ) //转0V N00ms { VOX_EN_Type(VOX_PD1K_Mode); Vox_TX_Timer++; } else #endif { /* 双向通讯,关盖发码。 */ if( !nVox_Comm_Flag ) { Vox_Comm_Cfg_Clear(); gVox_Comm.Cover_Close_Flag = TRUE; //置关盖发码标志位 nVox_Comm_Flag = TRUE; #ifdef _DEBUG_VOX printf("TX Comm Cover Close.(line:%d)\r\n ", (u16)__LINE__); #endif return; } else { if( gVox_Comm.Cover_Close_Flag ) //关盖发码中 { return; } } } } #endif } /*Vox 过流保护,两只耳机都每隔500ms打嗝一次*/ if( IRQ_FLAG0 & ( VOR_OutPut_Short | VOL_OutPut_Short ) ) { if( !Vox_Ocp_Flag ) { Vox_Output_Debounce++; if( Vox_Output_Debounce >= VOX_OCP_HICUUP_DEBOUNCE ) { Vox_Output_Debounce = 0; IRQ_FLAG0 = VOR_OutPut_Short | VOL_OutPut_Short; VOX_EN_Type(VOX_VOUT_Mode); Vox_Output_Short_Flag = TRUE; Vox_Vout_Enable = OFF; } } else { VOX_EN_Type(VOX_ADT_Mode); } return; } Vox_Output_Short_Flag = FALSE; Vox_Ocp_Flag = FALSE; /* 发完关盖码后,开启VOX VOUT 5V输出。 */ if( Cover_Close_Flag1 ) { VOX_EN_Type(VOX_VOUT_Mode); //VOX Enable 5V #ifdef _DEBUG_VOX printf("VOX Vout 5V(STA1:0x%x,line:%d).\r\n",(uint16_t)CHIP_STA1, (uint16_t)__LINE__); #endif Cover_Close_Flag1 = FALSE; Vox_Voltage_Hold_Timer = 0; } else { if( !Vox_Chg_Full_Flag ) { //if( ( CHIP_STA1 & ( VOR_Ioff | VOL_Ioff | VOL_LoadOn | VOR_LoadOn ) == ( VOR_Ioff | VOL_Ioff | VOL_LoadOn | VOR_LoadOn ) ) || F_batlevel_low ) //耳机充满、VOX无负载、盒子低电,则关闭Vout输出通路,关闭Boost。 if( ( (CHIP_STA1 & 0xAC) == 0xAC ) || F_batlevel_low ) { if( Vox_Voltage_Hold_Timer <= VOX_CHG_FULL_5V_LEAST_CNT ) //重载转轻载延时5s后关闭Boost输出。 { Vox_Voltage_Hold_Timer++; return; } #ifdef _DEBUG_VOX printf("VOX CHG Full.\r\n"); #endif Vox_Chg_Full_Flag = TRUE; Vox_Output_Cnt = 0; Vox_Voltage_Hold_Timer = 0; Vox_Getinto_Sleep_Flag = FALSE; VOX_EN_Type(VOX_ADT_Mode); //VOX Enable ADT } else { #if VOX_FOLLOW_CHG if ( Vox_Fllow_Chg.Vox_Follow_Stop == OFF ) { Vox_Follow_Chg( &Vox_Fllow_Chg ); //跟随充处理。 } #endif } } else { #ifdef VOX_COMM_ENABLE if( !Vox_Getinto_Sleep_Flag ) { Vox_Getinto_Sleep_Flag = TRUE; Vox_Comm_Cfg_Clear(); gVox_Comm.Vox_Chg_Full_Flag = TRUE; #ifdef _DEBUG_VOX printf("TX Comm Vox Chg Full.(line:%d)\r\n ", (u16)__LINE__); #endif } else #endif { #ifdef VOX_COMM_ENABLE if( !gVox_Comm.Vox_Chg_Full_Flag ) #endif { if ( !nVox_Comm_Over_Flag ) { nVox_Comm_Over_Flag = TRUE; VOX_EN_Type(VOX_ADT_Mode); Vox_Vout_Enable = OFF; #ifdef _DEBUG_VOX printf("VOX Get Into Sleep.\r\n"); #endif } } } } } } Bat_Low_Pro_Flag = FALSE; } else { if( !Bat_Low_Pro_Flag ) //低电保护后,VOX开启ADT模式。判断耳机出入盒,并显示相应的灯效。 { Bat_Low_Pro_Flag = TRUE; VOX_EN_Type(VOX_ADT_Mode); Vox_Vout_Enable = OFF; CHIP_STA1_BK = CHIP_STA1 & ( VOR_LoadOn | VOL_LoadOn ); return; } /*耳机出入盒判断*/ if( CHIP_STA1_BK != ( CHIP_STA1 & ( VOR_LoadOn | VOL_LoadOn ) ) ) //查询耳机loadon状态,loadon状态改变,则说明有耳机出入盒。 { if( CHIP_STA1 & ( VOR_LoadOn | VOL_LoadOn ) ) { Earphone_Chg_Flag_led = TRUE; #ifdef LED_DISPLAY LED_On_Flag = TRUE; #endif } CHIP_STA1_BK = ( CHIP_STA1 & ( VOR_LoadOn | VOL_LoadOn ) ); } } } #endif #if VOX_FOLLOW_CHG /* ******************************************************************************* * void Vox_Follow_Chg( g_Vox_Fllow_Chg_Cfg *g_Vox_Fllow_Chg ) * * Description : Vox 跟随充处理函数。 (100ms调用周期) * * Arguments : g_Vox_Fllow_Chg_Cfg *g_Vox_Fllow_Chg * Returns : NONE * Notes : NONE * ******************************************************************************* */ void Vox_Follow_Chg( g_Vox_Fllow_Chg_Cfg *n_Vox_Fllow_Chg ) { static bit nVpmid_Value_Setting; switch ( Follow_Chg_Sta ) { case Vox_Follow_Chg_InitSta: //STA0:PMID=5.2V可以保证耳机一定能进入充电状态,并持续一段时间保证耳机能开始抽电。 if( (n_Vox_Fllow_Chg->Vox_Follow_Stop == OFF) ) //启动跟随充 { if( Vox_Follow_Init_Deb <= VOX_FOLLOW_CHG_INIT_CNT ) { Vox_Follow_Init_Deb++; n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present = VOUT_MAX_THD; if( !nVpmid_Value_Setting ) { DisCharge_Boost_Open(OFF,n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present); #ifdef _DEBUG_FOLLOW printf("Follow CHG InitSta Set Max Vpmid.(Vox_sta:0x%x)(line:%d)\r\n",(uint16_t)CHIP_STA1, (uint16_t)__LINE__); #endif nVpmid_Value_Setting = TRUE; } } else { Vox_Follow_Init_Deb = 0; /* 参数初始化。 */ nVpmid_Value_Setting = FALSE; n_Vox_Fllow_Chg->Vpmid_AddSta[VOR_TYPE] = OFF; n_Vox_Fllow_Chg->Vpmid_AddSta[VOL_TYPE] = OFF; n_Vox_Fllow_Chg->Vpmid_SubSta[VOR_TYPE] = OFF; n_Vox_Fllow_Chg->Vpmid_SubSta[VOL_TYPE] = OFF; n_Vox_Fllow_Chg->IVox_TC_Mode[VOR_TYPE] = OFF; n_Vox_Fllow_Chg->IVox_TC_Mode[VOL_TYPE] = OFF; n_Vox_Fllow_Chg->Vox_InBox_Sta[VOR_TYPE] = OFF; n_Vox_Fllow_Chg->Vox_InBox_Sta[VOL_TYPE] = OFF; n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE] = 0; n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE] = 0; n_Vox_Fllow_Chg->Vpmid_Threshold_Neg = VOUT_MIN_THD; n_Vox_Fllow_Chg->Vpmid_Threshold_Pos = VOUT_MAX_THD; Follow_Chg_Sta = Vox_Follow_Chg_Sta1; Vox_Follow_Chg_Debounce = 0; #ifdef _DEBUG_FOLLOW printf("Follow CHG InitSta.(Vox_sta:0x%x)(line:%d)\r\n",(uint16_t)CHIP_STA1, (uint16_t)__LINE__); #endif } } break; case Vox_Follow_Chg_Sta1: //STA1:获取耳机当前抽电电流和设置Vox上下限电流阈值。 if ( ( CHIP_STA1 & VOR_Ioff ) && ( CHIP_STA1 & VOL_Ioff ) ) //VOL、VOR耳机无抽电,则说明耳机已充满,无需再继续跟随充。 { n_Vox_Fllow_Chg->Vox_Follow_Stop = ON; Follow_Chg_Sta = Vox_Follow_Chg_InitSta; #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta1,No EarPhone In Box.(line:%d)\r\n",(uint16_t)__LINE__); #endif } else { /*获取当前Ivox。Vox开启功率,且Ioff处于重载状态。*/ if( !( CHIP_STA1 & VOR_Ioff ) ) { n_Vox_Fllow_Chg->IVox_Init[VOR_TYPE] = g_pmu_Adc_Ivor; n_Vox_Fllow_Chg->IVox_Threshold_Neg[VOR_TYPE] = IVOR_Threshold_Neg(g_pmu_Adc_Ivor); //Ivox_Threshold_Neg = IVox_Init * 80% n_Vox_Fllow_Chg->IVox_Threshold_Pos[VOR_TYPE] = IVOR_Threshold_Pos(g_pmu_Adc_Ivor); //Ivox_Threshold_Neg = IVox_Init * 2 #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta1,VOR Chging(Ivor:%dmA).(line:%d)\r\n",(u16)g_pmu_Adc_Ivor,(uint16_t)__LINE__); #endif } if( !( CHIP_STA1 & VOL_Ioff ) ) { n_Vox_Fllow_Chg->IVox_Init[VOL_TYPE] = g_pmu_Adc_Ivol; n_Vox_Fllow_Chg->IVox_Threshold_Neg[VOL_TYPE] = IVOL_Threshold_Neg(g_pmu_Adc_Ivol); //Ivox_Threshold_Neg = IVox_Init * 80% n_Vox_Fllow_Chg->IVox_Threshold_Pos[VOL_TYPE] = IVOL_Threshold_Pos(g_pmu_Adc_Ivol); //Ivox_Threshold_Neg = IVox_Init * 2 #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta1,VOL Chging(Ivol:%dmA).(line:%d)\r\n",(u16)g_pmu_Adc_Ivol,(uint16_t)__LINE__); #endif } n_Vox_Fllow_Chg->Vox_Follow_Start = ON; Follow_Chg_Sta = Vox_Follow_Chg_Sta2; } break; case Vox_Follow_Chg_Sta2: //STA2:获取当前Vox电流,等待IVOX电流稳定,检测当前电流IVox_At_Present。 if( Vox_Follow_Chg_Debounce <= VOX_FOLLOW_CHG_NOWCURCHK_CNT ) { Vox_Follow_Chg_Debounce++; } else { Vox_Follow_Chg_Debounce = 0; if ( !( CHIP_STA1 & VOR_Ioff ) ) { n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE] = g_pmu_Adc_Ivor; n_Vox_Fllow_Chg->Vox_InBox_Sta[VOR_TYPE] = ON; //判断VOR有耳机在盒正常抽电 #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta2,Get IVOR:%dmA.(line:%d)\r\n",(uint16_t)g_pmu_Adc_Ivor,(u16)__LINE__); #endif } if ( !( CHIP_STA1 & VOL_Ioff) ) { n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE] = g_pmu_Adc_Ivol; n_Vox_Fllow_Chg->Vox_InBox_Sta[VOL_TYPE] = ON; //判断VOL有耳机在盒正常抽电 #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta2,Get IVOL:%dmA.(line:%d)\r\n",(uint16_t)g_pmu_Adc_Ivol,(u16)__LINE__); #endif } Follow_Chg_Sta = Vox_Follow_Chg_Sta3; } break; case Vox_Follow_Chg_Sta3: //STA3:根据Ivox电流,判断PMID是否需要降低。 if( Vox_Follow_Chg_Debounce <= VOX_FOLLOW_CHG_VOLTAGE_ADJUST_CNT ) { Vox_Follow_Chg_Debounce++; } else { Vox_Follow_Chg_Debounce = 0; if ( ( n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE] > n_Vox_Fllow_Chg->IVox_Threshold_Pos[VOR_TYPE] ) || \ ( n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE] > n_Vox_Fllow_Chg->IVox_Threshold_Pos[VOL_TYPE] ) ) //当前电流大于THP阈值电流,则说明耳机状态发生改变(TC跳转到CC或Recharge复充),需要重启跟随充。 { Follow_Chg_Sta = Vox_Follow_Chg_InitSta; n_Vox_Fllow_Chg->Vox_Follow_Start = OFF; //重启动跟随充 #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta3,VOX Chg ReInit.(line:%d)\r\n",(uint16_t)__LINE__); #endif } else { if ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOR_TYPE] == ON ) { if ( n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE] <= VOX_CV_TC_CURRENT ) //检测到Ivor小于CV/TC电流阈值,则说明耳机进入CV/TC阶段 { if ( CHIP_STA1 & VOR_Ioff ) //检测到Ivor Ioff,则VPMID升档。 { n_Vox_Fllow_Chg->Vpmid_AddSta[VOR_TYPE] = ON; if ( n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present >= VOUT_MAX_THD ) //Vpmid电压升到最大,并且IOFF标志存在,则说明耳机充满。 { n_Vox_Fllow_Chg->Vox_InBox_Sta[VOR_TYPE] = OFF; } #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta3(CV),VOR Vpmid AddSta(Ivor:%dmA).(line:%d)\r\n",n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE],(u16)__LINE__); #endif } else //未检测到Ivor Ioff,则Vpmid降档 { n_Vox_Fllow_Chg->Vpmid_SubSta[VOR_TYPE] = ON; #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta3(CV),VOR Vpmid SubSta(Ivor:%dmA).(line:%d)\r\n",n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE],(u16)__LINE__); #endif } } else { if ( n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE] > n_Vox_Fllow_Chg->IVox_Threshold_Neg[VOR_TYPE] ) { n_Vox_Fllow_Chg->Vpmid_SubSta[VOR_TYPE] = ON; #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta3(CC),VOR Vpmid SubSta(Ivor:%dmA).(line:%d)\r\n",n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE],(u16)__LINE__); #endif } else { n_Vox_Fllow_Chg->Vpmid_AddSta[VOR_TYPE] = ON; #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta3(CC),VOR Vpmid AddSta(Ivor:%dmA).(line:%d)\r\n",n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE],(u16)__LINE__); #endif } } } if ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOL_TYPE] == ON ) { if ( n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE] <= VOX_CV_TC_CURRENT ) //检测到Ivol小于CV/TC电流阈值,则说明耳机进入CV/TC阶段 { if ( CHIP_STA1 & VOL_Ioff ) //检测到Ivol Ioff,则VPMID升档。 { n_Vox_Fllow_Chg->Vpmid_AddSta[VOL_TYPE] = ON; if ( n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present >= VOUT_MAX_THD ) //Vpmid电压升到最大,并且IOFF标志存在,则说明耳机充满。 { n_Vox_Fllow_Chg->Vox_InBox_Sta[VOL_TYPE] = OFF; } #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta3(CV),VOL Vpmid AddSta(Ivol:%dmA).(line:%d)\r\n",n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE],(u16)__LINE__); #endif } else //未检测到Ivol Ioff,则Vpmid降档 { n_Vox_Fllow_Chg->Vpmid_SubSta[VOL_TYPE] = ON; #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta3(CV),VOL Vpmid SubSta(Ivol:%dmA).(line:%d)\r\n",n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE],(u16)__LINE__); #endif } } else { if ( n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE] > n_Vox_Fllow_Chg->IVox_Threshold_Neg[VOL_TYPE] ) { n_Vox_Fllow_Chg->Vpmid_SubSta[VOL_TYPE] = ON; #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta3(CC),VOL Vpmid SubSta(Ivol:%dmA).(line:%d)\r\n",n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE],(u16)__LINE__); #endif } else { n_Vox_Fllow_Chg->Vpmid_AddSta[VOL_TYPE] = ON; #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta3(CC),VOL Vpmid AddSta(Ivol:%dmA).(line:%d)\r\n",n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE],(u16)__LINE__); #endif } } } } } break; case Vox_Follow_Chg_Sta4: //STA4:根据IVOX电流,判断PMID是否升高:1、在此状态下,每2s检测一次IVOX电流;2、当检测到 IVOX < IVOX_THN or IVOX > IVOX_THP,则PMID 升高一个step(或N个step,根据实际测试设定。) if( Vox_Follow_Chg_Debounce <= VOX_FOLLOW_CHG_PMID_UP_CNT ) { /* 每2s检测一次IVOX电流。 */ Vox_Follow_Chg_Debounce++; n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE] = g_pmu_Adc_Ivor; n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE] = g_pmu_Adc_Ivol; } else { Vox_Follow_Chg_Debounce = 0; /* 充电效率优先 */ #ifdef FOLLOW_CHG_EFFICIENCY if ( ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOR_TYPE] == ON ) && ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOL_TYPE] == ON ) ) { if ( ( ( n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE] < n_Vox_Fllow_Chg->IVox_Threshold_Neg[VOR_TYPE] ) || \ ( n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE] > n_Vox_Fllow_Chg->IVox_Threshold_Pos[VOR_TYPE] ) ) && \ ( ( n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE] < n_Vox_Fllow_Chg->IVox_Threshold_Neg[VOL_TYPE] ) || \ ( n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE] > n_Vox_Fllow_Chg->IVox_Threshold_Pos[VOL_TYPE] ) ) ) { n_Vox_Fllow_Chg->Vpmid_AddSta[VOR_TYPE] = ON; n_Vox_Fllow_Chg->Vpmid_AddSta[VOL_TYPE] = ON; Follow_Chg_Sta = Vox_Follow_Chg_Sta2; #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta4,VOx Vpmid AddSta(Vout:0x%x,Ivol:%dmA,Ivor:%dmA)(line:%d).\r\n",(uint16_t)n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present,(uint16_t)g_pmu_Adc_Ivol,(uint16_t)g_pmu_Adc_Ivor,(u16)__LINE__); #endif } #ifdef _DEBUG_FOLLOW else { printf("Follow CHG Sta4,VOx Ching(Vout:0x%x,Ivol:%dmA,Ivor:%dmA)(line:%d).\r\n",(uint16_t)n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present,(uint16_t)g_pmu_Adc_Ivol,(uint16_t)g_pmu_Adc_Ivor,(u16)__LINE__); } #endif } else #endif { /* 充电速度优先 */ if ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOR_TYPE] == ON ) { /* 当检测到 IVOX < IVOX_THN or IVOX > IVOX_THP,则PMID 升高一个step(或N个step,根据实际测试设定。) */ if ( ( n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE] < n_Vox_Fllow_Chg->IVox_Threshold_Neg[VOR_TYPE] ) || \ ( n_Vox_Fllow_Chg->IVox_At_Present[VOR_TYPE] > n_Vox_Fllow_Chg->IVox_Threshold_Pos[VOR_TYPE] ) ) { n_Vox_Fllow_Chg->Vpmid_AddSta[VOR_TYPE] = ON; Follow_Chg_Sta = Vox_Follow_Chg_Sta2; #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta4,VOR Vpmid AddSta(Vout:0x%x,Ivor:%dmA)(line:%d).\r\n",(uint16_t)n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present,(uint16_t)g_pmu_Adc_Ivor,(u16)__LINE__); #endif } #ifdef _DEBUG_FOLLOW else { printf("Follow CHG Sta4,VOR Ching(Vout:0x%x,Ivor:%dmA)(line:%d).\r\n",(uint16_t)n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present,(uint16_t)g_pmu_Adc_Ivor,(u16)__LINE__); } #endif } if ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOL_TYPE] == ON ) { if ( ( n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE] > n_Vox_Fllow_Chg->IVox_Threshold_Pos[VOL_TYPE] ) || \ ( n_Vox_Fllow_Chg->IVox_At_Present[VOL_TYPE] < n_Vox_Fllow_Chg->IVox_Threshold_Neg[VOL_TYPE] ) ) { n_Vox_Fllow_Chg->Vpmid_AddSta[VOL_TYPE] = ON; Follow_Chg_Sta = Vox_Follow_Chg_Sta2; #ifdef _DEBUG_FOLLOW printf("Follow CHG Sta4,VOL Vpmid AddSta(Vout:0x%x,Ivol:%dmA)(line:%d).\r\n",(uint16_t)n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present,(uint16_t)g_pmu_Adc_Ivol,(u16)__LINE__); #endif } #ifdef _DEBUG_FOLLOW else { printf("Follow CHG Sta4,VOL Ching(Vout:0x%x,Ivol:%dmA)(line:%d).\r\n",(uint16_t)n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present,(uint16_t)g_pmu_Adc_Ivol,(u16)__LINE__); } #endif } } } break; default: break; } if( ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOR_TYPE] == ON ) || ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOL_TYPE] == ON ) ) { if( ( n_Vox_Fllow_Chg->Vpmid_SubSta[VOR_TYPE] == ON ) || ( n_Vox_Fllow_Chg->Vpmid_SubSta[VOL_TYPE] == ON ) ) //当需要降压Vpmid,则每降一次档位,都会充电至少2s。 { if( ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOR_TYPE] == ON ) && ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOL_TYPE] == ON ) ) { if( ( n_Vox_Fllow_Chg->Vpmid_SubSta[VOR_TYPE] == ON ) && ( n_Vox_Fllow_Chg->Vpmid_SubSta[VOR_TYPE] == ON ) ) { n_Vox_Fllow_Chg->Vpmid_SubSta_Flag = ON; #ifdef _DEBUG_FOLLOW printf("Follow CHG SubSta,VOL/VOR(line:%d).\r\n",(uint16_t)__LINE__); #endif } } if( ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOR_TYPE] == ON ) && ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOL_TYPE] == OFF ) ) { if( n_Vox_Fllow_Chg->Vpmid_SubSta[VOR_TYPE] == ON ) { n_Vox_Fllow_Chg->Vpmid_SubSta_Flag = ON; #ifdef _DEBUG_FOLLOW printf("Follow CHG SubSta,VOR(line:%d).\r\n",(uint16_t)__LINE__); #endif } } else if( ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOR_TYPE] == OFF ) && ( n_Vox_Fllow_Chg->Vox_InBox_Sta[VOL_TYPE] == ON ) ) { if( n_Vox_Fllow_Chg->Vpmid_SubSta[VOL_TYPE] == ON ) { n_Vox_Fllow_Chg->Vpmid_SubSta_Flag = ON; #ifdef _DEBUG_FOLLOW printf("Follow CHG SubSta,VOL(line:%d).\r\n",(uint16_t)__LINE__); #endif } } n_Vox_Fllow_Chg->Vpmid_SubSta[VOR_TYPE] = OFF; n_Vox_Fllow_Chg->Vpmid_SubSta[VOL_TYPE] = OFF; if ( n_Vox_Fllow_Chg->Vpmid_SubSta_Flag == ON ) { if( n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present > VOUT_MIN_THD ) { n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present = n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present - VOX_FOLLOW_CHG_PMID_DOWN_STEPS; } /* 1、当Vpmid降档到到下限阈值,则开始升压。2、Boost 直通模式使能条件判断:VOUT - VBAT > 200mV。*/ if( ( n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present <= n_Vox_Fllow_Chg->Vpmid_Threshold_Neg ) || \ ( g_pmu_Adc_Vout < ( g_Vbat_Adc + Vox_FOLLOW_CHG_PTM_THD ) ) ) { if( n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present <= n_Vox_Fllow_Chg->Vpmid_Threshold_Neg ) { n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present = n_Vox_Fllow_Chg->Vpmid_Threshold_Neg; n_Vox_Fllow_Chg->Vox_PTM_Type = OFF; } else { n_Vox_Fllow_Chg->Vox_PTM_Type = ON; n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present = n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present + VOX_FOLLOW_CHG_PMID_DOWN_STEPS; #ifdef _DEBUG_FOLLOW printf("Follow CHG PTM ON,(STA:0x%x,Vpmid:0x%x,PTM:%d,Vbat:%d,Vout:%d)(line:%d)\r\n",(uint16_t)Follow_Chg_Sta,(uint16_t)n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present,(uint16_t)n_Vox_Fllow_Chg->Vox_PTM_Type,(uint16_t)g_Vbat_Adc,(uint16_t)g_pmu_Adc_Vout,(uint16_t)__LINE__); #endif } Follow_Chg_Sta = Vox_Follow_Chg_Sta4; } else { Follow_Chg_Sta = Vox_Follow_Chg_Sta2; n_Vox_Fllow_Chg->Vox_PTM_Type = OFF; } Vox_Follow_Chg_Debounce = 0; n_Vox_Fllow_Chg->Vpmid_SubSta_Flag = OFF; #ifdef _DEBUG_FOLLOW printf("Follow CHG SubSta,(STA:0x%x,Vpmid:0x%x,PTM:%d,Vbat:%d,Vout:%d)(line:%d)\r\n",(uint16_t)Follow_Chg_Sta,(uint16_t)n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present,(uint16_t)n_Vox_Fllow_Chg->Vox_PTM_Type,(uint16_t)g_Vbat_Adc,(uint16_t)g_pmu_Adc_Vout,(uint16_t)__LINE__); #endif DisCharge_Boost_Open(n_Vox_Fllow_Chg->Vox_PTM_Type, n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present ); } } else { /* PMID > PMID_THP,且VOL和VOR的任意一支路电流超过阈值,Ivol_THN > Ivol > Ivol_THP 或 Ivor_THN > Ivor > Ivor_THP。*/ if( ( n_Vox_Fllow_Chg->Vpmid_AddSta[VOR_TYPE] == ON ) || ( n_Vox_Fllow_Chg->Vpmid_AddSta[VOL_TYPE] == ON ) ) { n_Vox_Fllow_Chg->Vpmid_AddSta[VOR_TYPE] = OFF; n_Vox_Fllow_Chg->Vpmid_AddSta[VOL_TYPE] = OFF; if( n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present < VOUT_MAX_THD ) { n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present = n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present + VOX_FOLLOW_CHG_PMID_UP_STEPS; } Follow_Chg_Sta = Vox_Follow_Chg_Sta4; //当有需要升压Vpmid,则需要重回Sta4。 /* 当VPMID 上升到上限阈值,则说明本轮跟随充调整结束,则重回StaInit。 */ if( n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present >= n_Vox_Fllow_Chg->Vpmid_Threshold_Pos ) { n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present = n_Vox_Fllow_Chg->Vpmid_Threshold_Pos; Follow_Chg_Sta = Vox_Follow_Chg_Sta1; } #ifdef _DEBUG_FOLLOW printf("Follow CHG AddSta,(STA:0x%x,Vpmid:0x%x)(line:%d)\r\n",(uint16_t)Follow_Chg_Sta,(uint16_t)n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present,(uint16_t)__LINE__); #endif DisCharge_Boost_Open(OFF, n_Vox_Fllow_Chg->Vpmid_Threshold_At_Present); } } } else { if( Follow_Chg_Sta > Vox_Follow_Chg_Sta2 ) { Follow_Chg_Sta = Vox_Follow_Chg_InitSta; n_Vox_Fllow_Chg->Vox_Follow_Stop = ON; } } } #endif #endif