#include "includes.h"

ZERO_CTRL_RLY c_rly;

void Relay_Init(void)
{
	memset(&c_rly,0, sizeof(ZERO_CTRL_RLY));
	
	EEPROM_Init();
	

	GPT_IO_Init(GPT_CHB_PB00);
	
	GPT_Configure(GPTCLK_EN,GPT_PCLK,GPT_IMMEDIATE,0);
	GPT_WaveCtrl_Configure(GPT_INCREASE,GPT_SWSYNDIS,GPT_IDLE_LOW,GPT_PRDLD_PEND,GPT_OPM_CONTINUOUS,GPT_BURST_DIS,GPT_CKS_PCLK,GPT_CG_CHAX,GPT_CGFLT_00,GPT_PRDLD_ZERO);
	GPT_Period_CMP_Write(10000,0,0);		
	GPT_WaveLoad_Configure(GPT_WAVEA_IMMEDIATE,GPT_WAVEB_SHADOW,GPT_AQLDA_ZERO,GPT_AQLDB_ZERO);
	GPT_WaveOut_Configure(GPT_CHB,GPT_CASEL_CMPA,GPT_CBSEL_CMPA,2,0,1,1,0,0,0,0,0,0);
	GPT_Start();
	GPT_ConfigInterrupt_CMD(ENABLE,GPT_INT_PEND);	
	
	
	
	
	
	
	
	
	//真-继电器
	GPIO_Init(GPIOA0,12,Output);
	GPIO_Init(GPIOA0,13,Output);	
	
	RLY_1_CLOSE;
	RLY_2_CLOSE;
	
	
	
	c_rly.rly_control = 0x01;	//继电器控制标志位
}

/*****************************************
  * @brief  和校验
  * @param  data: 校验数据
  * @param  len: 数据长度
  * @retval 和校验值
  ******************************************/
U8_T CheckSum(U8_T *data,U16_T len)
{
	U16_T data_sum = 0;
	
	for(U16_T i = 0;i<len;i++)
	{
		data_sum += data[i];
	}
	return data_sum;
}

U8_T CheckSum3(U8_T *data,U16_T len,U16_T n)
{
	U16_T data_sum = 0;
	
	for(U16_T i = 0;i<len;i++)
	{
		if(n != i){
			data_sum += data[i];
		}
	}
	return data_sum;
}


/*****************************************
  * @brief  和校验取反
  * @param  data: 校验数据
  * @param  len: 数据长度
  * @retval 和校验值
  ******************************************/
U8_T CheckSum_Check(U8_T *data,U16_T len)
{
	U16_T data_sum = 0;
	
	for(U16_T i = 0;i<len;i++)
	{
		data_sum += data[i];
	}
	return ~data_sum;
}
U8_T CheckSum_Overlook_Check(U8_T *data, U16_T len, U16_T check_id)
{
	U8_T data_sum = 0;
	
	for(U8_T i = 0;i<len;i++)
	{
		if(check_id != i) data_sum += data[i];
	}
	return ~data_sum;
}


//选择输出电压，0 - 10000mV
U8_T Change_OUTV(U16_T VolOut)
{
	if(VolOut > 10000) return 0x01;
	
	GPT0->CMPA = VolOut;
#if DBG_LOG_EN	
	Dbg_Println(DBG_BIT_SYS_STATUS,"CMPA:%d",VolOut);
#endif		
	return 0x00;
}
/********************************************************************
 *@brief	由继电器状态判断当前风速，输出PWM波
 * @param	
 * @retval 	None
 * */

void BLV_VolOut_Ctrl(void)
{
	c_rly.wind = WIND_STOP;

	if(c_rly.rly_state[WINDRLY_HIGH] == Control_ON)			// 优先级高>中>抵 , 若同时被控制多个风速继电器，则将按照优先级打开继电器  
	{
#if DBG_LOG_EN		
		Dbg_Println(DBG_BIT_SYS_STATUS,"WIND_HIGH");
#endif		
		c_rly.wind = WIND_HIGH;
		//c_rly.rly_state[WINDRLY_MID] = Control_OFF;
		//c_rly.rly_state[WINDRLY_LOW] = Control_OFF;		
	}else if(c_rly.rly_state[WINDRLY_MID] == Control_ON)	
	{
#if DBG_LOG_EN
		Dbg_Println(DBG_BIT_SYS_STATUS,"WIND_MID");
#endif		
		c_rly.wind = WIND_MID;
		//c_rly.rly_state[WINDRLY_LOW] = Control_OFF;
	}else if(c_rly.rly_state[WINDRLY_LOW] == Control_ON)	
	{
#if DBG_LOG_EN
		Dbg_Println(DBG_BIT_SYS_STATUS,"WIND_LOW");
#endif		
		c_rly.wind = WIND_LOW;
	}	


	Dbg_Println(DBG_BIT_SYS_STATUS,"VolOut_Ctrl wind:%d",c_rly.wind);

	
	if(c_rly.wind == WIND_STOP){
		Change_OUTV(c_rly.wind_STOP_vol);
	}else if(c_rly.wind == WIND_LOW){
		Change_OUTV(c_rly.wind_LOW_vol);
	}else if(c_rly.wind == WIND_MID){
		Change_OUTV(c_rly.wind_MID_vol);
	}else if(c_rly.wind == WIND_HIGH){
		Change_OUTV(c_rly.wind_HIGH_vol);
	}		
}
/********************************************************************
 *@brief	产生继电器控制，直接控制两个实体继电器状态
 * @param	rly_id:继电器id
 * @param	state：继电器要改变的状态
 * @retval 	None
 * */
void BLV_RLY_Ctrl_Purpose(U8_T rly_id,U8_T state)
{
	if(rly_id >= RLY_MAX) return;

	switch(state)
	{
		case Control_ON:
			if(c_rly.rly_state[rly_id] != Control_ON)
			{
				c_rly.rly_state[rly_id] = Control_ON;
				if(rly_id == CTRL_RLY1){
					RLY_1_OPEN;
				}else if(rly_id == CTRL_RLY2){
					RLY_2_OPEN;
				}
			}
		break;
		case Control_OFF:
			if(c_rly.rly_state[rly_id] != Control_OFF)
			{
				c_rly.rly_state[rly_id] = Control_OFF;
				if(rly_id == CTRL_RLY1){
					RLY_1_CLOSE;
				}else if(rly_id == CTRL_RLY2){
					RLY_2_CLOSE;
				}
			}			
		break;		
		case Cnotrol_RES:
			if(c_rly.rly_state[rly_id] != Control_OFF)
			{
				c_rly.rly_state[rly_id] = Control_OFF;
				if(rly_id == CTRL_RLY1){
					RLY_1_CLOSE;
				}else if(rly_id == CTRL_RLY2){
					RLY_2_CLOSE;
				}
			}else if(c_rly.rly_state[rly_id] != Control_ON)
			{
				c_rly.rly_state[rly_id] = Control_ON;
				if(rly_id == CTRL_RLY1){
					RLY_1_OPEN;
				}else if(rly_id == CTRL_RLY2){
					RLY_2_OPEN;
				}
			}				
		break;		
	}

}
//继电器动作处理
void BLV_RLY_Task(void)
{
	if(c_rly.rly_control != 0x01)return;
	
	for(U8_T i = 0;i<RLY_MAX;i++)
	{
		if(c_rly.rly_ctrl_state[i] == RLY_OFF)
		{
			BLV_RLY_Ctrl_Purpose(i,Control_OFF);
		}
		else if(c_rly.rly_ctrl_state[i] == RLY_ON)
		{
			BLV_RLY_Ctrl_Purpose(i,Control_ON);
			
		}else if(c_rly.rly_ctrl_state[i] == RLY_RES)
		{
			BLV_RLY_Ctrl_Purpose(i,Cnotrol_RES);
		}				

		c_rly.rly_ctrl_state[i] = NO_CTRL;
	}
	
	BLV_VolOut_Ctrl();		//风速判断，输出pwm
	
#if DBG_LOG_EN	
	Dbg_Println(DBG_BIT_SYS_STATUS,"BLV_RLY_Task");
#endif	
	c_rly.rly_control = 0x00;
}

U8_T BLV_CMD_SN(U8_T sn)
{
	U8_T rely_sn = (sn & 0x0f);
	
	if(rely_sn <0x0F)
	{
		rely_sn += 1;
	}else{
		rely_sn = 0x00;
	}
	
	return rely_sn;
}



//1、主机下发设置继电器状态
U8_T BLV_A9RLY_CMD_SET_Processing(U8_T *data,U16_T len)
{
	if(len < 9) return 0x01;
	
	U8_T t = 0x00;
	U8_T SendData[30];	
	U16_T SendLen = 0x00;
	
	U16_T RLY_STATE = 0x00;
	
	
//	if(len >= 9)
	{
		RLY_STATE =(data[SEND_PARA] + (data[SEND_PARA+1]<<8));
		c_rly.rly_control = 0x01;	//继电器控制标志
		
		for(U8_T i = 0;i<RLY_MAX;i++)
		{
			t = ((RLY_STATE>>(2*i)) & 0x03);
			
			if(t == NO_CTRL){
				c_rly.rly_ctrl_state[i] = NO_CTRL;	//默认状态，不用处理
			}else if(t == RLY_OFF){
				c_rly.rly_ctrl_state[i] = RLY_OFF;
			}else if(t == RLY_ON){
				c_rly.rly_ctrl_state[i] = RLY_ON;
			}else if(t == RLY_RES){
				c_rly.rly_ctrl_state[i] = RLY_RES;
	
			}				
		}
	}
	
	//BLV_RLY_Task();
	c_rly.SN = (data[1]&0x0F);
	//回复
	SendData[SendLen++] = g_Dip.addr;
	SendData[SendLen++] = c_rly.SN;		//SN
	SendData[SendLen++] = data[2];
	SendData[SendLen++] = data[0];
	SendData[SendLen++] = 0x00;		//len
	SendData[SendLen++] = 0x00;		//sum
	SendData[SendLen++] = CMD_SET_RLYSTATE_REPLY;		//回复CMD
	
	SendLen = 0x07;
	SendData[SEND_LEN] = SendLen;	//len
	SendData[SEND_SUM] = CheckSum_Check(SendData,SendLen);
	
	Set_GroupSend(SendData,SendLen,1,BUSSend_WaitTime1,20);	//组包	
	
	return 0x00;
}

//2、读取继电器状态的回复
void BLV_A9RLY_CMD_READ_Processing(U8_T *data,U16_T len)
{
	U8_T SendData[30];	
	U16_T SendLen = 0x00;
	
	U8_T RLY_State2 = 0x00;
	
	for(U8_T i = 0;i<RLY_MAX;i++)
	{
		if(c_rly.rly_state[i] == Control_ON)
		{
			RLY_State2 |= (0x01<<i);
		}
	}
	
	c_rly.SN = (data[1]&0x0F);
	//回复
	SendData[SendLen++] = g_Dip.addr;
	SendData[SendLen++] = c_rly.SN;
	SendData[SendLen++] = data[2];
	SendData[SendLen++] = data[0];
	SendData[SendLen++] = 0x00;		//len
	SendData[SendLen++] = 0x00;		//sum
	SendData[SendLen++] = CMD_READ_RLYSTATE_REPLY;		//回复CMD
	SendData[SendLen++] = RLY_State2;
	SendData[SendLen++] = 0x00;
	SendData[SendLen++] = 0x00;
	
	SendLen = 0x0A;
	SendData[SEND_LEN] = 0x0A;	//len
	SendData[SEND_SUM] = CheckSum_Check(SendData,SendLen);
	
	Set_GroupSend(SendData,SendLen,1,BUSSend_WaitTime1,20);	//组包	
}

//3、设置各个风速档位的电压输出值
U8_T BLV_WINDOUT_CMD_SET_Processing(U8_T *data,U16_T len)
{
	if(len < 15) return 0x01;
	
	U8_T save_flag = 0x00;
	U8_T SendData[30];	
	U16_T SendLen = 0x00;
	
	U16_T SetVol = 0x00;
	
//	if(len >= 15)
	{
		for(U8_T i = 0x00; i < 0x04; i++)
		{
			SetVol = (data[(SEND_PARA+(i*2))] + (data[(SEND_PARA+(i*2+1))]<<8 ));
			if(SetVol <= 10000){
				switch(i){
				case 0x00:
					if(c_rly.wind_STOP_vol != SetVol){
						c_rly.wind_STOP_vol = SetVol;
						save_flag++;
					}
				break;
				case 0x01:
					if(c_rly.wind_LOW_vol != SetVol){
						c_rly.wind_LOW_vol = SetVol;
						save_flag++;
					}
				break;
				case 0x02:
					if(c_rly.wind_MID_vol != SetVol){
						c_rly.wind_MID_vol = SetVol;
						save_flag++;
					}				
				break;
				case 0x03:
					if(c_rly.wind_HIGH_vol != SetVol){
						c_rly.wind_HIGH_vol = SetVol;
						save_flag++;
					}				
				break;					
				}
			}
		}
	}
	
	if(save_flag != 0x00)
	{
		EEPROM_WritePara();	//保存flash
		
	}
	
	BLV_VolOut_Ctrl();
	
	
	c_rly.SN = (data[1]&0x0F);
	//回复
	SendData[SendLen++] = g_Dip.addr;
	SendData[SendLen++] = c_rly.SN;
	SendData[SendLen++] = data[2];
	SendData[SendLen++] = data[0];
	SendData[SendLen++] = 0x00;		//len
	SendData[SendLen++] = 0x00;		//sum
	SendData[SendLen++] = CMD_SET_WINDOUTVOL_REPLY;		//回复CMD

	SendLen = 0x07;
	SendData[SEND_LEN] = SendLen;	//len
	SendData[SEND_SUM] = CheckSum_Check(SendData,SendLen);
	
	Set_GroupSend(SendData,SendLen,1,BUSSend_WaitTime1,20);	//组包	
	
	return 0x00;
}
//4、读取各个风速档位的电压输出值
U8_T BLV_WINDOUT_CMD_READ_Processing(U8_T *data,U16_T len)
{
	U8_T SendData[30];	
	U16_T SendLen = 0x00;
	
	
	c_rly.SN = (data[1]&0x0F);
	//回复
	SendData[SendLen++] = g_Dip.addr;
	SendData[SendLen++] = c_rly.SN;
	SendData[SendLen++] = data[2];
	SendData[SendLen++] = data[0];
	SendData[SendLen++] = 0x00;		//len
	SendData[SendLen++] = 0x00;		//sum
	SendData[SendLen++] = CMD_READ_WINDOUTVOL_REPLY;		//回复CMD
	SendData[SendLen++] = (c_rly.wind_STOP_vol & 0xFF);
	SendData[SendLen++] = (c_rly.wind_STOP_vol >> 8) & 0xFF;
	SendData[SendLen++] = (c_rly.wind_LOW_vol & 0xFF);
	SendData[SendLen++] = (c_rly.wind_LOW_vol >> 8) & 0xFF;
	SendData[SendLen++] = (c_rly.wind_MID_vol & 0xFF);
	SendData[SendLen++] = (c_rly.wind_MID_vol >> 8) & 0xFF;
	SendData[SendLen++] = (c_rly.wind_HIGH_vol & 0xFF);
	SendData[SendLen++] = (c_rly.wind_HIGH_vol >> 8) & 0xFF;
	
	SendLen = 0x0F;
	SendData[SEND_LEN] = SendLen;	//len
	SendData[SEND_SUM] = CheckSum_Check(SendData,SendLen);
	
	Set_GroupSend(SendData,SendLen,1,BUSSend_WaitTime1,20);	//组包	
	
	return 0x00;
}

//5、设置端口模式
U8_T BLV_DEVPROT_CMD_SET_Processing(U8_T *data,U16_T len)
{
	if(len != 0x08)  return 0x01;
	
	U8_T SendData[30];	
	U16_T SendLen = 0x00;
	
	if((data[SEND_PARA] == ACTIVE_PORT)||((data[SEND_PARA] == POLLING_PORT)))
	{
		if(data[SEND_PARA]  != c_rly.dev_port){
			c_rly.dev_port = data[SEND_PARA];
			
			EEPROM_WritePara();	//保存flash
		}
	}else{
		return 0x02;//设置的端口不合法
	}
	
	c_rly.SN = (data[1]&0x0F);
	//回复
	SendData[SendLen++] = g_Dip.addr;
	SendData[SendLen++] = c_rly.SN;
	SendData[SendLen++] = data[2];
	SendData[SendLen++] = data[0];
	SendData[SendLen++] = 0x00;		//len
	SendData[SendLen++] = 0x00;		//sum
	SendData[SendLen++] = CMD_SET_DEVPORT_REPLY;		//回复CMD

	SendLen = 0x07;
	SendData[SEND_LEN] = SendLen;	//len
	SendData[SEND_SUM] = CheckSum_Check(SendData,SendLen);
	
	Set_GroupSend(SendData,SendLen,1,BUSSend_WaitTime1,20);	//组包

	return 0x00;
}



//6、读取端口模式
U8_T BLV_DEVPROT_CMD_READ_Processing(U8_T *data,U16_T len)
{
	U8_T SendData[30];	
	U16_T SendLen = 0x00;
	
	
	c_rly.SN = (data[1]&0x0F);
	//回复
	SendData[SendLen++] = g_Dip.addr;
	SendData[SendLen++] = c_rly.SN;
	SendData[SendLen++] = data[2];
	SendData[SendLen++] = data[0];
	SendData[SendLen++] = 0x00;		//len
	SendData[SendLen++] = 0x00;		//sum
	SendData[SendLen++] = CMD_READ_DEVPORT_REPLY;		//回复CMD
	SendData[SendLen++] = c_rly.dev_port;		//端口模式
	SendData[SendLen++] = Project_FW_Version;	//软件版本号
	SendData[SendLen++] = Project_HW_Version;	//硬件版本号
	
	SendLen = 0x0A;
	SendData[SEND_LEN] = SendLen;	//len
	SendData[SEND_SUM] = CheckSum_Check(SendData,SendLen);
	
	Set_GroupSend(SendData,SendLen,1,BUSSend_WaitTime1,20);	//组包

	return 0x00;
}

U8_T BLV_RLY_RS485_Pro(U8_T *RecData, U16_T Len)
{
	U8_T ret = 0x00;
	
	if(Len < 0x07)
	{
		Dbg_Println(DBG_BIT_SYS_STATUS,"Data Len Err");
		return 0x01;
	}
	
	if(RecData[4] !=  Len)
	{
		Dbg_Println(DBG_BIT_SYS_STATUS,"Len Check Err");
		return 0x01;
	}	
	
	if(RecData[2] !=  A9EXPANDTYPE)			//A9继电器设备类型
	{
		Dbg_Println(DBG_BIT_SYS_STATUS,"Type Check Err");
		return 0x02;		
	}
	
	if(RecData[3] !=  g_Dip.addr)			//地址校验
	{
		Dbg_Println(DBG_BIT_SYS_STATUS,"Addr Check Err ");	
		return 0x03;		
	}
	

	if( CheckSum_Overlook_Check(RecData,Len,SEND_SUM) != RecData[SEND_SUM] )		//和校验
	{
		Dbg_Println(DBG_BIT_SYS_STATUS,"Sum Check Err: %02x,%02x",RecData[SEND_SUM],CheckSum_Overlook_Check(RecData,Len,SEND_SUM));
		Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"Sum Check Err: ",RecData,Len);
		return 0x05;		
	}
	
	if((RecData[SEND_SN]&0x0F) == c_rly.SN)
	{
		Dbg_Println(DBG_BIT_SYS_STATUS,"SN is Equal: %02x",c_rly.SN);	
		return 0x00;
	}	
	switch(RecData[0x06])
	{
#if DBG_LOG_EN		
		Dbg_Println(DBG_BIT_SYS_STATUS,"BLV_RLY_RS485 CMD:%02x",RecData[0x06]);	
#endif		
		case CMD_SET_RLYSTATE:
			BLV_A9RLY_CMD_SET_Processing(RecData,Len);
		break;
		case CMD_READ_RLYSTATE:
			BLV_A9RLY_CMD_READ_Processing(RecData,Len);
		break;
		case CMD_SET_WINDOUTVOL:
			BLV_WINDOUT_CMD_SET_Processing(RecData,Len);
		break;
		case CMD_READ_WINDOUTVOL:
			BLV_WINDOUT_CMD_READ_Processing(RecData,Len);
		break;		
		case CMD_SET_DEVPORT:
			BLV_DEVPROT_CMD_SET_Processing(RecData,Len);
		break;
		case CMD_READ_DEVPORT:
			BLV_DEVPROT_CMD_READ_Processing(RecData,Len);
		break;		
	}
	
}



void CTRL_LEDStatus_Task(void)
{
	static U32_T Ctrl_LED_tick = 0x00;
	
	if(SysTick_1ms - Ctrl_LED_tick >= 500)
	{
		Ctrl_LED_tick = SysTick_1ms;
		
		REVERISE_STATUS;
	}
}