/* ****************************************************************************** * * @file VOX_Module.c * @brief VOL/R module * * * @version 1.0 * @date 2022/07/18 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 2022/07/18 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" bit Vor_Vout_Enable = OFF; //OFF:用于BOOST开启后延时开启VOUT输出;TRUE:用于判断是正常充电还是IOFF充电。 bit Vol_Vout_Enable = OFF; #if VOX_ENABLE /******************************************************************************\ Macro definitions \******************************************************************************/ #define VOX_IOFF_DET_DEBOUNCE 40 //Vox Ioff检测延时4s,为了保证耳机端初始化完成,开始抽电流 #define VOX_LOADON_DET_DEBOUNCE 2 #define T10MIN_DEBOUNCE 150 //10分钟定时,4s一次。150 /******************************************************************************\ Variables definitions \******************************************************************************/ #if 0 Vox_State_e Vol_State = VOX_NONE_IN_BOX; uint8_t Vol_Loadon_Det_Debounce = 0; uint8_t Vol_Ioff_Det_Debounce = 0; uint8_t Vol_LiPro_Det_Debounce = 0; bit Vol_LiPro_Flag = 0; Vox_State_e Vor_State = VOX_NONE_IN_BOX; uint8_t Vor_Loadon_Det_Debounce = 0; uint8_t Vor_Ioff_Det_Debounce = 0; uint8_t Vor_LiPro_Det_Debounce = 0; bit Vor_LiPro_Flag = 0; uint8_t Vol_Output_Short_Debounce = 0; uint8_t Vor_Output_Short_Debounce = 0; bit Vol_Bat_Full_Flag = 0; bit Vor_Bat_Full_Flag = 0; uint8_t BES_Puls_Cnt = 0; //BES Reset脉冲计数 bit BES_Puls_Start = 0; //开启BES Reset脉冲信号 #endif /******************************************************************************\ Functions definitions \******************************************************************************/ /* ******************************************************************************* * void Vox_init(void) * * Description : Vox Initialization :Vox初始化函数 * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ void Vox_init(void) { VOX_CTL0 = 0xC3; //VOX 负载接入、存在识别功能使能,负载自动识别。打开Vox vds钳压环使能(主要用于VOX 5V输出)。 /* SFRADDR = VOX_CON0; //设置VOX输出500mA,负载识别电流2.5uA。 SFRDATA &= 0xE0; SFRDATA |= (VOX_IOUT_500MA << 3) | VOX_ADT_Cur_2_5UA; */ #if 0 Vol_State = VOX_NONE_IN_BOX; Vor_State = VOX_NONE_IN_BOX; #endif } #if 0 /* ******************************************************************************* * uint8_t VOL_EN_Type(VOL_Enable_Type_e VOL_Enable_Type) * * Description : VOL Open(EN_VO) * Arguments : * Returns : * Notes : * ******************************************************************************* */ void VOL_EN_Type(VOX_Enable_Mode_e VOL_Enable_Mode) { switch(VOL_Enable_Mode) { case VOX_VOUT_Mode: VOX_CTL0 &= ~0x10; //VOL Disable 5V And Disable VOR ADT VOX_CTL0 |= 0x10; //VOL Enable 5V break; case VOX_ADT_Mode: VOX_CTL0 &= ~0x10; //VOL 5v Off VOX_CTL0 |= 0x01; //VOL 负载接入、存在识别功能使能,负载自动识别 break; default: break; } } /* ******************************************************************************* * void VOR_EN_Type(VOR_Enable_Type_e VOR_Enable_Type) * * Description : VOL Open(EN_VO) * Arguments : * Returns : * Notes : * ******************************************************************************* */ void VOR_EN_Type(VOX_Enable_Mode_e VOR_Enable_Mode) { switch(VOR_Enable_Mode) { case VOX_VOUT_Mode: VOX_CTL0 &= ~0x20; //VOR Disable 5V And Disable VOR ADT VOX_CTL0 |= 0x20; //VOR Enable 5V break; case VOX_ADT_Mode: VOX_CTL0 &= ~0x20; //VOR 5v Off VOX_CTL0 |= 0x02; //VOR load detect On break; default: break; } } /* ******************************************************************************* * void Vol_Det_Machine(void) * * Description : Vol Detect:耳机识别。 (100ms调用周期) * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ void Vol_Det_Machine(void) { #ifdef BOOST_AOUT if( gBoost_Opened_Flag ) //进行Vox Det的条件:1、Vox处于非双向通信功能;2、Boost已经开启 #else if( gBoost_Prepared_Flag ) #endif { switch( Vol_State ) { case VOX_GET_INTO_BOX: //耳机入仓 if( (VOX_CTL0 & 0x10) != 0x10 ) //1、当前已经开启了VOUT,则无需重复开启;原因:在使能VOUT前需要先关闭VOUT使能,如果连续开,会出现一段时间断开的情况。 { VOL_EN_Type(VOX_VOUT_Mode); } Vol_Loadon_Det_Debounce++; if( Vol_Loadon_Det_Debounce >= VOX_LOADON_DET_DEBOUNCE ) //Vox开启VOUT输出后,debounce一段时间(200ms)后,IOFF状态消失,只存在loadon状态,则说明Vox正常充电。 { Vol_Loadon_Det_Debounce = 0; if( (CHIP_STA1 & 0x24) == 0x20 ) { Vol_Vout_Enable = ON; //正常充电标志置ON。 #ifdef _DEBUG_VOX printf("Vol Vo Nor\r\n"); #endif } Vol_State = VOX_STAY_IN_BOX; } break; case VOX_STAY_IN_BOX: //耳机在仓 if( (CHIP_STA1 & 0x24) == 0x24 ) //Vox在充电过程中出现了Loadon和IOFF同时存在的状态,则出现如下三种情况:1、耳机出仓;2、耳机电池充满;3、耳机电池锂保。 { Vol_Ioff_Det_Debounce++; if( Vol_Ioff_Det_Debounce >= VOX_IOFF_DET_DEBOUNCE ) //重载转轻载(耳机出仓后)需延时4s { Vol_Ioff_Det_Debounce = 0; if( ON == Vol_Vout_Enable ) //Vox在正常充电过程中出现了IOFF状态,则说明:1、耳机出仓;2、耳机电池充满; { VOL_EN_Type(VOX_ADT_Mode); //Vox进入ADT模式后,观察CHIP_STA1的状态,1、无Loadon、IOFF,则说明耳机出仓;2、只有Loadon,则说明耳机在仓,耳机电池充满。 Vol_Bat_Full_Flag = 1; #ifdef LED_DISPLAY //LED_R_FLASH(100,5); #endif #ifdef _DEBUG_VOX printf("Vol Get Out\r\n"); #endif } else //否则,耳机电池处于锂保状态,Vout输出电流5mA,充电10分钟。1、10分钟未满,耳机电池跳出锂保状态;2、10分钟满,耳机电池仍处于锂保状态。 { Vol_LiPro_Flag = 1; //耳机电池进入锂保状态后,不能倒数进休眠?or 需要定时唤醒进行计数? Vol_LiPro_Det_Debounce++; if( Vol_LiPro_Det_Debounce >= T10MIN_DEBOUNCE ) { Vol_LiPro_Det_Debounce = 0; VOL_EN_Type(VOX_ADT_Mode); //2、10分钟满,耳机电池仍处于锂保状态。则Vox转入ADT模式。只存在Loadon状态。 Vol_LiPro_Flag = 0; } #ifdef LED_DISPLAY //LED_R_KEEP_FLASHING(50); #endif #ifdef _DEBUG_VOX printf("Vol LiPro\r\n"); #endif } } } else if( (CHIP_STA1 & 0x24) == 0x20 ) //观察CHIP_STA1的状态,无IOFF有Loadon,说明:1、耳机出仓后4s内,耳机再次入仓;2、10分钟未满,耳机电池退出锂保状态,进入正常充电; { Vol_Ioff_Det_Debounce = 0; Vol_LiPro_Det_Debounce = 0; Vol_Vout_Enable = ON; //正常充电标志置ON。 #ifdef LED_DISPLAY //LED_R_ON(); #endif if( Vol_Bat_Full_Flag ) //耳机充满,在ADT模式下,只有Loadon状态,则说明耳机充满。 { Vol_Vout_Enable = OFF; Vol_Bat_Full_Flag = 0; #ifdef _DEBUG_VOX printf("Vol Bat Full\r\n"); #endif } } else if( !(CHIP_STA1 & 0x24) ) //CHIP_STA1无loadon和ioff状态,则说明耳机出仓了。 { Vol_State = VOX_NONE_IN_BOX; } break; case VOX_NONE_IN_BOX: //空仓 VOL_EN_Type(VOX_ADT_Mode); Vol_Loadon_Det_Debounce = 0; Vol_Ioff_Det_Debounce = 0; Vol_LiPro_Det_Debounce = 0; Vol_Vout_Enable = OFF; if( CHIP_STA1 & 0x20 ) //ADT模式下出现Loadon信号,则说明有耳机入仓。 { Vol_State = VOX_GET_INTO_BOX; #if DISCHARGE_ENABLE #ifndef BOOST_AOUT DisCharge_Boost_Open(); #endif #endif #ifdef _DEBUG_VOX printf("VO_INTO_BOX\r\n"); #endif } break; default: break; } } else //Boost保护后,VOX恢复到最初状态。 { Vol_State = VOX_NONE_IN_BOX; } /*Vol 过流保护,每隔200ms打嗝一次*/ if( IRQ_FLAG0 & 0x04 ) { Vol_Output_Short_Debounce++; if( Vol_Output_Short_Debounce >= 2 ) //Vor短路保护200ms后,重新开启ADT { Vol_Output_Short_Debounce = 0; IRQ_FLAG0 = 0x04; Vol_State = VOX_NONE_IN_BOX; } } } /* ******************************************************************************* * void Vor_Det_Machine(void) * * Description : Vor Detect:耳机识别。 (100ms调用周期) * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ void Vor_Det_Machine(void) { #ifdef BOOST_AOUT if( gBoost_Opened_Flag ) //进行Vox Det的条件:1、Vox处于非双向通信功能;2、Boost已经开启 #else if( gBoost_Prepared_Flag ) #endif { switch( Vor_State ) { case VOX_GET_INTO_BOX: //耳机入仓 if( (VOX_CTL0 & 0x20) != 0x20 ) //1、当前已经开启了VOUT,则无需重复开启;原因:在使能VOUT前需要先关闭VOUT使能,如果连续开,会出现一段时间断开的情况。 { VOR_EN_Type(VOX_VOUT_Mode); } Vor_Loadon_Det_Debounce++; if( Vor_Loadon_Det_Debounce >= VOX_LOADON_DET_DEBOUNCE ) //Vox开启VOUT输出后,debounce一段时间后,IOFF状态消失,则说明Vox正常充电。 { Vor_Loadon_Det_Debounce = 0; if( (CHIP_STA1 & 0x88) == 0x80 ) //耳机电池充满,Vox转入ADT模式,在ADT模式下,同时存在Loadon和IOFF状态,如果耳机端在复充条件下有拉Vox电流的功能,则同过loadin状态识别。 { Vor_Vout_Enable = ON; #ifdef _DEBUG_VOX printf("Vor Vo Nor\r\n"); #endif } Vor_State = VOX_STAY_IN_BOX; } break; case VOX_STAY_IN_BOX: //耳机在仓 if( (CHIP_STA1 & 0x88) == 0x88 ) //Vox在充电过程中出现了Loadon和IOFF同时存在的状态,则说明:1、耳机出仓;2、耳机电池充满;3、耳机电池锂保。 { Vor_Ioff_Det_Debounce++; if( Vor_Ioff_Det_Debounce >= VOX_IOFF_DET_DEBOUNCE ) //重载转轻载(耳机出仓后)需延时4s { Vor_Ioff_Det_Debounce = 0; if( ON == Vor_Vout_Enable ) //Vox在正常充电过程中出现了IOFF状态,则说明:1、耳机出仓;2、耳机电池充满; { VOR_EN_Type(VOX_ADT_Mode); //Vox进入ADT模式后,观察CHIP_STA1的状态,1、无Loadon、IOFF,则说明耳机出仓;2、只有Loadon,则说明耳机在仓,耳机电池充满。 Vor_Bat_Full_Flag = 1; #ifdef LED_DISPLAY //LED_G_FLASH(100,5); #endif #ifdef _DEBUG_VOX printf("Vor Get Out\r\n"); #endif } else //否则,耳机电池处于锂保状态,Vout输出电流5mA,充电10分钟。1、10分钟未满,耳机电池跳出锂保状态;2、10分钟满,耳机电池仍处于锂保状态。 { Vor_LiPro_Flag = 1; //耳机电池进入锂保状态后,不能倒数进休眠? Vor_LiPro_Det_Debounce++; if( Vor_LiPro_Det_Debounce >= T10MIN_DEBOUNCE ) { Vor_LiPro_Det_Debounce = 0; VOR_EN_Type(VOX_ADT_Mode); //2、10分钟满,耳机电池仍处于锂保状态。则Vox转入ADT模式。 Vor_LiPro_Flag = 0; } #ifdef LED_DISPLAY //LED_G_KEEP_FLASHING(50); #endif #ifdef _DEBUG_VOX printf("Vor LiP\r\n"); #endif } } } else if( (CHIP_STA1 & 0x88) == 0x80 ) //观察CHIP_STA1的状态,无IOFF有Loadon,说明:1、耳机出仓后4s内,耳机再次入仓;2、10分钟未满,耳机电池退出锂保状态,进入正常充电;3、耳机锂保满10分钟。 { Vor_Ioff_Det_Debounce = 0; Vor_LiPro_Det_Debounce = 0; Vor_Vout_Enable = ON; #ifdef LED_DISPLAY //LED_G_ON(); #endif if( Vor_Bat_Full_Flag ) { Vor_Vout_Enable = OFF; Vor_Bat_Full_Flag = 0; #ifdef _DEBUG_VOX printf("Vor Bat Full\r\n"); #endif } } else if( !(CHIP_STA1 & 0x88) ) //CHIP_STA1无loadon和ioff状态,则说明耳机出仓了。 { Vor_State = VOX_NONE_IN_BOX; } break; case VOX_NONE_IN_BOX: //空仓 VOR_EN_Type(VOX_ADT_Mode); Vor_Ioff_Det_Debounce = 0; Vor_LiPro_Det_Debounce = 0; Vor_Loadon_Det_Debounce = 0; Vor_Vout_Enable = OFF; /* Loadon状态位存在,则说明耳机入仓,开启后续充电流程。*/ if( CHIP_STA1 & 0x80 ) { Vor_State = VOX_GET_INTO_BOX; #if DISCHARGE_ENABLE #ifndef BOOST_AOUT DisCharge_Boost_Open(); //本周期开启Boost,下个周期开启VOUT(100ms一个周期) #endif #endif #ifdef _DEBUG_VOX printf("VOR_INTO_BOX\r\n"); #endif } break; default: break; } } else //Boost保护后,VOX恢复到最初状态。 { Vol_State = VOX_NONE_IN_BOX; } /*Vor 过流保护(读中断标志位),每隔200ms打嗝一次*/ if( IRQ_FLAG0 & 0x08 ) { Vor_Output_Short_Debounce++; if( Vor_Output_Short_Debounce >= 2 ) //Vor短路保护200ms后,重新开启ADT { Vor_Output_Short_Debounce = 0; IRQ_FLAG0 = 0x08; Vor_State = VOX_NONE_IN_BOX; } } } #endif /* ******************************************************************************* * void VOX_EN_Type(VOR_Enable_Type_e VOR_Enable_Type) * * Description : VOL Open(EN_VO) * Arguments : * Returns : * Notes : * ******************************************************************************* */ void VOX_EN_Type(VOX_Enable_Mode_e VOX_Enable_Mode) { COM_CTRL = ON; switch(VOX_Enable_Mode) { case VOX_VOUT_Mode: VOX_CTL0 &= ~0x30; //VOX Disable 5V And Disable VOX ADT VOX_CTL0 |= 0x30; //VOX Enable 5V break; case VOX_ADT_Mode: VOX_CTL0 &= ~0x30; //VOX 5v Off VOX_CTL0 |= 0x03; //VOX load detect On break; default: break; } } /* ******************************************************************************* * void Vox_Det_Machine(void) * * Description : Vox Detect:耳机识别。 (100ms调用周期) * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ /* 1、关盖开启VOUT;显示灯效。 2、开盖开启VOUT至少500ms用于唤醒耳机;后发送开盖指令,持续10s,间隔250-300ms。 3、发送开盖指令间隔(250-300ms)期间,Vox转入ADT模式,检测都Loadon状态需要有灯效。 */ uint8_t Vox_TX_Timer = 0; //VOX发送指令持续时间计数,在Hall_Handler检测中清0. #define VOX_TX_CNT 100 //VOX发送指令时间(10s) uint8_t BES_Rst_Puls_Timer = 0; //关盖15s后发送BES Reset 脉冲 #define BES_RST_PULS_CNT 150 bit BES_Rst_Puls_Flag = 0; uint8_t WkUp_EarPhone_Debounce = 0; #define EARPHONR_WKUP_CNT 5 bit Cover_Close_Flag = 0; bit Cover_Open_Flag = 0; void Vox_Det_Machine(void) { if( CoverEvent_Flg ) //Hall事件。 { if( CoverStatus == CLOSE ) //1、关盖开启VOUT;显示灯效。(无需查询Loadon、IOFF状态,无论耳机是否在仓,关盖发送指令间隔300ms持续10s,间隔之间开启VOUT。) { WkUp_EarPhone_Debounce = 0; Cover_Close_Flag = 1; Cover_Open_Flag = 0; if( !BES_Rst_Puls_Flag ) { BES_Rst_Puls_Timer++; if( BES_Rst_Puls_Timer > BES_RST_PULS_CNT ) { BES_Rst_Puls_Flag = 1; Vox_TX_Machine(BES_RESET); //发送BES Reset脉冲,只发一次。 22*5=110ms CoverEvent_Flg = 0; } } } else //2、开盖处理 { Cover_Close_Flag = 0; BES_Rst_Puls_Flag = 0; /*开启VOUT 500ms用于唤醒耳机。*/ if(WkUp_EarPhone_Debounce < EARPHONR_WKUP_CNT) //debounce 500ms { VOX_EN_Type(VOX_VOUT_Mode); WkUp_EarPhone_Debounce++; Cover_Open_Flag = 1; CoverEvent_Flg = 0; } } } if(Cover_Open_Flag || Cover_Close_Flag ) { /*间隔300ms发送关盖指令,持续10s,间隔之间开启VOUT。*/ if(Vox_TX_Timer < VOX_TX_CNT) { if( (Vox_TX_Timer % 3) == 0 ) //300ms发送一次 { if(BES_Rst_Puls_Flag) { if( (CHIP_STA1 & 0xAC) == 0xAC ) //loadon和ioff状态同时存在,说明1、耳机电池充满;2、耳机锂保;3、盒中没耳机。三种情况都发SHUT_DOWN。等待开盖重新插拔耳机。 { Vox_TX_Machine(SHUT_DOWN); /*耳机电池充满或仓处于低电,发关机指令*/ } } else if( CoverStatus == CLOSE ) { Vox_TX_Machine(CLOSE_COVER); //发送关盖指令 } else if( CoverStatus == OPEN ) { Vox_TX_Machine(OPEN_COVER); //发送开盖指令 } } else { if( CoverStatus == CLOSE ) { if( (VOX_CTL0 & 0x30) != 0x30 ) //1、当前已经开启了VOUT,则无需重复开启;原因:在使能VOUT前需要先关闭VOUT使能,如果连续开,会出现一段时间断开的情况。 { VOX_EN_Type(VOX_VOUT_Mode); } } else { VOX_EN_Type(VOX_ADT_Mode); } } Vox_TX_Timer++; } else //10s后清标志位。 { if(BES_Rst_Puls_Flag) { BES_Rst_Puls_Flag = 0; } else if( CoverStatus == CLOSE ) { Cover_Close_Flag = 0; } else if( CoverStatus == OPEN ) { Cover_Open_Flag = 0; } } } } /* ******************************************************************************* * void BES_Reset_Puls(void) * * Description : BES Reset用于产生蓝牙耳机复位时序。 (5ms调用周期) * Vox TX BES Plus,VOX发送如下时序给耳机端。 * 5T Low + 1T High + 1T lOW + 1T High + 1T Low + 1T High + 1T Low + 1T High + 1T Low + 2T Low + 2T High + 1T Low + 1T High + 1T Low + 1T High + 1T Low + 1T High + 1T Low * _ _ _ _ _ _ _ _ _ *0 0 0 0 0 |1|0|1|0|1|0|1|0 0|1 1|0|1|0|1|0|1|0 *__________| |_| |_|_|_|_|___|___|_|_|_|_|_|_|_______ * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ void BES_Reset_Puls(void) { if(BES_Puls_Start) { if(BES_Puls_Cnt <= 4) //持续5个低电平后加一高电平 { COM_CTRL = OFF; } else { if(BES_Puls_Cnt%2) { if(BES_Puls_Cnt == 13) { COM_CTRL = OFF; } else { COM_CTRL = ON; } } else { if(BES_Puls_Cnt == 14) { COM_CTRL = ON; } else { COM_CTRL = OFF; } } } if(BES_Puls_Cnt >= 23) { BES_Puls_Start = 0; BES_Puls_Cnt = 0; COM_CTRL = ON; } BES_Puls_Cnt++; } } /* ******************************************************************************* * void Vor_Det_Machine(void) * * Description : Vor Detect:耳机识别。 (100ms调用周期) * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ void Vox_TX_Machine(VOX_Comm_ID_e VOX_Comm_ID) { uint8_t tx_pData[10] = 0; uint8_t i = 0; tx_pData[0] = HEADER>>8; tx_pData[1] = HEADER; tx_pData[3] = 0x0A; tx_pData[5] = 0x02; tx_pData[6] = bat_level; tx_pData[7] = FW_VER; tx_pData[8] = bat_level; switch(VOX_Comm_ID) { case OPEN_COVER: //开盖指令 tx_pData[4] = 0x00; break; case CLOSE_COVER: //关盖指令 tx_pData[4] = 0x01; break; case BES_RESET: //BES 复位patten COM_CTRL = ON; BES_Puls_Start = 1; return; case SHUT_DOWN: //关机指令 tx_pData[4] = 0x03; break; default: break; } for(i=3 ;i<9 ;i++) { tx_pData[2] += tx_pData[i]; //求校验和 } COM_CTRL = OFF; //VOX切换到通讯TX功能模式(1.8V)。 Uart0SendPacket(9, tx_pData); } #endif