
/*
******************************************************************************************************
 @Module         RF_Communication
 @Filename       RF_Communication.h
 @Project        Sem-3000
-----------------------------------------------------------------------------------------------------
 @Controller     	Si1010

 @Compiler      	Keil 8.12

 @ Frequency   	Using Internal clock 24.5MHz

 @Codegenerator 	0.1

 @Description   

------------------------------------------------------------------------------------------------------
 @Date          		2013-07-05 11:00:00

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

#define _RF_COMMUNICATION_C_


/*
********************************************************************************************************
*
* 									@Project Includes
*
********************************************************************************************************
*/

#include "PROJECT_INCLUDES.H"

	
/*
********************************************************************************************************
*
* 										@Defines
*
********************************************************************************************************
*/

/*
********************************************************************************************************
*
* 										@Typedefs
*
********************************************************************************************************
*/



/*
*********************************************************************************************************
*
*									@Global Variables
*
*********************************************************************************************************
*/

volatile Rf_Command_Receive_Data RF_CMD;										
extern U8 Rf_Disconnected[Max_CHANNEL_ID];


typedef struct
{ 		
	U8    New_Power_Indicate[Max_CHANNEL_ID]; 

	U8    CT_Phase[Max_CHANNEL_ID]; 
	U8    Battery_Level[Max_CHANNEL_ID]; 
	U8    Rf_Power_Level[Max_CHANNEL_ID]; 
	
	U16  Rx_Count[Max_CHANNEL_ID];
	
	U32 Phase_1[Max_CHANNEL_ID];
	U32 Phase_2[Max_CHANNEL_ID];
	U32 Phase_3[Max_CHANNEL_ID];

	U32 V_Data[Max_CHANNEL_ID];
	U32 PF_Data[Max_CHANNEL_ID];

	U32 Power_Data[Max_CHANNEL_ID];

	U8 	Device_Type[Max_CHANNEL_ID];  // 0: PIT, 1: CRT
	
 	#if 1    // cmlee
	U8 Compare_Count1[Max_CHANNEL_ID];
	U8 Compare_Count2[Max_CHANNEL_ID];
	U16  Rx_Count_WEB[Max_CHANNEL_ID];
	U32  Power_Data_WEB[Max_CHANNEL_ID];
	U32 Previous_Power_Send[Max_CHANNEL_ID];
	#endif

} One_Hour_PowerData_Def;

volatile One_Hour_PowerData_Def	 One_Hour_Bf;



/*
**********************************************************************************************************
*
* 								@Prototypes Of Static  Functions
*
**********************************************************************************************************
*/



/*
*********************************************************************************************************
*                                                          RF_Communication_Initializ
*
* Description:   RF_Communication_Initializ
*
* Arguments  :  NONE
*
* Returns      :   NONE
*
*********************************************************************************************************
*/

void RF_Communication_Initializ(void) 
{
	memset(&One_Hour_Bf, 0, sizeof(One_Hour_Bf));
	memset(&One_Hour_Bf.New_Power_Indicate[0], 0, sizeof(One_Hour_Bf.New_Power_Indicate));	
	
	memset(&One_Hour_Bf.Rx_Count[0], 0, sizeof(One_Hour_Bf.Rx_Count));	
	memset(&One_Hour_Bf.Power_Data[0], 0, sizeof(One_Hour_Bf.Power_Data));	
	#if 1    //cmlee for initialization of cal of one minute on WEB 
	memset(&One_Hour_Bf.Rx_Count_WEB[0], 0, sizeof(One_Hour_Bf.Rx_Count_WEB));	
	memset(&One_Hour_Bf.Power_Data_WEB[0], 0, sizeof(One_Hour_Bf.Power_Data_WEB));	 

	memset(&One_Hour_Bf.Previous_Power_Send[0], 0, sizeof(One_Hour_Bf.Previous_Power_Send));	
	memset(&One_Hour_Bf.Compare_Count1[0], 0, sizeof(One_Hour_Bf.Compare_Count1));	
	memset(&One_Hour_Bf.Compare_Count2[0], 0, sizeof(One_Hour_Bf.Compare_Count2));	
	#endif
	memset(&One_Hour_Bf.Phase_1[0], 0, sizeof(One_Hour_Bf.Phase_1));	
	memset(&One_Hour_Bf.Phase_2[0], 0, sizeof(One_Hour_Bf.Phase_2));	
	memset(&One_Hour_Bf.Phase_3[0], 0, sizeof(One_Hour_Bf.Phase_3));	
	
	memset(&One_Hour_Bf.Device_Type[0], 0, sizeof(One_Hour_Bf.Device_Type));	// 0: PIT, 1: CRT
	memset(&One_Hour_Bf.V_Data[0], 0, sizeof(One_Hour_Bf.V_Data));
	memset(&One_Hour_Bf.PF_Data[0], 0, sizeof(One_Hour_Bf.PF_Data));
}

void Put_CT_Device_Type(U8 ID, U8  Device_Type)
{
 	One_Hour_Bf.Device_Type[ ID-1]=Device_Type;
}

U8 Get_CT_Device_Type(U8 ID)
{
 	return ( One_Hour_Bf.Device_Type[ ID-1] ) ;
}

void Put_CT_Sensor_Connection_Indicate(U8 ID, U8  CT_Sensor)
{
 	One_Hour_Bf.CT_Phase[ ID-1]=CT_Sensor;
}

void Put_CT_Sensor_Battery_Level_Indicate(U8 ID, U8  Battery_Level)
{
 	One_Hour_Bf.Battery_Level[ ID-1]=Battery_Level;
}

void Put_CT_Sensor_Rf_Power_Level_Indicate(U8 ID, U8  Rf__Level)
{
	if(Rf__Level<=120){
		One_Hour_Bf.Rf_Power_Level[ ID-1]=120-Rf__Level;
	}
 	else One_Hour_Bf.Rf_Power_Level[ ID-1]=Rf__Level-120;
	
	//printf(" re define RF=%d",(U16) One_Hour_Bf.Rf_Power_Level[ ID-1]);

}




U8 Get_CT_Sensor_Connection_Indicate(U8 ID)
{
 	return ( One_Hour_Bf.CT_Phase[ ID-1] );
}

U8 Get_CT_Sensor_Battery_Level_Indicate(U8 ID)
{
 	return ( One_Hour_Bf.Battery_Level[ ID-1] ) ;
}

U8 Get_CT_Sensor_Rf_Power_Level_Indicate(U8 ID)
{
 	return ( One_Hour_Bf.Rf_Power_Level[ ID-1]) ;
}

U32 Get_CT_PF_V_Data( U8 ID, U8 Sel_PF_Or_V) // return Voltage of PIT
{
	volatile  U32 idata Result;
	
	if(Sel_PF_Or_V == 0)
	Result = One_Hour_Bf.V_Data[ID-1];
	else
	Result = One_Hour_Bf.PF_Data[ID-1];
	
	return Result;
}

/*
*********************************************************************************************************
*                                                          Save_Buffer_CT_PowerData
*
* Description:   
*
* Arguments  :  ID:
*			   Power_Data	:
* Returns      :   NONE
*
*********************************************************************************************************
*/

#define MAX_COUNT    2000          //     650     650이상 가는 경우 존재          송신기에서  보내는 횟수가 많음 
#if 1
#define MAX_COUNT_WEB  50    // if thr value interval changed , this shouls be changed .  NOW based on 1 min ==> 10,  
#endif
extern U32 RealTime_PowerData[Max_CHANNEL_ID];
void Save_Buffer_CT_PowerData( U8 ID,  U32 *Power_Data ) 
{       			
	volatile  U32 idata Phase1, Phase2, Phase3;
	volatile  U32 idata Sum_Power_1hr;
	U32  Sum_Power_1min;
	//U8 real_count;
	U32 phase1_WEB; 

	
	Phase1 =0L;  Phase2 =0L;  Phase3 = 0L;  
	
	Phase1 = Power_Data[0];
	Phase2 = Power_Data[1];
	Phase3 = Power_Data[2];
	
	if(Get_CT_Device_Type(ID))	// 0: PIT, 1: CRT
	{
		if(event1.AC_voltage[ID-1] == AUTO_AC_VOLTAGE)
		{
			if(Get_CT_PF_V_Data(ID, 0) > 70)
			{
				Phase1=((Phase1 * Get_CT_PF_V_Data(ID, 0))/100);
				Phase2=((Phase2 * Get_CT_PF_V_Data(ID, 0))/100);
				Phase3=((Phase3 * Get_CT_PF_V_Data(ID, 0))/100);
			}
			else
			{
				Phase1=((Phase1 * (U32)Get_Setted_Voltage(ID))/100);
				Phase2=((Phase2 * (U32)Get_Setted_Voltage(ID))/100);
				Phase3=((Phase3 * (U32)Get_Setted_Voltage(ID))/100);
			}

			//printf("\n [1] ID=%d, Device_Type = %d, Power Data=%ld", (U16)ID, (U16)Get_CT_Device_Type(ID), Phase2);
		}
		else
		{
			Phase1=((Phase1 * (U32)Get_Setted_Voltage(ID))/100);
			Phase2=((Phase2 * (U32)Get_Setted_Voltage(ID))/100);
			Phase3=((Phase3 * (U32)Get_Setted_Voltage(ID))/100);
			//printf("\n [2] ID=%d, Device_Type = %d, Power Data = %ld", (U16)ID, (U16)Get_CT_Device_Type(ID), Phase2);
		}
	}
	
	One_Hour_Bf.New_Power_Indicate[ID-1]= RF_RECEIVE_DATA_EXIST;

	if(++One_Hour_Bf.Rx_Count[ID-1]>MAX_COUNT)One_Hour_Bf.Rx_Count[ID-1]=MAX_COUNT;
	#if 1
	if(++One_Hour_Bf.Rx_Count_WEB[ID-1]>MAX_COUNT_WEB)
	{
		 One_Hour_Bf.Power_Data_WEB[ID-1]=0;
		 One_Hour_Bf.Rx_Count_WEB[ID-1]=0;
		 
	}
	#endif
	
	if( Phase1<1000000)One_Hour_Bf.Phase_1[ID-1] =Phase1;  // 수신 된 데이터가   1,000,000 W 이상 이면  전에 수신한값 으로 한다 
       else           Phase1=One_Hour_Bf.Phase_1[ID-1] ;

	if( Phase2<1000000)One_Hour_Bf.Phase_2[ID-1] =Phase2;
       else 	    Phase2=One_Hour_Bf.Phase_2[ID-1] ;
	   
	if( Phase3<1000000)One_Hour_Bf.Phase_3[ID-1] =Phase3;
       else 	    Phase3=One_Hour_Bf.Phase_3[ID-1] ;
	
	// USB 로 전송 한다 
	Sum_Power_1hr= 0L;   

	Sum_Power_1hr = (Phase1+Phase2+ Phase3) ;  

	#if 1
	Sum_Power_1min = 0L;

	Sum_Power_1min=Sum_Power_1hr ;
	#endif
	#if 0    // cmlee   받은 값은 바로 저장한다. 나중에 웹 / PC 프로그램으로 전송 
			RealTime_PowerData[ID-1]=Sum_Power_1hr ;
		//printf("RealTime_PowerData=%ld\n", RealTime_PowerData[ID-1]) ;
		//printf("ID=%d\n",(ID-1));
	#endif 	
      //temp=One_Hour_Bf.Previous_Power_Send[ID];
	#if 1
	if(One_Hour_Bf.Previous_Power_Send[ID-1] *10 < Sum_Power_1min)
		{
		One_Hour_Bf.Compare_Count1[ID-1]++;
		One_Hour_Bf.Compare_Count2[ID-1]=0;
		if(One_Hour_Bf.Compare_Count1[ID-1]>2)   // real data
			{
			One_Hour_Bf.Compare_Count1[ID-1]=0;
			
			One_Hour_Bf.Previous_Power_Send[ID-1]=Sum_Power_1min; 
			
			}
		else     // 1인 경우     fake data
			{
			Sum_Power_1min=One_Hour_Bf.Previous_Power_Send[ID-1];
			
			}
		}
	else   // Normal state
		{
		One_Hour_Bf.Compare_Count1[ID-1]=0;
		 if((One_Hour_Bf.Previous_Power_Send[ID-1] !=0) && (Sum_Power_1min==0))      // when pwr data go to 0 suddenly
		 	{
			One_Hour_Bf.Compare_Count2[ID-1]++;
		 	if(One_Hour_Bf.Compare_Count2[ID-1]>3)   // real data
				{
				One_Hour_Bf.Compare_Count2[ID-1]=0;
				One_Hour_Bf.Previous_Power_Send[ID-1]=Sum_Power_1min; 
		 		}
			else       
				{
				Sum_Power_1min=One_Hour_Bf.Previous_Power_Send[ID-1];
				}
		 	}
		 else
		 	{
		 	One_Hour_Bf.Compare_Count2[ID-1]=0;
			One_Hour_Bf.Previous_Power_Send[ID-1]=Sum_Power_1min;
		 	}
		}
	Sum_Power_1hr=Sum_Power_1min;   //  To calculate one hour , 
	#endif

	Phase1= One_Hour_Bf.Power_Data[ID-1] ;
	Sum_Power_1hr += Phase1 ;
	One_Hour_Bf.Power_Data[ID-1] = Sum_Power_1hr;                     // 수신 된 전력을 모두 더해서  1시간 버퍼에 저장 한다 

	#if 1
	phase1_WEB = One_Hour_Bf.Power_Data_WEB[ID-1] ;
	Sum_Power_1min +=phase1_WEB;
	One_Hour_Bf.Power_Data_WEB[ID-1] = Sum_Power_1min;    
	#endif 
	
	#if (RF_POWER_RX_DEBUG)
		//printf("\n Sum= %ld ", One_Hour_Bf.Phase_1[ID-1] +  One_Hour_Bf.Phase_2[ID-1] + One_Hour_Bf.Phase_3[ID-1]  );
		//printf("\ CH1= %ld CH2= %ld CH3= %ld ", One_Hour_Bf.Phase_1[ID-1] ,  One_Hour_Bf.Phase_2[ID-1] , One_Hour_Bf.Phase_3[ID-1]  );
	     // printf("  sP=%ld", One_Hour_Bf.Power_Data[ID-1]);
		//printf("  Count=%ld", One_Hour_Bf.Rx_Count[ID-1]);
		// printf("  sP=%ld", One_Hour_Bf.Power_Data_WEB[ID-1]);
		// printf("  Count=%d", One_Hour_Bf.Rx_Count_WEB[ID-1]);
	Uart0_PutString("\n p1 ="); 	TwoByteHexTxSend((U16)BIN2BCD( One_Hour_Bf.Phase_1[ID-1]));
	Uart0_PutString("  p2="); 	TwoByteHexTxSend((U16)BIN2BCD( One_Hour_Bf.Phase_2[ID-1]));
	Uart0_PutString("  p3="); 	TwoByteHexTxSend((U16)BIN2BCD( One_Hour_Bf.Phase_3[ID-1]));
	Uart0_PutString("\n p11="); 	TwoByteHexTxSend((U16)BIN2BCD( Phase1));
	Uart0_PutString("\n p22="); 	TwoByteHexTxSend((U16)BIN2BCD( Phase2));
	Uart0_PutString("\n p33="); 	TwoByteHexTxSend((U16)BIN2BCD( Phase3));
	UART0_SEND();

	#endif
		
}

void Buffer_CT_PF_V_Data( U8 ID, U32 *PF_V_Data, U8 Sel) 
{
	if(Sel == 0)
	One_Hour_Bf.V_Data[ID-1] = PF_V_Data[0];
	else
	One_Hour_Bf.PF_Data[ID-1] = PF_V_Data[0];

	//printf("\n ID=%d, V=%ld, PF=%ld \n",(U16)(ID-1), One_Hour_Bf.V_Data[ID-1], One_Hour_Bf.PF_Data[ID-1]);

	#if (RF_POWER_RX_DEBUG)
	Uart0_PutString("\n V="); 	TwoByteHexTxSend((U16)BIN2BCD( One_Hour_Bf.V_Data[ID-1]));
	Uart0_PutString("\n  PF="); 	TwoByteHexTxSend((U16)BIN2BCD( One_Hour_Bf.PF_Data[ID-1]));
	UART0_SEND();
	#endif
}

void One_hour_Buff_Clr( U8 ID)
{
	One_Hour_Bf.Phase_1[ID-1] =0L;
	One_Hour_Bf.Phase_2[ID-1] =0L;
	One_Hour_Bf.Phase_3[ID-1] =0L;
	
	One_Hour_Bf.New_Power_Indicate[ID-1]=RF_RECEIVE_DATA_NONEXIST;	
	
}


/*
*********************************************************************************************************
*                                                          Get_RealTime_PowerData
*
* Description:   5초 Power Data 평균    
*
* Arguments  :  ID: 채널 
*			   
* Returns      :   RealTime_PowerData
*
*********************************************************************************************************
*/

volatile U32 Get_RealTime_PowerData( U8 ID) 
{       	
	volatile  U32 idata Phase1, Phase2, Phase3;

	if(One_Hour_Bf.New_Power_Indicate[ID-1]== RF_RECEIVE_DATA_NONEXIST)return NUN_POWER; 
	
	Phase1 =0L;  Phase2 =0L;  Phase3 = 0L;  

	Phase1 = One_Hour_Bf.Phase_1[ID-1]; 
	Phase2 = One_Hour_Bf.Phase_2[ID-1]; 
	Phase3 = One_Hour_Bf.Phase_3[ID-1]; 
	
	Phase1=(Phase1+Phase2+Phase3);

	//printf("\n RealTime_PowerData = %ld", Phase1);

	//printf("\n PIT Real Voltage=%ld, Set_AC_Voltage=%d", Get_CT_PF_V_Data(ID, 0), (U16)Set_AC_Voltage);

	One_hour_Buff_Clr(ID);
		
	return Phase1;    // Lcd Display Data
	
}

/*
*********************************************************************************************************
*                                                          Get_RealTime_One_Hour_PowerData
*
* Description:    1시간 의  3상 전력을 합하여 평균 전력으로 계산 후  리턴 한다    
*
* Arguments  :  ID
*			   
* Returns      :   Power_Data:  3상 피상 전력 
*
*********************************************************************************************************
*/

volatile U32 Get_RealTime_One_Hour_PowerData( U8 ID) 
{       	
  	idata U32  volatile  Sum_Power_Data;
  	idata U16  volatile  Cnt;

	Cnt=One_Hour_Bf.Rx_Count[ID] ;  // 수신된  체널 의  Power 데이터  의 카운터 

	if(Cnt==0){
		return  NUN_POWER;	// 받은 데이터가 없으면 
	}

	Sum_Power_Data= One_Hour_Bf.Power_Data[ID];

	Sum_Power_Data /= (U32)Cnt;            // 1시간  평균 전력  계산 

///	printf("  One Hour P=%ld  cnt=%d", Sum_Power_Data, Cnt );


	One_Hour_Bf.Power_Data[ID]=0L;
	One_Hour_Bf.Rx_Count[ID]=0 ;
	
	return  Sum_Power_Data;	
	
}
//=====================================================================
// average power value on WEB       cmlee
//=====================================================================
volatile U32 Get_RealTime_One_Min_PowerData( U8 ID) 
{       	
  	U32  volatile  Sum_Power_Data1;
  	U16  volatile  Cnt1;
	U32 test1, test2, test4;
	U8 test3;

	Sum_Power_Data1=0;
#if 0
	Cnt1=0;
#endif
	Cnt1=One_Hour_Bf.Rx_Count_WEB[ID] ;  // 수신된  체널 의  Power 데이터  의 카운터 
	
	if(Cnt1==0){
 		if(Rf_Disconnected[ID] > DISCONNECT_TIME_OUT)
			return RealTime_PowerData[ID];	
		else
			return One_Hour_Bf.Previous_Power_Send[ID];
		}
	Sum_Power_Data1= One_Hour_Bf.Power_Data_WEB[ID];
	Sum_Power_Data1 /= (U32)Cnt1;

	One_Hour_Bf.Power_Data_WEB[ID]=0L;
	One_Hour_Bf.Rx_Count_WEB[ID]=0 ;	
		
	return  Sum_Power_Data1;	
	
}

/*
*********************************************************************************************************
*                                                                   Rf_Command_Action_Proc
*
* Description:   Rf Command 를 실행 한다 
*
* Arguments  :   Return_Command: 수신된 컨멘드를  리터 받을 변수 
*                    
*
* Returns    :      RF_COMMAND_STATE : 다음 컨멘드 수행 

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

 RF_COMMAND_STATE  Rf_Command_Action_Proc( U8 * Return_Command)
{
	idata U8 volatile Del_Channel;
		
	if( Chk_Rf_Command_State()==EXIST_COMMAND)
	{		
		Get_Rf_Command(&RF_CMD);

		switch(RF_CMD.CMD){
			
				case PAIRING_CMD:	
					
								RF_Send_Command(RF_RADIO_NOT_SEND_CMD, Display_Channel, 0);  // 3) ACK 전송 ( 무선 송출 금지 컨멘드 )
																		
								*Return_Command=PAIRING_CMD;

								//printf("\nP Mac= %02x id=%d ",  RF_CMD.MAC_Addr, (U16)RF_CMD.PID);

								if(RF_CMD.MAC_Addr !=0xffff){					
									
															Del_Channel=Check_Memory_Pairing_ID( RF_CMD.MAC_Addr);
															
															if(Del_Channel)
															{																								
																event1.Channel_ID[ (Del_Channel -1)]=0xffff;

															//	printf("\n Del Id= %02x",  RF_CMD.MAC_Addr);
																
																System_Parameter_Init(SYSTEM_SETING);
															}
								}
								
								Rf_Command_Receive_Memory_Init();
								
					                     return NEXT; 
								break;		 
					
				case VOLTAGE_SETING_CMD:					
								
								if(RF_CMD.Data==ACK){
													*Return_Command=ACK;
													
													event1.Channel_ID[ (Display_Channel -1)]=PARING_RF_Key_ID;

												//	printf("\nid %02x,  %02x", event1.Channel_ID[ (Display_Channel -1)], PARING_RF_Key_ID);
													
													System_Parameter_Init(SYSTEM_SETING);									
													
													Rf_Command_Receive_Memory_Init();													
													
										                     return NEXT; 
								}
							//	else LCD_Display_Now_Energy(RF_CMD.Data);  

								*Return_Command=VOLTAGE_SETING_CMD;
								
								Rf_Command_Receive_Memory_Init();													

					                     return NEXT; 
								
								break;
		}

		Rf_Command_Receive_Memory_Init();

	}

       return WAITING_RECEIVING;
	   
}







 U16 Get_Rf_Receive_Data(void)
{
 	return RF_CMD.Data;
}





