/* ****************************************************************************** * * @file vox_comm.c * @brief VOX Communicate module * @ic sy8837/8/9 * * @version 1.0 * @date 2025/02/13 017:40:40 * @author Alex Xu * * Copyright (c) 2013-2099,Tkplusemi Technology Co.,Ltd. * All Rights Reserved * * History: * Revision Date Author Desc * 1.0.0 2025/02/13 Alex build this file ****************************************************************************** */ /*_____ I N C L U D E S ____________________________________________________*/ #include "vox_module.h" #include "vox_comm.h" #include "system.h" #include "bat.h" #include "hall.h" #include "key.h" /******************************************************************************\ Macro definitions \******************************************************************************/ #define MAX_PACKET_SIZE 0x20 /******************************************************************************\ Variables definitions \******************************************************************************/ #if XUANHENG idata uint8_t Vox_Pairing_State[2]; //耳机配对状态,0是无效,1是正在配对,2是配对成功,3不处理,保持当前状态。 uint8_t Vox_Set_BES_Addr_Flag[2]; idata uint8_t BES_Addr[6]; //蓝牙耳机地址,Vox_Bes_Addr[0][6]:VOL;Vox_Bes_Addr[1][6]:VOR idata uint8_t Random_Data[8]; uint8_t Bes_Bet_Level[2]; //对耳电池电量信息,Bes_Bet_Level[0]:左耳;Bes_Bet_Level[1]:右耳 uint8_t Bes_Chg_Full[2]; //对耳硬件是否满电:0非满电;1:满电。 uint8_t Tws_Paired_Record[2]; //TWS配对记录;0:有TWS配对记录;1:没有TWS配对记录; uint8_t Phone_Paired_Record[2]; //手机配对记录;0:有与手机配对记录;1:没有和手机配对记录。 uint8_t Bes_OTA_State[2]; //耳机静默升级状态;1:有;0:没有 uint8_t Bes_Set_SN_State[2]; //耳机应答仓写入SN是否成功。1:成功;0:失败 uint8_t Bes_In_Pair_State[2]; //耳机进入配对状态标志位 uint8_t Vox_Clear_Pair_Flag[2]; bit Vol_Bes_Addr_Flag; bit Vor_Bes_Addr_Flag; idata uint8_t SN_Num[22]; //SN码,需要从OTP的固定位置获取。 idata uint8_t SN_Num_Start; //SN码发送起始位置,有开盖动作时清零。 bit gShip_Mode_Flag; //船运模式标志位:0:正常关机;1:船运模式 #elif JIELI idata uint8_t Vox_Type; uint8_t Net_Info[2][13]; idata uint8_t MAC_Addr[2][18]; idata uint8_t Earphone_Vbat[2]; //对耳电量 #endif #ifdef VOX_RX idata uint8_t Vox_Get_Vbat_Flag[2]; //耳机配对状态,VOL:低4bit;VOR:高4bit。0是无效,1是正在配对,2是配对成功,3不处理,保持当前状态。 idata uint8_t Vox_Get_BES_Addr_Flag[2]; //idata uint8_t BES_Addr[6] = {0}; //蓝牙耳机地址,Vox_Bes_Addr[0][6]:VOL;Vox_Bes_Addr[1][6]:VOR #endif #ifdef VOX_COMM_ENABLE /* 双向通讯功能参数。 */ Vox_Comm_Cfg gVox_Comm; /******************************************************************************\ Functions definitions \******************************************************************************/ /* ******************************************************************************* * void Vox_Comm_Cfg_Init(void) * * Description : Vox 双向通讯参数初始化函数。 (系统初始化调用周期) * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ void Vox_Comm_Cfg_Clear(void) { #ifdef VOX_COVER_ENABLE gVox_Comm.Cover_Close_Flag = FALSE; gVox_Comm.Cover_Open_Flag = FALSE; gVox_Comm.Vox_Chg_Full_Flag = FALSE; #else gVox_Comm.Vol_GetInto_Box_Flag = FALSE; gVox_Comm.Vor_GetInto_Box_Flag = FALSE; gVox_Comm.Vol_Chg_Full_Flag = FALSE; gVox_Comm.Vor_Chg_Full_Flag = FALSE; #endif gVox_Comm.Key_L_2S_Flag = FALSE; gVox_Comm.Key_LL_8s_Flag = FALSE; /*发码相关计时器*/ gVox_Comm.Msg_TX_Debounce = 0; gVox_Comm.Msg_TX_Debounce1 = 0; /*按键发码相关计时器*/ gVox_Comm.Key_TWS_Pair_Tim = 0; gVox_Comm.Key_TWS_Clear_Pair_Tim= 0; gVox_Comm.Key_TWS_Pair_Cnt = 0; } /* ******************************************************************************* * void Vox_Comm_Handle(void) * * Description : Vox 双向通讯处理函数。 (100ms调用周期) * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ void Vox_Comm_Handle(void) { if( gVox_Comm.Cover_Open_Flag ) /* 发码:开盖码。 */ { if( gVox_Comm.Msg_TX_Debounce <= Vox_COM_MSG_Tim ) { if( ( gVox_Comm.Msg_TX_Debounce % Vox_TX_Interval_2 ) == 0 ) //200ms发送一次 { #ifdef VOX_TX #if JIELI HandleTxCommand(VHOUSE_CMD_OPEN_BOX,VOL_CHAN); //左耳发开盖指令,区分耳机通道。 #elif ZHONGKE HandleTxCommand(VHOUSE_CMD_OPEN_WINDOW,VOL_CHAN); //左耳发开盖指令,区分耳机通道。 #elif XUANHENG HandleTxCommand(CMD_HEARTBEAT,VOL_CHAN); #endif #endif } else if( ( gVox_Comm.Msg_TX_Debounce % Vox_TX_Interval ) == 0 ) //200ms发送一次 { #ifdef VOX_TX #if JIELI HandleTxCommand(VHOUSE_CMD_OPEN_BOX,VOR_CHAN); //右耳发开盖指令,区分耳机通道。 #elif ZHONGKE HandleTxCommand(VHOUSE_CMD_OPEN_WINDOW,VOR_CHAN); //右耳发开盖指令,区分耳机通道。 #elif XUANHENG HandleTxCommand(CMD_HEARTBEAT,VOR_CHAN); #endif #endif } gVox_Comm.Msg_TX_Debounce++; } else { Vox_Comm_Cfg_Clear(); } } else if( gVox_Comm.Cover_Close_Flag ) /*发码:关盖码*/ { if( gVox_Comm.Msg_TX_Debounce <= Vox_COM_MSG_Tim ) //发送关盖指令。 { if( (gVox_Comm.Msg_TX_Debounce % Vox_TX_Interval_2) == 0 ) //200ms发送一次 { #ifdef VOX_TX #if JIELI HandleTxCommand(VHOUSE_CMD_CLOSE_BOX,VOL_CHAN); //左耳发开盖指令,区分耳机通道。 #elif ZHONGKE HandleTxCommand(VHOUSE_CMD_CLOSE_WINDOW,VOL_CHAN); //左耳发开盖指令,区分耳机通道。 #elif XUANHENG HandleTxCommand(CMD_HEARTBEAT,VOL_CHAN); #endif #endif } else if( (gVox_Comm.Msg_TX_Debounce % Vox_TX_Interval) == 0 ) //200ms发送一次 { #ifdef VOX_TX #if JIELI HandleTxCommand(VHOUSE_CMD_CLOSE_BOX,VOR_CHAN); //右耳发开盖指令,区分耳机通道。 #elif ZHONGKE HandleTxCommand(VHOUSE_CMD_CLOSE_WINDOW,VOR_CHAN); //右耳发开盖指令,区分耳机通道。 #elif XUANHENG HandleTxCommand(CMD_HEARTBEAT,VOR_CHAN); #endif #endif } gVox_Comm.Msg_TX_Debounce++; return; } /*发码:获取耳机电量码*/ if( gVox_Comm.Msg_TX_Debounce1 <= Vox_COM_MSG_Tim ) //关盖后5s发送获取电量命令。 { if( (gVox_Comm.Msg_TX_Debounce1 % Vox_TX_Interval_2) == 0 ) //200ms发送一次 { #ifdef VOX_TX #if JIELI HandleTxCommand(VHOUSE_CMD_CLOSE_WIN_GET_VBAT,VOL_CHAN); //左耳发开盖指令,区分耳机通道。 #elif ZHONGKE HandleTxCommand(VHOUSE_CMD_CLOSE_WIN_GET_VBAT,VOL_CHAN); //左耳发开盖指令,区分耳机通道。 #elif XUANHENG HandleTxCommand(CMD_TWS_GET_BTADDR,VOL_CHAN); #endif #endif } else if( (gVox_Comm.Msg_TX_Debounce1 % Vox_TX_Interval) == 0 ) //200ms发送一次 { #ifdef VOX_TX #if JIELI HandleTxCommand(VHOUSE_CMD_CLOSE_WIN_GET_VBAT,VOR_CHAN); //右耳发开盖指令,区分耳机通道。 #elif ZHONGKE HandleTxCommand(VHOUSE_CMD_CLOSE_WIN_GET_VBAT,VOR_CHAN); //右耳发开盖指令,区分耳机通道。 #elif XUANHENG HandleTxCommand(CMD_TWS_GET_BTADDR,VOR_CHAN); #endif #endif } gVox_Comm.Msg_TX_Debounce1++; return; } Vox_Comm_Cfg_Clear(); } else if( gVox_Comm.Vox_Chg_Full_Flag ) /* 发码:Vox耳机充满发关机码。 */ { if( gVox_Comm.Msg_TX_Debounce <= Vox_COM_MSG_Tim ) { if( (gVox_Comm.Msg_TX_Debounce % Vox_TX_Interval_2) == 0 ) //200ms发送一次 { #ifdef VOX_TX #if XUANHENG HandleTxCommand(CMD_SHUT_DOWN,VOL_CHAN); //左耳发关机指令,区分耳机通道。 #else HandleTxCommand(VHOUSE_CMD_PWROFF,VOL_CHAN); //左耳发关机指令,区分耳机通道。 #endif #endif } else if( (gVox_Comm.Msg_TX_Debounce % Vox_TX_Interval) == 0 ) //200ms发送一次 { #ifdef VOX_TX #if XUANHENG HandleTxCommand(CMD_SHUT_DOWN,VOR_CHAN); //右耳发关机指令,区分耳机通道。 #else HandleTxCommand(VHOUSE_CMD_PWROFF,VOR_CHAN); //右耳发关机指令,区分耳机通道。 #endif #endif } gVox_Comm.Msg_TX_Debounce++; } else { Vox_Comm_Cfg_Clear(); } } else if( gVox_Comm.Key_L_2S_Flag ) /*按键2s发码:配对码*/ { if ( CoverStatus == OPEN ) { if( gVox_Comm.Key_TWS_Pair_Tim < 1 ) { #ifdef VOX_TX #if XUANHENG HandleTxCommand(CMD_TWS_GET_BTADDR,MASTER_SIDE); #else HandleTxCommand(VHOUSE_CMD_PAIR,MASTER_SIDE); //右耳发配对指令,区分耳机通道。 #endif #endif Vox_Get_BES_Addr_Flag[SLAVE_TYPE] = 0x00; Vox_Get_BES_Addr_Flag[MASTER_TYPE] = 0x00; #ifdef _DEBUG_KEY printf("Key Pair TX MASTER(line:%d).\r\n",(uint16_t)__LINE__); #endif } else { if(gVox_Comm.Key_TWS_Pair_Cnt > KEY_TWS_PAIR_CNT) //耳机蓝牙地址置换超时10s,关闭蓝牙地址置换,开启VOX 5V。 { gVox_Comm.Key_TWS_Pair_Cnt = 0; #if XUANHENG HandleTxCommand(CMD_PAIRING_IMD,MASTER_SIDE); HandleTxCommand(CMD_PAIRING_IMD,SLAVE_SIDE); #endif Event_key = KEY_EVENT_Empty; gVox_Comm.Key_L_2S_Flag = FALSE; OpenCover_TX_Cmd_Flag = TRUE; #if VOX_ENABLE #ifdef VOX_ADT_ENABLE Vol_State = VOX_GET_INTO_BOX; Vor_State = VOX_GET_INTO_BOX; #else VOX_EN_Type(VOX_VOUT_Mode); //VOX Enable 5V #endif #endif #ifdef _DEBUG_KEY printf("Key Pair TimeOut(line:%d).\r\n",(uint16_t)__LINE__); #endif return; } else { if( Vox_Get_BES_Addr_Flag[MASTER_TYPE] == 0x01 ) /*收到右耳回复的CMD3指令。*/ { #ifdef VOX_TX #if JIELI HandleTxCommand(VHOUSE_CMD_EXCH_TWS_BTADDR,SLAVE_SIDE); /*获取到右耳回复的CMD3指令,转发给左耳。*/ #elif ZHONGKE HandleTxCommand( VHOUSE_CMD_GET_TWS_BTADDR, SLAVE_SIDE ); /*获取到右耳回复的CMD3指令,转发给左耳。*/ #elif XUANHENG HandleTxCommand( CMD_TWS_SET_BTADDR, SLAVE_SIDE ); #endif #endif Vox_Get_BES_Addr_Flag[MASTER_TYPE] = 0x02; #ifdef _DEBUG_KEY printf("Key Pair Get SLAVE(line:%d).\r\n",(uint16_t)__LINE__); #endif } else if( Vox_Get_BES_Addr_Flag[MASTER_TYPE] == 0x02 ) { if( Vox_Get_BES_Addr_Flag[SLAVE_TYPE] != 0x00 ) { #ifdef VOX_TX #if JIELI HandleTxCommand(VHOUSE_CMD_EXCH_TWS_BTADDR,MASTER_SIDE); /*获取到右耳回复的CMD3指令,转发给左耳。*/ #elif ZHONGKE HandleTxCommand( VHOUSE_CMD_GET_TWS_BTADDR, MASTER_SIDE ); /*获取到右耳回复的CMD3指令,转发给左耳。*/ #elif XUANHENG HandleTxCommand( CMD_TWS_SET_BTADDR, MASTER_SIDE ); #endif #endif Vox_Get_BES_Addr_Flag[MASTER_TYPE] = 0x00; Vox_Get_BES_Addr_Flag[SLAVE_TYPE] = 0x00; gVox_Comm.Key_TWS_Pair_Tim = 0; gVox_Comm.Key_TWS_Pair_Cnt = 0; Event_key = KEY_EVENT_Empty; gVox_Comm.Key_L_2S_Flag = FALSE; OpenCover_TX_Cmd_Flag = TRUE; #if VOX_ENABLE #ifdef VOX_ADT_ENABLE Vol_State = VOX_NONE_IN_BOX; Vor_State = VOX_NONE_IN_BOX; #else VOX_EN_Type(VOX_ADT_Mode); //VOX Enable 5V #endif #endif #ifdef _DEBUG_KEY printf("Key Pair Get MASTER(line:%d).\r\n",(uint16_t)__LINE__); #endif return; } else { #ifdef VOX_TX #if XUANHENG HandleTxCommand(CMD_TWS_GET_BTADDR,SLAVE_SIDE); #else HandleTxCommand(VHOUSE_CMD_PAIR,SLAVE_SIDE); //右耳发配对指令,区分耳机通道。 #endif #endif #ifdef _DEBUG_KEY printf("Key Pair TX SLAVE(line:%d).\r\n",(uint16_t)__LINE__); #endif } } } } if(gVox_Comm.Key_TWS_Pair_Tim >= KEY_TWS_PAIR_TIMER) //3s重发一次。重发5次后超时 { gVox_Comm.Key_TWS_Pair_Cnt++; gVox_Comm.Key_TWS_Pair_Tim = 0; #ifdef _DEBUG_KEY printf("Key Pair Cnt:%d.(line:%d)\r\n",(uint16_t)gVox_Comm.Key_TWS_Pair_Cnt,(uint16_t)__LINE__); #endif } else { gVox_Comm.Key_TWS_Pair_Tim++; } } else { Vox_Comm_Cfg_Clear(); } } else if( gVox_Comm.Key_LL_8s_Flag ) /*按键8s发码:清配对码*/ { if( gVox_Comm.Key_TWS_Clear_Pair_Tim < Vox_COM_MSG_Tim ) //每隔200ms发送一次,持续时间3s。 { if( !( gVox_Comm.Key_TWS_Clear_Pair_Tim % Vox_TX_Interval_2 ) ) { #ifdef VOX_TX #if XUANHENG HandleTxCommand(CMD_CLEAR_PAIR,VOR_CHAN); #else HandleTxCommand(VHOUSE_CMD_CLEAR_PAIR,VOR_CHAN); #endif #endif } else if( !( gVox_Comm.Key_TWS_Clear_Pair_Tim % Vox_TX_Interval ) ) { #ifdef VOX_TX #if XUANHENG HandleTxCommand(CMD_CLEAR_PAIR,VOL_CHAN); #else HandleTxCommand(VHOUSE_CMD_CLEAR_PAIR,VOL_CHAN); #endif #endif } gVox_Comm.Key_TWS_Clear_Pair_Tim++; } else { Event_key = KEY_EVENT_Empty; OpenCover_TX_Cmd_Flag = TRUE; Vox_Comm_Cfg_Clear(); #if VOX_ENABLE #ifdef VOX_ADT_ENABLE Vol_State = VOX_NONE_IN_BOX; Vor_State = VOX_NONE_IN_BOX; #else VOX_EN_Type(VOX_ADT_Mode); //VOX Enable 5V #endif #endif } } } #endif #ifdef VOX_TX #if XUANHENG /* ******************************************************************************* * u16 CalCheckCrc16(u8 * pucFrame, u16 usLen) * * Description : 校验和的计算(CRC-16-CCITT-FALSE) * * * Arguments : u8 *pucFrame: 数据存放地址 u16 usLen: 数据长度, 以byte为单位 * Returns : * * Notes : * ******************************************************************************* */ static uint16_t CalCheckCrc16(uint8_t *pucFrame, unsigned int usLen) { uint16_t wCRCin = 0xFFFF; 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); } #else /* ******************************************************************************* * uint8_t Crc8Maxim(u8 *buf, u8 length) * * Description : 校验和的计算 * * * Arguments : u8 *buf: 数据存放地址 u8 length: 数据长度, 以byte为单位 * Returns : * * Notes : * ******************************************************************************* */ static 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; } #endif /* ******************************************************************************* * 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) { uint16_t dataLen = 0; uint8_t tx_pData[COM1_Data_Lenth] = 0; uint8_t i = 0; uint8_t Exch_BtAddr = 0; #if JIELI /*数据包头*/ tx_pData[0] = 0x00; tx_pData[1] = BOXHEADER>>8; tx_pData[2] = BOXHEADER; /*指令编号*/ tx_pData[4] = TxCommand; Vox_Type = nVox_Chn_Select; switch(TxCommand) { case VHOUSE_CMD_PAIR: /*Data Length*/ tx_pData[3] = 0x02; if( nVox_Chn_Select == VOL_CHAN ) { tx_pData[5] = 0x02; Vox_Get_BES_Addr_Flag[VOL_TYPE] = 0; } else if( nVox_Chn_Select == VOR_CHAN ) { tx_pData[5] = 0x01; Vox_Get_BES_Addr_Flag[VOR_TYPE] = 0; } break; case VHOUSE_CMD_EXCH_TWS_BTADDR: /*Data Length*/ tx_pData[3] = MAX_PACKET_SIZE; if( nVox_Chn_Select == VOL_CHAN ) { Exch_BtAddr = VOR_CHAN; } else if( nVox_Chn_Select == VOR_CHAN ) { Exch_BtAddr = VOL_CHAN; } for(i=5;i<23;i++) { tx_pData[i] = MAC_Addr[Exch_BtAddr][i-5]; } for(i=23;i<36;i++) { tx_pData[i] = Net_Info[Exch_BtAddr][i-23]; } break; case VHOUSE_CMD_CLEAR_PAIR: /*Data Length*/ tx_pData[3] = 0x02; tx_pData[5] = 0x03; break; case VHOUSE_CMD_CLOSE_WIN_GET_VBAT: //和开盖命令一样。 case VHOUSE_CMD_OPEN_BOX: //开盖获取电量命令 /*Data Length*/ tx_pData[3] = 0x05; tx_pData[5] = FW_VER; //Version tx_pData[6] = bat_level * 5; //电仓电量值 0~100; tx_pData[7] = MAX_PACKET_SIZE; //max_packet_size:0x20 if( nVox_Chn_Select == VOL_CHAN ) { if( Earphone_Vbat[VOL_CHAN] == 0 ) { tx_pData[8] = 0xFF; } else { tx_pData[8] = Earphone_Vbat[VOR_CHAN]; } } else if( nVox_Chn_Select == VOR_CHAN ) { if( Earphone_Vbat[VOR_CHAN] == 0 ) { tx_pData[8] = 0xFF; } else { tx_pData[8] = Earphone_Vbat[VOL_CHAN]; } } break; case VHOUSE_CMD_PWROFF: /*Data Length*/ tx_pData[3] = 0x01; break; case VHOUSE_CMD_CLOSE_BOX: //关盖指令 /*Data Length*/ tx_pData[3] = 0x02; tx_pData[5] = EarPhone_Num; //耳机个数 break; default: break; } dataLen = 4 + tx_pData[3]; tx_pData[dataLen] = Crc8Maxim(tx_pData,dataLen); #elif ZHONGKE /*数据包头*/ 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: case VHOUSE_CMD_OPEN_WINDOW: case VHOUSE_CMD_CLOSE_WIN_GET_VBAT: /*Data Length*/ tx_pData[4] = 0x03; tx_pData[6] = ( ( ChgStatus & CHG_STA_ING ) << 6 ) | bat_level; //bit 0~6 表示充电仓电量值 0~100;bit 7 为 1 表示在给充电仓充电,为 0 表示没有给充电仓充电; tx_pData[7] = 0x00; break; case VHOUSE_CMD_PAIR: //长按充电仓按键3s,充电仓发送配对指令。 /* 发送给右耳 CMD2,右耳接收到,发送 CMD3 指令给充电仓,充电仓 copy 该指令给 左耳,充电仓可随即发送 CMD2 指令给左耳,左耳会发送 CMD=0x03 给充电仓,充电仓直接 copy CMD3 给右耳即可,右耳接收到发送 VHOUSE_CMD_SUCCES 指令给充电仓。 */ /*Data Length*/ tx_pData[4] = 0x01; break; case VHOUSE_CMD_GET_TWS_BTADDR: //将收到的CMD3转发给对耳。 #ifdef VOX_RX for(i=0;i> 8; /*小端模式:低字节在前 Bit0-7:命令号 Bit8-14:预留 Bit15:包类型 0:REQ 1:ACK */ tx_pData[4] = CoverStatus; //开关盒状态 switch(TxCommand) { case CMD_TWS_GET_BTADDR: //获取耳机MAC地址 /*Data Length*/ tx_pData[5] = 0x00; //小端模式,低位在前,长2Bytes。 tx_pData[6] = 0x00; #ifdef VOX_RX for(i=0;i<6;i++) { BES_Addr[i] = 0; //清本地耳机蓝牙地址。 } #endif break; case CMD_TWS_SET_BTADDR: /*Data Length*/ tx_pData[5] = 0x0E; //小端模式,低位在前,长2Bytes。 tx_pData[6] = 0x00; #ifdef VOX_RX for(i=0;i<6;i++) { tx_pData[7+i] = BES_Addr[i]; //发送耳机蓝牙地址。 } #endif 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] = ( ( ChgStatus & CHG_STA_ING ) << 6 ) | ( 5 * 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: //复位patten return; default: break; } dataLen = (uint16_t)( tx_pData[5] | ( tx_pData[6] << 8 ) ) + 7; Checksum = CalCheckCrc16( tx_pData, dataLen ); //计算检验和 tx_pData[ dataLen ] = Checksum; tx_pData[ ++dataLen ] = Checksum >> 8; #endif /* vor、vol都使用uart1进行分时通讯,设置TX模式*/ #ifdef VOX_ADT_ENABLE if(nVox_Chn_Select == VOL_CHAN) { VOL_EN_Type( VOX_COMM_Mode_Uart ); } else { VOR_EN_Type( VOX_COMM_Mode_Uart ); } #else VOX_EN_Type( VOX_COMM_Mode_Uart ); #endif if(nVox_Chn_Select == VOL_CHAN) { COMM_CTL |= Vol_SWDT; COMM_CTL &= ~Vol_SWDR; } else if(nVox_Chn_Select == VOR_CHAN) { COMM_CTL |= Vor_SWDT; COMM_CTL &= ~Vor_SWDR; } else if(nVox_Chn_Select == VOX_BOTH) { COMM_CTL |= Vor_SWDT | Vol_SWDT; COMM_CTL &= ~( Vor_SWDR |Vol_SWDR ); } #if UART1_ENABLE Uart1SendPacket(dataLen + 2, tx_pData); #endif /* 设置RX模式。 */ if(nVox_Chn_Select == VOL_CHAN) { COMM_CTL &= ~ Vol_SWDT; COMM_CTL |= Vol_SWDR; } else if(nVox_Chn_Select == VOR_CHAN) { COMM_CTL &= ~Vor_SWDT; COMM_CTL |= Vor_SWDR; } else if(nVox_Chn_Select == VOX_BOTH) { COMM_CTL &= ~Vor_SWDT | Vol_SWDT; COMM_CTL |= ( Vor_SWDR |Vol_SWDR ); } } #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 : * ******************************************************************************* */ static void HandleRxMsg(VOX_BES_COMMAND_E RxCommand) { uint8_t i = 0; #if JIELI switch(RxCommand) { case VHOUSE_CMD_PAIR: for(i=0;i<18;i++) { MAC_Addr[Vox_Type][i] = RX1_Buffer[4+i]; } for(i=0;i<13;i++) { Net_Info[Vox_Type][i] = RX1_Buffer[22+i]; } if( Vox_Type == VOL_CHAN ) //根据耳机Side参数 { Vox_Get_BES_Addr_Flag[VOL_TYPE] = 1; //获取左耳机发的CMD3 } else { Vox_Get_BES_Addr_Flag[VOR_TYPE] = 1; //获取右耳机发的CMD3 } break; case VHOUSE_CMD_EXCH_TWS_BTADDR: break; case VHOUSE_CMD_OPEN_BOX: case VHOUSE_CMD_CLOSE_WIN_GET_VBAT: if( RX1_Buffer[4] == 0xE3 ) //根据耳机Side参数 { Vox_Get_Vbat_Flag[VOL_TYPE] = 1; //获取左耳机发的Vbat Earphone_Vbat[VOL_CHAN] = RX1_Buffer[5]; } else { Vox_Get_Vbat_Flag[VOR_TYPE] = 1; //获取右耳机发的Vbat Earphone_Vbat[VOR_CHAN] = RX1_Buffer[5]; } break; case VHOUSE_CMD_CLOSE_BOX: break; case VHOUSE_CMD_PWROFF: break; default: break; } #elif ZHONGKE switch(RxCommand) { case VHOUSE_CMD_GET_VBAT: case VHOUSE_CMD_CLOSE_WINDOW: case VHOUSE_CMD_OPEN_WINDOW: case VHOUSE_CMD_CLOSE_WIN_GET_VBAT: break; case VHOUSE_CMD_SUCCESS: break; case VHOUSE_CMD_GET_TWS_BTADDR: if( RX1_Buffer[5] == VOL_CHAN ) //根据耳机Side参数 { Vox_Get_BES_Addr_Flag[VOL_TYPE] = 1; //获取左耳机发的CMD3 } else { Vox_Get_BES_Addr_Flag[VOR_TYPE] = 1; //获取右耳机发的CMD3 } break; case VHOUSE_CMD_SYS_RST: //系统复位,耳机->充电仓 break; default: break; } #elif XUANHENG uint8_t CMD_Type = 0; CMD_Type = RX1_Buffer[1] >> 4; if( CMD_Type & TWS_PC ) //PC/工装->盒子 { } else //耳机->盒子 { switch(RxCommand) { case CMD_TWS_GET_BTADDR: for(i=0;i> 7; //获取耳机是否满电 Vox_Pairing_State[VOL_TYPE] = RX1_Buffer[10]; //获取耳机配对状态; Tws_Paired_Record[VOL_TYPE] = RX1_Buffer[11] & 0x01; //bit0:0:有TWS配对记录;1:没有TWS配对记录;bit1:0:有与手机配对记录;1:没有和手机配对记录。 Phone_Paired_Record[VOL_TYPE] = ( RX1_Buffer[11] >> 1 ) & 0x01; Bes_OTA_State[VOL_TYPE] = RX1_Buffer[12]; } else { Bes_Bet_Level[VOR_TYPE] = RX1_Buffer[9] & 0x7F; Bes_Chg_Full[VOR_TYPE] = RX1_Buffer[9] >> 7; Vox_Pairing_State[VOR_TYPE] = RX1_Buffer[10]; Tws_Paired_Record[VOR_TYPE] = RX1_Buffer[11] & 0x01; Phone_Paired_Record[VOR_TYPE] = (RX1_Buffer[11] >> 1) & 0x01; Bes_OTA_State[VOR_TYPE] = RX1_Buffer[12]; } break; case CMD_SN: if( CMD_Type == TWS_VOL ) //根据耳机Side参数 { Bes_Set_SN_State[VOL_TYPE] = RX1_Buffer[7]; //左耳机SN写入是否成功状态标志 } else { Bes_Set_SN_State[VOR_TYPE] = RX1_Buffer[7]; //右耳机SN写入是否成功状态标志 } break; case CMD_GET_INTO_PAIR: if( CMD_Type == TWS_VOL ) //根据耳机Side参数 { Bes_In_Pair_State[VOL_TYPE] = RX1_Buffer[7]; //左耳机是否进入配对状态成功状态标志 } else { Bes_In_Pair_State[VOR_TYPE] = RX1_Buffer[7]; //右耳机是否进入配对状态成功状态标志 } break; case CMD_PAIRING_IMD: if( CMD_Type == TWS_VOL ) //根据耳机Side参数 { Bes_In_Pair_State[VOL_TYPE] = 1; //左耳机是否进入配对状态成功状态标志 } else { Bes_In_Pair_State[VOR_TYPE] = 1; //右耳机是否进入配对状态成功状态标志 } break; default: break; } } #endif } /* ******************************************************************************* * void HandleVoxCommMsg(void) * * Description : Vox 通讯功能处理函数,100ms定时调用。由于和耳机通信前需要打开耳机端的TRX功能,并且每次通信只能一只耳机。通过切换VOL/VOR通信开关进行通信 * * Arguments : NONE * Returns : NONE * Notes : NONE * ******************************************************************************* */ void HandleVoxCommMsg(void) { uint8_t i = 0; #if XUANHENG uint16_t CrcCheckSum = 0; uint16_t Data_Len = 0; #else uint8_t CrcCheckSum = 0; #endif /*RX数据处理*/ if( Uart1_RX_Finish_Flag ) { Uart1_RX_Finish_Flag = FALSE; #ifdef _DEBUG_VOX // printf("RX0_Buffer[0]:0x%x,RX0_Buffer[1]:0x%x,RX0_Buffer[2]:0x%x,RX0_Buffer[3]:0x%x,RX0_Buffer[4]:0x%x,RX0_Buffer[5]:0x%x,RX0_Buffer[6]:0x%x,RX0_Buffer[7]:0x%x,RX0_Buffer[8]:0x%x,RX0_Buffer[9]:0x%x,RX0_Buffer[10]:0x%x,RX0_Buffer[11]:0x%x,line:%d\r\n",(u16)RX0_Buffer[0],(u16)RX0_Buffer[1],(u16)RX0_Buffer[2],(u16)RX0_Buffer[3],(u16)RX0_Buffer[4],(u16)RX0_Buffer[5],(u16)RX0_Buffer[6],(u16)RX0_Buffer[7],(u16)RX0_Buffer[8],(u16)RX0_Buffer[9],(u16)RX0_Buffer[10],(u16)RX0_Buffer[11],(u16)__LINE__); #endif #if JIELI CrcCheckSum = Crc8Maxim(RX1_Buffer, RX1_Buffer[2] + 3); //求校验和 if( CrcCheckSum == RX1_Buffer[RX1_Buffer[2] + 3] ) #elif ZHONGKE CrcCheckSum = Crc8Maxim( RX1_Buffer, RX1_Buffer[4] + 5 ); if( CrcCheckSum == RX1_Buffer[ RX1_Buffer[4] + 5 ] ) #elif XUANHENG Data_Len = RX1_Buffer[5] | ( RX1_Buffer[6] << 8 ) + 7; CrcCheckSum = CalCheckCrc16( RX1_Buffer, Data_Len); //计算检验和 if( CrcCheckSum == (uint16_t)(RX1_Buffer[ Data_Len + 1 ] | RX1_Buffer[ Data_Len + 2 ] << 8) ) //校验和小端模式,低位在前。 #endif { #if XUANHENG HandleRxMsg((VOX_BES_COMMAND_E)RX1_Buffer[2]); #else HandleRxMsg((VOX_BES_COMMAND_E)RX1_Buffer[3]); #endif } else { return; } } } #endif