/*Includes ----------------------------------------------*/
#include "system.h"
#include "exception.h"
#include "app_charge.h"
#include "app_flash.h"
#include "app_self_checking.h"
#include "hal_led.h"
#include "hal_mt.h"
#include "hal_ble_uart0.h"
#include "hal_ble_client.h"
#include "hal_ser_imu_mode_manage.h"
#include "app_flash.h"
#include "app_pair.h"
#include "bsp_time.h"
#include "hal_scan_manage.h"
#include "ble_comm.h"

/*Private macro ------------------------------------------------*/
#define	SELF_CHECK_WHEEL_EMPTY_TIMES_MAX		MONITOR_SUSPEND_MODE_OVERFLOW_ERR_SUM_MAX			//允许最大轮空次数
#define SELF_CHECK_ITEMS										6																							//自检项数
#define SELF_CHECK_ITEM_SUCCESS							0																							//自检项目成功
#define SELF_CHECK_ITEM_FAIL								1																							//自检项目失败

#define SELF_CHECK_ITEM_FRONT_SENSOR_INDEX	0																							//自检项目 - 前脚传感器
#define SELF_CHECK_ITEM_BACK_SENSOR_INDEX		1																							//自检项目 - 后脚传感器
#define SELF_CHECK_ITEM_BATTERY_INDEX				2																							//自检项目 - 电量
#define	SELF_CHECK_ITEM_CHARGE_INDEX				3																							//自检项目 - 充电电压
#define SELF_CHECK_ITEM_ANT_INDEX						4																							//自检项目 - 天线
#define SELF_CHECK_ITEM_SUSPEND_MODE_INDEX	5																							//自检项目 - 异常挂起			

#define SELF_CHECK_PROCESS_CYCLE						10																						//自检线程周期 - ms为单位

#define SELF_CHECK_LED_DISPLAY_TIME					3000					  //自检灯显示时长 - ms为单位

#define SELF_CHECK_LED_TOGGLE_TIME					200						  //自检灯翻转时长 - ms为单位

#define SELF_CHECK_SCAN_TRIGGER_TIMEOUT			10000						//扫描触发自检超时时间 - ms为单位

#define SELF_CHECK_SET_IMU_TIMEOUT			    20000						//等待IMU初始化成功的时间

#define SELF_CHECK_SCAN_TARGET_ADV_NAME			"SH_SELF_CHECK"																//扫描触发的目标广播名字

/*STRUCTION --------------------------------------------------
--*/
typedef enum {
	SELF_CHECK_STAGE_READY,																																	//准备阶段
	SELF_CHECK_STAGE_CHECK,																																	//自检阶段
	
} SELF_CHECK_STAGE_e;
typedef enum{
	SELF_CHECK_LED_ON,																																			//自检灯 - 开
	SELF_CHECK_LED_OFF,																																			//自检灯 - 关
	
} SELF_CHECK_LED_SWITCH_e;
typedef struct self_check
{
	/*private member*/
	SELF_CHECK_STAGE_e				stage;																												//阶段字段
	
	uint32_t								  ImuSetTime_times;																						  //轮空次数
	
	uint8_t										result[SELF_CHECK_ITEMS];																			//自检结果
	
	uint8_t										item_fail_num;																								//自检项目失败数量
	
	SELF_CHECK_LED_SWITCH_e		led_switch;																										//自检灯开关

	uint32_t									led_display_time;																							//自检灯显示时长
	
	uint32_t									led_toggle_time;																							//自检灯翻转时长
	
	uint32_t									scan_trigger_timeout;																					//扫描触发自检超时时间
	
	bool											is_scan_success;																							//是否找到广播名字

} Self_Check_t;

/*Local Variable -----------------------------------------------*/
static Self_Check_t ob_self_check;

/*Local Functions ----------------------------------------------*/
static void clear_all_except(void)
{
	Except_ClearExceptype(EXCEPT_DATA_BACK_MAG);
	Except_ClearExceptype(EXCEPT_DATA_FRONT_ACC);
	Except_ClearExceptype(EXCEPT_DATA_FRONT_GRY);
	Except_ClearExceptype(EXCEPT_DATA_FRONT_MAG);
	Except_ClearExceptype(EXCEPT_DATA_CHARGE);
	Except_ClearExceptype(EXCEPT_DATA_BATTERY);
	Except_ClearExceptype(EXCEPT_IMU_SUSPEND_OVERFLOW);
	Except_ClearExceptype(EXCEPT_ANT_DAMAGE);
}

static void selft_scan_cb(void)
{
	ob_self_check.is_scan_success = true;
}

static scan_reslt_t scan_reslt_handle ={
	.handle = selft_scan_cb,
	.scanname =SELF_CHECK_SCAN_TARGET_ADV_NAME,
};

static uint8_t self_uart_check_flag =0;
static void cb_UART0_R_LINE_CHECK_ACK(void* handle)
{	
	//主机接收到配对应答
	if(!mFlash.isHost) return; //从机自发自收
	self_uart_check_flag = 1;
}

static void cb_UART0_R_LINE_CHECK_ASK(void* handle)
{	//从机接收到配对申请
  uint32_t 		txd,rxd;
	if(mFlash.isHost){
		return; //防止主机自发自收
	}
	self_uart_check_flag =1;
	
	UART0_GetPinConfig(&txd, &rxd);
	UART0_Initialize(PIN_TXD_BLE,UART0_INVALID_PIN,UART_HZ);
	UART0_Config_Send(UART0_T_LINE_CHECK_ACK);//应答主机申请
	if(rxd == 0 && txd == 0){txd = UART0_INVALID_PIN;rxd = PIN_RXD_BLE;}
	UART0_Initialize(txd,rxd,UART_HZ);
}


static void app_UartLine_Pair_Process(){
	  static uint8_t state =0;
	  uint32_t 		txd,rxd;
	  switch(state){
			case 0:
				    if(true == ob_self_check.is_scan_success){
							 state =1;
							 self_uart_check_flag =0;
						}
				    break;
			case 1:
				    if(mFlash.isHost){
							UART0_GetPinConfig(&txd, &rxd);
							UART0_Initialize(PIN_TXD_BLE,UART0_INVALID_PIN,UART_HZ);
							UART0_Config_Send(UART0_T_LINE_CHECK_ASK);
							if(rxd == 0 && txd == 0){txd = UART0_INVALID_PIN;rxd = PIN_RXD_BLE;}
							UART0_Initialize(txd,rxd,UART_HZ);
					  } 
			      if(false == ob_self_check.is_scan_success){
							  state = 0;						
						}
				    break;
			default:
				    break;
		}
}


static void app_self_check_getreslut(){
		/*获取自检结果前---------------------------------------------------------------------*/
		ob_self_check.result[SELF_CHECK_ITEM_FRONT_SENSOR_INDEX] = SELF_CHECK_ITEM_SUCCESS;
		ob_self_check.result[SELF_CHECK_ITEM_BACK_SENSOR_INDEX] = SELF_CHECK_ITEM_SUCCESS;
		ob_self_check.result[SELF_CHECK_ITEM_BATTERY_INDEX] = SELF_CHECK_ITEM_SUCCESS;
		ob_self_check.result[SELF_CHECK_ITEM_CHARGE_INDEX] = SELF_CHECK_ITEM_SUCCESS;
		ob_self_check.result[SELF_CHECK_ITEM_ANT_INDEX] = SELF_CHECK_ITEM_SUCCESS;
		ob_self_check.result[SELF_CHECK_ITEM_SUSPEND_MODE_INDEX] = SELF_CHECK_ITEM_SUCCESS;						
		ob_self_check.item_fail_num = 0;

		/*获取自检结果中---------------------------------------------------------------------*/
		
		//自检结果 - 异常挂起
		if(Except_IsError(EXCEPT_IMU_SUSPEND_OVERFLOW)){ob_self_check.result[SELF_CHECK_ITEM_SUSPEND_MODE_INDEX] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_SUSPEND_MODE_INDEX + 1;}	
		//自检结果 - 前脚传感器
		if(Except_IsError(EXCEPT_DATA_FRONT_ACC)){ob_self_check.result[SELF_CHECK_ITEM_FRONT_SENSOR_INDEX] = SELF_CHECK_ITEM_FAIL;}
		if(Except_IsError(EXCEPT_DATA_FRONT_GRY)){ob_self_check.result[SELF_CHECK_ITEM_FRONT_SENSOR_INDEX] = SELF_CHECK_ITEM_FAIL;}
		if(Except_IsError(EXCEPT_DATA_FRONT_MAG)){ob_self_check.result[SELF_CHECK_ITEM_FRONT_SENSOR_INDEX] = SELF_CHECK_ITEM_FAIL;}
		if(Except_IsError(EXCEPT_DATA_FRONT_ACC) || Except_IsError(EXCEPT_DATA_FRONT_GRY) || Except_IsError(EXCEPT_DATA_FRONT_MAG)){ob_self_check.item_fail_num = SELF_CHECK_ITEM_FRONT_SENSOR_INDEX + 1;}
		//自检结果 - 后脚传感器
		if(Except_IsError(EXCEPT_DATA_BACK_MAG)){ob_self_check.result[SELF_CHECK_ITEM_BACK_SENSOR_INDEX] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_BACK_SENSOR_INDEX + 1;}
		//自检结果 - 电量
		if(Except_IsError(EXCEPT_DATA_BATTERY)){ob_self_check.result[SELF_CHECK_ITEM_BATTERY_INDEX] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_BATTERY_INDEX + 1;}
		//自检结果 - 充电电压
		if(Except_IsError(EXCEPT_DATA_CHARGE)){ob_self_check.result[SELF_CHECK_ITEM_CHARGE_INDEX] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_CHARGE_INDEX + 1;}
		//自检结果 - 天线
		if(Except_IsError(EXCEPT_ANT_DAMAGE)){ob_self_check.result[SELF_CHECK_ITEM_ANT_INDEX] = SELF_CHECK_ITEM_FAIL;ob_self_check.item_fail_num = SELF_CHECK_ITEM_ANT_INDEX + 1;}					
		
		//设置自检灯显示时长和翻转时长
		if(ob_self_check.item_fail_num != 0){
			ob_self_check.led_switch = SELF_CHECK_LED_ON;
			ob_self_check.led_display_time = TIME_GetTicks();
			ob_self_check.led_toggle_time = TIME_GetTicks();
		}else{
			ob_self_check.led_switch = SELF_CHECK_LED_ON;
			if(self_uart_check_flag){
				LED_Start(LED_SELF_CHECK,COLOR_BLUE);
			}
			else{
				LED_Start(LED_SELF_CHECK,COLOR_CYAN);
			}
		}
}

static void ReadyIntoSelfMode(void){
		//设置为自检模式，且跳转到下一个流程
		hal_ble_scan_result_Regist(&scan_reslt_handle);
		ob_self_check.is_scan_success 			= false;
		ob_self_check.scan_trigger_timeout 	= TIME_GetTicks();
	  ob_self_check.stage = SELF_CHECK_STAGE_READY;
		clear_all_except();	//清除所有异常
		LED_Start(LED_SELF_CHECK,COLOR_BLACK); 
		LED_Stop(LED_SELF_CHECK);
		hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_ON);
		
		memset(ob_self_check.result, SELF_CHECK_ITEM_SUCCESS, SELF_CHECK_ITEMS);	
		SEGGER_RTT_printf(0,"app_self_checking_Process clear_all_except\r\n");
}


static void app_self_checking_Process(void)
{
	static uint8_t state =0;
	static uint8_t state_selft =0;
	static uint8_t displaycnt =0;

	switch(state){
		case 0:
			    if(BLE_Client_T_CHARGE_DONE == app_charge_Getstate() || \
						 BLE_Client_T_CHARGE_INSERT == app_charge_Getstate()
						){
							if(Except_IsErrorExist())																																														//如果存在错误
							{
								if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK) != -1)																		//如果当前是自检配置
								{
									hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);	//关掉自检配置
								}
								else{																																																							//如果当前不是自检配置{
									ST_scan_start();
									ReadyIntoSelfMode();
									state =1;
									state_selft =0;
								}
							}
							else{
								//设置为自检模式，且跳转到下一个流程
								ST_scan_start();
								ReadyIntoSelfMode();
								state =1;
								state_selft =0;
							}
					}
			    break;
    case 1:
					if(ob_self_check.is_scan_success == true)
					{
						ob_self_check.stage = SELF_CHECK_STAGE_CHECK;																				//进入自检阶段
						state =2;
						Process_SetHoldOn(app_self_checking_Process,1);
						SEGGER_RTT_printf(0,"ob_self_check.is_scan_success\r\n");
					}else{
             if((TIME_GetTicks() - ob_self_check.scan_trigger_timeout) > SELF_CHECK_SCAN_TRIGGER_TIMEOUT)		//超时且没扫描到广播名
						 {
							  state = 2;
							  state_selft =3;
							  SEGGER_RTT_printf(0,"ob_self_check.scan_trigger_timeout\r\n");
						 }
					}
			    break;
		case 2:
			    if(BLE_Client_T_CHARGE_PULLOUT == app_charge_Getstate()){
						 ob_self_check.is_scan_success 			= false;																					//重置扫描成功标志位	
			       hal_ble_scan_result_Clear(&scan_reslt_handle);																				//禁止扫描触发
						 ST_scan_stop();
						 state = 0;
					}
			    break;
		default:
			    break;
	}
	
	switch(state_selft)
	{
		case 0:																															   
			  if(SELF_CHECK_STAGE_CHECK == ob_self_check.stage){//扫描成功
					  MT_Run(500);
						if(-1 == hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK)){
					       hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_ON);
						}
				    state_selft = 1;
					  ob_self_check.ImuSetTime_times = TIME_GetTicks();
				}
				break;
		case 1:
			  if(BLE_Client_T_CHARGE_PULLOUT == app_charge_Getstate()){
					 state_selft = 3;
				}
			  else {
						if(0 == hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK)){
							state_selft = 2;
							displaycnt =0;
							app_self_check_getreslut();
						}
						else if(TIME_GetTicks() - ob_self_check.ImuSetTime_times >= SELF_CHECK_SET_IMU_TIMEOUT){
							Except_SetExceptype(EXCEPT_DATA_FRONT_ACC);
							Except_SetExceptype(EXCEPT_DATA_FRONT_GRY);
							Except_SetExceptype(EXCEPT_DATA_FRONT_MAG);
							Except_SetExceptype(EXCEPT_IMU_SUSPEND_OVERFLOW); 
							state_selft = 2;
							displaycnt =0;
						}
			  }
			  break;
	  case 2:
			   if(displaycnt < ob_self_check.item_fail_num){
						if(TIME_GetTicks() - ob_self_check.led_toggle_time >= SELF_CHECK_LED_TOGGLE_TIME){ob_self_check.led_toggle_time = TIME_GetTicks();
							if(ob_self_check.led_switch == SELF_CHECK_LED_ON){
								LED_Start(LED_SELF_CHECK,COLOR_LIGHRED);
								ob_self_check.led_switch = SELF_CHECK_LED_OFF;
							}
							else{
								LED_Start(LED_SELF_CHECK,COLOR_BLACK);
								ob_self_check.led_switch = SELF_CHECK_LED_ON;
								displaycnt++;
							}
						}
					}
				  else if(TIME_GetTicks() - ob_self_check.led_display_time >= SELF_CHECK_LED_DISPLAY_TIME){//显示时间到了，重现读取自检结果，并显示
						ob_self_check.led_display_time = TIME_GetTicks();
						displaycnt =0;
						app_self_check_getreslut();
					}
			    break;
		 case 3:
				 state_selft = 0;
		     ob_self_check.stage = SELF_CHECK_STAGE_READY;
         LED_Start(LED_SELF_CHECK,COLOR_BLACK); 
				 LED_Stop(LED_SELF_CHECK);
				 ob_self_check.led_switch = SELF_CHECK_LED_OFF;																					//设置自检灯为关
				 if(hal_ser_imu_mode_manage_get_ready(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK) != -1)        //当前是自检模式，退出。
				 {
						hal_ser_imu_mode_manage_set_required(HAL_SER_IMU_MODE_MANAGE_SELF_CHECK, HAL_SER_IMU_MODE_MANAGE_IMU_MODE_OFF);
				 }								
				 break;
		 default:
			   break;
	}	
}
static void app_self_checking_printf_process(void)
{
	SEGGER_RTT_printf(0,"self_check: FRONT_SENSOR:%d BACK_SENSOR:%d BATTERY:%d CHARGE:%d ANT:%d suspend_mode:%d scan_trigger_timeout:%d\n", \
	Except_IsError(EXCEPT_DATA_FRONT_ACC) || Except_IsError(EXCEPT_DATA_FRONT_GRY) || Except_IsError(EXCEPT_DATA_FRONT_MAG), \
	Except_IsError(EXCEPT_DATA_BACK_MAG), \
	Except_IsError(EXCEPT_DATA_BATTERY), \
	Except_IsError(EXCEPT_DATA_CHARGE), \
	Except_IsError(EXCEPT_ANT_DAMAGE), \
	Except_IsError(EXCEPT_IMU_SUSPEND_OVERFLOW),ob_self_check.scan_trigger_timeout);
}

/*API ----------------------------------------------------------*/
void app_self_checking_Init(void)
{
	ob_self_check.stage = SELF_CHECK_STAGE_READY;
	ob_self_check.ImuSetTime_times = 0;
	ob_self_check.item_fail_num = 0;
	ob_self_check.led_switch = SELF_CHECK_LED_OFF;
	ob_self_check.led_display_time = 0;
	ob_self_check.led_toggle_time = 0;
	ob_self_check.is_scan_success = false;																		
	ob_self_check.scan_trigger_timeout = SELF_CHECK_SCAN_TRIGGER_TIMEOUT;								

	
	Process_Start(SELF_CHECK_PROCESS_CYCLE,"app_self_checking_Process",app_self_checking_Process);
	Process_Start(300,"app_UartLine_Pair_Process",app_UartLine_Pair_Process);
	UART0_Rx_Regist(UART0_R_LINE_CHECK_ASK,cb_UART0_R_LINE_CHECK_ASK);
	UART0_Rx_Regist(UART0_R_LINE_CHECK_ACK,cb_UART0_R_LINE_CHECK_ACK);
//	Process_Start(1000,"app_self_checking_printf_process",app_self_checking_printf_process);
}

uint32_t app_self_checking_get_scan_trigger_timeout(void)
{
	return ob_self_check.scan_trigger_timeout;
}




















