/****************************************************************************
*
* 文件名: usart_api.c
* 内容简述: 使用中断方式实现串口FIFO，提供易用的函数接口，便于用户程序调用。
	注意：
	(1) 中断程序未对发送缓冲区满做处理.也就是说调用comSendBuf()函数时，如果
		开辟的发送缓冲区不足，将导致最先放入FIFO的数据被冲掉。
		不过对以一般的应用程序，将发送缓冲区开的足够大以保证一个最长的通信帧能够容纳下即可。
*/


/* Includes ------------------------------------------------------------------*/
#include "uart_api.h"
#include "usart.h"
#include "include.h"
#include "apptocube.h"
#include "wireless.h"
#include "power.h"
#include "InnerFlash.h"
#include "rotation.h"
#include "delay.h"
#include "ADC.h"
//#include "cubecell.h"
#if ARCH_MODE == NRF52832_Slave_Mode
//#include "led.h"

#if MOTION_SENSOR_TYPE == MOTION_SENSOR_TYPE_9X_ACCEL_GYRO_MAG
#include "app_mpu9250.h"
#endif
//#include "ledGam.h"
#include "beep.h"
#elif ARCH_MODE == NRF51802_Peripheral_Mode
//#include "ledGam.h"
#include "beep.h"
//#include "rRecordGam.h"
#endif

u8 RollChar = 0x00; //串口接收到的有效转动字符，例如：R、r、U、u等
u8 RollChar_Flag = 0; //串口接收到的有效转动字符，例如：R、r、U、u等


u8 debugBuf[64] = {0x0};

/*******************************************************/
WIFI_INFO_STRUCT wifi_info;  //存储wifi芯片反馈的信息、状态
#if ARCH_MODE == CC254x_Slave_Mode
MSXX_CMD_STRUCT F103R8_CMD;  //存储主控f103R8 有效字符串信息

void initMSXX_CMD_data(void) //初始化MSXX_CMD_STRUCT 成员
{
	unsigned int i=0;
	for(i=0;i<MSXX_CMD_MAX;i++)
	{
		F103R8_CMD.MSXX_CMD[i] = 0x0;
	}
	F103R8_CMD.MSXX_CMD_Len = 0;
}
#endif

void initWifiInfo_data(void) //初始化WIFI_INFO_STRUCT wifi_info 成员
{
	unsigned int i=0;
	for(i=0;i<APIP_MAX;i++)
	{
		wifi_info.APIP[i] = '0';
	}
	for(i=0;i<APMAC_MAX;i++)
	{
		wifi_info.APMAC[i] = '0';
	}
	for(i=0;i<STAIP_MAX;i++)
	{
		wifi_info.STAIP[i] = '0';
	}
	for(i=0;i<STAMAC_MAX;i++)
	{
		wifi_info.STAMAC[i] = '0';
	}
	wifi_info.APIP_LEN = 0;
	wifi_info.APMAC_LEN = 0;
	wifi_info.STAIP_LEN = 0;//0 test 7
	wifi_info.STAMAC_LEN = 0;
}

/*******************************************************/
u16 getStrLen(char *sDataBuf)
{
	u16 ilen=0;
	u8 bflag = false;
	while(1)
	{
		if(NULL == sDataBuf)
		{
			break;
		}
		if(0x0 == *sDataBuf)
		{
			if(false == bflag)
			{
				bflag = true;
			}
			else
			{
				ilen--;
				break;
			}
		}
		sDataBuf++;
		ilen++;
	}
	return ilen;
}

//上传电池电压到App
void SendBatteryVoltageToApp()
{
	u8 battery_voltage_percent = 0;
	char rf_str[8] = "";
	
	GetBatteryPowerLeftPercent(&battery_voltage_percent);
	sprintf(rf_str, "%d", battery_voltage_percent);
	RfSend(82, rf_str, strlen(rf_str));
}

/*******************************************************/
unsigned char strAllCmd[128]={0x0};
unsigned char strTmp[128]={0x0};
u8 strlen1,strlen2 = 0xff;
#define RECV_HEAD_LEN	(strlen((const char *)RECV_HEAD[0]))
/*******************************************************/
/*
  RfSend 发送固定格式到App
	Cmd：指令码
	*str：指令内容，字符串形式
	istrlen：指令内容长度
*/
void RfSend(u16 Cmd,char *str, u16 istrlen)	 //
{
	u16 i=0;
	u8 cadd = 0x0;
	for(i=0;i<sizeof(strTmp);i++)
	{
		strTmp[i] = 0x0;
	}
	for(i=0;i<sizeof(strAllCmd);i++)
	{
		strAllCmd[i] = 0x0;
	}
	for(i=0;i<istrlen;i++)
	{
		cadd = cadd + *str;
		strTmp[i] = *str;
		str++;
	}
	strlen1 = istrlen/90+33;
	strlen2 = istrlen%90+33;
	sprintf((char *)strAllCmd,"%s%c%c%c%s%c\r\n",RECV_HEAD[0],Cmd,strlen1,strlen2,strTmp,cadd);
	print_wifi((u8 *)strAllCmd);
}

#if ARCH_MODE == ESP8266_Station_Mode || ARCH_MODE == CC254x_Slave_Mode
/*
  SlvSend 固定格式发送数据到子板
	Cmd：指令码
	*str：指令内容，字符串形式
	istrlen：指令内容长度
*/
void SlvSend(u16 Cmd,char *str, u16 istrlen)	 //
{
	u16 i=0;
	//u8 cadd = 0x0;
	for(i=0;i<sizeof(strTmp);i++)
	{
		strTmp[i] = 0x0;
	}
	for(i=0;i<sizeof(strAllCmd);i++)
	{
		strAllCmd[i] = 0x0;
	}
	for(i=0;i<istrlen;i++)
	{
		//cadd = cadd + *str;
		strTmp[i] = *str;
		str++;
	}
	sprintf((char *)strAllCmd,"MSF103R8%c%s",Cmd,strTmp);
	SendUsartxString_NewLine((u8 *)strAllCmd);
	SendUsartxString_NewLine((u8 *)strAllCmd);
}
#endif

/***************************************************************/
B2B_SERIAL_DATA_STRUCT sd1;
u8 SerialTail[] = "\r\n";
u8 Serialinit[] = "\0";
/***************************************************************/
uint16_t initSerialData(B2B_SERIAL_DATA_STRUCT *sd)
{
	u16 i=0;
	for(i=0;i<sizeof(SerialTail);i++)
	{	
		sd->sB2BEnd[i]=SerialTail[i];
	}

	sd->iB2BEndCnt = 0;
	for(i=0;i<iB2BDataMax;i++)
	{	
		sd->sB2BData[i]=0x0;
	}
	sd->iB2BDataCnt = 0;
	sd->cB2BRxTemp = 0x0;
	return true;
}

#if PROTOCOL_DATA_SOURCE == PROTOCOL_DATA_SOURCE_UART
//u8 cB2BRxTemp = 0x0;
/********************************************************
  板对板协议简单协议解析 （以\R\N结束）
********************************************************/
uint8_t COMB2BSerialCycleDetect(B2B_SERIAL_DATA_STRUCT *sd, u8 COMPort)
{
	if(true == comGetChar(COMPort, &(sd->cB2BRxTemp)))
	{
		if(sd->cB2BRxTemp == sd->sB2BEnd[sd->iB2BEndCnt])
		{
			sd->iB2BEndCnt++;
			if(sd->iB2BEndCnt >= iB2BEndMax)
			{
				sd->iB2BEndCnt = 0;
				//--------add \0 to end of string---------
				if(sd->iB2BDataCnt < iB2BDataMax) //exceed max storage len of data buf
				{
					sd->sB2BData[sd->iB2BDataCnt] = 0x0;
					sd->iB2BDataLen = sd->iB2BDataCnt; //storage valid data cnt len
				}
				sd->iB2BDataCnt = 0;
				if(sd->iB2BDataLen > 0)
				{
					//printf("recv one command1\n");
					return true;
				}
			}
		}
		else
		{
			sd->sB2BData[sd->iB2BDataCnt] = sd->cB2BRxTemp;
			sd->iB2BDataCnt++;
			if(sd->iB2BDataCnt >= iB2BDataMax) //exceed max storage len of data buf
			{
				sd->iB2BDataCnt = 0;
				sd->iB2BEndCnt = 0;
			}
		}
	}
	return false;
}
#endif

int isCmdFromApp_Flag = false;

#if PROTOCOL_DATA_SOURCE == PROTOCOL_DATA_SOURCE_UART
/****************************************************
	定时检测串口数据
****************************************************/
u8 periodDetectComCycle(void)
{
	u16 i=0;
	u8 rtn = true;
	//------- 串口字符串协议解析程序  ---------
	if(COMAppCmdCheckByte_Flag == true)
	{
		COMAppCmdCheckByte_Flag = false;
		/****************************** COM1 *****************************/
		
		if(true == COMB2BSerialCycleDetect(&sd1,COM1)) //cycle detect board to board communication
		{
			for(i=0;i<sd1.iB2BDataLen;i++)
			{
				if(RECV_HEAD[0][0] != sd1.sB2BData[i])
				{
					continue;
				}
				if((RECV_HEAD[0][1] == sd1.sB2BData[i+1])&&\
					(RECV_HEAD[0][2] == sd1.sB2BData[i+2]))
				{
					if(true == process_app_data_buf(&sd1, i))
					{
						parse_cmd_from_app();
						isCmdFromApp_Flag = true;
					}
				}
			}
#if ARCH_MODE == ESP8266_Station_Mode || ARCH_MODE == CC254x_Slave_Mode
			if(false == isCmdFromApp_Flag)
			{
				process_wifi_data_buf(&sd1);
			}
#endif
		}
	}
	return rtn;
}

#elif PROTOCOL_DATA_SOURCE == PROTOCOL_DATA_SOURCE_BLE
/********************************************************
  BLE接收数据解析
********************************************************/
uint8_t BLECycleDetect(B2B_SERIAL_DATA_STRUCT *sd, uint8_t data)
{
	sd->cB2BRxTemp = data;
	if(sd->cB2BRxTemp == sd->sB2BEnd[sd->iB2BEndCnt])
	{
		sd->iB2BEndCnt++;
		if(sd->iB2BEndCnt >= iB2BEndMax)
		{
			sd->iB2BEndCnt = 0;
			//--------add \0 to end of string---------
			if(sd->iB2BDataCnt < iB2BDataMax) //exceed max storage len of data buf
			{
				sd->sB2BData[sd->iB2BDataCnt] = 0x0;
				sd->iB2BDataLen = sd->iB2BDataCnt; //storage valid data cnt len
			}
			sd->iB2BDataCnt = 0;
			if(sd->iB2BDataLen > 0)
			{
				//printf("recv one command1\n");
				return true;
			}
		}
	}
	else
	{
		sd->sB2BData[sd->iB2BDataCnt] = sd->cB2BRxTemp;
		sd->iB2BDataCnt++;
		if(sd->iB2BDataCnt >= iB2BDataMax) //exceed max storage len of data buf
		{
			sd->iB2BDataCnt = 0;
			sd->iB2BEndCnt = 0;
		}
	}

	return false;
}

/****************************************************
	检测BLE接收的数据协议
****************************************************/
u8 detectDataFromBLE(uint8_t *p_data, uint16_t length)
{
	u16 i = 0;
	u16 j = 0;
	u8 rtn = true;
	//------- 字符串协议解析程序  ---------
	/****************************** BLE Data Process *****************************/
	for(j=0;j<length;j++)
	{
		if(true == BLECycleDetect(&sd1, *(p_data+j))) //cycle detect BLE communication bytes
		{
			for(i=0;i<sd1.iB2BDataLen;i++)
			{
				if(RECV_HEAD[0][0] != sd1.sB2BData[i])
				{
					continue;
				}
				if((RECV_HEAD[0][1] == sd1.sB2BData[i+1])&&\
					(RECV_HEAD[0][2] == sd1.sB2BData[i+2]))
				{
					if(true == process_app_data_buf(&sd1, i))
					{
						parse_cmd_from_app();
						isCmdFromApp_Flag = true;
						disAllowSystemOff();			//App有有效指令持续下发，不允许定时关机
					}
				}
			}
#if ARCH_MODE == ESP8266_Station_Mode || ARCH_MODE == CC254x_Slave_Mode
			if(false == isCmdFromApp_Flag)
			{
				process_wifi_data_buf(&sd1);
			}
#endif				
		}
	}
	
	return rtn;
}

#endif


/*********************************************************/
void clearCharBuf(char *buf, int ibuflen) //清空Char 数组所有成员数据为0x0
{
	u16 i=0;
	for(i=0;i<ibuflen;i++)
	{
		*(buf+i) = 0x0;
	}
}
/***************************************************************/
void clearUCharBuf(unsigned char *buf, int ibuflen) //清空Unsigned Char 数组所有成员数据为0x0
{
	u16 i=0;
	for(i=0;i<ibuflen;i++)
	{
		*(buf+i) = 0x0;
	}
}


#if ARCH_MODE == ESP8266_Station_Mode || ARCH_MODE == CC254x_Slave_Mode

/***************************************************************/
WIFI_STATUS_ENUM wifi_status = WIFI_STATUS_MIN;

/***************************************************************/
/***************************************************************/
u8 stripWifiValidStr( B2B_SERIAL_DATA_STRUCT *sd,
						u16 wifi_status,
						u8 *buf,
						u16 *bufLen)
{
	u16 len_base = 0;
	u16 i=0;
	len_base = getStrLen((char *)WifiATRespKeyWord[wifi_status]);
	for(i=len_base;i<sd->iB2BDataLen;i++)
	{
		*(buf+i-len_base) = *(sd->sB2BData+i);//+14
	}
	*(buf+sd->iB2BDataLen - len_base) = 0x0;
	*bufLen = sd->iB2BDataLen - len_base;
	return true;
}
#endif

#if ARCH_MODE == CC254x_Slave_Mode
/***************************************************************
来自主控板F103R8指令：
	    第一字节  第二字节  第三字节 第四字节
停止上传   1
开始上传   2
亮灯       A      1-9   (ASCII格式字符)                      
亮多灯     B      1         3         5  。。。 (ASCII格式字符)      
亮全灯     C                                
。。。
***************************************************************/
u8 process_MSF103R8_CMD(COM_NUM_ENUM com, MSXX_CMD_STRUCT *msCmd)
{
	u16 dataLen=0,SIGN_offset=0;
	u8 rtn=true,offset=0;
	//u8 multiLedNumBuf[20]={0x0};
	u8 *cmd=NULL;
	u8 cmdHead;
	if(true == DEBUG_FLAG)
	{
		//print_wifi("process_MSF103R8_CMD ->\n");
		snprintf((char *)debugBuf,msCmd->MSXX_CMD_Len,(const char *)msCmd->MSXX_CMD);
		print_wifi(debugBuf);
	}
	//-------------------------------
	if(msCmd->MSXX_CMD_Len <= 0)
	{
		return false;
	}
	offset = com-COM_MIN;
	cmd = msCmd->MSXX_CMD;
	dataLen = msCmd->MSXX_CMD_Len;
	cmdHead = *cmd;
	//print_wifi(&cmdHead);
	if(com == COM2)
	{
		offset = 0;
	}
	else if(com == COM3)
	{
		offset = 1;
	}
	else
	{
		return false;
	}
	
	switch(cmdHead)
	{
		case 'a':
		case 'b':
		case 'c':
		case 'd':
		case 'e':
		case 'f':
			//print_wifi((u8 *)&Num_Tab[dataLen]);
			SIGN_offset = offset*AxisPerFpc+(cmdHead-'a');
			if(SIGN_offset < ADC_CHAN_SIGN_MAX)
			{
#if CUBE_ND_MODE == CUBE_ND_MODE_1D_MAG	
				if(SIGN_offset == 5)
				{
					SIGN_offset = 2;
				}
#else
#endif
				SendRotationToAppByStr(41, cmd, dataLen, ADC_CHAN_SIGN[SIGN_offset], SIGN_offset);
				
			}
			//UART2_SendString("recved from com2 or com3 rotation data!\n");//test
			//debug_print_wifi(cmd);
			break;
		case 'A':
			ProAllPositionResAndUpload(com,msCmd);
	//snprintf((char *)cmdTmp2,msCmd->MSXX_CMD_Len,(char *)msCmd->MSXX_CMD);
	//print_wifi(cmdTmp2);
			break;
		//case 1:
		//case 2:
		//case 3:
		//	SendRotationToApp(cmd, dataLen, ADC_CHAN_SIGN[offset*AxisPerFpc+cmdHead]);
		//	break;
		default:
			rtn=false;
			break;
	}
	return rtn;
}


u8 ProAllPositionResAndUpload(COM_NUM_ENUM com, MSXX_CMD_STRUCT *msCmd)
{
	u16 i=0,ADC_Value=0;
	u8 *cmd = msCmd->MSXX_CMD;
	u16 dataLen = msCmd->MSXX_CMD_Len;
	u16 dataLenHalf = (dataLen-1)/2;
	u8 comport = 1,SeqOffset = 0,TypeNum = 0,ResSeqNum=0;
	if(COM2 == com)
	{
		comport = 1;
	}
	else if(COM3 == com)
	{
		comport = 2;
	}
	else
	{
		return false;
	}
	
	
	for(i=1;i<=dataLenHalf;i++)
	{
		if(true == get_Res_Seq_Color(comport, i-1, &SeqOffset, &TypeNum))
		{
			ADC_Value = (*(cmd+i*2-1)-33)*90 + *(cmd+i*2)-33;
			
			//------通过块类型及ADC采样值获取电阻全局编号------
			ResSeqNum = ADC_Value_Convert_to_SeqNum(TypeNum, ADC_Value); 
			//------通过电阻全局编号获取对应颜色首字母代号------
			SeqNum_Convert_to_ColorSideSign(SeqOffset, ResSeqNum);
			
			if(true == DEBUG_FLAG)
			{
				sprintf((char *)debugBuf, "ADC:%d\n", ADC_Value);//test
				debug_print_wifi(debugBuf);//test
			}
		}
	}
	return true;
}

/**************************************************************
	通过电阻全局编号获取对应颜色首字母代号
		颜色首字母代号：【U,R,D,L,F,B】
**************************************************************/
void SeqNum_Convert_to_ColorSideSign(	u16 SeqOffset, //电阻编号存储偏移量
										u16 ResSeqNum  //电阻全局编号  【1,48】
										)
{
	//通过电阻全局编号存储对应的颜色首字母代号
	sAllColorBuf[sAllSeqOffsetTab[SeqOffset]] = sAllSeqColorTab[ResSeqNum]; 
}

#if CUBE_NX_MODE == CUBE_NX_MODE_2X
int sAllColorBuf2XCnt = 0;  //sAllColorBuf2X 预设模拟所有色块颜色数组
typedef enum
{
	OffsetAllColorBuf_Min = 0,
	OffsetAllColorBuf_1,
	OffsetAllColorBuf_2,
	OffsetAllColorBuf_3,
	OffsetAllColorBuf_Max
}OffsetAllColorBuf_ENUM;
OffsetAllColorBuf_ENUM offsetACB = OffsetAllColorBuf_Min;

char sAllColorBuf2X_0[] = "YYYYYYYYY|RRRRRRRRR|WWWWWWWWW|OOOOOOOOO|BBBBBBBBB|GGGGGGGGG";
char sAllColorBuf2X_1[] = "YYYYYYYYY|GGGRRRRRR|WWWWWWWWW|BBBOOOOOO|RRRBBBBBB|OOOGGGGGG";
char sAllColorBuf2X_2[] = "RBBOOYYYY|BBRGGRBYR|RRRGOWWWW|YOOWGOOOO|BBWRWWWBB|YRGGGGYYG";
char sAllColorBuf2X_3[] = "OOYOOYYYY|BBRBBRBYR|RRRGRGGWW|WOOWGOOWO|BBWRWWWBB|GGGGYYYRG";

void changeAllColorBuf(char *fromBuf, u16 bufLen)
{
	u16 i=0;
	for(i=0;i<bufLen;i++)
	{
		sAllColorBuf[i] = *(fromBuf+i);
	}
}

void change2XOffsetAllColorBuf(void)
{
	char *ptr = NULL;
	OffsetAllColorBuf_ENUM offset = offsetACB;
	switch(offset)
	{
		case OffsetAllColorBuf_Min:
			ptr = sAllColorBuf2X_0;
			offsetACB = OffsetAllColorBuf_1;
			break;
		case OffsetAllColorBuf_1:
			ptr = sAllColorBuf2X_1;
			offsetACB = OffsetAllColorBuf_2;
			break;
		case OffsetAllColorBuf_2:
			ptr = sAllColorBuf2X_2;
			offsetACB = OffsetAllColorBuf_3;
			break;
		case OffsetAllColorBuf_3:
			ptr = sAllColorBuf2X_3;
			offsetACB = OffsetAllColorBuf_1;
			break;
		default:
			//ptr = sAllColorBuf2X_1;
			offsetACB = OffsetAllColorBuf_1;
			break;
	}
	if(*ptr != NULL)
	{
		changeAllColorBuf(ptr, sAllColorFullMax);
	}
}
#endif

//初始化sAllColorBuf  顺序存储汇总所有完整魔方块颜色代号 面[1-6] 块[1-9]
void initsAllColorBuf(void)
{
#if CUBE_NX_MODE == CUBE_NX_MODE_2X
	change2XOffsetAllColorBuf();
#else
	u16 i=0;
	for(i=0;i<sAllColorFullMax;i++)
	{
		sAllColorBuf[i] = ALL_COLOR_SIGN[i%6];
	}
	sAllColorBuf[ 4] = 'Y';
	sAllColorBuf[14] = 'R';
	sAllColorBuf[24] = 'W';
	sAllColorBuf[34] = 'O';
	sAllColorBuf[44] = 'B';
	sAllColorBuf[54] = 'G';
	
	sAllColorBuf[ 9] = '|';
	sAllColorBuf[19] = '|';
	sAllColorBuf[29] = '|';
	sAllColorBuf[39] = '|';
	sAllColorBuf[49] = '|';
	//sAllColorBuf[59] = '|';
#endif
}

#endif

s8 rledGamEnable_Flag = false;
s8 tledGamEnable_Flag = false;
s8 eledGamEnable_Flag = false;
s8 trackGamEnable_Flag = false;

/**************************************************************
	上传所有面块电阻颜色首字母代号
**************************************************************/
int send_all_res_directly(void)
{
#if ARCH_MODE == NRF52832_Slave_Mode || ARCH_MODE == NRF51802_Peripheral_Mode

	memset(sAllColorBuf, 0x00, sizeof(sAllColorBuf));
//	getAllCubeCellColor_general((u8 *)sAllColorBuf, sAllColorFullMax);
	RfSend(20,sAllColorBuf,sAllColorFullMax);
#else
	RfSend(20,sAllColorBuf,sAllColorFullMax);
#endif
	return true;
}

/**************************************************************
	基于转动的应用检测执行
**************************************************************/
s8 rotation_based_app_process(u32 time, u8 side, u16 angle)
{
	s8 rtn_flag = false;
#if ARCH_MODE == NRF52832_Slave_Mode
	if(true == rledGamEnable_Flag)
	{
		//rledGam_roll_detect(side, angle);  			//转转灯检测
		rtn_flag = true;
	}
	if(true == eledGamEnable_Flag)
	{
		//eledGam_roll_detect(side, angle);  			//抢吃灯检测
		rtn_flag = true;
	}
#if KEY_SWITCH_MODE == KEY_SWITCH_SEPERATE_MODE
	else
	{
		if(true == eledGam_check_switch_to_rledGam())
		{
			//模拟触发第一次转动，不会遗漏当前转动格
			rledGam_roll_detect(side, angle);
		}
	}
#endif	
	//if(true == trackGamEnable_Flag)
	//{
		//trackGam_roll_detect(time, side, angle);  	//还原记录检测(全局记录)
		//rtn_flag = true;
	//}
	if(true == tledGamEnable_Flag)					//离线教学检测
	{
		//tledGam_roll_detect(side, angle);
		rtn_flag = true;
	}

	
#endif	
	return rtn_flag;
}

#define cmdRotationStrBufMax  48
static u8 cmdRotationStrBuf[cmdRotationStrBufMax]={0x0};

u8 SendRotationToAppByNum(u8 cmdCode, u32 time, u8 side, u16 angle)
{
	if(false == wireless_connected_Flag)	//无线连接时拼接发送字符串
	{
		return false;
	}
	
	init_StrBuf(cmdRotationStrBuf, cmdRotationStrBufMax);
#if ARCH_MODE == NRF51802_Peripheral_Mode
	sprintf((char *)cmdRotationStrBuf,
			"%c",
			side
			);
#else
	if(43 == cmdCode)
	{
		sprintf((char *)cmdRotationStrBuf,
				"%c",
				side
				);
	}
	else
	{
		sprintf((char *)cmdRotationStrBuf,
				"%c|%d",
				side,
				angle
				);
	}
	if(true == DEBUG_FLAG)
	{
		sprintf((char *)debugBuf,"SRTABN side:%c angle:%d",side,angle);
		debug_print_wifi(debugBuf);
	}
#endif
	UploadRotationData(cmdCode);

	return true;
}

u16 convertToNum(u8 *cmd,u16 dataLen)
{
	u16 Num=0,i=0,baseNul=1;
	
	for(i=1;i<=dataLen;i++)
	{
		Num = Num + baseNul*(*(cmd+dataLen-i)-0x30);
		baseNul = baseNul*10;
	}
	return Num;
}

u8 SendRotationToAppByStr(u8 cmdCode, u8 *cmd, u16 dataLen, u8 side, u8 sideOffset)
{
	u16 angle = 0;
	
	//cmd真正数据从第二位开始，dataLen需减一
	angle = convertToNum(cmd+1, dataLen-1);
#if   CUBE_ND_MODE == CUBE_ND_MODE_1D_MAG || CUBE_ND_MODE == CUBE_ND_MODE_3D
	if(true == wireless_connected_Flag)	//无线连接时拼接发送字符串
	{
		init_StrBuf(cmdRotationStrBuf, cmdRotationStrBufMax);
		cmdRotationStrBuf[0] = side;
		cmdRotationStrBuf[1] = '|';
		memcpy((char *)cmdRotationStrBuf, cmd+1, dataLen);
		cmdRotationStrBuf[dataLen+1] = 0x0;
	}
	
#elif CUBE_ND_MODE == CUBE_ND_MODE_2D
	angle = ADC_RotationRes_Convert_to_AngleNum(sideOffset, angle);
	angle = RotationAngle_Other_Process(sideOffset, angle);
	sprintf((char *)cmdRotationStrBuf, "%c|%d\0", side, angle);
		
#endif

	if(true == updateCurrentAngleBySide(side, angle)) //转动角度有变化时才会上传App
	{
		UploadRotationData(cmdCode);
	}
	
	rotation_based_app_process(0, side, angle);	//转动应用检测执行
	
	return true;
}


int UploadRotationData(u8 cmdCode)  //上传面转动传感器数据到App
{
	if(false == wireless_connected_Flag)
	{
		return false;
	}
	
	if(true == rotation_upload_en_Flag)
	{
		RfSend(cmdCode,(char *)cmdRotationStrBuf,getStrLen((char *)cmdRotationStrBuf));//dataLen+1);
		return true;
	}
	//init_StrBuf(cmdRotationStrBuf,cmdRotationStrBufMax);
	return false;
}

int UploadRotationDataDirectly(u8 cmdCode) //强制上传转动数据到App
{
	RfSend(cmdCode,(char *)cmdRotationStrBuf,getStrLen((char *)cmdRotationStrBuf));//dataLen+1);
	//init_StrBuf(cmdRotationStrBuf,cmdRotationStrBufMax);
	return true;
}

/*********************************************************
	App发送的应用数据 处理
*********************************************************/
int process_app_data_buf(B2B_SERIAL_DATA_STRUCT *sd,u16 dataBegin)
{
	u16 len = sd->iB2BDataLen;
	u16 i=0;
	u8 flag = false;
	
	for(i=dataBegin;i<len;i++)
	{
		flag = ProtocolCmdCheckByte(sd->sB2BData+i);
		//printf("%d",*sd->sB2BData+i);//test
		if(true == flag)
		{
			break;
		}
	}
	if(true == flag)
	{
		return flag;
	}
	flag = ProtocolCmdCheckByte(SerialTail);
	flag = ProtocolCmdCheckByte(SerialTail+1);

	return flag;
}


/*

发送到主控板F103R8指令：
	    第一字节  第二字节  第三字节 第四字节
轴1转动	   a	  2         1        7        (ASCII格式字符)     
轴2转动	   b	  2         1        7        (ASCII格式字符)                   
轴3转动	   c	  2         1        7        (ASCII格式字符)    
*/
void SendToMS(u8 *str)
{
	SendString_NewLine(str);
}

/***************************************************************
去掉字符串中特定结尾字符子串
***************************************************************/
u8 TailQutation[] = "\"";
u16 TailQutationLen = sizeof(TailQutation)-1;
u8 stripStrTail(u8 *buf,
				u16 *bufLen,
				u8 *tailBuf,
				u16 tailBufLen)
{
	u16 i=0,tailBufCnt = 0,tailBufCntStartPos = 0,bufLenTemp=*bufLen;

	for(i=0;i<bufLenTemp;i++)
	{
		if(*(buf+i) == *(tailBuf+tailBufCnt))
		{
			if(tailBufCnt == 0)
			{
				tailBufCntStartPos = i;
				//printf("tailBufCntStartPos:%d\n",tailBufCntStartPos);
			}
			tailBufCnt++;
			if(tailBufCnt == tailBufLen)
			{
				//printf("tailBufCnt == tailBufLen\n");
				*(buf+i) = 0x0;
				*bufLen = tailBufCntStartPos;
				break;
			}
			if(tailBufCnt >= tailBufLen)
			{
				//printf("tailBufCnt >= tailBufLen\n");
				tailBufCnt = 0;
			}
		}
	}
	if(*bufLen < bufLenTemp)
	{
		for(i=*bufLen;i<bufLenTemp;i++)
		{
			*(buf+i) = 0x0;
		}
	}
	return true;
}

#if ARCH_MODE == ESP8266_Station_Mode || ARCH_MODE == CC254x_Slave_Mode

#if PROTOCOL_DATA_SOURCE == PROTOCOL_DATA_SOURCE_UART
/*********************************************************
	wifi芯片响应的AT指令返回结果 处理
*********************************************************/
int process_wifi_data_buf(B2B_SERIAL_DATA_STRUCT *sd)
{
	u8 flag = false;
//	char tempstr[40];//test
	flag = COMWifiCmdCheckByte(sd->sB2BData, sd->iB2BDataLen);
	if(false == flag)
	{
		debug_print_wifi("COMWifiCmdCheckByte failed\n");
		return flag;
	}
	//--------------------------------
//	printf("wifi_status = %d\n",wifi_status);
//	snprintf(tempstr,sd->iB2BDataLen,"%s",sd->sB2BData);//test
//	print_wifi(tempstr);//test
	switch(wifi_status)
	{
#if ARCH_MODE == ESP8266_Station_Mode        
		//根据第几条匹配AT指令存储不同状态和wifi信息		
		case WIFI_STATUS_WIFI_DISCONNECT     : 
			//wifiApConnected_Flag = false;
			break;
		case WIFI_STATUS_WIFI_CONNECTED     : 
			wifiApConnected_Flag = true;
			break;
		case WIFI_STATUS_WIFI_GOT_IP        : 
			wifiApConnected_Flag = true;
			break;
		case WIFI_STATUS_WIFI_CONNECT_FAIL  : 
			break;
		case WIFI_STATUS_CWJAP_OK           : 
			wifiApConnected_Flag = true;
			break;
		case WIFI_STATUS_CWJAP_NO_AP        : 
			wifiApConnected_Flag = false;
			break;
		case WIFI_STATUS_CIFSR_APIP         : 
			stripWifiValidStr(sd,wifi_status,wifi_info.APIP,&(wifi_info.APIP_LEN));
			stripStrTail(wifi_info.APIP,&(wifi_info.APIP_LEN),TailQutation,TailQutationLen);
			//printf("got APIP:%s len=%d %d\n",
			//			wifi_info.APIP,sd->iB2BDataLen,wifi_info.APIP_LEN);
			break;
		case WIFI_STATUS_CIFSR_APMAC        : 
			stripWifiValidStr(sd,wifi_status,wifi_info.APMAC,&(wifi_info.APMAC_LEN));
			stripStrTail(wifi_info.APMAC,&(wifi_info.APMAC_LEN),TailQutation,TailQutationLen);
			//printf("got APMAC:%s len=%d %d\n",
			//			wifi_info.APMAC,sd->iB2BDataLen,wifi_info.APMAC_LEN);
			break;
		case WIFI_STATUS_CIFSR_STAIP        :
			stripWifiValidStr(sd,wifi_status,wifi_info.STAIP,&(wifi_info.STAIP_LEN));
			stripStrTail(wifi_info.STAIP,&(wifi_info.STAIP_LEN),TailQutation,TailQutationLen);
			//printf("got STAIP:%s len=%d %d\n",
			//			wifi_info.STAIP,sd->iB2BDataLen,wifi_info.STAIP_LEN);
			break;
		case WIFI_STATUS_CIFSR_STAMAC       : 
			stripWifiValidStr(sd,wifi_status,wifi_info.STAMAC,&(wifi_info.STAMAC_LEN));
			stripStrTail(wifi_info.STAMAC,&(wifi_info.STAMAC_LEN),TailQutation,TailQutationLen);
			//printf("got STAMAC:%s len=%d %d\n",
			//			wifi_info.STAMAC,sd->iB2BDataLen,wifi_info.STAMAC_LEN);
			break;
		case WIFI_STATUS_TCUDP_CONNECT      :
			udpClientLink1Connected_Flag = true;
			break;
		case WIFI_STATUS_TCUDP_ARD_CONNECTED: 
			udpClientLink1Connected_Flag = true;
			break;
		case WIFI_STATUS_TCUDP_LINKED       :
			udpClientLink1Connected_Flag = true;
			break;
		case WIFI_STATUS_TCUDP_LINK_TYP_ERR : break;
		case WIFI_STATUS_CIP_SEND_IP_ERR    : break;
		case WIFI_STATUS_CON_CLOSED         : break;
#endif
		case WIFI_STATUS_MSF103C8_CMD       : break;
		case WIFI_STATUS_MSF103R8_CMD       : 
#if ARCH_MODE == CC254x_Slave_Mode
			stripWifiValidStr(sd,wifi_status,F103R8_CMD.MSXX_CMD,&(F103R8_CMD.MSXX_CMD_Len));
			process_MSF103R8_CMD(sd->com, &F103R8_CMD);
#endif
			break;
		case WIFI_STATUS_READY       		: 
			wifiResetReady_Flag = true;
			break;
		
		default:wifi_status = WIFI_STATUS_MIN; break;
	}
	//wifi_status = lineAllMatchCnt;
	return true;
}

/**********************************************************
  通过wifi串口 App发送的应用数据 字符串协议解析程序
**********************************************************/
uint8_t COMWifiCmdCheckByte(u8 *cdata, u16 len)
{
	uint16_t i=0,j=0;
	u8 lineAllMatch_Flag = false;
	u16 WifiATRespKeyWordRowLen = sizeof(WifiATRespKeyWord);
	
	//u8 RxTemp = *cdata;
	if(len > 1)
	{
		lineAllMatchCnt = 0;
		for(i=0;i<WifiATRespKeyWordRowLen;i++)
		{
			lineAllMatch_Flag = true;
			for(j=0;j<WifiATRespKeyWordColLen;j++)
			{
				if(0x0 == WifiATRespKeyWord[i][j])//exceed max len of WifiATRespKeyWord
				{
					break;
				}
				if(j >= len)//exceed max len of receved cdata
				{
					break;
				}
				
				if(*(cdata+j) != WifiATRespKeyWord[i][j])
				{
					lineAllMatch_Flag = false;
					break;
				}
			}
			if(true == lineAllMatch_Flag)
			{
				break;
			}
			lineAllMatchCnt++;
		}		
	}
	if(true == lineAllMatch_Flag)
	{
		switch(lineAllMatchCnt)
		{
			//根据第几条匹配AT指令存储不同状态和wifi信息
#if ARCH_MODE == ESP8266_Station_Mode        
			case WIFI_STATUS_WIFI_DISCONNECT    :wifi_status = WIFI_STATUS_WIFI_DISCONNECT     ; break;
			case WIFI_STATUS_WIFI_CONNECTED     :wifi_status = WIFI_STATUS_WIFI_CONNECTED     ; break;
			case WIFI_STATUS_WIFI_GOT_IP        :wifi_status = WIFI_STATUS_WIFI_GOT_IP        ; break;
			case WIFI_STATUS_WIFI_CONNECT_FAIL  :wifi_status = WIFI_STATUS_WIFI_CONNECT_FAIL  ; break;
			case WIFI_STATUS_CWJAP_OK           :wifi_status = WIFI_STATUS_CWJAP_OK           ; break;
			case WIFI_STATUS_CWJAP_NO_AP        :wifi_status = WIFI_STATUS_CWJAP_NO_AP        ; break;
			case WIFI_STATUS_CIFSR_APIP         :wifi_status = WIFI_STATUS_CIFSR_APIP         ; break;
			case WIFI_STATUS_CIFSR_APMAC        :wifi_status = WIFI_STATUS_CIFSR_APMAC        ; break;
			case WIFI_STATUS_CIFSR_STAIP        :wifi_status = WIFI_STATUS_CIFSR_STAIP        ; break;
			case WIFI_STATUS_CIFSR_STAMAC       :wifi_status = WIFI_STATUS_CIFSR_STAMAC       ; break;
			case WIFI_STATUS_TCUDP_CONNECT      :wifi_status = WIFI_STATUS_TCUDP_CONNECT      ; break;
			case WIFI_STATUS_TCUDP_ARD_CONNECTED:wifi_status = WIFI_STATUS_TCUDP_ARD_CONNECTED; break;
			case WIFI_STATUS_TCUDP_LINKED       :wifi_status = WIFI_STATUS_TCUDP_LINKED       ; break;
			case WIFI_STATUS_TCUDP_LINK_TYP_ERR :wifi_status = WIFI_STATUS_TCUDP_LINK_TYP_ERR ; break;
			case WIFI_STATUS_CIP_SEND_IP_ERR    :wifi_status = WIFI_STATUS_CIP_SEND_IP_ERR    ; break;
			case WIFI_STATUS_CON_CLOSED         :wifi_status = WIFI_STATUS_CON_CLOSED         ; break;
#endif
			case WIFI_STATUS_MSF103C8_CMD       :wifi_status = WIFI_STATUS_MSF103C8_CMD       ; break;
			case WIFI_STATUS_MSF103R8_CMD       :wifi_status = WIFI_STATUS_MSF103R8_CMD       ; break;
			case WIFI_STATUS_READY       		:wifi_status = WIFI_STATUS_READY			  ; break;

			default:wifi_status = WIFI_STATUS_MIN; break;
		}
		//wifi_status = lineAllMatchCnt;
	}
	return lineAllMatch_Flag;
}
#endif

#endif

/*********************************************************/
/*********************************************************/
DATA_RECEIVE_VIA_NET_STRUCT ledRollQueue,ledShinePort,ledShinePin;

void InitRollQueue(DATA_RECEIVE_VIA_NET_STRUCT *dataStruct)
{
	u16 i=0;
	for(i=0;i<sRollQueueMax;i++)
	{
		dataStruct->sRollQueue[i] = 0x0;
	}
#if ARCH_MODE == ESP8266_Station_Mode
	for(i=0;i<sAddrOfAppMax;i++)
	{
		dataStruct->sAddrOfApp[i] = 0x0;
	}
#endif
	dataStruct->cRollQueueHead = 0x0;
	dataStruct->cRollQueueTail = 0x0;
}

void ClearRollQueue(DATA_RECEIVE_VIA_NET_STRUCT *dataStruct)
{
	dataStruct->cRollQueueHead = 0x0;
	dataStruct->cRollQueueTail = 0x0;
}

u16 GetRollQueueLen(DATA_RECEIVE_VIA_NET_STRUCT *dataStruct)
{
	u16 len = 0;
	if(dataStruct->cRollQueueHead > dataStruct->cRollQueueTail)
	{
		len = dataStruct->cRollQueueHead - dataStruct->cRollQueueTail;
	}
	else if(dataStruct->cRollQueueHead < dataStruct->cRollQueueTail)
	{
		len = sRollQueueMax - dataStruct->cRollQueueTail + dataStruct->cRollQueueHead;
	}
	return len;
}

u8 PutRollQueue(DATA_RECEIVE_VIA_NET_STRUCT *dataStruct, u8 *str, u8 strLen)
{
	u16 i=0;
	for(i=0;i<strLen;i++)
	{
		dataStruct->sRollQueue[dataStruct->cRollQueueTail] = *(str+i);
		dataStruct->cRollQueueTail++;
		if(dataStruct->cRollQueueTail >= sRollQueueMax)
		{
			dataStruct->cRollQueueTail = 0;
		}
		if(dataStruct->cRollQueueTail == dataStruct->cRollQueueHead)
		{
			dataStruct->cRollQueueHead++;
			if(dataStruct->cRollQueueHead >= sRollQueueMax)
			{
				dataStruct->cRollQueueHead = 0;
			}
		}
	}
	return true;
}

u8 GetRollQueue(DATA_RECEIVE_VIA_NET_STRUCT *dataStruct, u8 *chr)
{
	if(dataStruct->cRollQueueTail == dataStruct->cRollQueueHead)
	{
		return false;
	}
	else
	{
		*chr = dataStruct->sRollQueue[dataStruct->cRollQueueHead];
		dataStruct->cRollQueueHead++;
	}
	
	if(dataStruct->cRollQueueHead >= sRollQueueMax)
	{
		dataStruct->cRollQueueHead = 0;
	}
	return true;
}


/**********************************************************
**********************************************************/

//初始化队列
void InitRollDetQue(ROLL_DETECT_QUEUE_STRUCT *dataS)
{
	u16 i=0;
	for(i=0;i<ROLL_DETECT_ITEM_MAX;i++)
	{
		dataS->roll[i].time = 0x0;
		dataS->roll[i].side = 0x0;
		dataS->roll[i].angle = 0x0;
	}

	dataS->head = 0x0;
	dataS->tail = 0x0;
}

//获取队列长度
u16 GetRollDetQueLen(ROLL_DETECT_QUEUE_STRUCT *dataS)
{
	u16 len = 0;
	if(dataS->tail > dataS->head)
	{
		len = dataS->tail - dataS->head;
	}
	else if(dataS->head > dataS->tail)
	{
		len = ROLL_DETECT_ITEM_MAX - dataS->head + dataS->tail;
	}
	return len;
}

//写入一个数据到队列
u8 PutRollDetQue(ROLL_DETECT_QUEUE_STRUCT *dataS, u32 *time, u8 *side, u16 *angle, u8 dataLen)
{
	u16 i=0;
	for(i=0;i<dataLen;i++)
	{
		dataS->roll[dataS->tail].time = *(time+i);
		dataS->roll[dataS->tail].side = *(side+i);
		dataS->roll[dataS->tail].angle = *(angle+i);
		dataS->tail++;
		if(dataS->tail >= ROLL_DETECT_ITEM_MAX)
		{
			dataS->tail = 0;
		}
		if(dataS->tail == dataS->head)
		{
			dataS->head++;
			if(dataS->head >= ROLL_DETECT_ITEM_MAX)
			{
				dataS->head = 0;
			}
		}
	}
	return true;
}

//获取队列中队首一个成员，改变读head
u8 GetRollDetQue(ROLL_DETECT_QUEUE_STRUCT *dataS, u32 *time, u8 *side, u16 *angle)
{

	return true;
}

//获取队列中所有成员，不改变读head
u8 GetRollDetQueAll(ROLL_DETECT_QUEUE_STRUCT *dataS, u32 *time, u8 *side, u16 *angle, u16 *dataLen)
{

	
	return true;
}

/**********************************************************
**********************************************************/
char bKeepZero_Flag = false;
u8 RxTemp = 0x0;
/**********************************************************
	App发送的应用数据 字符串协议解析程序
**********************************************************/
uint8_t ProtocolCmdCheckByte(u8 *cdata)
{
	//uint16_t i=0;
	u8 flag = false;
	RxTemp = *cdata;
	if(0x0 == RxTemp)
	{
		bKeepZero_Flag = true;				
	}
	else
	{
		if(false == bKeepZero_Flag)
		{
			flag = parsebyte(&RxTemp);
		}
		else //0x0 + ordinary byte
		{
			parsebyte(0x0);
			flag = parsebyte(&RxTemp);
			bKeepZero_Flag = false;
		}
	}
	return flag;
}

const u8 rotationSteps[] = "RuFfUrdLbBlDRuFfUrdLbBlD";
void test_send_rotation_steps(void)
{
	u16 i = 0;
	
	for(i = 0; i < strlen((char *)rotationSteps); i++)
	{
		RfSend(43, (char *)&rotationSteps[i], 1);
	}
}
/*
static uint32_t send_min_max_conn_interval(void)
{
    uint32_t                err_code;
    ble_gap_conn_params_t   gap_conn_params;
	
    memset(&gap_conn_params, 0, sizeof(gap_conn_params));

    err_code = sd_ble_gap_ppcp_get(&gap_conn_params);
    APP_ERROR_CHECK(err_code);
	
	sprintf((char *)debug_str, "conn min=%d max=%d", gap_conn_params.min_conn_interval, gap_conn_params.max_conn_interval);
	RfSend(13,(char *)debug_str,getStrLen((char *)debug_str));
	
	return err_code;
}*/

/**********************************************************
  wifi串口收到的命令执行
**********************************************************/
int parse_cmd_from_app(void)
{
#if ARCH_MODE == ESP8266_Station_Mode
	u16 i = 0;
#elif ARCH_MODE == NRF52832_Slave_Mode || ARCH_MODE == NRF51802_Peripheral_Mode
//	u32 general_u32_number = 0;
#endif
	uint16_t dataLen = 0;
	uint16_t iCmdCodeTmp = 0;
	u8 *data = NULL;
	u8 rtn = true;
	char sDataBuf[36] = {0x00};
    if(dataLen){}
	iCmdCodeTmp = netData.cCmdCode;
	data = netData.sDataBuf;
#if ARCH_MODE == NRF52832_Slave_Mode || ARCH_MODE == NRF51802_Peripheral_Mode
	dataLen = netData.iDataLenMax;
#endif
	
	if(true == DEBUG_FLAG)
	{
		debug_print_wifi(data);
	}
	
	switch(iCmdCodeTmp)
	{
#if ARCH_MODE == ESP8266_Station_Mode
		case 110:	//发送本身IP地址
			if(('W' == *data)&&('h' == *(data+1))&&('o' == *(data+2)))
			{
				debug_print_wifi(data);
				delay_ms(30);
				RfSend(10,(char *)wifi_info.STAIP,wifi_info.STAIP_LEN);
			}
			break;
		case 111:	//获取到app的IP地址
			for(i=0;i<dataLen;i++)
			{
				ledRollQueue.sAddrOfApp[i] = *data;
				data++;
			}
			break;
#endif	
		case 112:	//say Hi
			sprintf(sDataBuf, "Hi,I am ECube!");
			RfSend(12,sDataBuf,getStrLen(sDataBuf));
			break;

			
		default:
			rtn = false;
			break;
	}
	wireless_connected_Flag = true;
	
	return rtn;
}	

/*********************************************end of file*********************************************/
