/****************************************************************************************************
* created by sunpeng 2017 all rights reserved!
****************************************************************************************************/
#include "stdarg.h"
#include "include.h"
#include "wireless.h"
#include "apptocube.h"
#include "rotation.h"

//------------------------------------------------
const u8 Num_Tab[]="0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ";
u8 debug_str[64] = "";				//public debug printf string temp

//------------------------------------------------

#if ARCH_MODE == ESP8266_Station_Mode
s8 wifiResetReady_Flag = false;
s8 wifiApConnected_Flag = false;  			//wifi Ap 连接成功标志
u8 wifiConnectWaitDelayCnt = 0;
s8 udpClientLink1Connected_Flag = false; 	//udp Client 链接1 链接udpServer成功
u8 udpClientLink1ConnectedWaitDelayCnt = 0;
#endif

s8 wireless_connected_Flag = false;			//无线连接成功标志 true=已连接  false=断开
/* Public macro -------------------------------------------------------------*/
u16 iTimCntLedShineIntervalCnt = 0;       	//Led闪烁时间间隙计数

/* Public variables ---------------------------------------------------------*/
	
s8 RF_RecEN_Flag = false;		 			//无线定时接收中断使能标志位
s8 RevCmd_Flag = 0;	
s8 RevCmdHandle_Flag = 0;

#if PROTOCOL_DATA_SOURCE == PROTOCOL_DATA_SOURCE_UART
s8 COMAppCmdCheckByte_Flag = true; 			//串口字符串协议解析程序 标志位
#endif

#if ARCH_MODE == ESP8266_Station_Mode || ARCH_MODE == CC254x_Slave_Mode
int lineAllMatchCnt = WIFI_STATUS_MIN;  	//当前匹配第几条AT返回关键字符串
#endif

/* Private variables ---------------------------------------------------------*/
uint8_t WorkModeCount = 0;
uint8_t WorkMode = 0;	   					//  0--offline  1--online


s8 rotation_upload_en_Flag = false;  		//使能 上传 转动数据
s8 cell_res_data_upload_en_Flag = false;	//使能 上传 颜色电阻传感器

#if MOTION_SENSOR_TYPE != MOTION_SENSOR_TYPE_NONE
s8 angle_3x_upload_en_Flag = false;  		//使能 上传 三轴角度数据
s8 motion_sensor_inited_Flag = false;		//运动传感器已经初始化成功
u16 angle_3x_detect_Cnt = 0;
s8 angle_3x_detect_Flag = false;

float pitch, roll, yaw=0.0;  				//三轴角度数据
#endif

NET_DATA_STRUCT netData;
const u8 ADC_CHAN_SIGN[] = "RFULBD"; 		// BRULFD --2017-9-14 BLUFRD --2016-10-11
const u8 ADC_CHAN_SIGN_BL[] = "URDLFBurdlfb";
const u8 ALL_COLOR_SIGN[] = "RBYOGW"; 		//所有面颜色符号
//-------------------------------------------
s8 isLedTeachQueueDoing = false; 			//led转动面自动提示进行中标志

s8 DEBUG_FLAG = false;  					//全局调试模式 标志
s8 mpu_init_Flag = false; 					//mpu三轴是否初始化成功

s8 APServerCubeDebugMailAdd_Flag = false; 	//AP Server CubeDebug无线调试 回复抄送标志

/********************************************************************************************/
STATUS_CTL_STRUCT isLedTeachQueueDoingStatus;					//离线教学提示定时计数
s8 LedTeachQueueEnable_Flag = false; 							//使能离线模式 固定步骤教学提示 ,并清空之前所有Led提示队列

STATUS_CTL_STRUCT DispatchSetRotationUploadFreq,DispatchSetColorUploadFreq;  //上传频率控制
STATUS_CTL_STRUCT chargeDoingLedShineTimeout;   	//充电中提示灯自动超时关闭
STATUS_CTL_STRUCT chargeFinishedLedShineTimeout;  	//充电满提示灯自动超时关闭

STATUS_CTL_STRUCT chargeDoingLedShineInterval;   	//充电中提示灯间隔时间
STATUS_CTL_STRUCT chargeFinishedLedShineInterval;   //充电满提示灯间隔时间

s8 chargeStatusDisplay_EN_Flag = true;				//充电状态led提示 总使能开关

STATUS_CTL_STRUCT isAllowSystemOff;					//是否允许进入系统关闭状态定时器
STATUS_CTL_STRUCT chargeDonnotAllowSystemOffInterval;	//充电过程中不允许关机设置时间间隔
STATUS_CTL_STRUCT disallowShutdownAfterBootTimeout;	//开机后禁止关机时间

#if MOTION_SENSOR_TYPE != MOTION_SENSOR_TYPE_NONE
STATUS_CTL_STRUCT motionSensorReadInterval;			//运动传感器读取周期
STATUS_CTL_STRUCT motionSensorUploadInterval;		//运动传感器上传周期
#endif


#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
STATUS_CTL_STRUCT setSpeakerVoiceLower;				//设置扬声器声音小于30%触发标志
#endif

s8 isAllowSystemOff_EN_Flag = false;				//是否允许进入系统关闭状态标志

s8 allowChargingLedShining_EN_Flag = false;			//允许充电闪烁灯闪烁

/********************************************************************************************/
void setVariablseAtBoot(void)
{
	DEBUG_FLAG = false;
	RF_RecEN_Flag = true;
#if MOTION_SENSOR_TYPE != MOTION_SENSOR_TYPE_NONE
	angle_3x_detect_Flag = false;
	angle_3x_upload_en_Flag = false;  		//true for test :  false is offset
#endif
	rotation_upload_en_Flag = true; 		//true for test :  false is offset
	cell_res_data_upload_en_Flag = false;
	
	init_STATUS_CTL_STRUCT(&isLedTeachQueueDoingStatus,false,true,0,3);
	init_STATUS_CTL_STRUCT(&DispatchSetRotationUploadFreq,false,true,'#',3);
	init_STATUS_CTL_STRUCT(&DispatchSetColorUploadFreq,false,true,'#',3);
	init_STATUS_CTL_STRUCT(&chargeDoingLedShineTimeout,false,true,0,chargeDoingLedShineTimeout_Max);				//充电中led提示超时40s
	init_STATUS_CTL_STRUCT(&chargeFinishedLedShineTimeout,false,true,0,chargeFinishedLedShineTimeout_Max);		//充电满led提示超时20s
	init_STATUS_CTL_STRUCT(&chargeDoingLedShineInterval,false,true,0,12);		//充电中led闪烁间隔  n*100ms
	init_STATUS_CTL_STRUCT(&chargeFinishedLedShineInterval,false,true,0,22);		//充电满led闪烁间隔  n*100ms
	
#if MOTION_SENSOR_TYPE != MOTION_SENSOR_TYPE_NONE
	init_STATUS_CTL_STRUCT(&motionSensorReadInterval,false,true,0,5);		//运动传感器读取周期  n*10ms
	init_STATUS_CTL_STRUCT(&motionSensorUploadInterval,false,true,0,30);		//运动传感器上传周期  n*10ms
#endif
	
	init_STATUS_CTL_STRUCT(&isAllowSystemOff,false,true,0,SHUTDOWN_TIMEOUT_IN_SECONDS/4);					//n*4s 无动作，进入关机状态
	init_STATUS_CTL_STRUCT(&chargeDonnotAllowSystemOffInterval,false,true,0,27);	//n*50ms 充电过程中不允许关机设置时间间隔
	init_STATUS_CTL_STRUCT(&disallowShutdownAfterBootTimeout,false,false,0,2);		//开机后一段时间内禁止关机 n*4s
	
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
	init_STATUS_CTL_STRUCT(&setSpeakerVoiceLower,false,false,0,1);		//设置扬声器声音小于30%触发标志 初始化 一次触发
#endif	
	chargeStatusDisplay_EN_Flag = true; 	//false for test:   true is offset
	
	//--------------------------------------------------------
	set_all_com_recv_heads();
	initWifiInfo_data();
	sd1.com = COM1;
	initSerialData(&sd1); //init com1 b2b detect data struct
	initBesidePins();
	initAnglePer360Tab();
	initDetectVariable();  //检测转动12根管脚初始化指针
#if ARCH_MODE == CC254X_Peripheral_Mode
	initsAllColorBuf();
#elif ARCH_MODE == NRF51822_Peripheral_Mode
#elif ARCH_MODE == NRF51802_Peripheral_Mode
#else
	InitRollQueue(&ledShinePort);
	InitRollQueue(&ledShinePin);
	InitRollQueue(&ledRollQueue);
#endif
}

/********************************************************************************************/
u8 init_STATUS_CTL_STRUCT(	STATUS_CTL_STRUCT *statusControl, 		//周期存储变量
								char flag, 							//周期到达标志初始值
								char isAllowPeriodTrigFlag,			//周期重复触发标志
								unsigned int cnt, 					//周期计数
								unsigned int cntMax					//周期计数上限
									)
{
	statusControl->flag = flag;
	statusControl->isAllowPeriodTrigFlag = isAllowPeriodTrigFlag;
	statusControl->isTrigedOnceFlag = false;
	statusControl->cnt = cnt;
	statusControl->cntMax = cntMax;
	return true;
}

void clear_cnt_STATUS_CTL_STRUCT(	STATUS_CTL_STRUCT *statusControl)
{
	statusControl->cnt = 0;
}

u8 add_STATUS_CTL_STRUCT(	STATUS_CTL_STRUCT *statusControl)
{
	//单次模式触发过一次后直接跳过计数
	if(true == statusControl->isTrigedOnceFlag)
	{
		return false;
	}
	
	statusControl->cnt++;
	if(statusControl->cnt >= statusControl->cntMax)
	{
		if(false == statusControl->isAllowPeriodTrigFlag)
		{
			statusControl->isTrigedOnceFlag = true;
		}
		statusControl->cnt = 0;
		statusControl->flag = true;
		return true;
	}
	return false;
}

/**************************** functions *******************************/
u8 init_StrBuf(u8 *buf, u16 len)
{
	u16 i=0;
	for(i=0;i<len;i++)
	{
		*buf = 0x0;
		buf++;
	}
	return true;
}

//小写ASCII英文字符转大些
u8 charToUpper(u8 *chr)
{
	if((*chr <= 'z')&&(*chr >= 'a'))
	{
		return (*chr - 32);
	}
	else
	{
		return *chr;
	}
}

//翻转char 字符 0变1 1变0
u8 toggleChar(u8 chr)
{
	//翻转写入标志
	if(1 == chr)
	{
		return 0;
	}
	else
	{
		return 1;
	}
}

//minus_abs_u16_u16  两个u16数相减后取绝对值
u16 minus_abs_u16_u16(u16 a, u16 b)
{
	u16 rtn = 0;
	if(a > b)
	{
		rtn = a-b;
	}
	else
	{
		rtn = b-a;
	}
	return rtn;
}

static unsigned long m_pow(int x, int y)
{
	unsigned long sum = 1;
	while(y--)
	{
		sum *= x;
	}
	return sum;
}

//打印字符
void m_putchar(const char ch)
{
	print_wifi((u8 *)&ch);
}

//打印字符串
void m_putstr(const char *str)
{
	print_wifi((u8 *)str);
}

//实现类似printf功能
int m_printf(const char *str,...)
{
	va_list ap;  //定义一个可变参数的（字符指针）
	int val,r_val;
	char count,ch;
	char *s = NULL;
	int res = 0;
	
	va_start(ap, str);	//init ap
	while('\0' != *str)
	{
		switch(*str)
		{
			case '%':
				str++;
				switch(*str)
				{
					case 'd':
						val = va_arg(ap, int);
						r_val = val;
						count = 0;
						while(r_val)
						{
							count++;
							r_val /= 10;
						}
						res += count;
						r_val = val;
						while(count)
						{
							ch = r_val / m_pow(10, count - 1);
							r_val %= m_pow(10, count - 1);
							m_putchar(ch + '0');
							count--;
						}
						break;
					case 'x':
						val = va_arg(ap, int);
						r_val = val;
						count = 0;
						while(r_val)
						{
							count++;
							r_val /= 16;
							
						}
						res += count;
						r_val = val;
						while(count)
						{
							ch = r_val / m_pow(16, count - 1);
							r_val %= m_pow(16, count - 1);
							if(ch <= 9)
							{
								m_putchar(ch + '0');
							}
							else
							{
								m_putchar(ch - 10 + 'a');
							}
							count--;
						}
						break;
					case 's':
						s = va_arg(ap, char *);
						m_putstr(s);
						res += strlen(s);
						break;
					case 'c':
						m_putchar((char)va_arg(ap, int));
						res += 1;
						break;
					default:
						;
					
				}
				break;
			case '\n':
				m_putchar('\n');
				res += 1;
				break;
			case '\r':
				m_putchar('\r');
				res += 1;
				break;
			default:
				m_putchar(*str);
				res += 1;
		}
		str++;
	}
	va_end(ap);
		
	return res;	
}

s32 formatAngle360(s32 angle)
{
	if(angle >= 0)
	{
		return (angle % 360);
	}
	else
	{
		return (360 + angle);
	}
}

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


