/* ****************************************************************************** * * @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" #include "key.h" #include "sys_tim.h" #include "sys_tim.h" #include "adc.h" bit Vox_Vout_Enable = OFF; //Vox功率输出标志位 #if VOX_ENABLE /******************************************************************************\ Macro definitions \******************************************************************************/ #define EARPHONR_WKUP_CNT 2 #define BES_RST_PULS_CNT 20 #define Vox_TX_Interval 2 //Vox定时发送指令时间间隔 #define BOOST_VOUT_HIGH_CNT 100 //关盖,发完指令后,Boost Vout输出5.15V时间。 #define BES_ADDR_EXCHG_TIMOUT 30 //关盖5s后,耳机蓝牙地址置换,3s重发一次。直到10次后超时。 #define BES_ADDR_EXCHG_CNT 5 /******************************************************************************\ Variables definitions \******************************************************************************/ bit BES_Rst_Puls_Flag = 0; bit BES_Addr_Exchg_Flag = 0; bit Cover_Close_Flag = 0; bit Cover_Open_Flag = 0; bit EarPhone_ShutDown_Flag = 0; //耳机关机标志位 bit Boost_Open_Flag = 0; //用于开启Boost后延时开启Vox 5V。 uint8_t Vox_Output_Short_Debounce = 0; uint16_t Boost_Open_Atleast_Tim_Cnt = 0; uint8_t Box_To_Bes_Comm_Debounce = 0; uint8_t Box_To_Bes_Comm_Cnt = 0; bit Boost_Vout_Change_Flag = 0; #ifdef VOX_RX uint8_t Vox_Pairing_State[2] = {0}; //耳机配对状态,0是无效,1是正在配对,2是配对成功,3不处理,保持当前状态。 idata uint8_t Vox_Get_BES_Addr_Flag[2] = {0}; idata uint8_t BES_Addr[6] = {0}; //蓝牙耳机地址,Vox_Bes_Addr[0][6]:VOL;Vox_Bes_Addr[1][6]:VOR #if defined(XIAOMI) idata uint8_t Random_Data[8] = {0}; idata uint8_t Bes_Bet_Level[2] = {0}; //对耳电池电量信息,Bes_Bet_Level[0]:左耳;Bes_Bet_Level[1]:右耳 idata uint8_t Bes_Chg_Full[2] = {0}; //对耳硬件是否满电:0非满电;1:满电。 idata uint8_t Tws_Paired_Record[2] = {0}; //TWS配对记录;0:有TWS配对记录;1:没有TWS配对记录; idata uint8_t Phone_Paired_Record[2] = {0}; //手机配对记录;0:有与手机配对记录;1:没有和手机配对记录。 idata uint8_t Bes_OTA_State[2] = {0}; //耳机静默升级状态;1:有;0:没有 idata uint8_t Bes_Set_SN_State[2] = {0}; //耳机应答仓写入SN是否成功。1:成功;0:失败 idata uint8_t SN_Num[22] = {0}; //SN码,需要从OTP的固定位置获取。 uint8_t SN_Num_Start = 0; //SN码发送起始位置,有开盖动作时清零。 bit gShip_Mode_Flag = 0; //船运模式标志位:0:正常关机;1:船运模式 #define COVER_OPEN_CNT 600 //1分钟 uint16_t Vox_TX_Timer = 0; //VOX发送指令持续时间计数,在Hall_Handler检测中清0. #define VOX_TX_CNT 50 //VOX发送指令时间5s #elif defined(QIANCHENG) uint8_t Vox_TX_Timer = 0; //VOX发送指令持续时间计数,在Hall_Handler检测中清0. #define COVER_OPEN_CNT 0xff #define VOX_TX_CNT 30 //VOX发送指令时间3s #endif #endif /******************************************************************************\ Functions definitions \******************************************************************************/ /* ******************************************************************************* * 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; #if 1 if( VOX_Enable_Mode == VOX_VOUT_Mode) { VOX_CTL0 &= ~0x30; //VOX Disable 5V And Disable VOX ADT VOX_CTL0 |= 0x30; //VOX Enable 5V } else { VOX_CTL0 &= ~0x30; //VOX 5v Off } #else 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; } #endif } /* ******************************************************************************* * 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) { /*Vox 过流保护,两只耳机都每隔200ms打嗝一次(28Bytes)*/ if( IRQ_FLAG0 & 0x0C ) { Vox_Output_Short_Debounce++; if( Vox_Output_Short_Debounce >= 2 ) //Vox短路保护200ms后,重新开启Vox 5V。 { Vox_Output_Short_Debounce = 0; IRQ_FLAG0 = 0x0C; VOX_EN_Type(VOX_VOUT_Mode); return; } } if( CoverEvent_Flg ) //Hall事件。 { #if 0 if(gBoost_Prepared_Flag && ( CHIP_STA1 & 0xA0 ) ) //1、Boost开启条件不满足,则Vox一直处于ADT模式。2、存在loadon,有耳机在仓,开启Vox 5V输出 #else if( gBoost_Prepared_Flag ) #endif { if( !Boost_Open_Flag ) { BST_EN = 1; //Boost Enable;异常时由硬件主动关闭。开启Boost,开启Vox 5v会在开启Boost之后(100ms延时)。 Boost_Open_Flag = 1; return; } Vox_Pairing_State[VOL_CHAN] = 0; Vox_Pairing_State[VOR_CHAN] = 0; BES_Rst_Puls_Flag = 0; EarPhone_ShutDown_Flag = 0; Boost_Open_Atleast_Tim_Cnt = 0; if( CoverStatus == CLOSE ) //1、关盖关闭COM_CTRL;显示灯效。(无需查询Loadon、IOFF状态,无论耳机是否在仓,关盖发送指令间隔300ms持续10s,间隔之间关闭COM_CTRL。) { Cover_Close_Flag = 1; Cover_Open_Flag = 0; CoverEvent_Flg = 0; Vox_Vout_Enable = ON; Boost_Open_Flag = 0; COM_CTRL = OFF; //VOX_EN_Type(VOX_VOUT_Mode); VOX_CTL0 |= 0x30; //VOX Enable 5V,开启VOX端的NMOS } else //2、开盖处理,Vox 5V输出500ms用于唤醒耳机;500ms后vox设置为ADT模式,关Boost。 { Cover_Close_Flag = 0; BES_Addr_Exchg_Flag = 0; /*开启VOUT 500ms用于唤醒耳机。*/ if( Vox_TX_Timer < EARPHONR_WKUP_CNT ) //debounce 500ms { VOX_EN_Type(VOX_VOUT_Mode); Vox_TX_Timer++; } else { BST_EN = 0; //Boost Disable Cover_Open_Flag = 1; CoverEvent_Flg = 0; Boost_Open_Flag = 0; Vox_TX_Timer = 0; } } } else { VOX_EN_Type(VOX_ADT_Mode); } } /* 发送开盖指令*/ if( Cover_Open_Flag ) /*开盖后,每隔200-300ms发送一次开盖指令,并且接收耳机配对状态信息。*/ { if( Vox_TX_Timer < COVER_OPEN_CNT ) { if( (Vox_TX_Timer % Vox_TX_Interval) == 0 ) //200ms发送一次 { #ifdef VOX_TX #if defined(QIANCHENG) //岍丞 HandleTxCommand(CMD_BOX_OPEN,VOL_CHAN); //左耳发开盖指令,区分耳机通道。 #elif defined(XIAOMI) //小米 HandleTxCommand(CMD_HEARTBEAT,VOL_CHAN); #endif #endif } else { #ifdef VOX_TX #if defined(QIANCHENG) //岍丞 HandleTxCommand(CMD_BOX_OPEN,VOR_CHAN); //左耳发开盖指令,区分耳机通道。 #elif defined(XIAOMI) //小米 HandleTxCommand(CMD_HEARTBEAT,VOR_CHAN); #endif #endif } Vox_TX_Timer++; } #ifdef XIAOMI else { VOX_EN_Type(VOX_VOUT_Mode); } #endif } /* 发送开、关盖指令*/ if( Cover_Close_Flag || EarPhone_ShutDown_Flag ) { /*间隔300ms发送指令,持续3s,关盖间隔之间开启VOUT;开盖间隔之间开启ADT。*/ if( Vox_TX_Timer < VOX_TX_CNT ) { #if 0 if( (Vox_TX_Timer % Vox_TX_Interval) == 0 ) //200ms发送一次 { if( EarPhone_ShutDown_Flag ) { #ifdef VOX_TX HandleTxCommand(CMD_SHUT_DOWN,VOX_BOTH); /*耳机电池充满或仓处于低电,发关机指令*/ #endif } else if( CoverStatus == CLOSE ) { #ifdef VOX_TX HandleTxCommand(CMD_BOX_CLOSE,VOX_BOTH); //发送关盖指令 ,不区分耳机通道。 #endif } } #else if( (Vox_TX_Timer % Vox_TX_Interval) == 0 ) //200ms发送一次 { if( EarPhone_ShutDown_Flag ) { #ifdef VOX_TX HandleTxCommand(CMD_SHUT_DOWN,VOL_CHAN); /*耳机电池充满或仓处于低电,发关机指令*/ #endif } else if( CoverStatus == CLOSE ) { #ifdef VOX_TX #if defined(QIANCHENG) //岍丞 HandleTxCommand(CMD_BOX_CLOSE,VOL_CHAN); //左耳发关盖指令,区分耳机通道。 #elif defined(XIAOMI) //小米 HandleTxCommand(CMD_HEARTBEAT,VOL_CHAN); #endif #endif } } else { if( EarPhone_ShutDown_Flag ) { #ifdef VOX_TX HandleTxCommand(CMD_SHUT_DOWN,VOR_CHAN); /*耳机电池充满或仓处于低电,发关机指令*/ #endif } else if( CoverStatus == CLOSE ) { #ifdef VOX_TX #if defined(QIANCHENG) //岍丞 HandleTxCommand(CMD_BOX_CLOSE,VOR_CHAN); //左耳发开盖指令,区分耳机通道。 #elif defined(XIAOMI) //小米 HandleTxCommand(CMD_HEARTBEAT,VOR_CHAN); #endif #endif } } #endif Vox_TX_Timer++; } else //5s后清标志位。 { if( EarPhone_ShutDown_Flag ) { EarPhone_ShutDown_Flag = 0; Cover_Close_Flag = 0; Vox_Vout_Enable = OFF; BST_EN = 0; //Boost Disable VOX_EN_Type(VOX_ADT_Mode); } else if( Cover_Close_Flag ) //关盖发送完相应的指令后,VOX 5V充电,等待耳机电池充满。充满 { if( ((CHIP_STA1 & 0xAC) == 0xAC) || F_batlevel_low ) //一、loadon和ioff状态同时存在,说明1、耳机电池充满;2、耳机锂保;3、盒中没耳机;二、盒电池低电。两种情况都发SHUT_DOWN。等待开盖重新插拔耳机。 { if( Boost_Open_Atleast_Tim_Cnt >= TIM_SHUTDOWN_DEBOUNCE ) //Boost必须工作满10分钟软件才允许关机,原因,给耳机电池处于锂保状态进行充电。 { EarPhone_ShutDown_Flag = 1; Vox_TX_Timer = 0; //为了后面发送SHUT_DOWN指令。 } } if( !BES_Rst_Puls_Flag ) { Vox_TX_Timer++; if( Vox_TX_Timer > (BES_RST_PULS_CNT + VOX_TX_CNT) ) //关盖后3+2s后发送BES 复位 pattern { BES_Rst_Puls_Flag = 1; //发完复位Pattern后,开始蓝牙地址置换。 BES_Addr_Exchg_Flag = 1; Box_To_Bes_Comm_Debounce = 0; Box_To_Bes_Comm_Cnt = 0; COM_CTRL = ON; #ifdef VOX_TX HandleTxCommand(BES_RESET,VOX_BOTH); //发送BES Reset脉冲,只发一次。 23*5=115ms, #endif return; /*return的原因:Vox_Det_Machine() 100ms调用周期,BES_RESET在Timer1中5ms调用。整个复位Pattern需要115ms, 在此处return可以保证在200ms内只有BES 复位pattern在操作COM_CTRL。*/ } } /*蓝牙地址交互*/ // if( BES_Addr_Exchg_Flag && ( CHIP_STA1 & 0xA0 ) == 0xA0 ) /*1、关盖;2、有双耳机在盒。关盖5s后,发完关盖指令。*/ if( BES_Addr_Exchg_Flag ) { if( Box_To_Bes_Comm_Debounce < 1 ) { #ifdef VOX_TX HandleTxCommand(CMD_BES_PAIRING,VOL_CHAN); /*关盖5s后,左耳发送配对指令,获取左耳蓝牙地址。*/ #endif Vox_Get_BES_Addr_Flag[VOL_CHAN] = 0x00; Vox_Get_BES_Addr_Flag[VOR_CHAN] = 0x00; } else { if(Box_To_Bes_Comm_Cnt > BES_ADDR_EXCHG_CNT) //耳机蓝牙地址置换超时20s,关闭蓝牙地址置换,开启VOX 5V。 { // Box_To_Bes_Comm_Cnt = 0; BES_Addr_Exchg_Flag = 0; Boost_Vout_Change_Flag = 1; Box_To_Bes_Comm_Debounce = 0; VOX_EN_Type(VOX_VOUT_Mode); return; } else { if( Vox_Get_BES_Addr_Flag[VOL_CHAN] != 0x00 ) /*收到左耳回复的蓝牙地址*/ { if( Vox_Get_BES_Addr_Flag[VOR_CHAN] != 0x00 ) { // Box_To_Bes_Comm_Cnt = 0; BES_Addr_Exchg_Flag = 0; Boost_Vout_Change_Flag = 1; Box_To_Bes_Comm_Debounce = 0; VOX_EN_Type(VOX_VOUT_Mode); return; } else { #ifdef VOX_TX HandleTxCommand(CMD_BES_PAIRING,VOR_CHAN); /*发右耳配对指令,获取右耳蓝牙地址。*/ #endif Vox_Get_BES_Addr_Flag[VOL_CHAN] = 0x00; } } else if( Vox_Get_BES_Addr_Flag[VOR_CHAN] != 0x00 ) /*收到右耳回复的蓝牙地址,再将右蓝牙地址发给左耳。*/ { #ifdef VOX_TX HandleTxCommand(CMD_BES_PAIRING,VOL_CHAN); #endif } } } if(Box_To_Bes_Comm_Debounce > BES_ADDR_EXCHG_TIMOUT) //3s重发一次。重发5次后超时 { Box_To_Bes_Comm_Cnt++; Box_To_Bes_Comm_Debounce = 0; } else { Box_To_Bes_Comm_Debounce++; } } /* 关盖,发完指令后,Boost Vout输出5.15V时间1s。*/ if( Boost_Vout_Change_Flag ) { if( Box_To_Bes_Comm_Debounce < BOOST_VOUT_HIGH_CNT ) { SFRADDR = BST_CTL0; //设置输出5.15V SFRDATA |= 0x03; Box_To_Bes_Comm_Debounce++; } else { Boost_Vout_Change_Flag = 0; Box_To_Bes_Comm_Debounce = 0; SFRADDR = BST_CTL0; //设置输出5.05V SFRDATA &= ~0x03; SFRDATA |= 0x01; } } } } } } #if defined(ZHONGKELANXUN) uint8_t Crc8Maxim(u8 *buf, u8 length) { u8 i; u8 crc = 0; while(length--) { crc ^= *buf++; for(i=0;i<8;i++) { if( crc&1 ) { crc = (crc >> 1)^0x8c; } else { crc >>= 1; } } } return crc; } #elif defined(XIAOMI) /******************************************************************************\ Functions definitions \******************************************************************************/ /* ******************************************************************************* * u16 CalCheckCrc16(u8 * pucFrame, u16 usLen) * * Description : 校验和的计算 * * * Arguments : u8 *pucFrame: 数据存放地址 u16 usLen: 数据长度, 以byte为单位 * Returns : * * Notes : * ******************************************************************************* */ uint16_t CalCheckCrc16(uint8_t *pucFrame, unsigned int usLen) { uint16_t wCRCin = 0x0000; uint16_t wCPoly = 0x1021; uint8_t wChar = 0; unsigned int i; while (usLen--) { wChar = *(pucFrame++); wCRCin ^= (wChar << 8); for(i = 0;i < 8;i++) { if(wCRCin & 0x8000) { wCRCin = (wCRCin << 1) ^ wCPoly; } else { wCRCin = wCRCin << 1; } } } return (wCRCin); } #endif #ifdef VOX_TX /* ******************************************************************************* * void HandleTxCommand(VOX_BES_COMMAND_E RxCommand, e_Vox_Chan nVox_Chn_Select) * * Description : 发送数据包的封装,并打开相应的双向通信通道 * Command payload * Header checksum side cmd len Data * 1bytes 1byte 1byte 1byte 1byte Len bytes * * Arguments : VOX_BES_COMMAND_E TxCommand: , e_Vox_Chan nVox_Chn_Select * Returns : * * Notes : * ******************************************************************************* */ void HandleTxCommand(VOX_BES_COMMAND_E TxCommand, e_Vox_Chan nVox_Chn_Select) { #if defined(QIANCHENG) //岍丞 uint8_t tx_pData[11] = 0; uint8_t i = 0; /*数据包头*/ tx_pData[0] = BOXHEADER; /*耳机通道*/ tx_pData[2] = nVox_Chn_Select; /*指令编号*/ tx_pData[3] = TxCommand; switch(TxCommand) { case CMD_BOX_OPEN: case CMD_BOX_CLOSE: #if 0 /*Data Length*/ tx_pData[4] = 0x02; tx_pData[5] = bat_level; tx_pData[6] = FW_VER; break; #endif case CMD_SHUT_DOWN: /*Data Length*/ tx_pData[4] = 0x02; tx_pData[5] = bat_level; tx_pData[6] = FW_VER; break; case CMD_BES_PAIRING: /*Data Length*/ tx_pData[4] = 0x06; for(i=0;i<6;i++) { tx_pData[5+i] = BES_Addr[i]; //发送耳机蓝牙地址。 } break; case BES_RESET: //BES 复位patten SFRADDR = MFP_CTL0; //Set P01 Pinmux As GPIO Function SFRDATA &= ~0x0C; for(i=0;i<6;i++) { BES_Addr[i] = 0; //清本地耳机蓝牙地址。 } BES_Puls_Start = 1; return; default: break; } for(i=2;i<(tx_pData[4] + 5);i++) //datalen + side + cmd { tx_pData[1] += tx_pData[i]; //求校验和 } COM_CTRL = OFF; //VOX切换到通讯TX功能模式(1.8V)。 SFRADDR = MFP_CTL0; SFRDATA |= 0x04; //P01 as UART's TX #if UART0_ENABLE Uart0SendPacket(tx_pData[4] + 6, tx_pData); //+6的原因:多加一个字节发送,后面要设置TX为GPIO,会导致最后一个字节没来得及发出去。 #endif SFRADDR = MFP_CTL0; //Set P01 Pinmux As GPIO Function,原因:TX和RX连在一起,要保证RX能正常接收到数据,TX需设置为GPIO模式,并浮空或输入模式。 SFRDATA &= ~0x0C; #elif defined(ZHONGKELANXUN) //中科蓝讯 uint8_t tx_pData[11] = 0; uint8_t i = 0; /*数据包头*/ tx_pData[0] = BOXHEADER>>8; tx_pData[1] = BOXHEADER; /*充电仓识别码*/ tx_pData[2] = BOXIDCODE; /*耳机通道*/ tx_pData[5] = nVox_Chn_Select; /*指令编号*/ tx_pData[3] = TxCommand; switch(TxCommand) { case VHOUSE_CMD_GET_VBAT: /*Data Length*/ tx_pData[4] = 0x03; tx_pData[6] = (CHIP_STA4 & 0x80) | bat_level; //bit 0~6 表示充电仓电量值 0~100;bit 7 为 1 表示在给充电仓充电,为 0 表示没有给充电仓充电; tx_pData[7] = 0x03; //ear_vbat:对耳电量,例如充电仓从左耳获取到耳机电量,将该电量 bit7 置 1 发送给右耳,如 //果没有获取到,但是知道对耳在仓内都要将 bit7 置 1 break; case VHOUSE_CMD_PAIR: //长按充电仓按键3s,充电仓发送配对指令。 /*Data Length*/ tx_pData[4] = 0x01; break; case VHOUSE_CMD_GET_TWS_BTADDR: break; case CMD_BES_PAIRING: /*Data Length*/ tx_pData[4] = 0x06; for(i=0;i<6;i++) { tx_pData[5+i] = BES_Addr[nVox_Chn_Select][i]; //获取耳机蓝牙地址。 } break; case BES_RESET: //BES 复位patten BES_Puls_Start = 1; return; default: break; } #elif defined(XIAOMI) //小米 /* */ uint8_t tx_pData[11] = 0; uint8_t i = 0; uint16_t Checksum = 0; uint16_t DataLen = 0; /*数据包头*/ tx_pData[0] = BOXHEADER; /*耳机通道*/ tx_pData[1] = nVox_Chn_Select; /*传输方向:Bit0-3:接收端;Bit4-7:发送端 1:双耳 2:充电盒 3:PC/工装 4:左耳 5:右耳 */ /*指令编号*/ tx_pData[2] = TxCommand; tx_pData[3] = TxCommand >> 8; /*小端模式:低字节在前 Bit0-7:命令号 Bit8-14:预留 Bit15:包类型 0:REQ 1:ACK */ tx_pData[4] = CoverStatus; //开关盒状态 switch(TxCommand) { case CMD_TWS_PAIR: //获取耳机MAC地址 /*Data Length*/ tx_pData[5] = 0x00; //小端模式,低位在前,长2Bytes。 tx_pData[6] = 0x00; break; case CMD_TWS_BTADDR_EXCH: /*Data Length*/ tx_pData[5] = 0x0E; //小端模式,低位在前,长2Bytes。 tx_pData[6] = 0x00; for(i=0;i<6;i++) { tx_pData[7+i] = BES_Addr[i]; //发送耳机蓝牙地址。 } for(i=0;i<8;i++) { tx_pData[13+i] = Random_Data[i]; //发送随机数。 } break; case CMD_SHUT_DOWN: /*Data Length*/ tx_pData[5] = 0x01; //小端模式,低位在前,长2Bytes。 tx_pData[6] = 0x00; tx_pData[7] = gShip_Mode_Flag; //船运模式:0:正常关机;1:船运模式 break; case CMD_PAIRING_IMD: //立即执行TWS配对 /*Data Length*/ tx_pData[5] = 0x00; //小端模式,低位在前,长2Bytes。 tx_pData[6] = 0x00; break; case CMD_CLEAR_PAIR: /*Data Length*/ tx_pData[5] = 0x00; //小端模式,低位在前,长2Bytes。 tx_pData[6] = 0x00; break; case CMD_HEARTBEAT: /*Data Length*/ tx_pData[5] = 0x05; //小端模式,低位在前,长2Bytes。 tx_pData[6] = 0x00; /* data定义: 1、D0、D1(2Bytes)构成充电盒的版本信息,D0的高4bit为充电盒硬件PCBA版本号,D0低4bit和D1构成充电盒软件版本号。 2、D2(1Byte)构成充电盒电量和充电状态,D2的bit7为是否有PG接入;D2的低7位表示充电盒电量信息,范围0-100; 3、D3(1Byte)构成对耳电量信息,根据协议中的Side信息区分左右耳电量信息。 4、D4(1Byte)耳机静默升级,充电盒默认发0x00 */ tx_pData[7] = HW_VER << 4; tx_pData[7] = FW_VER >> 8; tx_pData[8] = FW_VER; tx_pData[9] = (CHIP_STA4 & 0x80) | bat_level; if(nVox_Chn_Select == VOL_CHAN) { tx_pData[10] = Bes_Bet_Level[0]; } else if(nVox_Chn_Select == VOR_CHAN) { tx_pData[10] = Bes_Bet_Level[1]; } tx_pData[11] = 0x00; break; case CMD_SN: //由于SN码较长,充电盒需分多次发送,D0表示充第几位开始发送,一次固定发送9Bytes。最后一包SN数据不够9Bytes的补0或0xff。 /*Data Length*/ tx_pData[5] = 0x0A; //小端模式,低位在前,长2Bytes。 tx_pData[6] = 0x00; tx_pData[7] = SN_Num_Start; for(i=0;i<9;i++) { if( (SN_Num_Start + i) > 22 ) { tx_pData[8+i] = 0xFF; } else { tx_pData[8+i] = SN_Num[ SN_Num_Start + i ]; //发送随机数。 } } SN_Num_Start += 9; break; case CMD_GET_INTO_PAIR: /*Data Length*/ tx_pData[5] = 0x01; //小端模式,低位在前,长2Bytes。 tx_pData[6] = 0x00; tx_pData[7] = 0x01; //01进入配对状态 break; case BES_RESET: //BES 复位patten BES_Puls_Start = 1; return; default: break; } DataLen = tx_pData[5] | (tx_pData[6] << 8) + 7; Checksum = CalCheckCrc16( tx_pData, DataLen ); //计算检验和 tx_pData[1 + DataLen] = Checksum; tx_pData[2 + DataLen] = Checksum >> 8; COM_CTRL = OFF; //VOX切换到通讯TX功能模式(1.8V)。 SFRADDR = MFP_CTL0; SFRDATA |= 0x04; //P01 as UART's TX #if UART0_ENABLE Uart0SendPacket(10 + DataLen, tx_pData); #endif SFRADDR = MFP_CTL0; //Set P01 Pinmux As GPIO Function,原因:TX和RX连在一起,要保证RX能正常接收到数据,TX需设置为GPIO模式,并浮空或输入模式。 SFRDATA &= ~0x0C; #endif } #endif #ifdef VOX_RX /* ******************************************************************************* * void HandleRxCommand(VOX_BES_COMMAND_E RxCommand) * * Description : 耳机端发送的数据包的解析及处理 * Ack payload: * Header checksum side cmd len Data * 1bytes 1byte 1byte 1byte 1byte Len bytes * * Arguments : VOX_BES_COMMAND_E RxCommand: * Returns : * * Notes : * ******************************************************************************* */ void HandleRxMsg(VOX_BES_COMMAND_E RxCommand) { uint8_t i = 0; #if defined(QIANCHENG) //岍丞 switch(RxCommand) { case CMD_BOX_OPEN: case CMD_BOX_CLOSE: if( RX0_Buffer[2] == VOL_CHAN ) //根据耳机Side参数 { Vox_Pairing_State[VOL_CHAN] = RX0_Buffer[5]; //获取左耳机配对状态 } else { Vox_Pairing_State[VOR_CHAN] = RX0_Buffer[5]; //获取右耳机配对状态 } break; case CMD_SHUT_DOWN: break; case CMD_BES_PAIRING: if( RX0_Buffer[2] == VOL_CHAN ) //根据耳机Side参数 { Vox_Get_BES_Addr_Flag[VOL_CHAN] = 1; //获取到左耳机蓝牙地址状态 } else { Vox_Get_BES_Addr_Flag[VOR_CHAN] = 1; //获取到右耳机蓝牙地址状态 } for(i=0;i<6;i++) { BES_Addr[i] = RX0_Buffer[i+5]; //获取左耳机蓝牙地址。 } break; default: break; } #elif defined(XIAOMI) //小米 uint8_t CMD_Type = 0; CMD_Type = RX0_Buffer[1] >> 4; if( CMD_Type & TWS_PC ) //PC/工装->盒子 { } else //耳机->盒子 { switch(RxCommand) { case CMD_TWS_PAIR: for(i=0;i> 7; //获取耳机是否满电 Vox_Pairing_State[0] = RX0_Buffer[10]; //获取耳机配对状态; Tws_Paired_Record[0] = RX0_Buffer[11] & 0x01; //bit0:0:有TWS配对记录;1:没有TWS配对记录;bit1:0:有与手机配对记录;1:没有和手机配对记录。 Phone_Paired_Record[0] = (RX0_Buffer[11] >> 1) & 0x01; Bes_OTA_State[0] = RX0_Buffer[12]; } else { Bes_Bet_Level[1] = RX0_Buffer[9]&0x7F; Bes_Chg_Full[1] = RX0_Buffer[9] >> 7; Vox_Pairing_State[1] = RX0_Buffer[10]; Tws_Paired_Record[1] = RX0_Buffer[11] & 0x01; Phone_Paired_Record[1] = (RX0_Buffer[11] >> 1) & 0x01; Bes_OTA_State[1] = RX0_Buffer[12]; } break; case CMD_SN: if( CMD_Type == TWS_VOL ) //根据耳机Side参数 { Bes_Set_SN_State[0] = RX0_Buffer[7]; //左耳机SN写入是否成功状态标志 } else { Bes_Set_SN_State[1] = RX0_Buffer[7]; //右耳机SN写入是否成功状态标志 } break; case CMD_GET_INTO_PAIR: break; case CMD_PAIRING_IMD: break; default: break; } } #endif } /* ******************************************************************************* * void HandleVoxCommMsg(void) * * Description : Vox 通讯功能处理函数,100ms定时调用。由于和耳机通信前需要打开耳机端的TRX功能,并且每次通信只能一只耳机。通过切换VOL/VOR通信开关进行通信 * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ void HandleVoxCommMsg(void) { #if defined(QIANCHENG) //岍丞 uint8_t CrcCheckSum = 0; #elif defined(ZHONGKELANXUN) //中科蓝讯 uint8_t CrcCheckSum = 0; #elif defined(XIAOMI) uint16_t CrcCheckSum = 0; uint16_t Data_Len = 0; #endif uint8_t i = 0; /*RX数据处理*/ if( Uart0_RX_Finish_Flag ) { Uart0_RX_Finish_Flag = 0; #if defined(QIANCHENG) //岍丞 for(i=2 ;i<(RX0_Buffer[4] + 5);i++) //计算校验和 { CrcCheckSum += RX0_Buffer[i]; //求校验和 } if( CrcCheckSum == RX0_Buffer[1] ) { HandleRxMsg((VOX_BES_COMMAND_E)RX0_Buffer[3]); } else { return; } #elif defined(XIAOMI) //小米 Data_Len = RX0_Buffer[5] | (RX0_Buffer[6] << 8) + 7; CrcCheckSum = CalCheckCrc16( RX0_Buffer, Data_Len); //计算检验和 if( CrcCheckSum == (uint16_t)(RX0_Buffer[Data_Len+1] | RX0_Buffer[Data_Len+2] << 8) ) //校验和小端模式,低位在前。 { HandleRxMsg((VOX_BES_COMMAND_E)RX0_Buffer[2]); } else { return; } #endif } } #endif #endif